All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables
@ 2021-07-08 15:45 Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 01/35] acpi: add helper routines to initialize " Igor Mammedov
                   ` (35 more replies)
  0 siblings, 36 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

v2:
  - drop test related patches, they will be sent as a separate series
  - fix bios_loader pointer initialization ordering when using TPM1.2
  - extend commit message of [1/35] and add extra comment about
    table length patching 

Highlights:
  * drop pointer arithmetic in ACPI tables code
  * use endian agnostic API
  * simplifies review of tables. /in most cases just line by line comparision with spec/

Series replaces build_header() with acpi_init_table()/acpi_table_composed()
API that hides pointer/offset arithmetic from user, to prevent
errors caused by it [1].
While doing above, it was necessary to split table header from
packed structure that was describing the table, which is
counter-productive since it still leaves packed structure drawbacks.
So that sort of forced me to rewrite tables that were composed with
help of packed structures to preferred build_append_int_noprefix() API.
In cases where refactoring to build_append_int_noprefix() was small,
it was squashed with acpi_init_table()/acpi_table_composed() patch.
Conversion reduced code size quite a bit despite me adding doc comments
for every table row.

1) commits
   bb9feea43179 x86: acpi: use offset instead of pointer when using build_header()
   4d027afeb3a9 Virt: ACPI: fix qemu assert due to re-assigned table data address

Link to repo:
   https://gitlab.com/imammedo/qemu/-/commits/acpi_build_header_refactoring_v2

CC: mst@redhat.com



Igor Mammedov (35):
  acpi: add helper routines to initialize ACPI tables
  acpi: build_rsdt: use acpi_init_table()/acpi_table_composed() instead
    of build_header()
  acpi: build_xsdt: use acpi_init_table()/acpi_table_composed() instead
    of build_header()
  acpi: build_slit: use acpi_init_table()/acpi_table_composed() instead
    of build_header()
  acpi: build_fadt: use acpi_init_table()/acpi_table_composed() instead
    of build_header()
  acpi: build_tpm2: use acpi_init_table()/acpi_table_composed() instead
    of build_header()
  acpi: acpi_build_hest: use acpi_init_table()/acpi_table_composed()
    instead of build_header()
  acpi: build_mcfg: use acpi_init_table()/acpi_table_composed() instead
    of build_header()
  acpi: build_hmat: use acpi_init_table()/acpi_table_composed() instead
    of build_header()
  acpi: nvdimm_build_nfit: use acpi_init_table()/acpi_table_composed()
    instead of build_header()
  acpi: nvdimm_build_ssdt: use acpi_init_table()/acpi_table_composed()
    instead of build_header()
  acpi: vmgenid_build_acpi: use acpi_init_table()/acpi_table_composed()
    instead of build_header()
  acpi: x86: build_dsdt: use acpi_init_table()/acpi_table_composed()
    instead of build_header()
  acpi: build_hpet: use acpi_init_table()/acpi_table_composed() instead
    of build_header()
  acpi: build_tpm_tcpa: use acpi_init_table()/acpi_table_composed()
    instead of build_header()
  acpi: arm/x86: build_srat: use acpi_init_table()/acpi_table_composed()
    instead of build_header()
  acpi: use build_append_int_noprefix() API to compose SRAT table
  acpi: build_dmar_q35: use acpi_init_table()/acpi_table_composed()
    instead of build_header()
  acpi: build_waet: use acpi_init_table()/acpi_table_composed() instead
    of build_header()
  acpi: build_amd_iommu: use acpi_init_table()/acpi_table_composed()
    instead of build_header()
  acpi: madt: arm/x86: use acpi_init_table()/acpi_table_composed()
    instead of build_header()
  acpi: x86: remove dead code
  acpi: x86: set enabled when composing _MAT entries
  acpi: x86: madt: use build_append_int_noprefix() API to compose MADT
    table
  acpi: arm/virt: madt: use build_append_int_noprefix() API to compose
    MADT table
  acpi: build_dsdt_microvm: use acpi_init_table()/acpi_table_composed()
    instead of build_header()
  acpi: arm: virt: build_dsdt: use
    acpi_init_table()/acpi_table_composed() instead of build_header()
  acpi: arm: virt: build_iort: use
    acpi_init_table()/acpi_table_composed() instead of build_header()
  acpi: arm/virt: convert build_iort() to endian agnostic
    build_append_FOO() API
  acpi: arm/virt: build_spcr: fix invalid cast
  acpi: arm/virt: build_spcr: use
    acpi_init_table()/acpi_table_composed() instead of build_header()
  acpi: arm/virt: build_gtdt: use
    acpi_init_table()/acpi_table_composed() instead of build_header()
  acpi: build_facs: use build_append_int_noprefix() API to compose table
  acpi: remove no longer used build_header()
  acpi: AcpiGenericAddress no longer used to map/access fields of MMIO,
    drop packed attribute

 include/hw/acpi/acpi-defs.h          | 528 +------------------------
 include/hw/acpi/acpi_dev_interface.h |   3 +-
 include/hw/acpi/aml-build.h          |  21 +-
 include/hw/i386/pc.h                 |   7 +-
 hw/acpi/acpi-x86-stub.c              |   3 +-
 hw/acpi/aml-build.c                  | 193 ++++++----
 hw/acpi/cpu.c                        |  17 +-
 hw/acpi/ghes.c                       |  10 +-
 hw/acpi/hmat.c                       |  14 +-
 hw/acpi/nvdimm.c                     |  64 ++--
 hw/acpi/pci.c                        |  18 +-
 hw/acpi/vmgenid.c                    |  16 +-
 hw/arm/virt-acpi-build.c             | 550 +++++++++++++++------------
 hw/i386/acpi-build.c                 | 284 ++++++++------
 hw/i386/acpi-common.c                | 158 ++++----
 hw/i386/acpi-microvm.c               |  13 +-
 16 files changed, 750 insertions(+), 1149 deletions(-)

-- 
2.27.0



^ permalink raw reply	[flat|nested] 56+ messages in thread

* [PATCH v2 01/35] acpi: add helper routines to initialize ACPI tables
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-09-02 12:56   ` Eric Auger
  2021-07-08 15:45 ` [PATCH v2 02/35] acpi: build_rsdt: use acpi_init_table()/acpi_table_composed() instead of build_header() Igor Mammedov
                   ` (34 subsequent siblings)
  35 siblings, 1 reply; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

Patch introduces acpi_init_table()/acpi_table_composed() API
that hides pointer/offset arithmetic from user as opposed
to build_header(), to prevent errors caused by it [1].

 acpi_init_table():
     initializes table header and keeps track of
     table data/offsets
 acpi_table_composed():
     sets actual table length and tells bios loader
     where table is for the later initialization on
     guest side.

1) commits
   bb9feea43179 x86: acpi: use offset instead of pointer when using build_header()
   4d027afeb3a9 Virt: ACPI: fix qemu assert due to re-assigned table data address

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 include/hw/acpi/aml-build.h | 14 +++++++++
 hw/acpi/aml-build.c         | 58 +++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 471266d739..d590660bd2 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -413,6 +413,20 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
 Aml *aml_object_type(Aml *object);
 
 void build_append_int_noprefix(GArray *table, uint64_t value, int size);
+
+typedef struct AcpiTable {
+    const char *sig;
+    const uint8_t rev;
+    const char *oem_id;
+    const char *oem_table_id;
+    /* private vars tracking table state */
+    GArray *array;
+    unsigned table_offset;
+} AcpiTable;
+
+void acpi_init_table(AcpiTable *desc, GArray *array);
+void acpi_table_composed(BIOSLinker *linker, AcpiTable *table);
+
 void
 build_header(BIOSLinker *linker, GArray *table_data,
              AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index d5103e6d7b..c598010144 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -52,6 +52,19 @@ static void build_append_byte(GArray *array, uint8_t val)
     g_array_append_val(array, val);
 }
 
+static void build_append_padded_str(GArray *array, const char *str,
+                                    size_t maxlen, char pad)
+{
+    size_t i;
+    size_t len = strlen(str);
+
+    g_assert(len <= maxlen);
+    g_array_append_vals(array, str, len);
+    for (i = maxlen - len; i > 0; i--) {
+        g_array_append_val(array, pad);
+    }
+}
+
 static void build_append_array(GArray *array, GArray *val)
 {
     g_array_append_vals(array, val->data, val->len);
@@ -1692,6 +1705,51 @@ Aml *aml_object_type(Aml *object)
     return var;
 }
 
+void acpi_init_table(AcpiTable *desc, GArray *array)
+{
+
+    desc->array = array;
+    desc->table_offset = array->len;
+
+    /*
+     * ACPI spec 1.0b
+     * 5.2.3 System Description Table Header
+     */
+    g_assert(strlen(desc->sig) == 4);
+    g_array_append_vals(array, desc->sig, 4); /* Signature */
+    build_append_int_noprefix(array, 0, 4); /* Length */
+    build_append_int_noprefix(array, desc->rev, 1); /* Revision */
+    build_append_int_noprefix(array, 0, 1); /* Checksum */
+    build_append_padded_str(array, desc->oem_id, 6, ' '); /* OEMID */
+    /* OEM Table ID */
+    build_append_padded_str(array, desc->oem_table_id, 8, ' ');
+    build_append_int_noprefix(array, 1, 4); /* OEM Revision */
+    g_array_append_vals(array, ACPI_BUILD_APPNAME8, 4); /* Creator ID */
+    build_append_int_noprefix(array, 1, 4); /* Creator Revision */
+}
+
+void acpi_table_composed(BIOSLinker *linker, AcpiTable *desc)
+{
+    /*
+     * ACPI spec 1.0b
+     * 5.2.3 System Description Table Header
+     * Table 5-2 DESCRIPTION_HEADER Fields
+     */
+    const unsigned checksum_offset = 9;
+    uint32_t table_len = desc->array->len - desc->table_offset;
+    uint32_t table_len_le = cpu_to_le32(table_len);
+    gchar *len_ptr = &desc->array->data[desc->table_offset + 4];
+
+    /* patch "Length" field that has been reserved by acpi_init_table()
+     * to the actual length, i.e. accumulated table length from
+     * acpi_init_table() till acpi_table_composed()
+     */
+    memcpy(len_ptr, &table_len_le, sizeof table_len_le);
+
+    bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
+        desc->table_offset, table_len, desc->table_offset + checksum_offset);
+}
+
 void
 build_header(BIOSLinker *linker, GArray *table_data,
              AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 02/35] acpi: build_rsdt: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 01/35] acpi: add helper routines to initialize " Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 03/35] acpi: build_xsdt: " Igor Mammedov
                   ` (33 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offests magic from API user.

While at it switch to build_append_int_noprefix() to build
entries to other tables (which also removes some manual offset
calculations).

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 include/hw/acpi/acpi-defs.h | 10 ----------
 hw/acpi/aml-build.c         | 27 ++++++++++++---------------
 2 files changed, 12 insertions(+), 25 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index cf9f44299c..ccfa3382aa 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -149,16 +149,6 @@ struct AcpiSerialPortConsoleRedirection {
 typedef struct AcpiSerialPortConsoleRedirection
                AcpiSerialPortConsoleRedirection;
 
-/*
- * ACPI 1.0 Root System Description Table (RSDT)
- */
-struct AcpiRsdtDescriptorRev1 {
-    ACPI_TABLE_HEADER_DEF       /* ACPI common table header */
-    uint32_t table_offset_entry[];  /* Array of pointers to other */
-    /* ACPI tables */
-} QEMU_PACKED;
-typedef struct AcpiRsdtDescriptorRev1 AcpiRsdtDescriptorRev1;
-
 /*
  * ACPI 2.0 eXtended System Description Table (XSDT)
  */
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index c598010144..705fe350bb 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1886,27 +1886,24 @@ build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
            const char *oem_id, const char *oem_table_id)
 {
     int i;
-    unsigned rsdt_entries_offset;
-    AcpiRsdtDescriptorRev1 *rsdt;
-    int rsdt_start = table_data->len;
-    const unsigned table_data_len = (sizeof(uint32_t) * table_offsets->len);
-    const unsigned rsdt_entry_size = sizeof(rsdt->table_offset_entry[0]);
-    const size_t rsdt_len = sizeof(*rsdt) + table_data_len;
-
-    rsdt = acpi_data_push(table_data, rsdt_len);
-    rsdt_entries_offset = (char *)rsdt->table_offset_entry - table_data->data;
+    AcpiTable table = { .sig = "RSDT", .rev = 1,
+                        .oem_id = oem_id, .oem_table_id = oem_table_id };
+
+    acpi_init_table(&table, table_data);
     for (i = 0; i < table_offsets->len; ++i) {
         uint32_t ref_tbl_offset = g_array_index(table_offsets, uint32_t, i);
-        uint32_t rsdt_entry_offset = rsdt_entries_offset + rsdt_entry_size * i;
+        uint32_t rsdt_entry_offset = table.array->len;
+
+        /* reserve space for entry */
+        build_append_int_noprefix(table.array, 0, 4);
 
-        /* rsdt->table_offset_entry to be filled by Guest linker */
+        /* mark position of RSDT entry to be filled by Guest linker */
         bios_linker_loader_add_pointer(linker,
-            ACPI_BUILD_TABLE_FILE, rsdt_entry_offset, rsdt_entry_size,
+            ACPI_BUILD_TABLE_FILE, rsdt_entry_offset, 4,
             ACPI_BUILD_TABLE_FILE, ref_tbl_offset);
+
     }
-    build_header(linker, table_data,
-                 (void *)(table_data->data + rsdt_start),
-                 "RSDT", rsdt_len, 1, oem_id, oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 
 /* Build xsdt table */
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 03/35] acpi: build_xsdt: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 01/35] acpi: add helper routines to initialize " Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 02/35] acpi: build_rsdt: use acpi_init_table()/acpi_table_composed() instead of build_header() Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 04/35] acpi: build_slit: " Igor Mammedov
                   ` (32 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

While at it switch to build_append_int_noprefix() to build
entries to other tables (which also removes some manual offset
calculations).

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 include/hw/acpi/acpi-defs.h | 10 ----------
 hw/acpi/aml-build.c         | 27 ++++++++++++---------------
 2 files changed, 12 insertions(+), 25 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index ccfa3382aa..f6d2ca172b 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -149,16 +149,6 @@ struct AcpiSerialPortConsoleRedirection {
 typedef struct AcpiSerialPortConsoleRedirection
                AcpiSerialPortConsoleRedirection;
 
-/*
- * ACPI 2.0 eXtended System Description Table (XSDT)
- */
-struct AcpiXsdtDescriptorRev2 {
-    ACPI_TABLE_HEADER_DEF       /* ACPI common table header */
-    uint64_t table_offset_entry[];  /* Array of pointers to other */
-    /* ACPI tables */
-} QEMU_PACKED;
-typedef struct AcpiXsdtDescriptorRev2 AcpiXsdtDescriptorRev2;
-
 /*
  * ACPI 1.0 Firmware ACPI Control Structure (FACS)
  */
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 705fe350bb..c33fa6c799 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1912,27 +1912,24 @@ build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
            const char *oem_id, const char *oem_table_id)
 {
     int i;
-    unsigned xsdt_entries_offset;
-    AcpiXsdtDescriptorRev2 *xsdt;
-    int xsdt_start = table_data->len;
-    const unsigned table_data_len = (sizeof(uint64_t) * table_offsets->len);
-    const unsigned xsdt_entry_size = sizeof(xsdt->table_offset_entry[0]);
-    const size_t xsdt_len = sizeof(*xsdt) + table_data_len;
-
-    xsdt = acpi_data_push(table_data, xsdt_len);
-    xsdt_entries_offset = (char *)xsdt->table_offset_entry - table_data->data;
+    AcpiTable table = { .sig = "XSDT", .rev = 1,
+                        .oem_id = oem_id, .oem_table_id = oem_table_id };
+
+    acpi_init_table(&table, table_data);
+
     for (i = 0; i < table_offsets->len; ++i) {
         uint64_t ref_tbl_offset = g_array_index(table_offsets, uint32_t, i);
-        uint64_t xsdt_entry_offset = xsdt_entries_offset + xsdt_entry_size * i;
+        uint64_t xsdt_entry_offset = table.array->len;
 
-        /* xsdt->table_offset_entry to be filled by Guest linker */
+        /* reserve space for entry */
+        build_append_int_noprefix(table.array, 0, 8);
+
+        /* mark position of RSDT entry to be filled by Guest linker */
         bios_linker_loader_add_pointer(linker,
-            ACPI_BUILD_TABLE_FILE, xsdt_entry_offset, xsdt_entry_size,
+            ACPI_BUILD_TABLE_FILE, xsdt_entry_offset, 8,
             ACPI_BUILD_TABLE_FILE, ref_tbl_offset);
     }
-    build_header(linker, table_data,
-                 (void *)(table_data->data + xsdt_start),
-                 "XSDT", xsdt_len, 1, oem_id, oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 
 void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 04/35] acpi: build_slit: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (2 preceding siblings ...)
  2021-07-08 15:45 ` [PATCH v2 03/35] acpi: build_xsdt: " Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 05/35] acpi: build_fadt: " Igor Mammedov
                   ` (31 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 hw/acpi/aml-build.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index c33fa6c799..80cd23f3a5 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1950,11 +1950,12 @@ void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
 void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms,
                 const char *oem_id, const char *oem_table_id)
 {
-    int slit_start, i, j;
-    slit_start = table_data->len;
+    int i, j;
     int nb_numa_nodes = ms->numa_state->num_nodes;
+    AcpiTable table = { .sig = "SLIT", .rev = 1,
+                        .oem_id = oem_id, .oem_table_id = oem_table_id };
 
-    acpi_data_push(table_data, sizeof(AcpiTableHeader));
+    acpi_init_table(&table, table_data);
 
     build_append_int_noprefix(table_data, nb_numa_nodes, 8);
     for (i = 0; i < nb_numa_nodes; i++) {
@@ -1965,11 +1966,7 @@ void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms,
                                       1);
         }
     }
-
-    build_header(linker, table_data,
-                 (void *)(table_data->data + slit_start),
-                 "SLIT",
-                 table_data->len - slit_start, 1, oem_id, oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 
 /* build rev1/rev3/rev5.1 FADT */
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 05/35] acpi: build_fadt: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (3 preceding siblings ...)
  2021-07-08 15:45 ` [PATCH v2 04/35] acpi: build_slit: " Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 06/35] acpi: build_tpm2: " Igor Mammedov
                   ` (30 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 hw/acpi/aml-build.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 80cd23f3a5..176d086b25 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1974,9 +1974,10 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
                 const char *oem_id, const char *oem_table_id)
 {
     int off;
-    int fadt_start = tbl->len;
+    AcpiTable table = { .sig = "FACP", .rev = f->rev,
+                        .oem_id = oem_id, .oem_table_id = oem_table_id };
 
-    acpi_data_push(tbl, sizeof(AcpiTableHeader));
+    acpi_init_table(&table, tbl);
 
     /* FACS address to be filled by Guest linker at runtime */
     off = tbl->len;
@@ -2040,7 +2041,7 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
     build_append_int_noprefix(tbl, f->flags, 4); /* Flags */
 
     if (f->rev == 1) {
-        goto build_hdr;
+        goto done;
     }
 
     build_append_gas_from_struct(tbl, &f->reset_reg); /* RESET_REG */
@@ -2077,7 +2078,7 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
     build_append_gas(tbl, AML_AS_SYSTEM_MEMORY, 0 , 0, 0, 0); /* X_GPE1_BLK */
 
     if (f->rev <= 4) {
-        goto build_hdr;
+        goto done;
     }
 
     /* SLEEP_CONTROL_REG */
@@ -2088,9 +2089,8 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
     /* TODO: extra fields need to be added to support revisions above rev5 */
     assert(f->rev == 5);
 
-build_hdr:
-    build_header(linker, tbl, (void *)(tbl->data + fadt_start),
-                 "FACP", tbl->len - fadt_start, f->rev, oem_id, oem_table_id);
+done:
+    acpi_table_composed(linker, &table);
 }
 
 #ifdef CONFIG_TPM
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 06/35] acpi: build_tpm2: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (4 preceding siblings ...)
  2021-07-08 15:45 ` [PATCH v2 05/35] acpi: build_fadt: " Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-09-02 12:59   ` Eric Auger
  2021-07-08 15:45 ` [PATCH v2 07/35] acpi: acpi_build_hest: " Igor Mammedov
                   ` (29 subsequent siblings)
  35 siblings, 1 reply; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanb, Stefan Berger, mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
---
CC: stefanb@linux.vnet.ibm.com
---
 hw/acpi/aml-build.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 176d086b25..057c64fb48 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -2103,13 +2103,14 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
                 const char *oem_id, const char *oem_table_id)
 {
     uint8_t start_method_params[12] = {};
-    unsigned log_addr_offset, tpm2_start;
+    unsigned log_addr_offset;
     uint64_t control_area_start_address;
     TPMIf *tpmif = tpm_find();
     uint32_t start_method;
+    AcpiTable table = { .sig = "TPM2", .rev = 4,
+                        .oem_id = oem_id, .oem_table_id = oem_table_id };
 
-    tpm2_start = table_data->len;
-    acpi_data_push(table_data, sizeof(AcpiTableHeader));
+    acpi_init_table(&table, table_data);
 
     /* Platform Class */
     build_append_int_noprefix(table_data, TPM2_ACPI_CLASS_CLIENT, 2);
@@ -2147,9 +2148,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
     bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
                                    log_addr_offset, 8,
                                    ACPI_BUILD_TPMLOG_FILE, 0);
-    build_header(linker, table_data,
-                 (void *)(table_data->data + tpm2_start),
-                 "TPM2", table_data->len - tpm2_start, 4, oem_id, oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 #endif
 
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 07/35] acpi: acpi_build_hest: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (5 preceding siblings ...)
  2021-07-08 15:45 ` [PATCH v2 06/35] acpi: build_tpm2: " Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 08/35] acpi: build_mcfg: " Igor Mammedov
                   ` (28 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: drjones, Dongjiu Geng, qemu-arm, mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Dongjiu Geng <gengdongjiu1@gmail.com>
---
CC: qemu-arm@nongnu.org
CC: drjones@redhat.com
CC: gengdongjiu1@gmail.com
---
 hw/acpi/ghes.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
index a749b84d62..bf58600a80 100644
--- a/hw/acpi/ghes.c
+++ b/hw/acpi/ghes.c
@@ -362,18 +362,16 @@ static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker)
 void acpi_build_hest(GArray *table_data, BIOSLinker *linker,
                      const char *oem_id, const char *oem_table_id)
 {
-    uint64_t hest_start = table_data->len;
+    AcpiTable table = { .sig = "HEST", .rev = 1,
+                        .oem_id = oem_id, .oem_table_id = oem_table_id };
 
-    /* Hardware Error Source Table header*/
-    acpi_data_push(table_data, sizeof(AcpiTableHeader));
+    acpi_init_table(&table, table_data);
 
     /* Error Source Count */
     build_append_int_noprefix(table_data, ACPI_GHES_ERROR_SOURCE_COUNT, 4);
-
     build_ghes_v2(table_data, ACPI_HEST_SRC_ID_SEA, linker);
 
-    build_header(linker, table_data, (void *)(table_data->data + hest_start),
-                 "HEST", table_data->len - hest_start, 1, oem_id, oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 
 void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 08/35] acpi: build_mcfg: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (6 preceding siblings ...)
  2021-07-08 15:45 ` [PATCH v2 07/35] acpi: acpi_build_hest: " Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 09/35] acpi: build_hmat: " Igor Mammedov
                   ` (27 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 hw/acpi/pci.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/hw/acpi/pci.c b/hw/acpi/pci.c
index 75b1103ec4..81ab83e636 100644
--- a/hw/acpi/pci.c
+++ b/hw/acpi/pci.c
@@ -28,19 +28,20 @@
 #include "hw/acpi/pci.h"
 #include "hw/pci/pcie_host.h"
 
+/*
+ * PCI Firmware Specification, Revision 3.0
+ * 4.1.2 MCFG Table Description.
+ */
 void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info,
                 const char *oem_id, const char *oem_table_id)
 {
-    int mcfg_start = table_data->len;
+    AcpiTable table = { .sig = "MCFG", .rev = 1,
+                        .oem_id = oem_id, .oem_table_id = oem_table_id };
+
+    acpi_init_table(&table, table_data);
 
-    /*
-     * PCI Firmware Specification, Revision 3.0
-     * 4.1.2 MCFG Table Description.
-     */
-    acpi_data_push(table_data, sizeof(AcpiTableHeader));
     /* Reserved */
     build_append_int_noprefix(table_data, 0, 8);
-
     /*
      * Memory Mapped Enhanced Configuration Space Base Address Allocation
      * Structure
@@ -56,6 +57,5 @@ void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info,
     /* Reserved */
     build_append_int_noprefix(table_data, 0, 4);
 
-    build_header(linker, table_data, (void *)(table_data->data + mcfg_start),
-                 "MCFG", table_data->len - mcfg_start, 1, oem_id, oem_table_id);
+    acpi_table_composed(linker, &table);
 }
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 09/35] acpi: build_hmat: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (7 preceding siblings ...)
  2021-07-08 15:45 ` [PATCH v2 08/35] acpi: build_mcfg: " Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 10/35] acpi: nvdimm_build_nfit: " Igor Mammedov
                   ` (26 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Also since acpi_init_table() reserves space only for standard header
while previous acpi_data_push() reserved the header + 4 bytes field,
add 4 bytes 'Reserved' field into hmat_build_table_structs()
which didn have it.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 hw/acpi/hmat.c | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/hw/acpi/hmat.c b/hw/acpi/hmat.c
index edb3fd91b2..5df4485298 100644
--- a/hw/acpi/hmat.c
+++ b/hw/acpi/hmat.c
@@ -200,6 +200,8 @@ static void hmat_build_table_structs(GArray *table_data, NumaState *numa_state)
     HMAT_LB_Info *hmat_lb;
     NumaHmatCacheOptions *hmat_cache;
 
+    build_append_int_noprefix(table_data, 0, 4); /* Reserved */
+
     for (i = 0; i < numa_state->num_nodes; i++) {
         flags = 0;
 
@@ -256,14 +258,10 @@ static void hmat_build_table_structs(GArray *table_data, NumaState *numa_state)
 void build_hmat(GArray *table_data, BIOSLinker *linker, NumaState *numa_state,
                 const char *oem_id, const char *oem_table_id)
 {
-    int hmat_start = table_data->len;
-
-    /* reserve space for HMAT header  */
-    acpi_data_push(table_data, 40);
+    AcpiTable table = { .sig = "HMAT", .rev = 2,
+                        .oem_id = oem_id, .oem_table_id = oem_table_id };
 
+    acpi_init_table(&table, table_data);
     hmat_build_table_structs(table_data, numa_state);
-
-    build_header(linker, table_data,
-                 (void *)(table_data->data + hmat_start),
-                 "HMAT", table_data->len - hmat_start, 2, oem_id, oem_table_id);
+    acpi_table_composed(linker, &table);
 }
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 10/35] acpi: nvdimm_build_nfit: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (8 preceding siblings ...)
  2021-07-08 15:45 ` [PATCH v2 09/35] acpi: build_hmat: " Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 11/35] acpi: nvdimm_build_ssdt: " Igor Mammedov
                   ` (25 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: xiaoguangrong.eric, mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Also since acpi_init_table() reserves space only for standard header
while previous acpi_data_push() reserved the header + 4 bytes field,
add 4 bytes 'Reserved' field into nvdimm_build_nfit() which didn't
have it.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: xiaoguangrong.eric@gmail.com
---
 hw/acpi/nvdimm.c | 42 +++++++++++++++++-------------------------
 1 file changed, 17 insertions(+), 25 deletions(-)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index e3d5fe1939..6a144b4542 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -44,22 +44,6 @@ static const uint8_t nvdimm_nfit_spa_uuid[] =
       UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
               0x18, 0xb7, 0x8c, 0xdb);
 
-/*
- * NVDIMM Firmware Interface Table
- * @signature: "NFIT"
- *
- * It provides information that allows OSPM to enumerate NVDIMM present in
- * the platform and associate system physical address ranges created by the
- * NVDIMMs.
- *
- * It is defined in ACPI 6.0: 5.2.25 NVDIMM Firmware Interface Table (NFIT)
- */
-struct NvdimmNfitHeader {
-    ACPI_TABLE_HEADER_DEF
-    uint32_t reserved;
-} QEMU_PACKED;
-typedef struct NvdimmNfitHeader NvdimmNfitHeader;
-
 /*
  * define NFIT structures according to ACPI 6.0: 5.2.25 NVDIMM Firmware
  * Interface Table (NFIT).
@@ -401,25 +385,33 @@ void nvdimm_plug(NVDIMMState *state)
     nvdimm_build_fit_buffer(state);
 }
 
+/*
+ * NVDIMM Firmware Interface Table
+ * @signature: "NFIT"
+ *
+ * It provides information that allows OSPM to enumerate NVDIMM present in
+ * the platform and associate system physical address ranges created by the
+ * NVDIMMs.
+ *
+ * It is defined in ACPI 6.0: 5.2.25 NVDIMM Firmware Interface Table (NFIT)
+ */
+
 static void nvdimm_build_nfit(NVDIMMState *state, GArray *table_offsets,
                               GArray *table_data, BIOSLinker *linker,
                               const char *oem_id, const char *oem_table_id)
 {
     NvdimmFitBuffer *fit_buf = &state->fit_buf;
-    unsigned int header;
+    AcpiTable table = { .sig = "NFIT", .rev = 1,
+                        .oem_id = oem_id, .oem_table_id = oem_table_id };
 
     acpi_add_table(table_offsets, table_data);
 
-    /* NFIT header. */
-    header = table_data->len;
-    acpi_data_push(table_data, sizeof(NvdimmNfitHeader));
+    acpi_init_table(&table, table_data);
+    /* Reserved */
+    build_append_int_noprefix(table_data, 0, 4);
     /* NVDIMM device structures. */
     g_array_append_vals(table_data, fit_buf->fit->data, fit_buf->fit->len);
-
-    build_header(linker, table_data,
-                 (void *)(table_data->data + header), "NFIT",
-                 sizeof(NvdimmNfitHeader) + fit_buf->fit->len, 1, oem_id,
-                 oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 
 #define NVDIMM_DSM_MEMORY_SIZE      4096
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 11/35] acpi: nvdimm_build_ssdt: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (9 preceding siblings ...)
  2021-07-08 15:45 ` [PATCH v2 10/35] acpi: nvdimm_build_nfit: " Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 12/35] acpi: vmgenid_build_acpi: " Igor Mammedov
                   ` (24 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: xiaoguangrong.eric, mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: xiaoguangrong.eric@gmail.com
---
 hw/acpi/nvdimm.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index 6a144b4542..b61bd681a1 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -1274,14 +1274,15 @@ static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data,
                               NVDIMMState *nvdimm_state,
                               uint32_t ram_slots, const char *oem_id)
 {
+    int mem_addr_offset;
     Aml *ssdt, *sb_scope, *dev;
-    int mem_addr_offset, nvdimm_ssdt;
+    AcpiTable table = { .sig = "SSDT", .rev = 1,
+                        .oem_id = oem_id, .oem_table_id = "NVDIMM" };
 
     acpi_add_table(table_offsets, table_data);
 
+    acpi_init_table(&table, table_data);
     ssdt = init_aml_allocator();
-    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
-
     sb_scope = aml_scope("\\_SB");
 
     dev = aml_device("NVDR");
@@ -1310,8 +1311,6 @@ static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data,
     aml_append(sb_scope, dev);
     aml_append(ssdt, sb_scope);
 
-    nvdimm_ssdt = table_data->len;
-
     /* copy AML table into ACPI tables blob and patch header there */
     g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len);
     mem_addr_offset = build_append_named_dword(table_data,
@@ -1323,10 +1322,13 @@ static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data,
     bios_linker_loader_add_pointer(linker,
         ACPI_BUILD_TABLE_FILE, mem_addr_offset, sizeof(uint32_t),
         NVDIMM_DSM_MEM_FILE, 0);
-    build_header(linker, table_data,
-        (void *)(table_data->data + nvdimm_ssdt),
-                 "SSDT", table_data->len - nvdimm_ssdt, 1, oem_id, "NVDIMM");
     free_aml_allocator();
+    /*
+     * must be executed as the last so that pointer patching command above
+     * would be executed by guest before it recalculates checksum which were
+     * scheduled by acpi_table_composed()
+     */
+    acpi_table_composed(linker, &table);
 }
 
 void nvdimm_build_srat(GArray *table_data)
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 12/35] acpi: vmgenid_build_acpi: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (10 preceding siblings ...)
  2021-07-08 15:45 ` [PATCH v2 11/35] acpi: nvdimm_build_ssdt: " Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 13/35] acpi: x86: build_dsdt: " Igor Mammedov
                   ` (23 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 hw/acpi/vmgenid.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/hw/acpi/vmgenid.c b/hw/acpi/vmgenid.c
index 4f41a13ea0..1801e8badf 100644
--- a/hw/acpi/vmgenid.c
+++ b/hw/acpi/vmgenid.c
@@ -29,6 +29,8 @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid,
     Aml *ssdt, *dev, *scope, *method, *addr, *if_ctx;
     uint32_t vgia_offset;
     QemuUUID guid_le;
+    AcpiTable table = { .sig = "SSDT", .rev = 1,
+                        .oem_id = oem_id, .oem_table_id = "VMGENID" };
 
     /* Fill in the GUID values.  These need to be converted to little-endian
      * first, since that's what the guest expects
@@ -42,15 +44,12 @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid,
     g_array_insert_vals(guid, VMGENID_GUID_OFFSET, guid_le.data,
                         ARRAY_SIZE(guid_le.data));
 
-    /* Put this in a separate SSDT table */
+    /* Put VMGNEID into a separate SSDT table */
+    acpi_init_table(&table, table_data);
     ssdt = init_aml_allocator();
 
-    /* Reserve space for header */
-    acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
-
     /* Storage for the GUID address */
-    vgia_offset = table_data->len +
-        build_append_named_dword(ssdt->buf, "VGIA");
+    vgia_offset = table_data->len + build_append_named_dword(ssdt->buf, "VGIA");
     scope = aml_scope("\\_SB");
     dev = aml_device("VGEN");
     aml_append(dev, aml_name_decl("_HID", aml_string("QEMUVGID")));
@@ -116,9 +115,8 @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid,
         ACPI_BUILD_TABLE_FILE, vgia_offset, sizeof(uint32_t),
         VMGENID_GUID_FW_CFG_FILE, 0);
 
-    build_header(linker, table_data,
-        (void *)(table_data->data + table_data->len - ssdt->buf->len),
-        "SSDT", ssdt->buf->len, 1, oem_id, "VMGENID");
+    /* must be called after above command to ensure correct table checksum */
+    acpi_table_composed(linker, &table);
     free_aml_allocator();
 }
 
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 13/35] acpi: x86: build_dsdt: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (11 preceding siblings ...)
  2021-07-08 15:45 ` [PATCH v2 12/35] acpi: vmgenid_build_acpi: " Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-09-02 15:35   ` Eric Auger
  2021-07-08 15:45 ` [PATCH v2 14/35] acpi: build_hpet: " Igor Mammedov
                   ` (22 subsequent siblings)
  35 siblings, 1 reply; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: marcel.apfelbaum@gmail.com
---
 hw/i386/acpi-build.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 796ffc6f5c..538af9d944 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1380,12 +1380,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 #endif
     int i;
     VMBusBridge *vmbus_bridge = vmbus_bridge_find();
+    AcpiTable table = { .sig = "DSDT", .rev = 1, .oem_id = x86ms->oem_id,
+                        .oem_table_id = x86ms->oem_table_id };
 
+    acpi_init_table(&table, table_data);
     dsdt = init_aml_allocator();
 
-    /* Reserve space for header */
-    acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader));
-
     build_dbg_aml(dsdt);
     if (misc->is_piix4) {
         sb_scope = aml_scope("_SB");
@@ -1816,9 +1816,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 
     /* copy AML table into ACPI tables blob and patch header there */
     g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
-    build_header(linker, table_data,
-        (void *)(table_data->data + table_data->len - dsdt->buf->len),
-                 "DSDT", dsdt->buf->len, 1, x86ms->oem_id, x86ms->oem_table_id);
+    acpi_table_composed(linker, &table);
     free_aml_allocator();
 }
 
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 14/35] acpi: build_hpet: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (12 preceding siblings ...)
  2021-07-08 15:45 ` [PATCH v2 13/35] acpi: x86: build_dsdt: " Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 15/35] acpi: build_tpm_tcpa: " Igor Mammedov
                   ` (21 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

while at it convert build_hpet() to endian agnostic
build_append_FOO() API

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: marcel.apfelbaum@gmail.com
---
 include/hw/acpi/acpi-defs.h | 13 -------------
 hw/i386/acpi-build.c        | 26 ++++++++++++++++++--------
 2 files changed, 18 insertions(+), 21 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index f6d2ca172b..4d8f8b34b0 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -358,19 +358,6 @@ struct AcpiGenericTimerTable {
 } QEMU_PACKED;
 typedef struct AcpiGenericTimerTable AcpiGenericTimerTable;
 
-/*
- * HPET Description Table
- */
-struct Acpi20Hpet {
-    ACPI_TABLE_HEADER_DEF                    /* ACPI common table header */
-    uint32_t           timer_block_id;
-    struct AcpiGenericAddress addr;
-    uint8_t            hpet_number;
-    uint16_t           min_tick;
-    uint8_t            page_protect;
-} QEMU_PACKED;
-typedef struct Acpi20Hpet Acpi20Hpet;
-
 /*
  * SRAT (NUMA topology description) table
  */
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 538af9d944..96ad3e1b9d 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1820,22 +1820,32 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
     free_aml_allocator();
 }
 
+/*
+ * IA-PC HPET (High Precision Event Timers) Specification (Revision: 1.0a)
+ * 3.2.4The ACPI 2.0 HPET Description Table (HPET)
+ */
 static void
 build_hpet(GArray *table_data, BIOSLinker *linker, const char *oem_id,
            const char *oem_table_id)
 {
-    Acpi20Hpet *hpet;
-    int hpet_start = table_data->len;
+    AcpiTable table = { .sig = "HPET", .rev = 1,
+                        .oem_id = oem_id, .oem_table_id = oem_table_id };
 
-    hpet = acpi_data_push(table_data, sizeof(*hpet));
+    acpi_init_table(&table, table_data);
     /* Note timer_block_id value must be kept in sync with value advertised by
      * emulated hpet
      */
-    hpet->timer_block_id = cpu_to_le32(0x8086a201);
-    hpet->addr.address = cpu_to_le64(HPET_BASE);
-    build_header(linker, table_data,
-                 (void *)(table_data->data + hpet_start),
-                 "HPET", sizeof(*hpet), 1, oem_id, oem_table_id);
+    /* Event Timer Block ID */
+    build_append_int_noprefix(table_data, 0x8086a201, 4);
+    /* BASE_ADDRESS */
+    build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0, 0, 0, HPET_BASE);
+    /* HPET Number */
+    build_append_int_noprefix(table_data, 0, 1);
+    /* Main Counter Minimum Clock_tick in Periodic Mode */
+    build_append_int_noprefix(table_data, 0, 2);
+    /* Page Protection And OEM Attribute */
+    build_append_int_noprefix(table_data, 0, 1);
+    acpi_table_composed(linker, &table);
 }
 
 #ifdef CONFIG_TPM
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 15/35] acpi: build_tpm_tcpa: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (13 preceding siblings ...)
  2021-07-08 15:45 ` [PATCH v2 14/35] acpi: build_hpet: " Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 16/35] acpi: arm/x86: build_srat: " Igor Mammedov
                   ` (20 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanb, Stefan Berger, mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

While at it switch to build_append_int_noprefix() to build
table entries (which also removes some manual offset
calculations).

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Tested-by: Stefan Berger <stefanb@linux.ibm.com>
---
v2:
  * fix assert when starting QEMU with TPM 1.2
      Stefan Berger <stefanb@linux.ibm.com>

CC: stefanb@linux.vnet.ibm.com
---
 include/hw/acpi/acpi-defs.h | 14 -------------
 hw/i386/acpi-build.c        | 40 ++++++++++++++++++++++---------------
 2 files changed, 24 insertions(+), 30 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 4d8f8b34b0..3b42b138f0 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -418,20 +418,6 @@ struct AcpiSratProcessorGiccAffinity {
 
 typedef struct AcpiSratProcessorGiccAffinity AcpiSratProcessorGiccAffinity;
 
-/*
- * TCPA Description Table
- *
- * Following Level 00, Rev 00.37 of specs:
- * http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification
- */
-struct Acpi20Tcpa {
-    ACPI_TABLE_HEADER_DEF                    /* ACPI common table header */
-    uint16_t platform_class;
-    uint32_t log_area_minimum_length;
-    uint64_t log_area_start_address;
-} QEMU_PACKED;
-typedef struct Acpi20Tcpa Acpi20Tcpa;
-
 /* DMAR - DMA Remapping table r2.2 */
 struct AcpiTableDmar {
     ACPI_TABLE_HEADER_DEF
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 96ad3e1b9d..5457e35798 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1849,31 +1849,39 @@ build_hpet(GArray *table_data, BIOSLinker *linker, const char *oem_id,
 }
 
 #ifdef CONFIG_TPM
+/*
+ * TCPA Description Table
+ *
+ * Following Level 00, Rev 00.37 of specs:
+ * http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification
+ * 7.1.2 ACPI Table Layout
+ */
 static void
 build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
                const char *oem_id, const char *oem_table_id)
 {
-    int tcpa_start = table_data->len;
-    Acpi20Tcpa *tcpa = acpi_data_push(table_data, sizeof *tcpa);
-    unsigned log_addr_size = sizeof(tcpa->log_area_start_address);
-    unsigned log_addr_offset =
-        (char *)&tcpa->log_area_start_address - table_data->data;
+    unsigned log_addr_offset;
+    AcpiTable table = { .sig = "TCPA", .rev = 2,
+                        .oem_id = oem_id, .oem_table_id = oem_table_id };
 
-    tcpa->platform_class = cpu_to_le16(TPM_TCPA_ACPI_CLASS_CLIENT);
-    tcpa->log_area_minimum_length = cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
-    acpi_data_push(tcpalog, le32_to_cpu(tcpa->log_area_minimum_length));
+    acpi_init_table(&table, table_data);
+    /* Platform Class */
+    build_append_int_noprefix(table_data, TPM_TCPA_ACPI_CLASS_CLIENT, 2);
+    /* Log Area Minimum Length (LAML) */
+    build_append_int_noprefix(table_data, TPM_LOG_AREA_MINIMUM_SIZE, 4);
+    /* Log Area Start Address (LASA) */
+    log_addr_offset = table_data->len;
+    build_append_int_noprefix(table_data, 0, 8);
 
+    acpi_table_composed(linker, &table);
+
+    /* allocate/reserve space for TPM log area */
+    acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE);
     bios_linker_loader_alloc(linker, ACPI_BUILD_TPMLOG_FILE, tcpalog, 1,
                              false /* high memory */);
-
     /* log area start address to be filled by Guest linker */
-    bios_linker_loader_add_pointer(linker,
-        ACPI_BUILD_TABLE_FILE, log_addr_offset, log_addr_size,
-        ACPI_BUILD_TPMLOG_FILE, 0);
-
-    build_header(linker, table_data,
-                 (void *)(table_data->data + tcpa_start),
-                 "TCPA", sizeof(*tcpa), 2, oem_id, oem_table_id);
+    bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+        log_addr_offset, 8, ACPI_BUILD_TPMLOG_FILE, 0);
 }
 #endif
 
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 16/35] acpi: arm/x86: build_srat: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (14 preceding siblings ...)
  2021-07-08 15:45 ` [PATCH v2 15/35] acpi: build_tpm_tcpa: " Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-07-08 15:45 ` [PATCH v2 17/35] acpi: use build_append_int_noprefix() API to compose SRAT table Igor Mammedov
                   ` (19 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, drjones, mst, shannon.zhaosl, qemu-arm

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: shannon.zhaosl@gmail.com
CC: peter.maydell@linaro.org
CC: marcel.apfelbaum@gmail.com
CC: qemu-arm@nongnu.org
CC: drjones@redhat.com
---
 include/hw/acpi/acpi-defs.h | 11 -----------
 hw/arm/virt-acpi-build.c    | 15 +++++++--------
 hw/i386/acpi-build.c        | 18 +++++++-----------
 3 files changed, 14 insertions(+), 30 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 3b42b138f0..5826ee04b6 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -358,17 +358,6 @@ struct AcpiGenericTimerTable {
 } QEMU_PACKED;
 typedef struct AcpiGenericTimerTable AcpiGenericTimerTable;
 
-/*
- * SRAT (NUMA topology description) table
- */
-
-struct AcpiSystemResourceAffinityTable {
-    ACPI_TABLE_HEADER_DEF
-    uint32_t    reserved1;
-    uint32_t    reserved2[2];
-} QEMU_PACKED;
-typedef struct AcpiSystemResourceAffinityTable AcpiSystemResourceAffinityTable;
-
 #define ACPI_SRAT_PROCESSOR_APIC     0
 #define ACPI_SRAT_MEMORY             1
 #define ACPI_SRAT_PROCESSOR_x2APIC   2
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index f1024843dd..c4416ac696 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -385,18 +385,19 @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 static void
 build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
-    AcpiSystemResourceAffinityTable *srat;
     AcpiSratProcessorGiccAffinity *core;
     AcpiSratMemoryAffinity *numamem;
-    int i, srat_start;
+    int i;
     uint64_t mem_base;
     MachineClass *mc = MACHINE_GET_CLASS(vms);
     MachineState *ms = MACHINE(vms);
     const CPUArchIdList *cpu_list = mc->possible_cpu_arch_ids(ms);
+    AcpiTable table = { .sig = "SRAT", .rev = 3, .oem_id = vms->oem_id,
+                        .oem_table_id = vms->oem_table_id };
 
-    srat_start = table_data->len;
-    srat = acpi_data_push(table_data, sizeof(*srat));
-    srat->reserved1 = cpu_to_le32(1);
+    acpi_init_table(&table, table_data);
+    build_append_int_noprefix(table_data, 1, 4); /* Reserved */
+    build_append_int_noprefix(table_data, 0, 8); /* Reserved */
 
     for (i = 0; i < cpu_list->len; ++i) {
         core = acpi_data_push(table_data, sizeof(*core));
@@ -430,9 +431,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
                           MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
     }
 
-    build_header(linker, table_data, (void *)(table_data->data + srat_start),
-                 "SRAT", table_data->len - srat_start, 3, vms->oem_id,
-                 vms->oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 
 /* GTDT */
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 5457e35798..275ad0b941 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1891,11 +1891,10 @@ build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
 static void
 build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
 {
-    AcpiSystemResourceAffinityTable *srat;
     AcpiSratMemoryAffinity *numamem;
 
     int i;
-    int srat_start, numa_start, slots;
+    int numa_start, slots;
     uint64_t mem_len, mem_base, next_base;
     MachineClass *mc = MACHINE_GET_CLASS(machine);
     X86MachineState *x86ms = X86_MACHINE(machine);
@@ -1904,11 +1903,12 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
     ram_addr_t hotplugabble_address_space_size =
         object_property_get_int(OBJECT(pcms), PC_MACHINE_DEVMEM_REGION_SIZE,
                                 NULL);
+    AcpiTable table = { .sig = "SRAT", .rev = 1, .oem_id = x86ms->oem_id,
+                        .oem_table_id = x86ms->oem_table_id };
 
-    srat_start = table_data->len;
-
-    srat = acpi_data_push(table_data, sizeof *srat);
-    srat->reserved1 = cpu_to_le32(1);
+    acpi_init_table(&table, table_data);
+    build_append_int_noprefix(table_data, 1, 4); /* Reserved */
+    build_append_int_noprefix(table_data, 0, 8); /* Reserved */
 
     for (i = 0; i < apic_ids->len; i++) {
         int node_id = apic_ids->cpus[i].props.node_id;
@@ -2014,11 +2014,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
                           MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
     }
 
-    build_header(linker, table_data,
-                 (void *)(table_data->data + srat_start),
-                 "SRAT",
-                 table_data->len - srat_start, 1, x86ms->oem_id,
-                 x86ms->oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 
 /*
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 17/35] acpi: use build_append_int_noprefix() API to compose SRAT table
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (15 preceding siblings ...)
  2021-07-08 15:45 ` [PATCH v2 16/35] acpi: arm/x86: build_srat: " Igor Mammedov
@ 2021-07-08 15:45 ` Igor Mammedov
  2021-07-08 15:46 ` [PATCH v2 18/35] acpi: build_dmar_q35: use acpi_init_table()/acpi_table_composed() instead of build_header() Igor Mammedov
                   ` (18 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, drjones, xiaoguangrong.eric, mst, shannon.zhaosl,
	qemu-arm

Drop usage of packed structures and explicit endian conversions
when building SRAT tables for arm/x86 and use endian agnostic
build_append_int_noprefix() API to build it.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: xiaoguangrong.eric@gmail.com
CC: shannon.zhaosl@gmail.com
CC: peter.maydell@linaro.org
CC: marcel.apfelbaum@gmail.com
CC: qemu-arm@nongnu.org
CC: drjones@redhat.com
---
 include/hw/acpi/acpi-defs.h | 49 -----------------------
 include/hw/acpi/aml-build.h |  2 +-
 hw/acpi/aml-build.c         | 24 ++++++++----
 hw/acpi/nvdimm.c            |  4 +-
 hw/arm/virt-acpi-build.c    | 29 ++++++++------
 hw/i386/acpi-build.c        | 78 +++++++++++++++++++++----------------
 6 files changed, 80 insertions(+), 106 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 5826ee04b6..d293304f9c 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -358,55 +358,6 @@ struct AcpiGenericTimerTable {
 } QEMU_PACKED;
 typedef struct AcpiGenericTimerTable AcpiGenericTimerTable;
 
-#define ACPI_SRAT_PROCESSOR_APIC     0
-#define ACPI_SRAT_MEMORY             1
-#define ACPI_SRAT_PROCESSOR_x2APIC   2
-#define ACPI_SRAT_PROCESSOR_GICC     3
-
-struct AcpiSratProcessorAffinity {
-    ACPI_SUB_HEADER_DEF
-    uint8_t     proximity_lo;
-    uint8_t     local_apic_id;
-    uint32_t    flags;
-    uint8_t     local_sapic_eid;
-    uint8_t     proximity_hi[3];
-    uint32_t    reserved;
-} QEMU_PACKED;
-typedef struct AcpiSratProcessorAffinity AcpiSratProcessorAffinity;
-
-struct AcpiSratProcessorX2ApicAffinity {
-    ACPI_SUB_HEADER_DEF
-    uint16_t    reserved;
-    uint32_t    proximity_domain;
-    uint32_t    x2apic_id;
-    uint32_t    flags;
-    uint32_t    clk_domain;
-    uint32_t    reserved2;
-} QEMU_PACKED;
-typedef struct AcpiSratProcessorX2ApicAffinity AcpiSratProcessorX2ApicAffinity;
-
-struct AcpiSratMemoryAffinity {
-    ACPI_SUB_HEADER_DEF
-    uint32_t    proximity;
-    uint16_t    reserved1;
-    uint64_t    base_addr;
-    uint64_t    range_length;
-    uint32_t    reserved2;
-    uint32_t    flags;
-    uint32_t    reserved3[2];
-} QEMU_PACKED;
-typedef struct AcpiSratMemoryAffinity AcpiSratMemoryAffinity;
-
-struct AcpiSratProcessorGiccAffinity {
-    ACPI_SUB_HEADER_DEF
-    uint32_t    proximity;
-    uint32_t    acpi_processor_uid;
-    uint32_t    flags;
-    uint32_t    clock_domain;
-} QEMU_PACKED;
-
-typedef struct AcpiSratProcessorGiccAffinity AcpiSratProcessorGiccAffinity;
-
 /* DMAR - DMA Remapping table r2.2 */
 struct AcpiTableDmar {
     ACPI_TABLE_HEADER_DEF
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index d590660bd2..dcb7ce11a8 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -470,7 +470,7 @@ Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set, uint32_t io_offset,
                uint32_t mmio32_offset, uint64_t mmio64_offset,
                uint16_t bus_nr_offset);
 
-void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
+void build_srat_memory(GArray *table_data, uint64_t base,
                        uint64_t len, int node, MemoryAffinityFlags flags);
 
 void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms,
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 057c64fb48..8427713ee3 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1932,15 +1932,25 @@ build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
     acpi_table_composed(linker, &table);
 }
 
-void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
+/*
+ * ACPI spec, Revision 4.0
+ * 5.2.16.2 Memory Affinity Structure
+ */
+void build_srat_memory(GArray *table_data, uint64_t base,
                        uint64_t len, int node, MemoryAffinityFlags flags)
 {
-    numamem->type = ACPI_SRAT_MEMORY;
-    numamem->length = sizeof(*numamem);
-    numamem->proximity = cpu_to_le32(node);
-    numamem->flags = cpu_to_le32(flags);
-    numamem->base_addr = cpu_to_le64(base);
-    numamem->range_length = cpu_to_le64(len);
+    build_append_int_noprefix(table_data, 1, 1); /* Type */
+    build_append_int_noprefix(table_data, 40, 1); /* Length */
+    build_append_int_noprefix(table_data, node, 4); /* Proximity Domain */
+    build_append_int_noprefix(table_data, 0, 2); /* Reserved */
+    build_append_int_noprefix(table_data, base, 4); /* Base Address Low */
+    /* Base Address High */
+    build_append_int_noprefix(table_data, base >> 32, 4);
+    build_append_int_noprefix(table_data, len, 4); /* Length Low */
+    build_append_int_noprefix(table_data, len >> 32, 4); /* Length High */
+    build_append_int_noprefix(table_data, 0, 4); /* Reserved */
+    build_append_int_noprefix(table_data, flags, 4); /* Flags */
+    build_append_int_noprefix(table_data, 0, 8); /* Reserved */
 }
 
 /*
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
index b61bd681a1..8753616322 100644
--- a/hw/acpi/nvdimm.c
+++ b/hw/acpi/nvdimm.c
@@ -1336,7 +1336,6 @@ void nvdimm_build_srat(GArray *table_data)
     GSList *device_list = nvdimm_get_device_list();
 
     for (; device_list; device_list = device_list->next) {
-        AcpiSratMemoryAffinity *numamem = NULL;
         DeviceState *dev = device_list->data;
         Object *obj = OBJECT(dev);
         uint64_t addr, size;
@@ -1346,8 +1345,7 @@ void nvdimm_build_srat(GArray *table_data)
         addr = object_property_get_uint(obj, PC_DIMM_ADDR_PROP, &error_abort);
         size = object_property_get_uint(obj, PC_DIMM_SIZE_PROP, &error_abort);
 
-        numamem = acpi_data_push(table_data, sizeof *numamem);
-        build_srat_memory(numamem, addr, size, node,
+        build_srat_memory(table_data, addr, size, node,
                           MEM_AFFINITY_ENABLED | MEM_AFFINITY_NON_VOLATILE);
     }
     g_slist_free(device_list);
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index c4416ac696..159e71dbdd 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -382,11 +382,13 @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
                  vms->oem_table_id);
 }
 
+/*
+ * ACPI spec, Revision 5.1
+ * 5.2.16 System Resource Affinity Table (SRAT)
+ */
 static void
 build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
-    AcpiSratProcessorGiccAffinity *core;
-    AcpiSratMemoryAffinity *numamem;
     int i;
     uint64_t mem_base;
     MachineClass *mc = MACHINE_GET_CLASS(vms);
@@ -400,19 +402,23 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     build_append_int_noprefix(table_data, 0, 8); /* Reserved */
 
     for (i = 0; i < cpu_list->len; ++i) {
-        core = acpi_data_push(table_data, sizeof(*core));
-        core->type = ACPI_SRAT_PROCESSOR_GICC;
-        core->length = sizeof(*core);
-        core->proximity = cpu_to_le32(cpu_list->cpus[i].props.node_id);
-        core->acpi_processor_uid = cpu_to_le32(i);
-        core->flags = cpu_to_le32(1);
+        uint32_t nodeid = cpu_list->cpus[i].props.node_id;
+        /*
+         * 5.2.16.4 GICC Affinity Structure
+         */
+        build_append_int_noprefix(table_data, 3, 1);      /* Type */
+        build_append_int_noprefix(table_data, 18, 1);     /* Length */
+        build_append_int_noprefix(table_data, nodeid, 4); /* Proximity Domain */
+        build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */
+        /* Flags, Table 5-76 */
+        build_append_int_noprefix(table_data, 1 /* Enabled */, 4);
+        build_append_int_noprefix(table_data, 0, 4); /* Clock Domain */
     }
 
     mem_base = vms->memmap[VIRT_MEM].base;
     for (i = 0; i < ms->numa_state->num_nodes; ++i) {
         if (ms->numa_state->nodes[i].node_mem > 0) {
-            numamem = acpi_data_push(table_data, sizeof(*numamem));
-            build_srat_memory(numamem, mem_base,
+            build_srat_memory(table_data, mem_base,
                               ms->numa_state->nodes[i].node_mem, i,
                               MEM_AFFINITY_ENABLED);
             mem_base += ms->numa_state->nodes[i].node_mem;
@@ -424,8 +430,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     }
 
     if (ms->device_memory) {
-        numamem = acpi_data_push(table_data, sizeof *numamem);
-        build_srat_memory(numamem, ms->device_memory->base,
+        build_srat_memory(table_data, ms->device_memory->base,
                           memory_region_size(&ms->device_memory->mr),
                           ms->numa_state->num_nodes - 1,
                           MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 275ad0b941..a97d090ef3 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1888,13 +1888,15 @@ build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
 #define HOLE_640K_START  (640 * KiB)
 #define HOLE_640K_END   (1 * MiB)
 
+/*
+ * ACPI spec, Revision 3.0
+ * 5.2.15 System Resource Affinity Table (SRAT)
+ */
 static void
 build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
 {
-    AcpiSratMemoryAffinity *numamem;
-
     int i;
-    int numa_start, slots;
+    int numa_mem_start, slots;
     uint64_t mem_len, mem_base, next_base;
     MachineClass *mc = MACHINE_GET_CLASS(machine);
     X86MachineState *x86ms = X86_MACHINE(machine);
@@ -1915,34 +1917,41 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
         uint32_t apic_id = apic_ids->cpus[i].arch_id;
 
         if (apic_id < 255) {
-            AcpiSratProcessorAffinity *core;
-
-            core = acpi_data_push(table_data, sizeof *core);
-            core->type = ACPI_SRAT_PROCESSOR_APIC;
-            core->length = sizeof(*core);
-            core->local_apic_id = apic_id;
-            core->proximity_lo = node_id;
-            memset(core->proximity_hi, 0, 3);
-            core->local_sapic_eid = 0;
-            core->flags = cpu_to_le32(1);
+            /* 5.2.15.1 Processor Local APIC/SAPIC Affinity Structure */
+            build_append_int_noprefix(table_data, 0, 1);  /* Type  */
+            build_append_int_noprefix(table_data, 16, 1); /* Length */
+            /* Proximity Domain [7:0] */
+            build_append_int_noprefix(table_data, node_id, 1);
+            build_append_int_noprefix(table_data, apic_id, 1); /* APIC ID */
+            /* Flags, Table 5-36 */
+            build_append_int_noprefix(table_data, 1, 4);
+            build_append_int_noprefix(table_data, 0, 1); /* Local SAPIC EID */
+            /* Proximity Domain [31:8] */
+            build_append_int_noprefix(table_data, 0, 3);
+            build_append_int_noprefix(table_data, 0, 4); /* Reserved */
         } else {
-            AcpiSratProcessorX2ApicAffinity *core;
-
-            core = acpi_data_push(table_data, sizeof *core);
-            core->type = ACPI_SRAT_PROCESSOR_x2APIC;
-            core->length = sizeof(*core);
-            core->x2apic_id = cpu_to_le32(apic_id);
-            core->proximity_domain = cpu_to_le32(node_id);
-            core->flags = cpu_to_le32(1);
+            /*
+             * ACPI spec, Revision 4.0
+             * 5.2.16.3 Processor Local x2APIC Affinity Structure
+             */
+            build_append_int_noprefix(table_data, 2, 1);  /* Type  */
+            build_append_int_noprefix(table_data, 24, 1); /* Length */
+            build_append_int_noprefix(table_data, 0, 2); /* Reserved */
+            /* Proximity Domain */
+            build_append_int_noprefix(table_data, node_id, 4);
+            build_append_int_noprefix(table_data, apic_id, 4); /* X2APIC ID */
+            /* Flags, Table 5-39 */
+            build_append_int_noprefix(table_data, 1 /* Enabled */, 4);
+            build_append_int_noprefix(table_data, 0, 4); /* Clock Domain */
+            build_append_int_noprefix(table_data, 0, 4); /* Reserved */
         }
     }
 
-
     /* the memory map is a bit tricky, it contains at least one hole
      * from 640k-1M and possibly another one from 3.5G-4G.
      */
     next_base = 0;
-    numa_start = table_data->len;
+    numa_mem_start = table_data->len;
 
     for (i = 1; i < pcms->numa_nodes + 1; ++i) {
         mem_base = next_base;
@@ -1954,8 +1963,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
             next_base > HOLE_640K_START) {
             mem_len -= next_base - HOLE_640K_START;
             if (mem_len > 0) {
-                numamem = acpi_data_push(table_data, sizeof *numamem);
-                build_srat_memory(numamem, mem_base, mem_len, i - 1,
+                build_srat_memory(table_data, mem_base, mem_len, i - 1,
                                   MEM_AFFINITY_ENABLED);
             }
 
@@ -1973,8 +1981,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
             next_base > x86ms->below_4g_mem_size) {
             mem_len -= next_base - x86ms->below_4g_mem_size;
             if (mem_len > 0) {
-                numamem = acpi_data_push(table_data, sizeof *numamem);
-                build_srat_memory(numamem, mem_base, mem_len, i - 1,
+                build_srat_memory(table_data, mem_base, mem_len, i - 1,
                                   MEM_AFFINITY_ENABLED);
             }
             mem_base = 1ULL << 32;
@@ -1983,8 +1990,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
         }
 
         if (mem_len > 0) {
-            numamem = acpi_data_push(table_data, sizeof *numamem);
-            build_srat_memory(numamem, mem_base, mem_len, i - 1,
+            build_srat_memory(table_data, mem_base, mem_len, i - 1,
                               MEM_AFFINITY_ENABLED);
         }
     }
@@ -1993,10 +1999,15 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
         nvdimm_build_srat(table_data);
     }
 
-    slots = (table_data->len - numa_start) / sizeof *numamem;
+    /*
+     * TODO: this part is not in ACPI spec and current linux kernel boots fine
+     * without these entries. But I recall there were issues the last time I
+     * tried to remove it with some ancient guest OS, however I can't remember
+     * what that was so keep this around for now
+     */
+    slots = (table_data->len - numa_mem_start) / 40 /* mem affinity len */;
     for (; slots < pcms->numa_nodes + 2; slots++) {
-        numamem = acpi_data_push(table_data, sizeof *numamem);
-        build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
+        build_srat_memory(table_data, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
     }
 
     /*
@@ -2008,8 +2019,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
      * providing _PXM method if necessary.
      */
     if (hotplugabble_address_space_size) {
-        numamem = acpi_data_push(table_data, sizeof *numamem);
-        build_srat_memory(numamem, machine->device_memory->base,
+        build_srat_memory(table_data, machine->device_memory->base,
                           hotplugabble_address_space_size, pcms->numa_nodes - 1,
                           MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
     }
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 18/35] acpi: build_dmar_q35: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (16 preceding siblings ...)
  2021-07-08 15:45 ` [PATCH v2 17/35] acpi: use build_append_int_noprefix() API to compose SRAT table Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-07-08 15:46 ` [PATCH v2 19/35] acpi: build_waet: " Igor Mammedov
                   ` (17 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

While at it switch to build_append_int_noprefix() to build
table entries tables.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: marcel.apfelbaum@gmail.com
---
 include/hw/acpi/acpi-defs.h | 68 --------------------------------
 hw/i386/acpi-build.c        | 77 ++++++++++++++++++++-----------------
 2 files changed, 42 insertions(+), 103 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index d293304f9c..c4f0a202e8 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -358,74 +358,6 @@ struct AcpiGenericTimerTable {
 } QEMU_PACKED;
 typedef struct AcpiGenericTimerTable AcpiGenericTimerTable;
 
-/* DMAR - DMA Remapping table r2.2 */
-struct AcpiTableDmar {
-    ACPI_TABLE_HEADER_DEF
-    uint8_t host_address_width; /* Maximum DMA physical addressability */
-    uint8_t flags;
-    uint8_t reserved[10];
-} QEMU_PACKED;
-typedef struct AcpiTableDmar AcpiTableDmar;
-
-/* Masks for Flags field above */
-#define ACPI_DMAR_INTR_REMAP        1
-#define ACPI_DMAR_X2APIC_OPT_OUT    (1 << 1)
-
-/* Values for sub-structure type for DMAR */
-enum {
-    ACPI_DMAR_TYPE_HARDWARE_UNIT = 0,       /* DRHD */
-    ACPI_DMAR_TYPE_RESERVED_MEMORY = 1,     /* RMRR */
-    ACPI_DMAR_TYPE_ATSR = 2,                /* ATSR */
-    ACPI_DMAR_TYPE_HARDWARE_AFFINITY = 3,   /* RHSR */
-    ACPI_DMAR_TYPE_ANDD = 4,                /* ANDD */
-    ACPI_DMAR_TYPE_RESERVED = 5             /* Reserved for furture use */
-};
-
-/*
- * Sub-structures for DMAR
- */
-
-/* Device scope structure for DRHD. */
-struct AcpiDmarDeviceScope {
-    uint8_t entry_type;
-    uint8_t length;
-    uint16_t reserved;
-    uint8_t enumeration_id;
-    uint8_t bus;
-    struct {
-        uint8_t device;
-        uint8_t function;
-    } path[];
-} QEMU_PACKED;
-typedef struct AcpiDmarDeviceScope AcpiDmarDeviceScope;
-
-/* Type 0: Hardware Unit Definition */
-struct AcpiDmarHardwareUnit {
-    uint16_t type;
-    uint16_t length;
-    uint8_t flags;
-    uint8_t reserved;
-    uint16_t pci_segment;   /* The PCI Segment associated with this unit */
-    uint64_t address;   /* Base address of remapping hardware register-set */
-    AcpiDmarDeviceScope scope[];
-} QEMU_PACKED;
-typedef struct AcpiDmarHardwareUnit AcpiDmarHardwareUnit;
-
-/* Type 2: Root Port ATS Capability Reporting Structure */
-struct AcpiDmarRootPortATS {
-    uint16_t type;
-    uint16_t length;
-    uint8_t flags;
-    uint8_t reserved;
-    uint16_t pci_segment;
-    AcpiDmarDeviceScope scope[];
-} QEMU_PACKED;
-typedef struct AcpiDmarRootPortATS AcpiDmarRootPortATS;
-
-/* Masks for Flags field above */
-#define ACPI_DMAR_INCLUDE_PCI_ALL   1
-#define ACPI_DMAR_ATSR_ALL_PORTS    1
-
 /*
  * Input Output Remapping Table (IORT)
  * Conforms to "IO Remapping Table System Software on ARM Platforms",
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index a97d090ef3..f23250421f 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2028,62 +2028,69 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
 }
 
 /*
- * VT-d spec 8.1 DMA Remapping Reporting Structure
- * (version Oct. 2014 or later)
+ * Intel ® Virtualization Technology for Directed I/O
+ * Architecture Specification. Revision 3.3
+ * 8.1 DMA Remapping Reporting Structure
  */
 static void
 build_dmar_q35(GArray *table_data, BIOSLinker *linker, const char *oem_id,
                const char *oem_table_id)
 {
-    int dmar_start = table_data->len;
-
-    AcpiTableDmar *dmar;
-    AcpiDmarHardwareUnit *drhd;
-    AcpiDmarRootPortATS *atsr;
     uint8_t dmar_flags = 0;
+    uint8_t rsvd10[10] = {};
+    /* Root complex IOAPIC uses one path only */
+    const size_t ioapic_scope_size = 6 /* device scope structure */ +
+                                     2 /* 1 path entry */;
     X86IOMMUState *iommu = x86_iommu_get_default();
-    AcpiDmarDeviceScope *scope = NULL;
-    /* Root complex IOAPIC use one path[0] only */
-    size_t ioapic_scope_size = sizeof(*scope) + sizeof(scope->path[0]);
     IntelIOMMUState *intel_iommu = INTEL_IOMMU_DEVICE(iommu);
+    AcpiTable table = { .sig = "DMAR", .rev = 1, .oem_id = oem_id,
+                        .oem_table_id = oem_table_id };
 
     assert(iommu);
     if (x86_iommu_ir_supported(iommu)) {
         dmar_flags |= 0x1;      /* Flags: 0x1: INT_REMAP */
     }
 
-    dmar = acpi_data_push(table_data, sizeof(*dmar));
-    dmar->host_address_width = intel_iommu->aw_bits - 1;
-    dmar->flags = dmar_flags;
-
-    /* DMAR Remapping Hardware Unit Definition structure */
-    drhd = acpi_data_push(table_data, sizeof(*drhd) + ioapic_scope_size);
-    drhd->type = cpu_to_le16(ACPI_DMAR_TYPE_HARDWARE_UNIT);
-    drhd->length = cpu_to_le16(sizeof(*drhd) + ioapic_scope_size);
-    drhd->flags = ACPI_DMAR_INCLUDE_PCI_ALL;
-    drhd->pci_segment = cpu_to_le16(0);
-    drhd->address = cpu_to_le64(Q35_HOST_BRIDGE_IOMMU_ADDR);
+    acpi_init_table(&table, table_data);
+    /* Host Address Width */
+    build_append_int_noprefix(table_data, intel_iommu->aw_bits - 1, 1);
+    build_append_int_noprefix(table_data, dmar_flags, 1); /* Flags */
+    g_array_append_vals(table_data, rsvd10, sizeof(rsvd10)); /* Reserved */
+
+    /* 8.3 DMAR Remapping Hardware Unit Definition structure */
+    build_append_int_noprefix(table_data, 0, 2); /* Type */
+    /* Length */
+    build_append_int_noprefix(table_data, 16 + ioapic_scope_size, 2);
+    /* Flags */
+    build_append_int_noprefix(table_data, 1 /* INCLUDE_PCI_ALL */ , 1);
+    build_append_int_noprefix(table_data, 0 , 1); /* Reserved */
+    build_append_int_noprefix(table_data, 0 , 2); /* Segment Number */
+    /* Register Base Address */
+    build_append_int_noprefix(table_data, Q35_HOST_BRIDGE_IOMMU_ADDR , 8);
 
     /* Scope definition for the root-complex IOAPIC. See VT-d spec
      * 8.3.1 (version Oct. 2014 or later). */
-    scope = &drhd->scope[0];
-    scope->entry_type = 0x03;   /* Type: 0x03 for IOAPIC */
-    scope->length = ioapic_scope_size;
-    scope->enumeration_id = ACPI_BUILD_IOAPIC_ID;
-    scope->bus = Q35_PSEUDO_BUS_PLATFORM;
-    scope->path[0].device = PCI_SLOT(Q35_PSEUDO_DEVFN_IOAPIC);
-    scope->path[0].function = PCI_FUNC(Q35_PSEUDO_DEVFN_IOAPIC);
+    build_append_int_noprefix(table_data, 0x03 /* IOAPIC */, 1); /* Type */
+    build_append_int_noprefix(table_data, ioapic_scope_size, 1); /* Length */
+    build_append_int_noprefix(table_data, 0, 2); /* Reserved */
+    /* Enumeration ID */
+    build_append_int_noprefix(table_data, ACPI_BUILD_IOAPIC_ID, 1);
+    /* Start Bus Number */
+    build_append_int_noprefix(table_data, Q35_PSEUDO_BUS_PLATFORM, 1);
+    /* Path, {Device, Function} pair */
+    build_append_int_noprefix(table_data, PCI_SLOT(Q35_PSEUDO_DEVFN_IOAPIC), 1);
+    build_append_int_noprefix(table_data, PCI_FUNC(Q35_PSEUDO_DEVFN_IOAPIC), 1);
 
     if (iommu->dt_supported) {
-        atsr = acpi_data_push(table_data, sizeof(*atsr));
-        atsr->type = cpu_to_le16(ACPI_DMAR_TYPE_ATSR);
-        atsr->length = cpu_to_le16(sizeof(*atsr));
-        atsr->flags = ACPI_DMAR_ATSR_ALL_PORTS;
-        atsr->pci_segment = cpu_to_le16(0);
+        /* 8.5 Root Port ATS Capability Reporting Structure */
+        build_append_int_noprefix(table_data, 2, 2); /* Type */
+        build_append_int_noprefix(table_data, 8, 2); /* Length */
+        build_append_int_noprefix(table_data, 1 /* ALL_PORTS */, 1); /* Flags */
+        build_append_int_noprefix(table_data, 0, 1); /* Reserved */
+        build_append_int_noprefix(table_data, 0, 2); /* Segment Number */
     }
 
-    build_header(linker, table_data, (void *)(table_data->data + dmar_start),
-                 "DMAR", table_data->len - dmar_start, 1, oem_id, oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 
 /*
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 19/35] acpi: build_waet: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (17 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 18/35] acpi: build_dmar_q35: use acpi_init_table()/acpi_table_composed() instead of build_header() Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-07-08 15:46 ` [PATCH v2 20/35] acpi: build_amd_iommu: " Igor Mammedov
                   ` (16 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: marcel.apfelbaum@gmail.com
---
 hw/i386/acpi-build.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index f23250421f..0085398360 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2104,10 +2104,10 @@ static void
 build_waet(GArray *table_data, BIOSLinker *linker, const char *oem_id,
            const char *oem_table_id)
 {
-    int waet_start = table_data->len;
+    AcpiTable table = { .sig = "WAET", .rev = 1, .oem_id = oem_id,
+                        .oem_table_id = oem_table_id };
 
-    /* WAET header */
-    acpi_data_push(table_data, sizeof(AcpiTableHeader));
+    acpi_init_table(&table, table_data);
     /*
      * Set "ACPI PM timer good" flag.
      *
@@ -2116,9 +2116,7 @@ build_waet(GArray *table_data, BIOSLinker *linker, const char *oem_id,
      * Which avoids costly VMExits caused by guest re-reading it unnecessarily.
      */
     build_append_int_noprefix(table_data, 1 << 1 /* ACPI PM timer good */, 4);
-
-    build_header(linker, table_data, (void *)(table_data->data + waet_start),
-                 "WAET", table_data->len - waet_start, 1, oem_id, oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 
 /*
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 20/35] acpi: build_amd_iommu: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (18 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 19/35] acpi: build_waet: " Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-07-08 15:46 ` [PATCH v2 21/35] acpi: madt: arm/x86: " Igor Mammedov
                   ` (15 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: marcel.apfelbaum@gmail.com
---
 hw/i386/acpi-build.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 0085398360..e655d93bad 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2222,12 +2222,12 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
                 const char *oem_table_id)
 {
     int ivhd_table_len = 24;
-    int iommu_start = table_data->len;
     AMDVIState *s = AMD_IOMMU_DEVICE(x86_iommu_get_default());
     GArray *ivhd_blob = g_array_new(false, true, 1);
+    AcpiTable table = { .sig = "IVRS", .rev = 1, .oem_id = oem_id,
+                        .oem_table_id = oem_table_id };
 
-    /* IVRS header */
-    acpi_data_push(table_data, sizeof(AcpiTableHeader));
+    acpi_init_table(&table, table_data);
     /* IVinfo - IO virtualization information common to all
      * IOMMU units in a system
      */
@@ -2312,10 +2312,7 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
                                  0x48,                      /* special device */
                                  8);
     }
-
-    build_header(linker, table_data, (void *)(table_data->data + iommu_start),
-                 "IVRS", table_data->len - iommu_start, 1, oem_id,
-                 oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 
 typedef
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 21/35] acpi: madt: arm/x86: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (19 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 20/35] acpi: build_amd_iommu: " Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-07-08 15:46 ` [PATCH v2 22/35] acpi: x86: remove dead code Igor Mammedov
                   ` (14 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, drjones, mst, shannon.zhaosl, qemu-arm

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: marcel.apfelbaum@gmail.com
CC: shannon.zhaosl@gmail.com
CC: peter.maydell@linaro.org
CC: qemu-arm@nongnu.org
CC: drjones@redhat.com
---
 include/hw/acpi/acpi-defs.h |  9 ---------
 hw/arm/virt-acpi-build.c    | 19 +++++++++++--------
 hw/i386/acpi-common.c       | 19 +++++++++++--------
 3 files changed, 22 insertions(+), 25 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index c4f0a202e8..c7fa5caa06 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -176,15 +176,6 @@ typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
 #define ACPI_DUAL_PIC                0
 #define ACPI_MULTIPLE_APIC           1
 
-/* Master MADT */
-
-struct AcpiMultipleApicTable {
-    ACPI_TABLE_HEADER_DEF     /* ACPI common table header */
-    uint32_t local_apic_address;     /* Physical address of local APIC */
-    uint32_t flags;
-} QEMU_PACKED;
-typedef struct AcpiMultipleApicTable AcpiMultipleApicTable;
-
 /* Values for Type in APIC sub-headers */
 
 #define ACPI_APIC_PROCESSOR          0
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 159e71dbdd..cd8b73dde9 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -475,19 +475,26 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
                  vms->oem_table_id);
 }
 
-/* MADT */
+/*
+ * ACPI spec, Revision 5.0
+ * 5.2.12 Multiple APIC Description Table (MADT)
+ */
 static void
 build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
     VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
-    int madt_start = table_data->len;
     const MemMapEntry *memmap = vms->memmap;
     const int *irqmap = vms->irqmap;
     AcpiMadtGenericDistributor *gicd;
     AcpiMadtGenericMsiFrame *gic_msi;
     int i;
+    AcpiTable table = { .sig = "APIC", .rev = 3, .oem_id = vms->oem_id,
+                        .oem_table_id = vms->oem_table_id };
 
-    acpi_data_push(table_data, sizeof(AcpiMultipleApicTable));
+    acpi_init_table(&table, table_data);
+    /* Local Interrupt Controller Address */
+    build_append_int_noprefix(table_data, 0, 4);
+    build_append_int_noprefix(table_data, 0, 4); /* Flags */
 
     gicd = acpi_data_push(table_data, sizeof *gicd);
     gicd->type = ACPI_APIC_GENERIC_DISTRIBUTOR;
@@ -558,11 +565,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
         gic_msi->spi_count = cpu_to_le16(NUM_GICV2M_SPIS);
         gic_msi->spi_base = cpu_to_le16(irqmap[VIRT_GIC_V2M] + ARM_SPI_BASE);
     }
-
-    build_header(linker, table_data,
-                 (void *)(table_data->data + madt_start), "APIC",
-                 table_data->len - madt_start, 3, vms->oem_id,
-                 vms->oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 
 /* FADT */
diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 1f5947fcf9..219dcded02 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -71,24 +71,29 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
     }
 }
 
+/*
+ * ACPI spec, Revision 1.0b
+ * 5.2.8 Multiple APIC Description Table
+ */
 void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
                      X86MachineState *x86ms, AcpiDeviceIf *adev,
                      const char *oem_id, const char *oem_table_id)
 {
     MachineClass *mc = MACHINE_GET_CLASS(x86ms);
     const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
-    int madt_start = table_data->len;
     AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
     bool x2apic_mode = false;
 
-    AcpiMultipleApicTable *madt;
     AcpiMadtIoApic *io_apic;
     AcpiMadtIntsrcovr *intsrcovr;
     int i;
+    AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = oem_id,
+                        .oem_table_id = oem_table_id };
 
-    madt = acpi_data_push(table_data, sizeof *madt);
-    madt->local_apic_address = cpu_to_le32(APIC_DEFAULT_ADDRESS);
-    madt->flags = cpu_to_le32(1);
+    acpi_init_table(&table, table_data);
+    /* Local APIC Address */
+    build_append_int_noprefix(table_data, APIC_DEFAULT_ADDRESS, 4);
+    build_append_int_noprefix(table_data, 1 /* PCAT_COMPAT */, 4); /* Flags */
 
     for (i = 0; i < apic_ids->len; i++) {
         adevc->madt_cpu(adev, i, apic_ids, table_data);
@@ -156,8 +161,6 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
         local_nmi->lint         = 1; /* ACPI_LINT1 */
     }
 
-    build_header(linker, table_data,
-                 (void *)(table_data->data + madt_start), "APIC",
-                 table_data->len - madt_start, 1, oem_id, oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 22/35] acpi: x86: remove dead code
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (20 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 21/35] acpi: madt: arm/x86: " Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-07-08 15:46 ` [PATCH v2 23/35] acpi: x86: set enabled when composing _MAT entries Igor Mammedov
                   ` (13 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 include/hw/acpi/acpi-defs.h | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index c7fa5caa06..af4fa412a5 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -163,19 +163,6 @@ struct AcpiFacsDescriptorRev1 {
 } QEMU_PACKED;
 typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
 
-/*
- * Differentiated System Description Table (DSDT)
- */
-
-/*
- * MADT values and structures
- */
-
-/* Values for MADT PCATCompat */
-
-#define ACPI_DUAL_PIC                0
-#define ACPI_MULTIPLE_APIC           1
-
 /* Values for Type in APIC sub-headers */
 
 #define ACPI_APIC_PROCESSOR          0
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 23/35] acpi: x86: set enabled when composing _MAT entries
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (21 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 22/35] acpi: x86: remove dead code Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-07-08 15:46 ` [PATCH v2 24/35] acpi: x86: madt: use build_append_int_noprefix() API to compose MADT table Igor Mammedov
                   ` (12 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

Instead of composing disabled _MAT entry and then later on
patching it to enabled for hotpluggbale CPUs in DSDT,
set it to enabled at the time _MAT entry is built.

It will allow to drop usage of packed structures in
following patches when build_madt() is switched to use
build_append_int_noprefix() API.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: marcel.apfelbaum@gmail.com
---
 include/hw/acpi/acpi_dev_interface.h |  3 ++-
 include/hw/i386/pc.h                 |  7 ++++---
 hw/acpi/acpi-x86-stub.c              |  3 ++-
 hw/acpi/cpu.c                        | 17 ++---------------
 hw/i386/acpi-common.c                | 18 ++++++------------
 5 files changed, 16 insertions(+), 32 deletions(-)

diff --git a/include/hw/acpi/acpi_dev_interface.h b/include/hw/acpi/acpi_dev_interface.h
index 769ff55c7e..ea6056ab92 100644
--- a/include/hw/acpi/acpi_dev_interface.h
+++ b/include/hw/acpi/acpi_dev_interface.h
@@ -53,6 +53,7 @@ struct AcpiDeviceIfClass {
     void (*ospm_status)(AcpiDeviceIf *adev, ACPIOSTInfoList ***list);
     void (*send_event)(AcpiDeviceIf *adev, AcpiEventStatusBits ev);
     void (*madt_cpu)(AcpiDeviceIf *adev, int uid,
-                     const CPUArchIdList *apic_ids, GArray *entry);
+                     const CPUArchIdList *apic_ids, GArray *entry,
+                     bool force_enabled);
 };
 #endif
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 87294f2632..7eb42195b3 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -189,11 +189,12 @@ void pc_system_firmware_init(PCMachineState *pcms, MemoryRegion *rom_memory);
 bool pc_system_ovmf_table_find(const char *entry, uint8_t **data,
                                int *data_len);
 
-
-/* acpi-build.c */
+/* hw/i386/acpi-common.c */
 void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
-                       const CPUArchIdList *apic_ids, GArray *entry);
+                       const CPUArchIdList *apic_ids, GArray *entry,
+                       bool force_enabled);
 
+/* acpi-build.c */
 extern GlobalProperty pc_compat_6_0[];
 extern const size_t pc_compat_6_0_len;
 
diff --git a/hw/acpi/acpi-x86-stub.c b/hw/acpi/acpi-x86-stub.c
index f88d6a090b..987fc64b36 100644
--- a/hw/acpi/acpi-x86-stub.c
+++ b/hw/acpi/acpi-x86-stub.c
@@ -2,6 +2,7 @@
 #include "hw/i386/pc.h"
 
 void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
-                       const CPUArchIdList *apic_ids, GArray *entry)
+                       const CPUArchIdList *apic_ids, GArray *entry,
+                       bool force_enabled)
 {
 }
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index f82e9512fd..b20903ea30 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -669,21 +669,8 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
 
             /* build _MAT object */
             assert(adevc && adevc->madt_cpu);
-            adevc->madt_cpu(adev, i, arch_ids, madt_buf);
-            switch (madt_buf->data[0]) {
-            case ACPI_APIC_PROCESSOR: {
-                AcpiMadtProcessorApic *apic = (void *)madt_buf->data;
-                apic->flags = cpu_to_le32(1);
-                break;
-            }
-            case ACPI_APIC_LOCAL_X2APIC: {
-                AcpiMadtProcessorX2Apic *apic = (void *)madt_buf->data;
-                apic->flags = cpu_to_le32(1);
-                break;
-            }
-            default:
-                assert(0);
-            }
+            adevc->madt_cpu(adev, i, arch_ids, madt_buf,
+                            true); /* set enabled flag */
             aml_append(dev, aml_name_decl("_MAT",
                 aml_buffer(madt_buf->len, (uint8_t *)madt_buf->data)));
             g_array_free(madt_buf, true);
diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 219dcded02..9d213edece 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -34,9 +34,11 @@
 #include "acpi-common.h"
 
 void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
-                       const CPUArchIdList *apic_ids, GArray *entry)
+                       const CPUArchIdList *apic_ids, GArray *entry,
+                       bool force_enabled)
 {
     uint32_t apic_id = apic_ids->cpus[uid].arch_id;
+    uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ? 1 : 0;
 
     /* ACPI spec says that LAPIC entry for non present
      * CPU may be omitted from MADT or it must be marked
@@ -51,11 +53,7 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
         apic->length = sizeof(*apic);
         apic->processor_id = uid;
         apic->local_apic_id = apic_id;
-        if (apic_ids->cpus[uid].cpu != NULL) {
-            apic->flags = cpu_to_le32(1);
-        } else {
-            apic->flags = cpu_to_le32(0);
-        }
+        apic->flags = cpu_to_le32(flags);
     } else {
         AcpiMadtProcessorX2Apic *apic = acpi_data_push(entry, sizeof *apic);
 
@@ -63,11 +61,7 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
         apic->length = sizeof(*apic);
         apic->uid = cpu_to_le32(uid);
         apic->x2apic_id = cpu_to_le32(apic_id);
-        if (apic_ids->cpus[uid].cpu != NULL) {
-            apic->flags = cpu_to_le32(1);
-        } else {
-            apic->flags = cpu_to_le32(0);
-        }
+        apic->flags = cpu_to_le32(flags);
     }
 }
 
@@ -96,7 +90,7 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
     build_append_int_noprefix(table_data, 1 /* PCAT_COMPAT */, 4); /* Flags */
 
     for (i = 0; i < apic_ids->len; i++) {
-        adevc->madt_cpu(adev, i, apic_ids, table_data);
+        adevc->madt_cpu(adev, i, apic_ids, table_data, false);
         if (apic_ids->cpus[i].arch_id > 254) {
             x2apic_mode = true;
         }
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 24/35] acpi: x86: madt: use build_append_int_noprefix() API to compose MADT table
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (22 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 23/35] acpi: x86: set enabled when composing _MAT entries Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-07-08 15:46 ` [PATCH v2 25/35] acpi: arm/virt: " Igor Mammedov
                   ` (11 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

Drop usage of packed structures and explicit endian conversions
when building MADT table for arm/x86 and use endian agnostic
build_append_int_noprefix() API to build it.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: marcel.apfelbaum@gmail.com
---
 include/hw/acpi/acpi-defs.h |  64 ------------------
 hw/i386/acpi-common.c       | 127 ++++++++++++++++++------------------
 2 files changed, 65 insertions(+), 126 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index af4fa412a5..3f174ba208 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -165,17 +165,6 @@ typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
 
 /* Values for Type in APIC sub-headers */
 
-#define ACPI_APIC_PROCESSOR          0
-#define ACPI_APIC_IO                 1
-#define ACPI_APIC_XRUPT_OVERRIDE     2
-#define ACPI_APIC_NMI                3
-#define ACPI_APIC_LOCAL_NMI          4
-#define ACPI_APIC_ADDRESS_OVERRIDE   5
-#define ACPI_APIC_IO_SAPIC           6
-#define ACPI_APIC_LOCAL_SAPIC        7
-#define ACPI_APIC_XRUPT_SOURCE       8
-#define ACPI_APIC_LOCAL_X2APIC       9
-#define ACPI_APIC_LOCAL_X2APIC_NMI      10
 #define ACPI_APIC_GENERIC_CPU_INTERFACE 11
 #define ACPI_APIC_GENERIC_DISTRIBUTOR   12
 #define ACPI_APIC_GENERIC_MSI_FRAME     13
@@ -192,59 +181,6 @@ typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
 
 /* Sub-structures for MADT */
 
-struct AcpiMadtProcessorApic {
-    ACPI_SUB_HEADER_DEF
-    uint8_t  processor_id;           /* ACPI processor id */
-    uint8_t  local_apic_id;          /* Processor's local APIC id */
-    uint32_t flags;
-} QEMU_PACKED;
-typedef struct AcpiMadtProcessorApic AcpiMadtProcessorApic;
-
-struct AcpiMadtIoApic {
-    ACPI_SUB_HEADER_DEF
-    uint8_t  io_apic_id;             /* I/O APIC ID */
-    uint8_t  reserved;               /* Reserved - must be zero */
-    uint32_t address;                /* APIC physical address */
-    uint32_t interrupt;              /* Global system interrupt where INTI
-                                 * lines start */
-} QEMU_PACKED;
-typedef struct AcpiMadtIoApic AcpiMadtIoApic;
-
-struct AcpiMadtIntsrcovr {
-    ACPI_SUB_HEADER_DEF
-    uint8_t  bus;
-    uint8_t  source;
-    uint32_t gsi;
-    uint16_t flags;
-} QEMU_PACKED;
-typedef struct AcpiMadtIntsrcovr AcpiMadtIntsrcovr;
-
-struct AcpiMadtLocalNmi {
-    ACPI_SUB_HEADER_DEF
-    uint8_t  processor_id;           /* ACPI processor id */
-    uint16_t flags;                  /* MPS INTI flags */
-    uint8_t  lint;                   /* Local APIC LINT# */
-} QEMU_PACKED;
-typedef struct AcpiMadtLocalNmi AcpiMadtLocalNmi;
-
-struct AcpiMadtProcessorX2Apic {
-    ACPI_SUB_HEADER_DEF
-    uint16_t reserved;
-    uint32_t x2apic_id;              /* Processor's local x2APIC ID */
-    uint32_t flags;
-    uint32_t uid;                    /* Processor object _UID */
-} QEMU_PACKED;
-typedef struct AcpiMadtProcessorX2Apic AcpiMadtProcessorX2Apic;
-
-struct AcpiMadtLocalX2ApicNmi {
-    ACPI_SUB_HEADER_DEF
-    uint16_t flags;                  /* MPS INTI flags */
-    uint32_t uid;                    /* Processor object _UID */
-    uint8_t  lint;                   /* Local APIC LINT# */
-    uint8_t  reserved[3];            /* Local APIC LINT# */
-} QEMU_PACKED;
-typedef struct AcpiMadtLocalX2ApicNmi AcpiMadtLocalX2ApicNmi;
-
 struct AcpiMadtGenericCpuInterface {
     ACPI_SUB_HEADER_DEF
     uint16_t reserved;
diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c
index 9d213edece..6261f45c23 100644
--- a/hw/i386/acpi-common.c
+++ b/hw/i386/acpi-common.c
@@ -38,7 +38,9 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
                        bool force_enabled)
 {
     uint32_t apic_id = apic_ids->cpus[uid].arch_id;
-    uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ? 1 : 0;
+    /* Flags – Local APIC Flags */
+    uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
+                     1 /* Enabled */ : 0;
 
     /* ACPI spec says that LAPIC entry for non present
      * CPU may be omitted from MADT or it must be marked
@@ -47,24 +49,47 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
      * should be put in MADT but kept disabled.
      */
     if (apic_id < 255) {
-        AcpiMadtProcessorApic *apic = acpi_data_push(entry, sizeof *apic);
-
-        apic->type = ACPI_APIC_PROCESSOR;
-        apic->length = sizeof(*apic);
-        apic->processor_id = uid;
-        apic->local_apic_id = apic_id;
-        apic->flags = cpu_to_le32(flags);
+        /* Rev 1.0b, Table 5-13 Processor Local APIC Structure */
+        build_append_int_noprefix(entry, 0, 1);       /* Type */
+        build_append_int_noprefix(entry, 8, 1);       /* Length */
+        build_append_int_noprefix(entry, uid, 1);     /* ACPI Processor ID */
+        build_append_int_noprefix(entry, apic_id, 1); /* APIC ID */
+        build_append_int_noprefix(entry, flags, 4); /* Flags */
     } else {
-        AcpiMadtProcessorX2Apic *apic = acpi_data_push(entry, sizeof *apic);
-
-        apic->type = ACPI_APIC_LOCAL_X2APIC;
-        apic->length = sizeof(*apic);
-        apic->uid = cpu_to_le32(uid);
-        apic->x2apic_id = cpu_to_le32(apic_id);
-        apic->flags = cpu_to_le32(flags);
+        /* Rev 4.0, 5.2.12.12 Processor Local x2APIC Structure */
+        build_append_int_noprefix(entry, 9, 1);       /* Type */
+        build_append_int_noprefix(entry, 16, 1);      /* Length */
+        build_append_int_noprefix(entry, 0, 2);       /* Reserved */
+        build_append_int_noprefix(entry, apic_id, 4); /* X2APIC ID */
+        build_append_int_noprefix(entry, flags, 4);   /* Flags */
+        build_append_int_noprefix(entry, uid, 4);     /* ACPI Processor UID */
     }
 }
 
+static void build_ioapic(GArray *entry, uint8_t id, uint32_t addr, uint32_t irq)
+{
+    /* Rev 1.0b, 5.2.8.2 IO APIC */
+    build_append_int_noprefix(entry, 1, 1);    /* Type */
+    build_append_int_noprefix(entry, 12, 1);   /* Length */
+    build_append_int_noprefix(entry, id, 1);   /* IO APIC ID */
+    build_append_int_noprefix(entry, 0, 1);    /* Reserved */
+    build_append_int_noprefix(entry, addr, 4); /* IO APIC Address */
+    build_append_int_noprefix(entry, irq, 4);  /* System Vector Base */
+}
+
+static void
+build_xrupt_override(GArray *entry, uint8_t src, uint32_t gsi, uint16_t flags)
+{
+    /* Rev 1.0b, 5.2.8.3.1 Interrupt Source Overrides */
+    build_append_int_noprefix(entry, 2, 1);  /* Type */
+    build_append_int_noprefix(entry, 10, 1); /* Length */
+    build_append_int_noprefix(entry, 0, 1);  /* Bus */
+    build_append_int_noprefix(entry, src, 1);  /* Source */
+    /* Global System Interrupt Vector */
+    build_append_int_noprefix(entry, gsi, 4);
+    build_append_int_noprefix(entry, flags, 2);  /* Flags */
+}
+
 /*
  * ACPI spec, Revision 1.0b
  * 5.2.8 Multiple APIC Description Table
@@ -73,14 +98,11 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
                      X86MachineState *x86ms, AcpiDeviceIf *adev,
                      const char *oem_id, const char *oem_table_id)
 {
+    int i;
+    bool x2apic_mode = false;
     MachineClass *mc = MACHINE_GET_CLASS(x86ms);
     const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
     AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
-    bool x2apic_mode = false;
-
-    AcpiMadtIoApic *io_apic;
-    AcpiMadtIntsrcovr *intsrcovr;
-    int i;
     AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = oem_id,
                         .oem_table_id = oem_table_id };
 
@@ -96,30 +118,14 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
         }
     }
 
-    io_apic = acpi_data_push(table_data, sizeof *io_apic);
-    io_apic->type = ACPI_APIC_IO;
-    io_apic->length = sizeof(*io_apic);
-    io_apic->io_apic_id = ACPI_BUILD_IOAPIC_ID;
-    io_apic->address = cpu_to_le32(IO_APIC_DEFAULT_ADDRESS);
-    io_apic->interrupt = cpu_to_le32(0);
-
+    build_ioapic(table_data, ACPI_BUILD_IOAPIC_ID, IO_APIC_DEFAULT_ADDRESS, 0);
     if (x86ms->ioapic2) {
-        AcpiMadtIoApic *io_apic2;
-        io_apic2 = acpi_data_push(table_data, sizeof *io_apic);
-        io_apic2->type = ACPI_APIC_IO;
-        io_apic2->length = sizeof(*io_apic);
-        io_apic2->io_apic_id = ACPI_BUILD_IOAPIC_ID + 1;
-        io_apic2->address = cpu_to_le32(IO_APIC_SECONDARY_ADDRESS);
-        io_apic2->interrupt = cpu_to_le32(IO_APIC_SECONDARY_IRQBASE);
+        build_ioapic(table_data, ACPI_BUILD_IOAPIC_ID + 1,
+                     IO_APIC_SECONDARY_ADDRESS, IO_APIC_SECONDARY_IRQBASE);
     }
 
     if (x86ms->apic_xrupt_override) {
-        intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr);
-        intsrcovr->type   = ACPI_APIC_XRUPT_OVERRIDE;
-        intsrcovr->length = sizeof(*intsrcovr);
-        intsrcovr->source = 0;
-        intsrcovr->gsi    = cpu_to_le32(2);
-        intsrcovr->flags  = cpu_to_le16(0); /* conforms to bus specifications */
+        build_xrupt_override(table_data, 0, 2, 0);
     }
 
     for (i = 1; i < 16; i++) {
@@ -127,32 +133,29 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
             /* No need for a INT source override structure. */
             continue;
         }
-        intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr);
-        intsrcovr->type   = ACPI_APIC_XRUPT_OVERRIDE;
-        intsrcovr->length = sizeof(*intsrcovr);
-        intsrcovr->source = i;
-        intsrcovr->gsi    = cpu_to_le32(i);
-        intsrcovr->flags  = cpu_to_le16(0xd); /* active high, level triggered */
+        build_xrupt_override(table_data, i, i, 0xd);
     }
 
     if (x2apic_mode) {
-        AcpiMadtLocalX2ApicNmi *local_nmi;
-
-        local_nmi = acpi_data_push(table_data, sizeof *local_nmi);
-        local_nmi->type   = ACPI_APIC_LOCAL_X2APIC_NMI;
-        local_nmi->length = sizeof(*local_nmi);
-        local_nmi->uid    = 0xFFFFFFFF; /* all processors */
-        local_nmi->flags  = cpu_to_le16(0);
-        local_nmi->lint   = 1; /* ACPI_LINT1 */
+        /* Rev 4.0, 5.2.12.13 Local x2APIC NMI Structure*/
+        build_append_int_noprefix(table_data, 0xA, 1); /* Type */
+        build_append_int_noprefix(table_data, 12, 1);  /* Length */
+        build_append_int_noprefix(table_data, 0, 2);   /* Flags */
+        /* ACPI Processor UID */
+        build_append_int_noprefix(table_data, 0xFFFFFFFF /* all processors */,
+                                  4);
+        /* Local x2APIC INTI# */
+        build_append_int_noprefix(table_data, 1 /* ACPI_LINT1 */, 1);
+        build_append_int_noprefix(table_data, 0, 3);
     } else {
-        AcpiMadtLocalNmi *local_nmi;
-
-        local_nmi = acpi_data_push(table_data, sizeof *local_nmi);
-        local_nmi->type         = ACPI_APIC_LOCAL_NMI;
-        local_nmi->length       = sizeof(*local_nmi);
-        local_nmi->processor_id = 0xff; /* all processors */
-        local_nmi->flags        = cpu_to_le16(0);
-        local_nmi->lint         = 1; /* ACPI_LINT1 */
+        /* Rev 1.0b, 5.2.8.3.3 Local APIC NMI */
+        build_append_int_noprefix(table_data, 4, 1);  /* Type */
+        build_append_int_noprefix(table_data, 6, 1);  /* Length */
+        /* ACPI Processor ID */
+        build_append_int_noprefix(table_data, 0xff /* all processors */, 1);
+        build_append_int_noprefix(table_data, 0, 2);  /* Flags */
+        /* Local APIC INTI# */
+        build_append_int_noprefix(table_data, 1 /* ACPI_LINT1 */, 1);
     }
 
     acpi_table_composed(linker, &table);
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 25/35] acpi: arm/virt: madt: use build_append_int_noprefix() API to compose MADT table
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (23 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 24/35] acpi: x86: madt: use build_append_int_noprefix() API to compose MADT table Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-09-03 13:45   ` Eric Auger
  2021-07-08 15:46 ` [PATCH v2 26/35] acpi: build_dsdt_microvm: use acpi_init_table()/acpi_table_composed() instead of build_header() Igor Mammedov
                   ` (10 subsequent siblings)
  35 siblings, 1 reply; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, drjones, shannon.zhaosl, qemu-arm, mst

Drop usage of packed structures and explicit endian conversions
when building MADT table for arm/x86 and use endian agnostic
build_append_int_noprefix() API to build it.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: drjones@redhat.com
CC: peter.maydell@linaro.org
CC: shannon.zhaosl@gmail.com
CC: qemu-arm@nongnu.org
---
 include/hw/acpi/acpi-defs.h |  84 --------------------
 hw/arm/virt-acpi-build.c    | 149 +++++++++++++++++++++---------------
 2 files changed, 89 insertions(+), 144 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 3f174ba208..bcada37601 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -163,90 +163,6 @@ struct AcpiFacsDescriptorRev1 {
 } QEMU_PACKED;
 typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
 
-/* Values for Type in APIC sub-headers */
-
-#define ACPI_APIC_GENERIC_CPU_INTERFACE 11
-#define ACPI_APIC_GENERIC_DISTRIBUTOR   12
-#define ACPI_APIC_GENERIC_MSI_FRAME     13
-#define ACPI_APIC_GENERIC_REDISTRIBUTOR 14
-#define ACPI_APIC_GENERIC_TRANSLATOR    15
-#define ACPI_APIC_RESERVED              16   /* 16 and greater are reserved */
-
-/*
- * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
- */
-#define ACPI_SUB_HEADER_DEF   /* Common ACPI sub-structure header */\
-    uint8_t  type;                               \
-    uint8_t  length;
-
-/* Sub-structures for MADT */
-
-struct AcpiMadtGenericCpuInterface {
-    ACPI_SUB_HEADER_DEF
-    uint16_t reserved;
-    uint32_t cpu_interface_number;
-    uint32_t uid;
-    uint32_t flags;
-    uint32_t parking_version;
-    uint32_t performance_interrupt;
-    uint64_t parked_address;
-    uint64_t base_address;
-    uint64_t gicv_base_address;
-    uint64_t gich_base_address;
-    uint32_t vgic_interrupt;
-    uint64_t gicr_base_address;
-    uint64_t arm_mpidr;
-} QEMU_PACKED;
-
-typedef struct AcpiMadtGenericCpuInterface AcpiMadtGenericCpuInterface;
-
-/* GICC CPU Interface Flags */
-#define ACPI_MADT_GICC_ENABLED 1
-
-struct AcpiMadtGenericDistributor {
-    ACPI_SUB_HEADER_DEF
-    uint16_t reserved;
-    uint32_t gic_id;
-    uint64_t base_address;
-    uint32_t global_irq_base;
-    /* ACPI 5.1 Errata 1228 Present GIC version in MADT table */
-    uint8_t version;
-    uint8_t reserved2[3];
-} QEMU_PACKED;
-
-typedef struct AcpiMadtGenericDistributor AcpiMadtGenericDistributor;
-
-struct AcpiMadtGenericMsiFrame {
-    ACPI_SUB_HEADER_DEF
-    uint16_t reserved;
-    uint32_t gic_msi_frame_id;
-    uint64_t base_address;
-    uint32_t flags;
-    uint16_t spi_count;
-    uint16_t spi_base;
-} QEMU_PACKED;
-
-typedef struct AcpiMadtGenericMsiFrame AcpiMadtGenericMsiFrame;
-
-struct AcpiMadtGenericRedistributor {
-    ACPI_SUB_HEADER_DEF
-    uint16_t reserved;
-    uint64_t base_address;
-    uint32_t range_length;
-} QEMU_PACKED;
-
-typedef struct AcpiMadtGenericRedistributor AcpiMadtGenericRedistributor;
-
-struct AcpiMadtGenericTranslator {
-    ACPI_SUB_HEADER_DEF
-    uint16_t reserved;
-    uint32_t translation_id;
-    uint64_t base_address;
-    uint32_t reserved2;
-} QEMU_PACKED;
-
-typedef struct AcpiMadtGenericTranslator AcpiMadtGenericTranslator;
-
 /*
  * Generic Timer Description Table (GTDT)
  */
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index cd8b73dde9..dd8011a670 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -476,94 +476,123 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 }
 
 /*
- * ACPI spec, Revision 5.0
+ * ACPI spec, Revision 5.1 Errata A
  * 5.2.12 Multiple APIC Description Table (MADT)
  */
+static void build_append_gicr(GArray *table_data, uint64_t base, uint32_t size)
+{
+    build_append_int_noprefix(table_data, 0xE, 1);  /* Type */
+    build_append_int_noprefix(table_data, 16, 1);   /* Length */
+    build_append_int_noprefix(table_data, 0, 2);    /* Reserved */
+    /* Discovery Range Base Addres */
+    build_append_int_noprefix(table_data, base, 8);
+    build_append_int_noprefix(table_data, size, 4); /* Discovery Range Length */
+}
+
 static void
 build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
+    int i;
     VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
     const MemMapEntry *memmap = vms->memmap;
-    const int *irqmap = vms->irqmap;
-    AcpiMadtGenericDistributor *gicd;
-    AcpiMadtGenericMsiFrame *gic_msi;
-    int i;
     AcpiTable table = { .sig = "APIC", .rev = 3, .oem_id = vms->oem_id,
                         .oem_table_id = vms->oem_table_id };
 
     acpi_init_table(&table, table_data);
     /* Local Interrupt Controller Address */
     build_append_int_noprefix(table_data, 0, 4);
-    build_append_int_noprefix(table_data, 0, 4); /* Flags */
-
-    gicd = acpi_data_push(table_data, sizeof *gicd);
-    gicd->type = ACPI_APIC_GENERIC_DISTRIBUTOR;
-    gicd->length = sizeof(*gicd);
-    gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base);
-    gicd->version = vms->gic_version;
+    build_append_int_noprefix(table_data, 0, 4);   /* Flags */
+
+    /* 5.2.12.15 GIC Distributor Structure */
+    build_append_int_noprefix(table_data, 0xC, 1); /* Type */
+    build_append_int_noprefix(table_data, 24, 1);  /* Length */
+    build_append_int_noprefix(table_data, 0, 2);   /* Reserved */
+    build_append_int_noprefix(table_data, 0, 4);   /* GIC ID */
+    /* Physical Base Address */
+    build_append_int_noprefix(table_data, memmap[VIRT_GIC_DIST].base, 8);
+    build_append_int_noprefix(table_data, 0, 4);   /* System Vector Base */
+    /* GIC version */
+    build_append_int_noprefix(table_data, vms->gic_version, 1);
+    build_append_int_noprefix(table_data, 0, 3);   /* Reserved */
 
     for (i = 0; i < MACHINE(vms)->smp.cpus; i++) {
-        AcpiMadtGenericCpuInterface *gicc = acpi_data_push(table_data,
-                                                           sizeof(*gicc));
         ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
+        uint64_t physical_base_address = 0, gich = 0, gicv = 0;
+        uint32_t vgic_interrupt = vms->virt ? PPI(ARCH_GIC_MAINT_IRQ) : 0;
+        uint32_t pmu_interrupt = arm_feature(&armcpu->env, ARM_FEATURE_PMU) ?
+                                             PPI(VIRTUAL_PMU_IRQ) : 0;
 
-        gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE;
-        gicc->length = sizeof(*gicc);
         if (vms->gic_version == 2) {
-            gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base);
-            gicc->gich_base_address = cpu_to_le64(memmap[VIRT_GIC_HYP].base);
-            gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base);
+            physical_base_address = memmap[VIRT_GIC_CPU].base;
+            gicv = memmap[VIRT_GIC_VCPU].base;
+            gich = memmap[VIRT_GIC_HYP].base;
         }
-        gicc->cpu_interface_number = cpu_to_le32(i);
-        gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity);
-        gicc->uid = cpu_to_le32(i);
-        gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED);
 
-        if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
-            gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ));
-        }
-        if (vms->virt) {
-            gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GIC_MAINT_IRQ));
-        }
+        /* 5.2.12.14 GIC Structure */
+        build_append_int_noprefix(table_data, 0xB, 1);  /* Type */
+        build_append_int_noprefix(table_data, 76, 1);   /* Length */
+        build_append_int_noprefix(table_data, 0, 2);    /* Reserved */
+        build_append_int_noprefix(table_data, i, 4);    /* GIC ID */
+        build_append_int_noprefix(table_data, i, 4);    /* ACPI Processor UID */
+        /* Flags */
+        build_append_int_noprefix(table_data, 1, 4);    /* Enabled */
+        /* Parking Protocol Version */
+        build_append_int_noprefix(table_data, 0, 4);
+        /* Performance Interrupt GSIV */
+        build_append_int_noprefix(table_data, pmu_interrupt, 4);
+        build_append_int_noprefix(table_data, 0, 8); /* Parked Address */
+        /* Physical Base Address */
+        build_append_int_noprefix(table_data, physical_base_address, 8);
+        build_append_int_noprefix(table_data, gicv, 8); /* GICV */
+        build_append_int_noprefix(table_data, gich, 8); /* GICH */
+        /* VGIC Maintenance interrupt */
+        build_append_int_noprefix(table_data, vgic_interrupt, 4);
+        build_append_int_noprefix(table_data, 0, 8);    /* GICR Base Address*/
+        /* MPIDR */
+        build_append_int_noprefix(table_data, armcpu->mp_affinity, 8);
     }
 
     if (vms->gic_version == 3) {
-        AcpiMadtGenericTranslator *gic_its;
-        int nb_redist_regions = virt_gicv3_redist_region_count(vms);
-        AcpiMadtGenericRedistributor *gicr = acpi_data_push(table_data,
-                                                         sizeof *gicr);
-
-        gicr->type = ACPI_APIC_GENERIC_REDISTRIBUTOR;
-        gicr->length = sizeof(*gicr);
-        gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST].base);
-        gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST].size);
-
-        if (nb_redist_regions == 2) {
-            gicr = acpi_data_push(table_data, sizeof(*gicr));
-            gicr->type = ACPI_APIC_GENERIC_REDISTRIBUTOR;
-            gicr->length = sizeof(*gicr);
-            gicr->base_address =
-                cpu_to_le64(memmap[VIRT_HIGH_GIC_REDIST2].base);
-            gicr->range_length =
-                cpu_to_le32(memmap[VIRT_HIGH_GIC_REDIST2].size);
+        build_append_gicr(table_data, memmap[VIRT_GIC_REDIST].base,
+                                      memmap[VIRT_GIC_REDIST].size);
+        if (virt_gicv3_redist_region_count(vms) == 2) {
+            build_append_gicr(table_data, memmap[VIRT_HIGH_GIC_REDIST2].base,
+                                          memmap[VIRT_HIGH_GIC_REDIST2].size);
         }
 
         if (its_class_name() && !vmc->no_its) {
-            gic_its = acpi_data_push(table_data, sizeof *gic_its);
-            gic_its->type = ACPI_APIC_GENERIC_TRANSLATOR;
-            gic_its->length = sizeof(*gic_its);
-            gic_its->translation_id = 0;
-            gic_its->base_address = cpu_to_le64(memmap[VIRT_GIC_ITS].base);
+            /*
+             * FIXME: Structure is from Revision 6.0 where 'GIC Structure'
+             * has additional fields on top of implemented 5.1 Errata A
+             * make it consistent with v6.0 if ITS is present or bump
+             * everything to v6.0 unconditionally
+             */
+            /*
+             * ACPI spec, Revision  6.0
+             * 5.2.12.18 GIC ITS Structure
+             */
+            build_append_int_noprefix(table_data, 0xF, 1);  /* Type */
+            build_append_int_noprefix(table_data, 16, 1);   /* Length */
+            build_append_int_noprefix(table_data, 0, 2);    /* Reserved */
+            build_append_int_noprefix(table_data, 0, 4);    /* GIC ITS ID */
+            /* Physical Base Address */
+            build_append_int_noprefix(table_data, memmap[VIRT_GIC_ITS].base, 8);
+            build_append_int_noprefix(table_data, 0, 4);    /* Reserved */
         }
     } else {
-        gic_msi = acpi_data_push(table_data, sizeof *gic_msi);
-        gic_msi->type = ACPI_APIC_GENERIC_MSI_FRAME;
-        gic_msi->length = sizeof(*gic_msi);
-        gic_msi->gic_msi_frame_id = 0;
-        gic_msi->base_address = cpu_to_le64(memmap[VIRT_GIC_V2M].base);
-        gic_msi->flags = cpu_to_le32(1);
-        gic_msi->spi_count = cpu_to_le16(NUM_GICV2M_SPIS);
-        gic_msi->spi_base = cpu_to_le16(irqmap[VIRT_GIC_V2M] + ARM_SPI_BASE);
+        const uint16_t spi_base = vms->irqmap[VIRT_GIC_V2M] + ARM_SPI_BASE;
+
+        /* 5.2.12.16 GIC MSI Frame Structure */
+        build_append_int_noprefix(table_data, 0xD, 1);  /* Type */
+        build_append_int_noprefix(table_data, 24, 1);   /* Length */
+        build_append_int_noprefix(table_data, 0, 2);    /* Reserved */
+        build_append_int_noprefix(table_data, 0, 4);    /* GIC MSI Frame ID */
+        /* Physical Base Address */
+        build_append_int_noprefix(table_data, memmap[VIRT_GIC_V2M].base, 8);
+        build_append_int_noprefix(table_data, 1, 4);    /* Flags */
+        /* SPI Count */
+        build_append_int_noprefix(table_data, NUM_GICV2M_SPIS, 2);
+        build_append_int_noprefix(table_data, spi_base, 2); /* SPI Base */
     }
     acpi_table_composed(linker, &table);
 }
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 26/35] acpi: build_dsdt_microvm: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (24 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 25/35] acpi: arm/virt: " Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-07-08 15:46 ` [PATCH v2 27/35] acpi: arm: virt: build_dsdt: " Igor Mammedov
                   ` (9 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: marcel.apfelbaum@gmail.com
---
 hw/i386/acpi-microvm.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c
index 1a0f77b911..82126680bb 100644
--- a/hw/i386/acpi-microvm.c
+++ b/hw/i386/acpi-microvm.c
@@ -113,16 +113,16 @@ build_dsdt_microvm(GArray *table_data, BIOSLinker *linker,
     Aml *dsdt, *sb_scope, *scope, *pkg;
     bool ambiguous;
     Object *isabus;
+    AcpiTable table = { .sig = "DSDT", .rev = 2, .oem_id = x86ms->oem_id,
+                        .oem_table_id = x86ms->oem_table_id };
 
     isabus = object_resolve_path_type("", TYPE_ISA_BUS, &ambiguous);
     assert(isabus);
     assert(!ambiguous);
 
+    acpi_init_table(&table, table_data);
     dsdt = init_aml_allocator();
 
-    /* Reserve space for header */
-    acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader));
-
     sb_scope = aml_scope("_SB");
     fw_cfg_add_acpi_dsdt(sb_scope, x86ms->fw_cfg);
     isa_build_aml(ISA_BUS(isabus), sb_scope);
@@ -144,11 +144,10 @@ build_dsdt_microvm(GArray *table_data, BIOSLinker *linker,
     aml_append(scope, aml_name_decl("_S5", pkg));
     aml_append(dsdt, scope);
 
-    /* copy AML table into ACPI tables blob and patch header there */
+    /* copy AML bytecode into ACPI tables blob */
     g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
-    build_header(linker, table_data,
-        (void *)(table_data->data + table_data->len - dsdt->buf->len),
-                 "DSDT", dsdt->buf->len, 2, x86ms->oem_id, x86ms->oem_table_id);
+
+    acpi_table_composed(linker, &table);
     free_aml_allocator();
 }
 
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 27/35] acpi: arm: virt: build_dsdt: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (25 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 26/35] acpi: build_dsdt_microvm: use acpi_init_table()/acpi_table_composed() instead of build_header() Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-09-02 15:34   ` Eric Auger
  2021-07-08 15:46 ` [PATCH v2 28/35] acpi: arm: virt: build_iort: " Igor Mammedov
                   ` (8 subsequent siblings)
  35 siblings, 1 reply; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, drjones, shannon.zhaosl, qemu-arm, mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: peter.maydell@linaro.org
CC: shannon.zhaosl@gmail.com
CC: qemu-arm@nongnu.org
CC: drjones@redhat.com
---
 hw/arm/virt-acpi-build.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index dd8011a670..d15e67a39b 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -636,10 +636,11 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     MachineState *ms = MACHINE(vms);
     const MemMapEntry *memmap = vms->memmap;
     const int *irqmap = vms->irqmap;
+    AcpiTable table = { .sig = "DSDT", .rev = 2, .oem_id = vms->oem_id,
+                        .oem_table_id = vms->oem_table_id };
 
+    acpi_init_table(&table, table_data);
     dsdt = init_aml_allocator();
-    /* Reserve space for header */
-    acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader));
 
     /* When booting the VM with UEFI, UEFI takes ownership of the RTC hardware.
      * While UEFI can use libfdt to disable the RTC device node in the DTB that
@@ -686,12 +687,10 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 
     aml_append(dsdt, scope);
 
-    /* copy AML table into ACPI tables blob and patch header there */
+    /* copy AML table into ACPI tables blob */
     g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
-    build_header(linker, table_data,
-        (void *)(table_data->data + table_data->len - dsdt->buf->len),
-                 "DSDT", dsdt->buf->len, 2, vms->oem_id,
-                 vms->oem_table_id);
+
+    acpi_table_composed(linker, &table);
     free_aml_allocator();
 }
 
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 28/35] acpi: arm: virt: build_iort: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (26 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 27/35] acpi: arm: virt: build_dsdt: " Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-07-08 15:46 ` [PATCH v2 29/35] acpi: arm/virt: convert build_iort() to endian agnostic build_append_FOO() API Igor Mammedov
                   ` (7 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, drjones, shannon.zhaosl, qemu-arm, mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: drjones@redhat.com
CC: peter.maydell@linaro.org
CC: shannon.zhaosl@gmail.com
CC: qemu-arm@nongnu.org
---
 include/hw/acpi/acpi-defs.h | 14 ------------
 hw/arm/virt-acpi-build.c    | 43 +++++++++++++++----------------------
 2 files changed, 17 insertions(+), 40 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index bcada37601..195f90caf6 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -188,20 +188,6 @@ struct AcpiGenericTimerTable {
 } QEMU_PACKED;
 typedef struct AcpiGenericTimerTable AcpiGenericTimerTable;
 
-/*
- * Input Output Remapping Table (IORT)
- * Conforms to "IO Remapping Table System Software on ARM Platforms",
- * Document number: ARM DEN 0049B, October 2015
- */
-
-struct AcpiIortTable {
-    ACPI_TABLE_HEADER_DEF     /* ACPI common table header */
-    uint32_t node_count;
-    uint32_t node_offset;
-    uint32_t reserved;
-} QEMU_PACKED;
-typedef struct AcpiIortTable AcpiIortTable;
-
 /*
  * IORT node types
  */
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index d15e67a39b..ac5e07e43c 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -239,18 +239,22 @@ static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms)
 }
 #endif
 
+/*
+ * Input Output Remapping Table (IORT)
+ * Conforms to "IO Remapping Table System Software on ARM Platforms",
+ * Document number: ARM DEN 0049B, October 2015
+ */
 static void
 build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
-    int nb_nodes, iort_start = table_data->len;
+    int nb_nodes;
     AcpiIortIdMapping *idmap;
     AcpiIortItsGroup *its;
-    AcpiIortTable *iort;
     AcpiIortSmmu3 *smmu;
-    size_t node_size, iort_node_offset, iort_length, smmu_offset = 0;
+    size_t node_size, iort_node_offset = 48, smmu_offset = 0;
     AcpiIortRC *rc;
-
-    iort = acpi_data_push(table_data, sizeof(*iort));
+    AcpiTable table = { .sig = "IORT", .rev = 0, .oem_id = vms->oem_id,
+                        .oem_table_id = vms->oem_table_id };
 
     if (vms->iommu == VIRT_IOMMU_SMMUV3) {
         nb_nodes = 3; /* RC, ITS, SMMUv3 */
@@ -258,18 +262,16 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
         nb_nodes = 2; /* RC, ITS */
     }
 
-    iort_length = sizeof(*iort);
-    iort->node_count = cpu_to_le32(nb_nodes);
-    /*
-     * Use a copy in case table_data->data moves during acpi_data_push
-     * operations.
-     */
-    iort_node_offset = sizeof(*iort);
-    iort->node_offset = cpu_to_le32(iort_node_offset);
+    /* Table 2 The IORT */
+    acpi_init_table(&table, table_data);
+    /* Number of IORT Nodes */
+    build_append_int_noprefix(table_data, nb_nodes, 4);
+    /* Offset to Array of IORT Nodes */
+    build_append_int_noprefix(table_data, iort_node_offset, 4);
+    build_append_int_noprefix(table_data, 0, 4); /* Reserved */
 
     /* ITS group node */
     node_size =  sizeof(*its) + sizeof(uint32_t);
-    iort_length += node_size;
     its = acpi_data_push(table_data, node_size);
 
     its->type = ACPI_IORT_NODE_ITS_GROUP;
@@ -283,7 +285,6 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
         /* SMMUv3 node */
         smmu_offset = iort_node_offset + node_size;
         node_size = sizeof(*smmu) + sizeof(*idmap);
-        iort_length += node_size;
         smmu = acpi_data_push(table_data, node_size);
 
         smmu->type = ACPI_IORT_NODE_SMMU_V3;
@@ -308,7 +309,6 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 
     /* Root Complex Node */
     node_size = sizeof(*rc) + sizeof(*idmap);
-    iort_length += node_size;
     rc = acpi_data_push(table_data, node_size);
 
     rc->type = ACPI_IORT_NODE_PCI_ROOT_COMPLEX;
@@ -335,16 +335,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
         idmap->output_reference = cpu_to_le32(iort_node_offset);
     }
 
-    /*
-     * Update the pointer address in case table_data->data moves during above
-     * acpi_data_push operations.
-     */
-    iort = (AcpiIortTable *)(table_data->data + iort_start);
-    iort->length = cpu_to_le32(iort_length);
-
-    build_header(linker, table_data, (void *)(table_data->data + iort_start),
-                 "IORT", table_data->len - iort_start, 0, vms->oem_id,
-                 vms->oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 
 static void
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 29/35] acpi: arm/virt: convert build_iort() to endian agnostic build_append_FOO() API
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (27 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 28/35] acpi: arm: virt: build_iort: " Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-07-09  7:11   ` Michael S. Tsirkin
  2021-07-08 15:46 ` [PATCH v2 30/35] acpi: arm/virt: build_spcr: fix invalid cast Igor Mammedov
                   ` (6 subsequent siblings)
  35 siblings, 1 reply; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, drjones, shannon.zhaosl, qemu-arm, mst

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: drjones@redhat.com
CC: peter.maydell@linaro.org
CC: shannon.zhaosl@gmail.com
CC: qemu-arm@nongnu.org
---
 include/hw/acpi/acpi-defs.h |  71 ------------------
 hw/arm/virt-acpi-build.c    | 143 +++++++++++++++++++-----------------
 2 files changed, 77 insertions(+), 137 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 195f90caf6..6f2f08a9de 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -188,75 +188,4 @@ struct AcpiGenericTimerTable {
 } QEMU_PACKED;
 typedef struct AcpiGenericTimerTable AcpiGenericTimerTable;
 
-/*
- * IORT node types
- */
-
-#define ACPI_IORT_NODE_HEADER_DEF   /* Node format common fields */ \
-    uint8_t  type;          \
-    uint16_t length;        \
-    uint8_t  revision;      \
-    uint32_t reserved;      \
-    uint32_t mapping_count; \
-    uint32_t mapping_offset;
-
-/* Values for node Type above */
-enum {
-        ACPI_IORT_NODE_ITS_GROUP = 0x00,
-        ACPI_IORT_NODE_NAMED_COMPONENT = 0x01,
-        ACPI_IORT_NODE_PCI_ROOT_COMPLEX = 0x02,
-        ACPI_IORT_NODE_SMMU = 0x03,
-        ACPI_IORT_NODE_SMMU_V3 = 0x04
-};
-
-struct AcpiIortIdMapping {
-    uint32_t input_base;
-    uint32_t id_count;
-    uint32_t output_base;
-    uint32_t output_reference;
-    uint32_t flags;
-} QEMU_PACKED;
-typedef struct AcpiIortIdMapping AcpiIortIdMapping;
-
-struct AcpiIortMemoryAccess {
-    uint32_t cache_coherency;
-    uint8_t  hints;
-    uint16_t reserved;
-    uint8_t  memory_flags;
-} QEMU_PACKED;
-typedef struct AcpiIortMemoryAccess AcpiIortMemoryAccess;
-
-struct AcpiIortItsGroup {
-    ACPI_IORT_NODE_HEADER_DEF
-    uint32_t its_count;
-    uint32_t identifiers[];
-} QEMU_PACKED;
-typedef struct AcpiIortItsGroup AcpiIortItsGroup;
-
-#define ACPI_IORT_SMMU_V3_COHACC_OVERRIDE 1
-
-struct AcpiIortSmmu3 {
-    ACPI_IORT_NODE_HEADER_DEF
-    uint64_t base_address;
-    uint32_t flags;
-    uint32_t reserved2;
-    uint64_t vatos_address;
-    uint32_t model;
-    uint32_t event_gsiv;
-    uint32_t pri_gsiv;
-    uint32_t gerr_gsiv;
-    uint32_t sync_gsiv;
-    AcpiIortIdMapping id_mapping_array[];
-} QEMU_PACKED;
-typedef struct AcpiIortSmmu3 AcpiIortSmmu3;
-
-struct AcpiIortRC {
-    ACPI_IORT_NODE_HEADER_DEF
-    AcpiIortMemoryAccess memory_properties;
-    uint32_t ats_attribute;
-    uint32_t pci_segment_number;
-    AcpiIortIdMapping id_mapping_array[];
-} QEMU_PACKED;
-typedef struct AcpiIortRC AcpiIortRC;
-
 #endif
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index ac5e07e43c..b88ea4b70a 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -239,6 +239,21 @@ static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms)
 }
 #endif
 
+#define ID_MAPPING_ENTRY_SIZE 20
+#define SMMU_V3_ENTRY_SIZE 60
+#define ROOT_COMPLEX_ENTRY_SIZE 32
+#define IORT_NODE_OFFSET 48
+
+static void build_iort_id_mapping(GArray *table_data, uint32_t out_ref)
+{
+    /* Identity RID mapping covering the whole input RID range */
+    build_append_int_noprefix(table_data, 0, 4); /* Input base */
+    build_append_int_noprefix(table_data, 0xFFFF, 4); /* Number of IDs */
+    build_append_int_noprefix(table_data, 0, 4); /* Output base */
+    build_append_int_noprefix(table_data, out_ref, 4); /* Output Reference */
+    build_append_int_noprefix(table_data, 0, 4); /* Flags */
+}
+
 /*
  * Input Output Remapping Table (IORT)
  * Conforms to "IO Remapping Table System Software on ARM Platforms",
@@ -247,92 +262,88 @@ static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms)
 static void
 build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
-    int nb_nodes;
-    AcpiIortIdMapping *idmap;
-    AcpiIortItsGroup *its;
-    AcpiIortSmmu3 *smmu;
-    size_t node_size, iort_node_offset = 48, smmu_offset = 0;
-    AcpiIortRC *rc;
+    size_t node_size, smmu_offset = 0;
     AcpiTable table = { .sig = "IORT", .rev = 0, .oem_id = vms->oem_id,
                         .oem_table_id = vms->oem_table_id };
 
-    if (vms->iommu == VIRT_IOMMU_SMMUV3) {
-        nb_nodes = 3; /* RC, ITS, SMMUv3 */
-    } else {
-        nb_nodes = 2; /* RC, ITS */
-    }
-
     /* Table 2 The IORT */
     acpi_init_table(&table, table_data);
     /* Number of IORT Nodes */
-    build_append_int_noprefix(table_data, nb_nodes, 4);
+    if (vms->iommu == VIRT_IOMMU_SMMUV3) {
+        build_append_int_noprefix(table_data, 3 /* RC, ITS, SMMUv3 */, 4);
+    } else {
+        build_append_int_noprefix(table_data, 2 /* RC, ITS */, 4);
+    }
     /* Offset to Array of IORT Nodes */
-    build_append_int_noprefix(table_data, iort_node_offset, 4);
+    build_append_int_noprefix(table_data, IORT_NODE_OFFSET, 4);
     build_append_int_noprefix(table_data, 0, 4); /* Reserved */
 
-    /* ITS group node */
-    node_size =  sizeof(*its) + sizeof(uint32_t);
-    its = acpi_data_push(table_data, node_size);
-
-    its->type = ACPI_IORT_NODE_ITS_GROUP;
-    its->length = cpu_to_le16(node_size);
-    its->its_count = cpu_to_le32(1);
-    its->identifiers[0] = 0; /* MADT translation_id */
+    /* 3.1.1.3 ITS group node */
+    build_append_int_noprefix(table_data, 0 /* ITS Group */, 1); /* Type */
+    node_size =  20 /* fixed header size */ + 4 /* 1 GIC ITS Identifier */;
+    build_append_int_noprefix(table_data, node_size, 2); /* Length */
+    build_append_int_noprefix(table_data, 0, 1); /* Revision */
+    build_append_int_noprefix(table_data, 0, 4); /* Reserved */
+    build_append_int_noprefix(table_data, 0, 4); /* Number of ID mappings */
+    build_append_int_noprefix(table_data, 0, 4); /* Reference to ID Array */
+    build_append_int_noprefix(table_data, 1, 4); /* Number of ITSs */
+    /* GIC ITS Identifier Array */
+    build_append_int_noprefix(table_data, 0 /* MADT translation_id */, 4);
 
     if (vms->iommu == VIRT_IOMMU_SMMUV3) {
         int irq =  vms->irqmap[VIRT_SMMU] + ARM_SPI_BASE;
 
-        /* SMMUv3 node */
-        smmu_offset = iort_node_offset + node_size;
-        node_size = sizeof(*smmu) + sizeof(*idmap);
-        smmu = acpi_data_push(table_data, node_size);
-
-        smmu->type = ACPI_IORT_NODE_SMMU_V3;
-        smmu->length = cpu_to_le16(node_size);
-        smmu->mapping_count = cpu_to_le32(1);
-        smmu->mapping_offset = cpu_to_le32(sizeof(*smmu));
-        smmu->base_address = cpu_to_le64(vms->memmap[VIRT_SMMU].base);
-        smmu->flags = cpu_to_le32(ACPI_IORT_SMMU_V3_COHACC_OVERRIDE);
-        smmu->event_gsiv = cpu_to_le32(irq);
-        smmu->pri_gsiv = cpu_to_le32(irq + 1);
-        smmu->sync_gsiv = cpu_to_le32(irq + 2);
-        smmu->gerr_gsiv = cpu_to_le32(irq + 3);
-
-        /* Identity RID mapping covering the whole input RID range */
-        idmap = &smmu->id_mapping_array[0];
-        idmap->input_base = 0;
-        idmap->id_count = cpu_to_le32(0xFFFF);
-        idmap->output_base = 0;
-        /* output IORT node is the ITS group node (the first node) */
-        idmap->output_reference = cpu_to_le32(iort_node_offset);
+        smmu_offset = table_data->len - table.table_offset;
+        /* 3.1.1.2 SMMUv3 */
+        build_append_int_noprefix(table_data, 4 /* SMMUv3 */, 1); /* Type */
+        node_size =  SMMU_V3_ENTRY_SIZE + ID_MAPPING_ENTRY_SIZE;
+        build_append_int_noprefix(table_data, node_size, 2); /* Length */
+        build_append_int_noprefix(table_data, 0, 1); /* Revision */
+        build_append_int_noprefix(table_data, 0, 4); /* Reserved */
+        build_append_int_noprefix(table_data, 1, 4); /* Number of ID mappings */
+        /* Reference to ID Array */
+        build_append_int_noprefix(table_data, SMMU_V3_ENTRY_SIZE, 4);
+        /* Base address */
+        build_append_int_noprefix(table_data, vms->memmap[VIRT_SMMU].base, 8);
+        /* Flags */
+        build_append_int_noprefix(table_data, 1 /* COHACC OverrideNote */, 4);
+        build_append_int_noprefix(table_data, 0, 4); /* Reserved */
+        build_append_int_noprefix(table_data, 0, 8); /* VATOS address */
+        /* Model */
+        build_append_int_noprefix(table_data, 0 /* Generic SMMU-v3 */, 4);
+        build_append_int_noprefix(table_data, irq, 4); /* Event */
+        build_append_int_noprefix(table_data, irq + 1, 4); /* PRI */
+        build_append_int_noprefix(table_data, irq + 3, 4); /* GERR */
+        build_append_int_noprefix(table_data, irq + 2, 4); /* Sync */
+
+        build_iort_id_mapping(table_data, IORT_NODE_OFFSET);
     }
 
-    /* Root Complex Node */
-    node_size = sizeof(*rc) + sizeof(*idmap);
-    rc = acpi_data_push(table_data, node_size);
-
-    rc->type = ACPI_IORT_NODE_PCI_ROOT_COMPLEX;
-    rc->length = cpu_to_le16(node_size);
-    rc->mapping_count = cpu_to_le32(1);
-    rc->mapping_offset = cpu_to_le32(sizeof(*rc));
-
+    /* Table 16 Root Complex Node */
+    build_append_int_noprefix(table_data, 2 /* Root complex */, 1); /* Type */
+    node_size =  ROOT_COMPLEX_ENTRY_SIZE + ID_MAPPING_ENTRY_SIZE;
+    build_append_int_noprefix(table_data, node_size, 2); /* Length */
+    build_append_int_noprefix(table_data, 0, 1); /* Revision */
+    build_append_int_noprefix(table_data, 0, 4); /* Reserved */
+    build_append_int_noprefix(table_data, 1, 4); /* Number of ID mappings */
+    /* Reference to ID Array */
+    build_append_int_noprefix(table_data, ROOT_COMPLEX_ENTRY_SIZE, 4);
     /* fully coherent device */
-    rc->memory_properties.cache_coherency = cpu_to_le32(1);
-    rc->memory_properties.memory_flags = 0x3; /* CCA = CPM = DCAS = 1 */
-    rc->pci_segment_number = 0; /* MCFG pci_segment */
-
-    /* Identity RID mapping covering the whole input RID range */
-    idmap = &rc->id_mapping_array[0];
-    idmap->input_base = 0;
-    idmap->id_count = cpu_to_le32(0xFFFF);
-    idmap->output_base = 0;
-
+    build_append_int_noprefix(table_data,
+        1 | /* CCA: Cache Coherent Attribute, The device is fully coherent */
+        (3ULL << 7 * 8) /* MAF: Memory Access Flags, CCA = CPM = DCAS = 1 */,
+        8);
+    build_append_int_noprefix(table_data, 0, 4); /* ATS Attribute */
+    /* MCFG pci_segment */
+    build_append_int_noprefix(table_data, 0, 4); /* PCI Segment number */
+
+    /* Output Reference */
     if (vms->iommu == VIRT_IOMMU_SMMUV3) {
         /* output IORT node is the smmuv3 node */
-        idmap->output_reference = cpu_to_le32(smmu_offset);
+        build_iort_id_mapping(table_data, smmu_offset);
     } else {
         /* output IORT node is the ITS group node (the first node) */
-        idmap->output_reference = cpu_to_le32(iort_node_offset);
+        build_iort_id_mapping(table_data, IORT_NODE_OFFSET);
     }
 
     acpi_table_composed(linker, &table);
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 30/35] acpi: arm/virt: build_spcr: fix invalid cast
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (28 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 29/35] acpi: arm/virt: convert build_iort() to endian agnostic build_append_FOO() API Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-09-02 15:51   ` Eric Auger
  2021-07-08 15:46 ` [PATCH v2 31/35] acpi: arm/virt: build_spcr: use acpi_init_table()/acpi_table_composed() instead of build_header() Igor Mammedov
                   ` (5 subsequent siblings)
  35 siblings, 1 reply; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, drjones, shannon.zhaosl, qemu-arm, mst

implicit cast to structure uint8_t member didn't raise error when
assigning value from incorrect enum, but when using build_append_gas()
(next patch) it will error out with (clang):
  implicit conversion from enumeration type 'AmlRegionSpace'
  to different enumeration type 'AmlAddressSpace'
fix cast error by using correct AML_AS_SYSTEM_MEMORY enum

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: drjones@redhat.com
CC: peter.maydell@linaro.org
CC: shannon.zhaosl@gmail.com
CC: qemu-arm@nongnu.org
---
 hw/arm/virt-acpi-build.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index b88ea4b70a..a07540affb 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -361,7 +361,7 @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 
     spcr->interface_type = 0x3;    /* ARM PL011 UART */
 
-    spcr->base_address.space_id = AML_SYSTEM_MEMORY;
+    spcr->base_address.space_id = AML_AS_SYSTEM_MEMORY;
     spcr->base_address.bit_width = 8;
     spcr->base_address.bit_offset = 0;
     spcr->base_address.access_width = 1;
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 31/35] acpi: arm/virt: build_spcr: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (29 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 30/35] acpi: arm/virt: build_spcr: fix invalid cast Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-09-02 15:49   ` Eric Auger
  2021-07-08 15:46 ` [PATCH v2 32/35] acpi: arm/virt: build_gtdt: " Igor Mammedov
                   ` (4 subsequent siblings)
  35 siblings, 1 reply; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, drjones, shannon.zhaosl, qemu-arm, mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

while at it, replace packed structure with endian agnostic
build_append_FOO() API.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: drjones@redhat.com
CC: peter.maydell@linaro.org
CC: shannon.zhaosl@gmail.com
CC: qemu-arm@nongnu.org
---
 include/hw/acpi/acpi-defs.h | 32 -----------------
 hw/arm/virt-acpi-build.c    | 68 ++++++++++++++++++++++---------------
 2 files changed, 41 insertions(+), 59 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 6f2f08a9de..012c4ffb3a 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -117,38 +117,6 @@ typedef struct AcpiFadtData {
 #define ACPI_FADT_ARM_PSCI_COMPLIANT  (1 << 0)
 #define ACPI_FADT_ARM_PSCI_USE_HVC    (1 << 1)
 
-/*
- * Serial Port Console Redirection Table (SPCR), Rev. 1.02
- *
- * For .interface_type see Debug Port Table 2 (DBG2) serial port
- * subtypes in Table 3, Rev. May 22, 2012
- */
-struct AcpiSerialPortConsoleRedirection {
-    ACPI_TABLE_HEADER_DEF
-    uint8_t  interface_type;
-    uint8_t  reserved1[3];
-    struct AcpiGenericAddress base_address;
-    uint8_t  interrupt_types;
-    uint8_t  irq;
-    uint32_t gsi;
-    uint8_t  baud;
-    uint8_t  parity;
-    uint8_t  stopbits;
-    uint8_t  flowctrl;
-    uint8_t  term_type;
-    uint8_t  reserved2;
-    uint16_t pci_device_id;
-    uint16_t pci_vendor_id;
-    uint8_t  pci_bus;
-    uint8_t  pci_slot;
-    uint8_t  pci_func;
-    uint32_t pci_flags;
-    uint8_t  pci_seg;
-    uint32_t reserved3;
-} QEMU_PACKED;
-typedef struct AcpiSerialPortConsoleRedirection
-               AcpiSerialPortConsoleRedirection;
-
 /*
  * ACPI 1.0 Firmware ACPI Control Structure (FACS)
  */
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index a07540affb..e8553dcae5 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -349,39 +349,53 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     acpi_table_composed(linker, &table);
 }
 
+/*
+ * Serial Port Console Redirection Table (SPCR)
+ * Rev: 1.07
+ */
 static void
 build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
-    AcpiSerialPortConsoleRedirection *spcr;
-    const MemMapEntry *uart_memmap = &vms->memmap[VIRT_UART];
-    int irq = vms->irqmap[VIRT_UART] + ARM_SPI_BASE;
-    int spcr_start = table_data->len;
-
-    spcr = acpi_data_push(table_data, sizeof(*spcr));
-
-    spcr->interface_type = 0x3;    /* ARM PL011 UART */
-
-    spcr->base_address.space_id = AML_AS_SYSTEM_MEMORY;
-    spcr->base_address.bit_width = 8;
-    spcr->base_address.bit_offset = 0;
-    spcr->base_address.access_width = 1;
-    spcr->base_address.address = cpu_to_le64(uart_memmap->base);
-
-    spcr->interrupt_types = (1 << 3); /* Bit[3] ARMH GIC interrupt */
-    spcr->gsi = cpu_to_le32(irq);  /* Global System Interrupt */
+    AcpiTable table = { .sig = "SPCR", .rev = 2, .oem_id = vms->oem_id,
+                        .oem_table_id = vms->oem_table_id };
 
-    spcr->baud = 3;                /* Baud Rate: 3 = 9600 */
-    spcr->parity = 0;              /* No Parity */
-    spcr->stopbits = 1;            /* 1 Stop bit */
-    spcr->flowctrl = (1 << 1);     /* Bit[1] = RTS/CTS hardware flow control */
-    spcr->term_type = 0;           /* Terminal Type: 0 = VT100 */
+    acpi_init_table(&table, table_data);
 
-    spcr->pci_device_id = 0xffff;  /* PCI Device ID: not a PCI device */
-    spcr->pci_vendor_id = 0xffff;  /* PCI Vendor ID: not a PCI device */
+    /* Interface Type */
+    build_append_int_noprefix(table_data, 3, 1); /* ARM PL011 UART */
+    build_append_int_noprefix(table_data, 0, 3); /* Reserved */
+    /* Base Address */
+    build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 8, 0, 1,
+                     vms->memmap[VIRT_UART].base);
+    /* Interrupt Type */
+    build_append_int_noprefix(table_data,
+        (1 << 3) /* Bit[3] ARMH GIC interrupt */, 1);
+    build_append_int_noprefix(table_data, 0, 1); /* IRQ */
+    /* Global System Interrupt */
+    build_append_int_noprefix(table_data,
+                              vms->irqmap[VIRT_UART] + ARM_SPI_BASE, 4);
+    build_append_int_noprefix(table_data, 3 /* 9600 */, 1); /* Baud Rate */
+    build_append_int_noprefix(table_data, 0 /* No Parity */, 1); /* Parity */
+    /* Stop Bits */
+    build_append_int_noprefix(table_data, 1 /* 1 Stop bit */, 1);
+    /* Flow Control */
+    build_append_int_noprefix(table_data,
+        (1 << 1) /* RTS/CTS hardware flow control */, 1);
+    /* Terminal Type */
+    build_append_int_noprefix(table_data, 0 /* VT100 */, 1);
+    build_append_int_noprefix(table_data, 0, 1); /* Language */
+    /* PCI Device ID  */
+    build_append_int_noprefix(table_data, 0xffff /* not a PCI device*/, 2);
+    /* PCI Vendor ID */
+    build_append_int_noprefix(table_data, 0xffff /* not a PCI device*/, 2);
+    build_append_int_noprefix(table_data, 0, 1); /* PCI Bus Number */
+    build_append_int_noprefix(table_data, 0, 1); /* PCI Device Number */
+    build_append_int_noprefix(table_data, 0, 1); /* PCI Function Number */
+    build_append_int_noprefix(table_data, 0, 4); /* PCI Flags */
+    build_append_int_noprefix(table_data, 0, 1); /* PCI Segment */
+    build_append_int_noprefix(table_data, 0, 4); /* Reserved */
 
-    build_header(linker, table_data, (void *)(table_data->data + spcr_start),
-                 "SPCR", table_data->len - spcr_start, 2, vms->oem_id,
-                 vms->oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 
 /*
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 32/35] acpi: arm/virt: build_gtdt: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (30 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 31/35] acpi: arm/virt: build_spcr: use acpi_init_table()/acpi_table_composed() instead of build_header() Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-09-02 16:07   ` Eric Auger
  2021-07-08 15:46 ` [PATCH v2 33/35] acpi: build_facs: use build_append_int_noprefix() API to compose table Igor Mammedov
                   ` (3 subsequent siblings)
  35 siblings, 1 reply; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, drjones, shannon.zhaosl, qemu-arm, mst

it replaces error-prone pointer arithmetic for build_header() API,
with 2 calls to start and finish table creation,
which hides offsets magic from API user.

while at it, replace packed structure with endian agnostic
build_append_FOO() API.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: drjones@redhat.com
CC: peter.maydell@linaro.org
CC: shannon.zhaosl@gmail.com
CC: qemu-arm@nongnu.org
---
 include/hw/acpi/acpi-defs.h | 25 -------------
 hw/arm/virt-acpi-build.c    | 75 ++++++++++++++++++++++++-------------
 2 files changed, 48 insertions(+), 52 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 012c4ffb3a..0b375e7589 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -131,29 +131,4 @@ struct AcpiFacsDescriptorRev1 {
 } QEMU_PACKED;
 typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
 
-/*
- * Generic Timer Description Table (GTDT)
- */
-#define ACPI_GTDT_INTERRUPT_MODE_LEVEL    (0 << 0)
-#define ACPI_GTDT_INTERRUPT_MODE_EDGE     (1 << 0)
-#define ACPI_GTDT_CAP_ALWAYS_ON           (1 << 2)
-
-struct AcpiGenericTimerTable {
-    ACPI_TABLE_HEADER_DEF
-    uint64_t counter_block_addresss;
-    uint32_t reserved;
-    uint32_t secure_el1_interrupt;
-    uint32_t secure_el1_flags;
-    uint32_t non_secure_el1_interrupt;
-    uint32_t non_secure_el1_flags;
-    uint32_t virtual_timer_interrupt;
-    uint32_t virtual_timer_flags;
-    uint32_t non_secure_el2_interrupt;
-    uint32_t non_secure_el2_flags;
-    uint64_t counter_read_block_address;
-    uint32_t platform_timer_count;
-    uint32_t platform_timer_offset;
-} QEMU_PACKED;
-typedef struct AcpiGenericTimerTable AcpiGenericTimerTable;
-
 #endif
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index e8553dcae5..8f28e82760 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -455,40 +455,61 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
     acpi_table_composed(linker, &table);
 }
 
-/* GTDT */
+/*
+ * ACPI spec, Revision 5.1
+ * 5.2.24 Generic Timer Description Table (GTDT)
+ */
 static void
 build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
 {
     VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
-    int gtdt_start = table_data->len;
-    AcpiGenericTimerTable *gtdt;
-    uint32_t irqflags;
-
-    if (vmc->claim_edge_triggered_timers) {
-        irqflags = ACPI_GTDT_INTERRUPT_MODE_EDGE;
-    } else {
-        irqflags = ACPI_GTDT_INTERRUPT_MODE_LEVEL;
-    }
-
-    gtdt = acpi_data_push(table_data, sizeof *gtdt);
-    /* The interrupt values are the same with the device tree when adding 16 */
-    gtdt->secure_el1_interrupt = cpu_to_le32(ARCH_TIMER_S_EL1_IRQ + 16);
-    gtdt->secure_el1_flags = cpu_to_le32(irqflags);
-
-    gtdt->non_secure_el1_interrupt = cpu_to_le32(ARCH_TIMER_NS_EL1_IRQ + 16);
-    gtdt->non_secure_el1_flags = cpu_to_le32(irqflags |
-                                             ACPI_GTDT_CAP_ALWAYS_ON);
+    /*
+     * Table 5-117 Flag Definitions
+     * set only "Timer interrupt Mode" and assume "Timer Interrupt
+     * polarity" bit as '0: Interrupt is Active high'
+     */
+    uint32_t irqflags = vmc->claim_edge_triggered_timers ?
+        1 : /* Interrupt is Edge triggered */
+        0;  /* Interrupt is Level triggered  */
+    AcpiTable table = { .sig = "GTDT", .rev = 2, .oem_id = vms->oem_id,
+                        .oem_table_id = vms->oem_table_id };
 
-    gtdt->virtual_timer_interrupt = cpu_to_le32(ARCH_TIMER_VIRT_IRQ + 16);
-    gtdt->virtual_timer_flags = cpu_to_le32(irqflags);
+    acpi_init_table(&table, table_data);
 
-    gtdt->non_secure_el2_interrupt = cpu_to_le32(ARCH_TIMER_NS_EL2_IRQ + 16);
-    gtdt->non_secure_el2_flags = cpu_to_le32(irqflags);
+    /* CntControlBase Physical Address */
+    /* FIXME: invalid value, should be 0xFFFFFFFFFFFFFFFF if not impl. ? */
+    build_append_int_noprefix(table_data, 0, 8);
+    build_append_int_noprefix(table_data, 0, 4); /* Reserved */
+    /*
+     * FIXME: clarify comment:
+     * The interrupt values are the same with the device tree when adding 16
+     */
+    /* Secure EL1 timer GSIV */
+    build_append_int_noprefix(table_data, ARCH_TIMER_S_EL1_IRQ + 16, 4);
+    /* Secure EL1 timer Flags */
+    build_append_int_noprefix(table_data, irqflags, 4);
+    /* Non-Secure EL1 timer GSIV */
+    build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL1_IRQ + 16, 4);
+    /* Non-Secure EL1 timer Flags */
+    build_append_int_noprefix(table_data, irqflags |
+                              1UL << 2, /* Always-on Capability */
+                              4);
+    /* Virtual timer GSIV */
+    build_append_int_noprefix(table_data, ARCH_TIMER_VIRT_IRQ + 16, 4);
+    /* Virtual Timer Flags */
+    build_append_int_noprefix(table_data, irqflags, 4);
+    /* Non-Secure EL2 timer GSIV */
+    build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_IRQ + 16, 4);
+    /* Non-Secure EL2 timer Flags */
+    build_append_int_noprefix(table_data, irqflags, 4);
+    /* CntReadBase Physical address */
+    build_append_int_noprefix(table_data, 0, 8);
+    /* Platform Timer Count */
+    build_append_int_noprefix(table_data, 0, 4);
+    /* Platform Timer Offset */
+    build_append_int_noprefix(table_data, 0, 4);
 
-    build_header(linker, table_data,
-                 (void *)(table_data->data + gtdt_start), "GTDT",
-                 table_data->len - gtdt_start, 2, vms->oem_id,
-                 vms->oem_table_id);
+    acpi_table_composed(linker, &table);
 }
 
 /*
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 33/35] acpi: build_facs: use build_append_int_noprefix() API to compose table
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (31 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 32/35] acpi: arm/virt: build_gtdt: " Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-07-08 15:46 ` [PATCH v2 34/35] acpi: remove no longer used build_header() Igor Mammedov
                   ` (2 subsequent siblings)
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

Drop usage of packed structures and explicit endian
conversions when building table and use endian agnostic
build_append_int_noprefix() API to build it.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
CC: marcel.apfelbaum@gmail.com
---
 include/hw/acpi/acpi-defs.h | 14 --------------
 include/hw/acpi/aml-build.h |  1 +
 hw/acpi/aml-build.c         |  2 +-
 hw/i386/acpi-build.c        | 18 ++++++++++++++----
 4 files changed, 16 insertions(+), 19 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 0b375e7589..1a0774edd6 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -117,18 +117,4 @@ typedef struct AcpiFadtData {
 #define ACPI_FADT_ARM_PSCI_COMPLIANT  (1 << 0)
 #define ACPI_FADT_ARM_PSCI_USE_HVC    (1 << 1)
 
-/*
- * ACPI 1.0 Firmware ACPI Control Structure (FACS)
- */
-struct AcpiFacsDescriptorRev1 {
-    uint32_t signature;           /* ACPI Signature */
-    uint32_t length;                 /* Length of structure, in bytes */
-    uint32_t hardware_signature;     /* Hardware configuration signature */
-    uint32_t firmware_waking_vector; /* ACPI OS waking vector */
-    uint32_t global_lock;            /* Global Lock */
-    uint32_t flags;
-    uint8_t  resverved3 [40];        /* Reserved - must be zero */
-} QEMU_PACKED;
-typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
-
 #endif
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index dcb7ce11a8..de7d50a5a0 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -413,6 +413,7 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
 Aml *aml_object_type(Aml *object);
 
 void build_append_int_noprefix(GArray *table, uint64_t value, int size);
+void build_append_byte(GArray *array, uint8_t val);
 
 typedef struct AcpiTable {
     const char *sig;
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 8427713ee3..91c30c32fc 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -47,7 +47,7 @@ static void build_prepend_byte(GArray *array, uint8_t val)
     g_array_prepend_val(array, val);
 }
 
-static void build_append_byte(GArray *array, uint8_t val)
+void build_append_byte(GArray *array, uint8_t val)
 {
     g_array_append_val(array, val);
 }
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index e655d93bad..d6077a2127 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -346,13 +346,23 @@ static void acpi_align_size(GArray *blob, unsigned align)
     g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
 }
 
-/* FACS */
+/*
+ * ACPI spec 1.0b,
+ * 5.2.6 Firmware ACPI Control Structure
+ */
 static void
 build_facs(GArray *table_data)
 {
-    AcpiFacsDescriptorRev1 *facs = acpi_data_push(table_data, sizeof *facs);
-    memcpy(&facs->signature, "FACS", 4);
-    facs->length = cpu_to_le32(sizeof(*facs));
+    const char *sig = "FACS";
+    const uint8_t reserved[40] = {};
+
+    g_array_append_vals(table_data, sig, 4); /* Signature */
+    build_append_int_noprefix(table_data, 64, 4); /* Length */
+    build_append_int_noprefix(table_data, 0, 4); /* Hardware Signature */
+    build_append_int_noprefix(table_data, 0, 4); /* Firmware Waking Vector */
+    build_append_int_noprefix(table_data, 0, 4); /* Global Lock */
+    build_append_int_noprefix(table_data, 0, 4); /* Flags */
+    g_array_append_vals(table_data, reserved, 40); /* Reserved */
 }
 
 static void build_append_pcihp_notify_entry(Aml *method, int slot)
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 34/35] acpi: remove no longer used build_header()
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (32 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 33/35] acpi: build_facs: use build_append_int_noprefix() API to compose table Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-07-08 15:46 ` [PATCH v2 35/35] acpi: AcpiGenericAddress no longer used to map/access fields of MMIO, drop packed attribute Igor Mammedov
  2021-07-13 15:45 ` [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Michael S. Tsirkin
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 include/hw/acpi/acpi-defs.h | 25 -------------------------
 include/hw/acpi/aml-build.h |  4 ----
 hw/acpi/aml-build.c         | 23 -----------------------
 3 files changed, 52 deletions(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index 1a0774edd6..ee733840aa 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -48,31 +48,6 @@ typedef struct AcpiRsdpData {
     unsigned *xsdt_tbl_offset;
 } AcpiRsdpData;
 
-/* Table structure from Linux kernel (the ACPI tables are under the
-   BSD license) */
-
-
-#define ACPI_TABLE_HEADER_DEF   /* ACPI common table header */ \
-    uint32_t signature;          /* ACPI signature (4 ASCII characters) */ \
-    uint32_t length;                 /* Length of table, in bytes, including header */ \
-    uint8_t  revision;               /* ACPI Specification minor version # */ \
-    uint8_t  checksum;               /* To make sum of entire table == 0 */ \
-    uint8_t  oem_id[6] \
-                 QEMU_NONSTRING;     /* OEM identification */ \
-    uint8_t  oem_table_id[8] \
-                 QEMU_NONSTRING;     /* OEM table identification */ \
-    uint32_t oem_revision;           /* OEM revision number */ \
-    uint8_t  asl_compiler_id[4] \
-                 QEMU_NONSTRING;     /* ASL compiler vendor ID */ \
-    uint32_t asl_compiler_revision;  /* ASL compiler revision number */
-
-
-/* ACPI common table header */
-struct AcpiTableHeader {
-    ACPI_TABLE_HEADER_DEF
-} QEMU_PACKED;
-typedef struct AcpiTableHeader AcpiTableHeader;
-
 struct AcpiGenericAddress {
     uint8_t space_id;        /* Address space where struct or register exists */
     uint8_t bit_width;       /* Size in bits of given register */
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index de7d50a5a0..c53e4b2988 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -428,10 +428,6 @@ typedef struct AcpiTable {
 void acpi_init_table(AcpiTable *desc, GArray *array);
 void acpi_table_composed(BIOSLinker *linker, AcpiTable *table);
 
-void
-build_header(BIOSLinker *linker, GArray *table_data,
-             AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
-             const char *oem_id, const char *oem_table_id);
 void *acpi_data_push(GArray *table_data, unsigned size);
 unsigned acpi_data_len(GArray *table);
 void acpi_add_table(GArray *table_offsets, GArray *table_data);
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 91c30c32fc..3aec332790 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1750,29 +1750,6 @@ void acpi_table_composed(BIOSLinker *linker, AcpiTable *desc)
         desc->table_offset, table_len, desc->table_offset + checksum_offset);
 }
 
-void
-build_header(BIOSLinker *linker, GArray *table_data,
-             AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
-             const char *oem_id, const char *oem_table_id)
-{
-    unsigned tbl_offset = (char *)h - table_data->data;
-    unsigned checksum_offset = (char *)&h->checksum - table_data->data;
-    memcpy(&h->signature, sig, 4);
-    h->length = cpu_to_le32(len);
-    h->revision = rev;
-
-    strpadcpy((char *)h->oem_id, sizeof h->oem_id, oem_id, ' ');
-    strpadcpy((char *)h->oem_table_id, sizeof h->oem_table_id,
-              oem_table_id, ' ');
-
-    h->oem_revision = cpu_to_le32(1);
-    memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME8, 4);
-    h->asl_compiler_revision = cpu_to_le32(1);
-    /* Checksum to be filled in by Guest linker */
-    bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
-        tbl_offset, len, checksum_offset);
-}
-
 void *acpi_data_push(GArray *table_data, unsigned size)
 {
     unsigned off = table_data->len;
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* [PATCH v2 35/35] acpi: AcpiGenericAddress no longer used to map/access fields of MMIO, drop packed attribute
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (33 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 34/35] acpi: remove no longer used build_header() Igor Mammedov
@ 2021-07-08 15:46 ` Igor Mammedov
  2021-07-13 15:45 ` [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Michael S. Tsirkin
  35 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-08 15:46 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 include/hw/acpi/acpi-defs.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
index ee733840aa..c97e8633ad 100644
--- a/include/hw/acpi/acpi-defs.h
+++ b/include/hw/acpi/acpi-defs.h
@@ -55,7 +55,7 @@ struct AcpiGenericAddress {
     uint8_t access_width;    /* ACPI 3.0: Minimum Access size (ACPI 3.0),
                                 ACPI 2.0: Reserved, Table 5-1 */
     uint64_t address;        /* 64-bit address of struct or register */
-} QEMU_PACKED;
+};
 
 typedef struct AcpiFadtData {
     struct AcpiGenericAddress pm1a_cnt;   /* PM1a_CNT_BLK */
-- 
2.27.0



^ permalink raw reply related	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 29/35] acpi: arm/virt: convert build_iort() to endian agnostic build_append_FOO() API
  2021-07-08 15:46 ` [PATCH v2 29/35] acpi: arm/virt: convert build_iort() to endian agnostic build_append_FOO() API Igor Mammedov
@ 2021-07-09  7:11   ` Michael S. Tsirkin
  2021-07-09  8:59     ` Igor Mammedov
  0 siblings, 1 reply; 56+ messages in thread
From: Michael S. Tsirkin @ 2021-07-09  7:11 UTC (permalink / raw)
  To: Igor Mammedov
  Cc: peter.maydell, drjones, qemu-arm, qemu-devel, shannon.zhaosl

On Thu, Jul 08, 2021 at 11:46:11AM -0400, Igor Mammedov wrote:
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>

BTW is this actually a bugfix? Worth adding a Fixes tag maybe.

> ---
> CC: drjones@redhat.com
> CC: peter.maydell@linaro.org
> CC: shannon.zhaosl@gmail.com
> CC: qemu-arm@nongnu.org

I think these get dropped on git-am then not sure this is what you wanted.

> ---
>  include/hw/acpi/acpi-defs.h |  71 ------------------
>  hw/arm/virt-acpi-build.c    | 143 +++++++++++++++++++-----------------
>  2 files changed, 77 insertions(+), 137 deletions(-)
> 
> diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
> index 195f90caf6..6f2f08a9de 100644
> --- a/include/hw/acpi/acpi-defs.h
> +++ b/include/hw/acpi/acpi-defs.h
> @@ -188,75 +188,4 @@ struct AcpiGenericTimerTable {
>  } QEMU_PACKED;
>  typedef struct AcpiGenericTimerTable AcpiGenericTimerTable;
>  
> -/*
> - * IORT node types
> - */
> -
> -#define ACPI_IORT_NODE_HEADER_DEF   /* Node format common fields */ \
> -    uint8_t  type;          \
> -    uint16_t length;        \
> -    uint8_t  revision;      \
> -    uint32_t reserved;      \
> -    uint32_t mapping_count; \
> -    uint32_t mapping_offset;
> -
> -/* Values for node Type above */
> -enum {
> -        ACPI_IORT_NODE_ITS_GROUP = 0x00,
> -        ACPI_IORT_NODE_NAMED_COMPONENT = 0x01,
> -        ACPI_IORT_NODE_PCI_ROOT_COMPLEX = 0x02,
> -        ACPI_IORT_NODE_SMMU = 0x03,
> -        ACPI_IORT_NODE_SMMU_V3 = 0x04
> -};
> -
> -struct AcpiIortIdMapping {
> -    uint32_t input_base;
> -    uint32_t id_count;
> -    uint32_t output_base;
> -    uint32_t output_reference;
> -    uint32_t flags;
> -} QEMU_PACKED;
> -typedef struct AcpiIortIdMapping AcpiIortIdMapping;
> -
> -struct AcpiIortMemoryAccess {
> -    uint32_t cache_coherency;
> -    uint8_t  hints;
> -    uint16_t reserved;
> -    uint8_t  memory_flags;
> -} QEMU_PACKED;
> -typedef struct AcpiIortMemoryAccess AcpiIortMemoryAccess;
> -
> -struct AcpiIortItsGroup {
> -    ACPI_IORT_NODE_HEADER_DEF
> -    uint32_t its_count;
> -    uint32_t identifiers[];
> -} QEMU_PACKED;
> -typedef struct AcpiIortItsGroup AcpiIortItsGroup;
> -
> -#define ACPI_IORT_SMMU_V3_COHACC_OVERRIDE 1
> -
> -struct AcpiIortSmmu3 {
> -    ACPI_IORT_NODE_HEADER_DEF
> -    uint64_t base_address;
> -    uint32_t flags;
> -    uint32_t reserved2;
> -    uint64_t vatos_address;
> -    uint32_t model;
> -    uint32_t event_gsiv;
> -    uint32_t pri_gsiv;
> -    uint32_t gerr_gsiv;
> -    uint32_t sync_gsiv;
> -    AcpiIortIdMapping id_mapping_array[];
> -} QEMU_PACKED;
> -typedef struct AcpiIortSmmu3 AcpiIortSmmu3;
> -
> -struct AcpiIortRC {
> -    ACPI_IORT_NODE_HEADER_DEF
> -    AcpiIortMemoryAccess memory_properties;
> -    uint32_t ats_attribute;
> -    uint32_t pci_segment_number;
> -    AcpiIortIdMapping id_mapping_array[];
> -} QEMU_PACKED;
> -typedef struct AcpiIortRC AcpiIortRC;
> -
>  #endif
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index ac5e07e43c..b88ea4b70a 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -239,6 +239,21 @@ static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms)
>  }
>  #endif
>  
> +#define ID_MAPPING_ENTRY_SIZE 20
> +#define SMMU_V3_ENTRY_SIZE 60
> +#define ROOT_COMPLEX_ENTRY_SIZE 32
> +#define IORT_NODE_OFFSET 48
> +
> +static void build_iort_id_mapping(GArray *table_data, uint32_t out_ref)
> +{
> +    /* Identity RID mapping covering the whole input RID range */
> +    build_append_int_noprefix(table_data, 0, 4); /* Input base */
> +    build_append_int_noprefix(table_data, 0xFFFF, 4); /* Number of IDs */
> +    build_append_int_noprefix(table_data, 0, 4); /* Output base */
> +    build_append_int_noprefix(table_data, out_ref, 4); /* Output Reference */
> +    build_append_int_noprefix(table_data, 0, 4); /* Flags */
> +}
> +
>  /*
>   * Input Output Remapping Table (IORT)
>   * Conforms to "IO Remapping Table System Software on ARM Platforms",
> @@ -247,92 +262,88 @@ static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms)
>  static void
>  build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>  {
> -    int nb_nodes;
> -    AcpiIortIdMapping *idmap;
> -    AcpiIortItsGroup *its;
> -    AcpiIortSmmu3 *smmu;
> -    size_t node_size, iort_node_offset = 48, smmu_offset = 0;
> -    AcpiIortRC *rc;
> +    size_t node_size, smmu_offset = 0;
>      AcpiTable table = { .sig = "IORT", .rev = 0, .oem_id = vms->oem_id,
>                          .oem_table_id = vms->oem_table_id };
>  
> -    if (vms->iommu == VIRT_IOMMU_SMMUV3) {
> -        nb_nodes = 3; /* RC, ITS, SMMUv3 */
> -    } else {
> -        nb_nodes = 2; /* RC, ITS */
> -    }
> -
>      /* Table 2 The IORT */
>      acpi_init_table(&table, table_data);
>      /* Number of IORT Nodes */
> -    build_append_int_noprefix(table_data, nb_nodes, 4);
> +    if (vms->iommu == VIRT_IOMMU_SMMUV3) {
> +        build_append_int_noprefix(table_data, 3 /* RC, ITS, SMMUv3 */, 4);
> +    } else {
> +        build_append_int_noprefix(table_data, 2 /* RC, ITS */, 4);
> +    }
>      /* Offset to Array of IORT Nodes */
> -    build_append_int_noprefix(table_data, iort_node_offset, 4);
> +    build_append_int_noprefix(table_data, IORT_NODE_OFFSET, 4);
>      build_append_int_noprefix(table_data, 0, 4); /* Reserved */
>  
> -    /* ITS group node */
> -    node_size =  sizeof(*its) + sizeof(uint32_t);
> -    its = acpi_data_push(table_data, node_size);
> -
> -    its->type = ACPI_IORT_NODE_ITS_GROUP;
> -    its->length = cpu_to_le16(node_size);
> -    its->its_count = cpu_to_le32(1);
> -    its->identifiers[0] = 0; /* MADT translation_id */
> +    /* 3.1.1.3 ITS group node */
> +    build_append_int_noprefix(table_data, 0 /* ITS Group */, 1); /* Type */
> +    node_size =  20 /* fixed header size */ + 4 /* 1 GIC ITS Identifier */;
> +    build_append_int_noprefix(table_data, node_size, 2); /* Length */
> +    build_append_int_noprefix(table_data, 0, 1); /* Revision */
> +    build_append_int_noprefix(table_data, 0, 4); /* Reserved */
> +    build_append_int_noprefix(table_data, 0, 4); /* Number of ID mappings */
> +    build_append_int_noprefix(table_data, 0, 4); /* Reference to ID Array */
> +    build_append_int_noprefix(table_data, 1, 4); /* Number of ITSs */
> +    /* GIC ITS Identifier Array */
> +    build_append_int_noprefix(table_data, 0 /* MADT translation_id */, 4);
>  
>      if (vms->iommu == VIRT_IOMMU_SMMUV3) {
>          int irq =  vms->irqmap[VIRT_SMMU] + ARM_SPI_BASE;
>  
> -        /* SMMUv3 node */
> -        smmu_offset = iort_node_offset + node_size;
> -        node_size = sizeof(*smmu) + sizeof(*idmap);
> -        smmu = acpi_data_push(table_data, node_size);
> -
> -        smmu->type = ACPI_IORT_NODE_SMMU_V3;
> -        smmu->length = cpu_to_le16(node_size);
> -        smmu->mapping_count = cpu_to_le32(1);
> -        smmu->mapping_offset = cpu_to_le32(sizeof(*smmu));
> -        smmu->base_address = cpu_to_le64(vms->memmap[VIRT_SMMU].base);
> -        smmu->flags = cpu_to_le32(ACPI_IORT_SMMU_V3_COHACC_OVERRIDE);
> -        smmu->event_gsiv = cpu_to_le32(irq);
> -        smmu->pri_gsiv = cpu_to_le32(irq + 1);
> -        smmu->sync_gsiv = cpu_to_le32(irq + 2);
> -        smmu->gerr_gsiv = cpu_to_le32(irq + 3);
> -
> -        /* Identity RID mapping covering the whole input RID range */
> -        idmap = &smmu->id_mapping_array[0];
> -        idmap->input_base = 0;
> -        idmap->id_count = cpu_to_le32(0xFFFF);
> -        idmap->output_base = 0;
> -        /* output IORT node is the ITS group node (the first node) */
> -        idmap->output_reference = cpu_to_le32(iort_node_offset);
> +        smmu_offset = table_data->len - table.table_offset;
> +        /* 3.1.1.2 SMMUv3 */
> +        build_append_int_noprefix(table_data, 4 /* SMMUv3 */, 1); /* Type */
> +        node_size =  SMMU_V3_ENTRY_SIZE + ID_MAPPING_ENTRY_SIZE;
> +        build_append_int_noprefix(table_data, node_size, 2); /* Length */
> +        build_append_int_noprefix(table_data, 0, 1); /* Revision */
> +        build_append_int_noprefix(table_data, 0, 4); /* Reserved */
> +        build_append_int_noprefix(table_data, 1, 4); /* Number of ID mappings */
> +        /* Reference to ID Array */
> +        build_append_int_noprefix(table_data, SMMU_V3_ENTRY_SIZE, 4);
> +        /* Base address */
> +        build_append_int_noprefix(table_data, vms->memmap[VIRT_SMMU].base, 8);
> +        /* Flags */
> +        build_append_int_noprefix(table_data, 1 /* COHACC OverrideNote */, 4);
> +        build_append_int_noprefix(table_data, 0, 4); /* Reserved */
> +        build_append_int_noprefix(table_data, 0, 8); /* VATOS address */
> +        /* Model */
> +        build_append_int_noprefix(table_data, 0 /* Generic SMMU-v3 */, 4);
> +        build_append_int_noprefix(table_data, irq, 4); /* Event */
> +        build_append_int_noprefix(table_data, irq + 1, 4); /* PRI */
> +        build_append_int_noprefix(table_data, irq + 3, 4); /* GERR */
> +        build_append_int_noprefix(table_data, irq + 2, 4); /* Sync */
> +
> +        build_iort_id_mapping(table_data, IORT_NODE_OFFSET);
>      }
>  
> -    /* Root Complex Node */
> -    node_size = sizeof(*rc) + sizeof(*idmap);
> -    rc = acpi_data_push(table_data, node_size);
> -
> -    rc->type = ACPI_IORT_NODE_PCI_ROOT_COMPLEX;
> -    rc->length = cpu_to_le16(node_size);
> -    rc->mapping_count = cpu_to_le32(1);
> -    rc->mapping_offset = cpu_to_le32(sizeof(*rc));
> -
> +    /* Table 16 Root Complex Node */
> +    build_append_int_noprefix(table_data, 2 /* Root complex */, 1); /* Type */
> +    node_size =  ROOT_COMPLEX_ENTRY_SIZE + ID_MAPPING_ENTRY_SIZE;
> +    build_append_int_noprefix(table_data, node_size, 2); /* Length */
> +    build_append_int_noprefix(table_data, 0, 1); /* Revision */
> +    build_append_int_noprefix(table_data, 0, 4); /* Reserved */
> +    build_append_int_noprefix(table_data, 1, 4); /* Number of ID mappings */
> +    /* Reference to ID Array */
> +    build_append_int_noprefix(table_data, ROOT_COMPLEX_ENTRY_SIZE, 4);
>      /* fully coherent device */
> -    rc->memory_properties.cache_coherency = cpu_to_le32(1);
> -    rc->memory_properties.memory_flags = 0x3; /* CCA = CPM = DCAS = 1 */
> -    rc->pci_segment_number = 0; /* MCFG pci_segment */
> -
> -    /* Identity RID mapping covering the whole input RID range */
> -    idmap = &rc->id_mapping_array[0];
> -    idmap->input_base = 0;
> -    idmap->id_count = cpu_to_le32(0xFFFF);
> -    idmap->output_base = 0;
> -
> +    build_append_int_noprefix(table_data,
> +        1 | /* CCA: Cache Coherent Attribute, The device is fully coherent */
> +        (3ULL << 7 * 8) /* MAF: Memory Access Flags, CCA = CPM = DCAS = 1 */,
> +        8);
> +    build_append_int_noprefix(table_data, 0, 4); /* ATS Attribute */
> +    /* MCFG pci_segment */
> +    build_append_int_noprefix(table_data, 0, 4); /* PCI Segment number */
> +
> +    /* Output Reference */
>      if (vms->iommu == VIRT_IOMMU_SMMUV3) {
>          /* output IORT node is the smmuv3 node */
> -        idmap->output_reference = cpu_to_le32(smmu_offset);
> +        build_iort_id_mapping(table_data, smmu_offset);
>      } else {
>          /* output IORT node is the ITS group node (the first node) */
> -        idmap->output_reference = cpu_to_le32(iort_node_offset);
> +        build_iort_id_mapping(table_data, IORT_NODE_OFFSET);
>      }
>  
>      acpi_table_composed(linker, &table);
> -- 
> 2.27.0



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 29/35] acpi: arm/virt: convert build_iort() to endian agnostic build_append_FOO() API
  2021-07-09  7:11   ` Michael S. Tsirkin
@ 2021-07-09  8:59     ` Igor Mammedov
  0 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-07-09  8:59 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: peter.maydell, drjones, qemu-arm, qemu-devel, shannon.zhaosl

On Fri, 9 Jul 2021 03:11:52 -0400
"Michael S. Tsirkin" <mst@redhat.com> wrote:

> On Thu, Jul 08, 2021 at 11:46:11AM -0400, Igor Mammedov wrote:
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>  
> 
> BTW is this actually a bugfix? Worth adding a Fixes tag maybe.
I don't think I've made any fixes in this patch, maybe you are
talking the next patch [30/35]?

As for 30/35 it's not visible bugfix since both values were
the same, that's probably why I haven't added any tags
as tags would be pretty much useless there.

When I stumbled on a bug during refactoring, I've tried
to fix it in separate a patch or added TODO/FIXME comment,
since that is not relevant to refactoring itself.

> 
> > ---
> > CC: drjones@redhat.com
> > CC: peter.maydell@linaro.org
> > CC: shannon.zhaosl@gmail.com
> > CC: qemu-arm@nongnu.org  
> 
> I think these get dropped on git-am then not sure this is what you wanted.
That was intention, to make git-send-email CC [at patch granularity]
relevant people for review and drop CC list when patch is applied.


> > ---
> >  include/hw/acpi/acpi-defs.h |  71 ------------------
> >  hw/arm/virt-acpi-build.c    | 143 +++++++++++++++++++-----------------
> >  2 files changed, 77 insertions(+), 137 deletions(-)
> > 
> > diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
> > index 195f90caf6..6f2f08a9de 100644
> > --- a/include/hw/acpi/acpi-defs.h
> > +++ b/include/hw/acpi/acpi-defs.h
> > @@ -188,75 +188,4 @@ struct AcpiGenericTimerTable {
> >  } QEMU_PACKED;
> >  typedef struct AcpiGenericTimerTable AcpiGenericTimerTable;
> >  
> > -/*
> > - * IORT node types
> > - */
> > -
> > -#define ACPI_IORT_NODE_HEADER_DEF   /* Node format common fields */ \
> > -    uint8_t  type;          \
> > -    uint16_t length;        \
> > -    uint8_t  revision;      \
> > -    uint32_t reserved;      \
> > -    uint32_t mapping_count; \
> > -    uint32_t mapping_offset;
> > -
> > -/* Values for node Type above */
> > -enum {
> > -        ACPI_IORT_NODE_ITS_GROUP = 0x00,
> > -        ACPI_IORT_NODE_NAMED_COMPONENT = 0x01,
> > -        ACPI_IORT_NODE_PCI_ROOT_COMPLEX = 0x02,
> > -        ACPI_IORT_NODE_SMMU = 0x03,
> > -        ACPI_IORT_NODE_SMMU_V3 = 0x04
> > -};
> > -
> > -struct AcpiIortIdMapping {
> > -    uint32_t input_base;
> > -    uint32_t id_count;
> > -    uint32_t output_base;
> > -    uint32_t output_reference;
> > -    uint32_t flags;
> > -} QEMU_PACKED;
> > -typedef struct AcpiIortIdMapping AcpiIortIdMapping;
> > -
> > -struct AcpiIortMemoryAccess {
> > -    uint32_t cache_coherency;
> > -    uint8_t  hints;
> > -    uint16_t reserved;
> > -    uint8_t  memory_flags;
> > -} QEMU_PACKED;
> > -typedef struct AcpiIortMemoryAccess AcpiIortMemoryAccess;
> > -
> > -struct AcpiIortItsGroup {
> > -    ACPI_IORT_NODE_HEADER_DEF
> > -    uint32_t its_count;
> > -    uint32_t identifiers[];
> > -} QEMU_PACKED;
> > -typedef struct AcpiIortItsGroup AcpiIortItsGroup;
> > -
> > -#define ACPI_IORT_SMMU_V3_COHACC_OVERRIDE 1
> > -
> > -struct AcpiIortSmmu3 {
> > -    ACPI_IORT_NODE_HEADER_DEF
> > -    uint64_t base_address;
> > -    uint32_t flags;
> > -    uint32_t reserved2;
> > -    uint64_t vatos_address;
> > -    uint32_t model;
> > -    uint32_t event_gsiv;
> > -    uint32_t pri_gsiv;
> > -    uint32_t gerr_gsiv;
> > -    uint32_t sync_gsiv;
> > -    AcpiIortIdMapping id_mapping_array[];
> > -} QEMU_PACKED;
> > -typedef struct AcpiIortSmmu3 AcpiIortSmmu3;
> > -
> > -struct AcpiIortRC {
> > -    ACPI_IORT_NODE_HEADER_DEF
> > -    AcpiIortMemoryAccess memory_properties;
> > -    uint32_t ats_attribute;
> > -    uint32_t pci_segment_number;
> > -    AcpiIortIdMapping id_mapping_array[];
> > -} QEMU_PACKED;
> > -typedef struct AcpiIortRC AcpiIortRC;
> > -
> >  #endif
> > diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> > index ac5e07e43c..b88ea4b70a 100644
> > --- a/hw/arm/virt-acpi-build.c
> > +++ b/hw/arm/virt-acpi-build.c
> > @@ -239,6 +239,21 @@ static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms)
> >  }
> >  #endif
> >  
> > +#define ID_MAPPING_ENTRY_SIZE 20
> > +#define SMMU_V3_ENTRY_SIZE 60
> > +#define ROOT_COMPLEX_ENTRY_SIZE 32
> > +#define IORT_NODE_OFFSET 48
> > +
> > +static void build_iort_id_mapping(GArray *table_data, uint32_t out_ref)
> > +{
> > +    /* Identity RID mapping covering the whole input RID range */
> > +    build_append_int_noprefix(table_data, 0, 4); /* Input base */
> > +    build_append_int_noprefix(table_data, 0xFFFF, 4); /* Number of IDs */
> > +    build_append_int_noprefix(table_data, 0, 4); /* Output base */
> > +    build_append_int_noprefix(table_data, out_ref, 4); /* Output Reference */
> > +    build_append_int_noprefix(table_data, 0, 4); /* Flags */
> > +}
> > +
> >  /*
> >   * Input Output Remapping Table (IORT)
> >   * Conforms to "IO Remapping Table System Software on ARM Platforms",
> > @@ -247,92 +262,88 @@ static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms)
> >  static void
> >  build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> >  {
> > -    int nb_nodes;
> > -    AcpiIortIdMapping *idmap;
> > -    AcpiIortItsGroup *its;
> > -    AcpiIortSmmu3 *smmu;
> > -    size_t node_size, iort_node_offset = 48, smmu_offset = 0;
> > -    AcpiIortRC *rc;
> > +    size_t node_size, smmu_offset = 0;
> >      AcpiTable table = { .sig = "IORT", .rev = 0, .oem_id = vms->oem_id,
> >                          .oem_table_id = vms->oem_table_id };
> >  
> > -    if (vms->iommu == VIRT_IOMMU_SMMUV3) {
> > -        nb_nodes = 3; /* RC, ITS, SMMUv3 */
> > -    } else {
> > -        nb_nodes = 2; /* RC, ITS */
> > -    }
> > -
> >      /* Table 2 The IORT */
> >      acpi_init_table(&table, table_data);
> >      /* Number of IORT Nodes */
> > -    build_append_int_noprefix(table_data, nb_nodes, 4);
> > +    if (vms->iommu == VIRT_IOMMU_SMMUV3) {
> > +        build_append_int_noprefix(table_data, 3 /* RC, ITS, SMMUv3 */, 4);
> > +    } else {
> > +        build_append_int_noprefix(table_data, 2 /* RC, ITS */, 4);
> > +    }
> >      /* Offset to Array of IORT Nodes */
> > -    build_append_int_noprefix(table_data, iort_node_offset, 4);
> > +    build_append_int_noprefix(table_data, IORT_NODE_OFFSET, 4);
> >      build_append_int_noprefix(table_data, 0, 4); /* Reserved */
> >  
> > -    /* ITS group node */
> > -    node_size =  sizeof(*its) + sizeof(uint32_t);
> > -    its = acpi_data_push(table_data, node_size);
> > -
> > -    its->type = ACPI_IORT_NODE_ITS_GROUP;
> > -    its->length = cpu_to_le16(node_size);
> > -    its->its_count = cpu_to_le32(1);
> > -    its->identifiers[0] = 0; /* MADT translation_id */
> > +    /* 3.1.1.3 ITS group node */
> > +    build_append_int_noprefix(table_data, 0 /* ITS Group */, 1); /* Type */
> > +    node_size =  20 /* fixed header size */ + 4 /* 1 GIC ITS Identifier */;
> > +    build_append_int_noprefix(table_data, node_size, 2); /* Length */
> > +    build_append_int_noprefix(table_data, 0, 1); /* Revision */
> > +    build_append_int_noprefix(table_data, 0, 4); /* Reserved */
> > +    build_append_int_noprefix(table_data, 0, 4); /* Number of ID mappings */
> > +    build_append_int_noprefix(table_data, 0, 4); /* Reference to ID Array */
> > +    build_append_int_noprefix(table_data, 1, 4); /* Number of ITSs */
> > +    /* GIC ITS Identifier Array */
> > +    build_append_int_noprefix(table_data, 0 /* MADT translation_id */, 4);
> >  
> >      if (vms->iommu == VIRT_IOMMU_SMMUV3) {
> >          int irq =  vms->irqmap[VIRT_SMMU] + ARM_SPI_BASE;
> >  
> > -        /* SMMUv3 node */
> > -        smmu_offset = iort_node_offset + node_size;
> > -        node_size = sizeof(*smmu) + sizeof(*idmap);
> > -        smmu = acpi_data_push(table_data, node_size);
> > -
> > -        smmu->type = ACPI_IORT_NODE_SMMU_V3;
> > -        smmu->length = cpu_to_le16(node_size);
> > -        smmu->mapping_count = cpu_to_le32(1);
> > -        smmu->mapping_offset = cpu_to_le32(sizeof(*smmu));
> > -        smmu->base_address = cpu_to_le64(vms->memmap[VIRT_SMMU].base);
> > -        smmu->flags = cpu_to_le32(ACPI_IORT_SMMU_V3_COHACC_OVERRIDE);
> > -        smmu->event_gsiv = cpu_to_le32(irq);
> > -        smmu->pri_gsiv = cpu_to_le32(irq + 1);
> > -        smmu->sync_gsiv = cpu_to_le32(irq + 2);
> > -        smmu->gerr_gsiv = cpu_to_le32(irq + 3);
> > -
> > -        /* Identity RID mapping covering the whole input RID range */
> > -        idmap = &smmu->id_mapping_array[0];
> > -        idmap->input_base = 0;
> > -        idmap->id_count = cpu_to_le32(0xFFFF);
> > -        idmap->output_base = 0;
> > -        /* output IORT node is the ITS group node (the first node) */
> > -        idmap->output_reference = cpu_to_le32(iort_node_offset);
> > +        smmu_offset = table_data->len - table.table_offset;
> > +        /* 3.1.1.2 SMMUv3 */
> > +        build_append_int_noprefix(table_data, 4 /* SMMUv3 */, 1); /* Type */
> > +        node_size =  SMMU_V3_ENTRY_SIZE + ID_MAPPING_ENTRY_SIZE;
> > +        build_append_int_noprefix(table_data, node_size, 2); /* Length */
> > +        build_append_int_noprefix(table_data, 0, 1); /* Revision */
> > +        build_append_int_noprefix(table_data, 0, 4); /* Reserved */
> > +        build_append_int_noprefix(table_data, 1, 4); /* Number of ID mappings */
> > +        /* Reference to ID Array */
> > +        build_append_int_noprefix(table_data, SMMU_V3_ENTRY_SIZE, 4);
> > +        /* Base address */
> > +        build_append_int_noprefix(table_data, vms->memmap[VIRT_SMMU].base, 8);
> > +        /* Flags */
> > +        build_append_int_noprefix(table_data, 1 /* COHACC OverrideNote */, 4);
> > +        build_append_int_noprefix(table_data, 0, 4); /* Reserved */
> > +        build_append_int_noprefix(table_data, 0, 8); /* VATOS address */
> > +        /* Model */
> > +        build_append_int_noprefix(table_data, 0 /* Generic SMMU-v3 */, 4);
> > +        build_append_int_noprefix(table_data, irq, 4); /* Event */
> > +        build_append_int_noprefix(table_data, irq + 1, 4); /* PRI */
> > +        build_append_int_noprefix(table_data, irq + 3, 4); /* GERR */
> > +        build_append_int_noprefix(table_data, irq + 2, 4); /* Sync */
> > +
> > +        build_iort_id_mapping(table_data, IORT_NODE_OFFSET);
> >      }
> >  
> > -    /* Root Complex Node */
> > -    node_size = sizeof(*rc) + sizeof(*idmap);
> > -    rc = acpi_data_push(table_data, node_size);
> > -
> > -    rc->type = ACPI_IORT_NODE_PCI_ROOT_COMPLEX;
> > -    rc->length = cpu_to_le16(node_size);
> > -    rc->mapping_count = cpu_to_le32(1);
> > -    rc->mapping_offset = cpu_to_le32(sizeof(*rc));
> > -
> > +    /* Table 16 Root Complex Node */
> > +    build_append_int_noprefix(table_data, 2 /* Root complex */, 1); /* Type */
> > +    node_size =  ROOT_COMPLEX_ENTRY_SIZE + ID_MAPPING_ENTRY_SIZE;
> > +    build_append_int_noprefix(table_data, node_size, 2); /* Length */
> > +    build_append_int_noprefix(table_data, 0, 1); /* Revision */
> > +    build_append_int_noprefix(table_data, 0, 4); /* Reserved */
> > +    build_append_int_noprefix(table_data, 1, 4); /* Number of ID mappings */
> > +    /* Reference to ID Array */
> > +    build_append_int_noprefix(table_data, ROOT_COMPLEX_ENTRY_SIZE, 4);
> >      /* fully coherent device */
> > -    rc->memory_properties.cache_coherency = cpu_to_le32(1);
> > -    rc->memory_properties.memory_flags = 0x3; /* CCA = CPM = DCAS = 1 */
> > -    rc->pci_segment_number = 0; /* MCFG pci_segment */
> > -
> > -    /* Identity RID mapping covering the whole input RID range */
> > -    idmap = &rc->id_mapping_array[0];
> > -    idmap->input_base = 0;
> > -    idmap->id_count = cpu_to_le32(0xFFFF);
> > -    idmap->output_base = 0;
> > -
> > +    build_append_int_noprefix(table_data,
> > +        1 | /* CCA: Cache Coherent Attribute, The device is fully coherent */
> > +        (3ULL << 7 * 8) /* MAF: Memory Access Flags, CCA = CPM = DCAS = 1 */,
> > +        8);
> > +    build_append_int_noprefix(table_data, 0, 4); /* ATS Attribute */
> > +    /* MCFG pci_segment */
> > +    build_append_int_noprefix(table_data, 0, 4); /* PCI Segment number */
> > +
> > +    /* Output Reference */
> >      if (vms->iommu == VIRT_IOMMU_SMMUV3) {
> >          /* output IORT node is the smmuv3 node */
> > -        idmap->output_reference = cpu_to_le32(smmu_offset);
> > +        build_iort_id_mapping(table_data, smmu_offset);
> >      } else {
> >          /* output IORT node is the ITS group node (the first node) */
> > -        idmap->output_reference = cpu_to_le32(iort_node_offset);
> > +        build_iort_id_mapping(table_data, IORT_NODE_OFFSET);
> >      }
> >  
> >      acpi_table_composed(linker, &table);
> > -- 
> > 2.27.0  
> 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables
  2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
                   ` (34 preceding siblings ...)
  2021-07-08 15:46 ` [PATCH v2 35/35] acpi: AcpiGenericAddress no longer used to map/access fields of MMIO, drop packed attribute Igor Mammedov
@ 2021-07-13 15:45 ` Michael S. Tsirkin
  2021-07-14  8:53   ` Igor Mammedov
  35 siblings, 1 reply; 56+ messages in thread
From: Michael S. Tsirkin @ 2021-07-13 15:45 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel

On Thu, Jul 08, 2021 at 11:45:42AM -0400, Igor Mammedov wrote:
> v2:
>   - drop test related patches, they will be sent as a separate series
>   - fix bios_loader pointer initialization ordering when using TPM1.2
>   - extend commit message of [1/35] and add extra comment about
>     table length patching 


So I think this is in good shape, and I really like the code size
reduction. Given a rush to push things before the freeze, I'm inclined
to just defer API rework to the next release. This kind of thing is
better at the beginning of the cycle so we can iron out API kinks if any
surface.

> Highlights:
>   * drop pointer arithmetic in ACPI tables code
>   * use endian agnostic API
>   * simplifies review of tables. /in most cases just line by line comparision with spec/
> 
> Series replaces build_header() with acpi_init_table()/acpi_table_composed()
> API that hides pointer/offset arithmetic from user, to prevent
> errors caused by it [1].
> While doing above, it was necessary to split table header from
> packed structure that was describing the table, which is
> counter-productive since it still leaves packed structure drawbacks.
> So that sort of forced me to rewrite tables that were composed with
> help of packed structures to preferred build_append_int_noprefix() API.
> In cases where refactoring to build_append_int_noprefix() was small,
> it was squashed with acpi_init_table()/acpi_table_composed() patch.
> Conversion reduced code size quite a bit despite me adding doc comments
> for every table row.
> 
> 1) commits
>    bb9feea43179 x86: acpi: use offset instead of pointer when using build_header()
>    4d027afeb3a9 Virt: ACPI: fix qemu assert due to re-assigned table data address
> 
> Link to repo:
>    https://gitlab.com/imammedo/qemu/-/commits/acpi_build_header_refactoring_v2
> 
> CC: mst@redhat.com
> 
> 
> 
> Igor Mammedov (35):
>   acpi: add helper routines to initialize ACPI tables
>   acpi: build_rsdt: use acpi_init_table()/acpi_table_composed() instead
>     of build_header()
>   acpi: build_xsdt: use acpi_init_table()/acpi_table_composed() instead
>     of build_header()
>   acpi: build_slit: use acpi_init_table()/acpi_table_composed() instead
>     of build_header()
>   acpi: build_fadt: use acpi_init_table()/acpi_table_composed() instead
>     of build_header()
>   acpi: build_tpm2: use acpi_init_table()/acpi_table_composed() instead
>     of build_header()
>   acpi: acpi_build_hest: use acpi_init_table()/acpi_table_composed()
>     instead of build_header()
>   acpi: build_mcfg: use acpi_init_table()/acpi_table_composed() instead
>     of build_header()
>   acpi: build_hmat: use acpi_init_table()/acpi_table_composed() instead
>     of build_header()
>   acpi: nvdimm_build_nfit: use acpi_init_table()/acpi_table_composed()
>     instead of build_header()
>   acpi: nvdimm_build_ssdt: use acpi_init_table()/acpi_table_composed()
>     instead of build_header()
>   acpi: vmgenid_build_acpi: use acpi_init_table()/acpi_table_composed()
>     instead of build_header()
>   acpi: x86: build_dsdt: use acpi_init_table()/acpi_table_composed()
>     instead of build_header()
>   acpi: build_hpet: use acpi_init_table()/acpi_table_composed() instead
>     of build_header()
>   acpi: build_tpm_tcpa: use acpi_init_table()/acpi_table_composed()
>     instead of build_header()
>   acpi: arm/x86: build_srat: use acpi_init_table()/acpi_table_composed()
>     instead of build_header()
>   acpi: use build_append_int_noprefix() API to compose SRAT table
>   acpi: build_dmar_q35: use acpi_init_table()/acpi_table_composed()
>     instead of build_header()
>   acpi: build_waet: use acpi_init_table()/acpi_table_composed() instead
>     of build_header()
>   acpi: build_amd_iommu: use acpi_init_table()/acpi_table_composed()
>     instead of build_header()
>   acpi: madt: arm/x86: use acpi_init_table()/acpi_table_composed()
>     instead of build_header()
>   acpi: x86: remove dead code
>   acpi: x86: set enabled when composing _MAT entries
>   acpi: x86: madt: use build_append_int_noprefix() API to compose MADT
>     table
>   acpi: arm/virt: madt: use build_append_int_noprefix() API to compose
>     MADT table
>   acpi: build_dsdt_microvm: use acpi_init_table()/acpi_table_composed()
>     instead of build_header()
>   acpi: arm: virt: build_dsdt: use
>     acpi_init_table()/acpi_table_composed() instead of build_header()
>   acpi: arm: virt: build_iort: use
>     acpi_init_table()/acpi_table_composed() instead of build_header()
>   acpi: arm/virt: convert build_iort() to endian agnostic
>     build_append_FOO() API
>   acpi: arm/virt: build_spcr: fix invalid cast
>   acpi: arm/virt: build_spcr: use
>     acpi_init_table()/acpi_table_composed() instead of build_header()
>   acpi: arm/virt: build_gtdt: use
>     acpi_init_table()/acpi_table_composed() instead of build_header()
>   acpi: build_facs: use build_append_int_noprefix() API to compose table
>   acpi: remove no longer used build_header()
>   acpi: AcpiGenericAddress no longer used to map/access fields of MMIO,
>     drop packed attribute
> 
>  include/hw/acpi/acpi-defs.h          | 528 +------------------------
>  include/hw/acpi/acpi_dev_interface.h |   3 +-
>  include/hw/acpi/aml-build.h          |  21 +-
>  include/hw/i386/pc.h                 |   7 +-
>  hw/acpi/acpi-x86-stub.c              |   3 +-
>  hw/acpi/aml-build.c                  | 193 ++++++----
>  hw/acpi/cpu.c                        |  17 +-
>  hw/acpi/ghes.c                       |  10 +-
>  hw/acpi/hmat.c                       |  14 +-
>  hw/acpi/nvdimm.c                     |  64 ++--
>  hw/acpi/pci.c                        |  18 +-
>  hw/acpi/vmgenid.c                    |  16 +-
>  hw/arm/virt-acpi-build.c             | 550 +++++++++++++++------------
>  hw/i386/acpi-build.c                 | 284 ++++++++------
>  hw/i386/acpi-common.c                | 158 ++++----
>  hw/i386/acpi-microvm.c               |  13 +-
>  16 files changed, 750 insertions(+), 1149 deletions(-)
> 
> -- 
> 2.27.0



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables
  2021-07-13 15:45 ` [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Michael S. Tsirkin
@ 2021-07-14  8:53   ` Igor Mammedov
  2021-07-14 10:31     ` Michael S. Tsirkin
  0 siblings, 1 reply; 56+ messages in thread
From: Igor Mammedov @ 2021-07-14  8:53 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: qemu-devel

On Tue, 13 Jul 2021 11:45:46 -0400
"Michael S. Tsirkin" <mst@redhat.com> wrote:

> On Thu, Jul 08, 2021 at 11:45:42AM -0400, Igor Mammedov wrote:
> > v2:
> >   - drop test related patches, they will be sent as a separate series
> >   - fix bios_loader pointer initialization ordering when using TPM1.2
> >   - extend commit message of [1/35] and add extra comment about
> >     table length patching   
> 
> 
> So I think this is in good shape, and I really like the code size
> reduction. Given a rush to push things before the freeze, I'm inclined
> to just defer API rework to the next release. This kind of thing is
> better at the beginning of the cycle so we can iron out API kinks if any
> surface.

ok, I'll respin once another merge window is open.

As for tests part, that I dropped, should I repost it
for merging during soft-freeze or we postpone that as well?

> 
> > Highlights:
> >   * drop pointer arithmetic in ACPI tables code
> >   * use endian agnostic API
> >   * simplifies review of tables. /in most cases just line by line comparision with spec/
> > 
> > Series replaces build_header() with acpi_init_table()/acpi_table_composed()
> > API that hides pointer/offset arithmetic from user, to prevent
> > errors caused by it [1].
> > While doing above, it was necessary to split table header from
> > packed structure that was describing the table, which is
> > counter-productive since it still leaves packed structure drawbacks.
> > So that sort of forced me to rewrite tables that were composed with
> > help of packed structures to preferred build_append_int_noprefix() API.
> > In cases where refactoring to build_append_int_noprefix() was small,
> > it was squashed with acpi_init_table()/acpi_table_composed() patch.
> > Conversion reduced code size quite a bit despite me adding doc comments
> > for every table row.
> > 
> > 1) commits
> >    bb9feea43179 x86: acpi: use offset instead of pointer when using build_header()
> >    4d027afeb3a9 Virt: ACPI: fix qemu assert due to re-assigned table data address
> > 
> > Link to repo:
> >    https://gitlab.com/imammedo/qemu/-/commits/acpi_build_header_refactoring_v2
> > 
> > CC: mst@redhat.com
> > 
> > 
> > 
> > Igor Mammedov (35):
> >   acpi: add helper routines to initialize ACPI tables
> >   acpi: build_rsdt: use acpi_init_table()/acpi_table_composed() instead
> >     of build_header()
> >   acpi: build_xsdt: use acpi_init_table()/acpi_table_composed() instead
> >     of build_header()
> >   acpi: build_slit: use acpi_init_table()/acpi_table_composed() instead
> >     of build_header()
> >   acpi: build_fadt: use acpi_init_table()/acpi_table_composed() instead
> >     of build_header()
> >   acpi: build_tpm2: use acpi_init_table()/acpi_table_composed() instead
> >     of build_header()
> >   acpi: acpi_build_hest: use acpi_init_table()/acpi_table_composed()
> >     instead of build_header()
> >   acpi: build_mcfg: use acpi_init_table()/acpi_table_composed() instead
> >     of build_header()
> >   acpi: build_hmat: use acpi_init_table()/acpi_table_composed() instead
> >     of build_header()
> >   acpi: nvdimm_build_nfit: use acpi_init_table()/acpi_table_composed()
> >     instead of build_header()
> >   acpi: nvdimm_build_ssdt: use acpi_init_table()/acpi_table_composed()
> >     instead of build_header()
> >   acpi: vmgenid_build_acpi: use acpi_init_table()/acpi_table_composed()
> >     instead of build_header()
> >   acpi: x86: build_dsdt: use acpi_init_table()/acpi_table_composed()
> >     instead of build_header()
> >   acpi: build_hpet: use acpi_init_table()/acpi_table_composed() instead
> >     of build_header()
> >   acpi: build_tpm_tcpa: use acpi_init_table()/acpi_table_composed()
> >     instead of build_header()
> >   acpi: arm/x86: build_srat: use acpi_init_table()/acpi_table_composed()
> >     instead of build_header()
> >   acpi: use build_append_int_noprefix() API to compose SRAT table
> >   acpi: build_dmar_q35: use acpi_init_table()/acpi_table_composed()
> >     instead of build_header()
> >   acpi: build_waet: use acpi_init_table()/acpi_table_composed() instead
> >     of build_header()
> >   acpi: build_amd_iommu: use acpi_init_table()/acpi_table_composed()
> >     instead of build_header()
> >   acpi: madt: arm/x86: use acpi_init_table()/acpi_table_composed()
> >     instead of build_header()
> >   acpi: x86: remove dead code
> >   acpi: x86: set enabled when composing _MAT entries
> >   acpi: x86: madt: use build_append_int_noprefix() API to compose MADT
> >     table
> >   acpi: arm/virt: madt: use build_append_int_noprefix() API to compose
> >     MADT table
> >   acpi: build_dsdt_microvm: use acpi_init_table()/acpi_table_composed()
> >     instead of build_header()
> >   acpi: arm: virt: build_dsdt: use
> >     acpi_init_table()/acpi_table_composed() instead of build_header()
> >   acpi: arm: virt: build_iort: use
> >     acpi_init_table()/acpi_table_composed() instead of build_header()
> >   acpi: arm/virt: convert build_iort() to endian agnostic
> >     build_append_FOO() API
> >   acpi: arm/virt: build_spcr: fix invalid cast
> >   acpi: arm/virt: build_spcr: use
> >     acpi_init_table()/acpi_table_composed() instead of build_header()
> >   acpi: arm/virt: build_gtdt: use
> >     acpi_init_table()/acpi_table_composed() instead of build_header()
> >   acpi: build_facs: use build_append_int_noprefix() API to compose table
> >   acpi: remove no longer used build_header()
> >   acpi: AcpiGenericAddress no longer used to map/access fields of MMIO,
> >     drop packed attribute
> > 
> >  include/hw/acpi/acpi-defs.h          | 528 +------------------------
> >  include/hw/acpi/acpi_dev_interface.h |   3 +-
> >  include/hw/acpi/aml-build.h          |  21 +-
> >  include/hw/i386/pc.h                 |   7 +-
> >  hw/acpi/acpi-x86-stub.c              |   3 +-
> >  hw/acpi/aml-build.c                  | 193 ++++++----
> >  hw/acpi/cpu.c                        |  17 +-
> >  hw/acpi/ghes.c                       |  10 +-
> >  hw/acpi/hmat.c                       |  14 +-
> >  hw/acpi/nvdimm.c                     |  64 ++--
> >  hw/acpi/pci.c                        |  18 +-
> >  hw/acpi/vmgenid.c                    |  16 +-
> >  hw/arm/virt-acpi-build.c             | 550 +++++++++++++++------------
> >  hw/i386/acpi-build.c                 | 284 ++++++++------
> >  hw/i386/acpi-common.c                | 158 ++++----
> >  hw/i386/acpi-microvm.c               |  13 +-
> >  16 files changed, 750 insertions(+), 1149 deletions(-)
> > 
> > -- 
> > 2.27.0  
> 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables
  2021-07-14  8:53   ` Igor Mammedov
@ 2021-07-14 10:31     ` Michael S. Tsirkin
  0 siblings, 0 replies; 56+ messages in thread
From: Michael S. Tsirkin @ 2021-07-14 10:31 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel

On Wed, Jul 14, 2021 at 10:53:59AM +0200, Igor Mammedov wrote:
> On Tue, 13 Jul 2021 11:45:46 -0400
> "Michael S. Tsirkin" <mst@redhat.com> wrote:
> 
> > On Thu, Jul 08, 2021 at 11:45:42AM -0400, Igor Mammedov wrote:
> > > v2:
> > >   - drop test related patches, they will be sent as a separate series
> > >   - fix bios_loader pointer initialization ordering when using TPM1.2
> > >   - extend commit message of [1/35] and add extra comment about
> > >     table length patching   
> > 
> > 
> > So I think this is in good shape, and I really like the code size
> > reduction. Given a rush to push things before the freeze, I'm inclined
> > to just defer API rework to the next release. This kind of thing is
> > better at the beginning of the cycle so we can iron out API kinks if any
> > surface.
> 
> ok, I'll respin once another merge window is open.
> 
> As for tests part, that I dropped, should I repost it
> for merging during soft-freeze or we postpone that as well?

I'm inclined to say it's best to defer that too.
The point of the freeze is so we can focus on fixing errors,
mostly regressions.


> > 
> > > Highlights:
> > >   * drop pointer arithmetic in ACPI tables code
> > >   * use endian agnostic API
> > >   * simplifies review of tables. /in most cases just line by line comparision with spec/
> > > 
> > > Series replaces build_header() with acpi_init_table()/acpi_table_composed()
> > > API that hides pointer/offset arithmetic from user, to prevent
> > > errors caused by it [1].
> > > While doing above, it was necessary to split table header from
> > > packed structure that was describing the table, which is
> > > counter-productive since it still leaves packed structure drawbacks.
> > > So that sort of forced me to rewrite tables that were composed with
> > > help of packed structures to preferred build_append_int_noprefix() API.
> > > In cases where refactoring to build_append_int_noprefix() was small,
> > > it was squashed with acpi_init_table()/acpi_table_composed() patch.
> > > Conversion reduced code size quite a bit despite me adding doc comments
> > > for every table row.
> > > 
> > > 1) commits
> > >    bb9feea43179 x86: acpi: use offset instead of pointer when using build_header()
> > >    4d027afeb3a9 Virt: ACPI: fix qemu assert due to re-assigned table data address
> > > 
> > > Link to repo:
> > >    https://gitlab.com/imammedo/qemu/-/commits/acpi_build_header_refactoring_v2
> > > 
> > > CC: mst@redhat.com
> > > 
> > > 
> > > 
> > > Igor Mammedov (35):
> > >   acpi: add helper routines to initialize ACPI tables
> > >   acpi: build_rsdt: use acpi_init_table()/acpi_table_composed() instead
> > >     of build_header()
> > >   acpi: build_xsdt: use acpi_init_table()/acpi_table_composed() instead
> > >     of build_header()
> > >   acpi: build_slit: use acpi_init_table()/acpi_table_composed() instead
> > >     of build_header()
> > >   acpi: build_fadt: use acpi_init_table()/acpi_table_composed() instead
> > >     of build_header()
> > >   acpi: build_tpm2: use acpi_init_table()/acpi_table_composed() instead
> > >     of build_header()
> > >   acpi: acpi_build_hest: use acpi_init_table()/acpi_table_composed()
> > >     instead of build_header()
> > >   acpi: build_mcfg: use acpi_init_table()/acpi_table_composed() instead
> > >     of build_header()
> > >   acpi: build_hmat: use acpi_init_table()/acpi_table_composed() instead
> > >     of build_header()
> > >   acpi: nvdimm_build_nfit: use acpi_init_table()/acpi_table_composed()
> > >     instead of build_header()
> > >   acpi: nvdimm_build_ssdt: use acpi_init_table()/acpi_table_composed()
> > >     instead of build_header()
> > >   acpi: vmgenid_build_acpi: use acpi_init_table()/acpi_table_composed()
> > >     instead of build_header()
> > >   acpi: x86: build_dsdt: use acpi_init_table()/acpi_table_composed()
> > >     instead of build_header()
> > >   acpi: build_hpet: use acpi_init_table()/acpi_table_composed() instead
> > >     of build_header()
> > >   acpi: build_tpm_tcpa: use acpi_init_table()/acpi_table_composed()
> > >     instead of build_header()
> > >   acpi: arm/x86: build_srat: use acpi_init_table()/acpi_table_composed()
> > >     instead of build_header()
> > >   acpi: use build_append_int_noprefix() API to compose SRAT table
> > >   acpi: build_dmar_q35: use acpi_init_table()/acpi_table_composed()
> > >     instead of build_header()
> > >   acpi: build_waet: use acpi_init_table()/acpi_table_composed() instead
> > >     of build_header()
> > >   acpi: build_amd_iommu: use acpi_init_table()/acpi_table_composed()
> > >     instead of build_header()
> > >   acpi: madt: arm/x86: use acpi_init_table()/acpi_table_composed()
> > >     instead of build_header()
> > >   acpi: x86: remove dead code
> > >   acpi: x86: set enabled when composing _MAT entries
> > >   acpi: x86: madt: use build_append_int_noprefix() API to compose MADT
> > >     table
> > >   acpi: arm/virt: madt: use build_append_int_noprefix() API to compose
> > >     MADT table
> > >   acpi: build_dsdt_microvm: use acpi_init_table()/acpi_table_composed()
> > >     instead of build_header()
> > >   acpi: arm: virt: build_dsdt: use
> > >     acpi_init_table()/acpi_table_composed() instead of build_header()
> > >   acpi: arm: virt: build_iort: use
> > >     acpi_init_table()/acpi_table_composed() instead of build_header()
> > >   acpi: arm/virt: convert build_iort() to endian agnostic
> > >     build_append_FOO() API
> > >   acpi: arm/virt: build_spcr: fix invalid cast
> > >   acpi: arm/virt: build_spcr: use
> > >     acpi_init_table()/acpi_table_composed() instead of build_header()
> > >   acpi: arm/virt: build_gtdt: use
> > >     acpi_init_table()/acpi_table_composed() instead of build_header()
> > >   acpi: build_facs: use build_append_int_noprefix() API to compose table
> > >   acpi: remove no longer used build_header()
> > >   acpi: AcpiGenericAddress no longer used to map/access fields of MMIO,
> > >     drop packed attribute
> > > 
> > >  include/hw/acpi/acpi-defs.h          | 528 +------------------------
> > >  include/hw/acpi/acpi_dev_interface.h |   3 +-
> > >  include/hw/acpi/aml-build.h          |  21 +-
> > >  include/hw/i386/pc.h                 |   7 +-
> > >  hw/acpi/acpi-x86-stub.c              |   3 +-
> > >  hw/acpi/aml-build.c                  | 193 ++++++----
> > >  hw/acpi/cpu.c                        |  17 +-
> > >  hw/acpi/ghes.c                       |  10 +-
> > >  hw/acpi/hmat.c                       |  14 +-
> > >  hw/acpi/nvdimm.c                     |  64 ++--
> > >  hw/acpi/pci.c                        |  18 +-
> > >  hw/acpi/vmgenid.c                    |  16 +-
> > >  hw/arm/virt-acpi-build.c             | 550 +++++++++++++++------------
> > >  hw/i386/acpi-build.c                 | 284 ++++++++------
> > >  hw/i386/acpi-common.c                | 158 ++++----
> > >  hw/i386/acpi-microvm.c               |  13 +-
> > >  16 files changed, 750 insertions(+), 1149 deletions(-)
> > > 
> > > -- 
> > > 2.27.0  
> > 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 01/35] acpi: add helper routines to initialize ACPI tables
  2021-07-08 15:45 ` [PATCH v2 01/35] acpi: add helper routines to initialize " Igor Mammedov
@ 2021-09-02 12:56   ` Eric Auger
  2021-09-03  7:12     ` Igor Mammedov
  0 siblings, 1 reply; 56+ messages in thread
From: Eric Auger @ 2021-09-02 12:56 UTC (permalink / raw)
  To: Igor Mammedov, qemu-devel; +Cc: mst

Hi Igor,

On 7/8/21 5:45 PM, Igor Mammedov wrote:
> Patch introduces acpi_init_table()/acpi_table_composed() API
> that hides pointer/offset arithmetic from user as opposed
> to build_header(), to prevent errors caused by it [1].
> 
>  acpi_init_table():
>      initializes table header and keeps track of
>      table data/offsets
>  acpi_table_composed():
>      sets actual table length and tells bios loader
>      where table is for the later initialization on
>      guest side.
might be worth to put those comments in the code as doc comments since
"_composed" terminology is not self-explanatory?
> 
> 1) commits
>    bb9feea43179 x86: acpi: use offset instead of pointer when using build_header()
>    4d027afeb3a9 Virt: ACPI: fix qemu assert due to re-assigned table data address
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
>  include/hw/acpi/aml-build.h | 14 +++++++++
>  hw/acpi/aml-build.c         | 58 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 72 insertions(+)
> 
> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> index 471266d739..d590660bd2 100644
> --- a/include/hw/acpi/aml-build.h
> +++ b/include/hw/acpi/aml-build.h
> @@ -413,6 +413,20 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
>  Aml *aml_object_type(Aml *object);
>  
>  void build_append_int_noprefix(GArray *table, uint64_t value, int size);
> +
> +typedef struct AcpiTable {
> +    const char *sig;
> +    const uint8_t rev;
> +    const char *oem_id;
> +    const char *oem_table_id;
> +    /* private vars tracking table state */
> +    GArray *array;
> +    unsigned table_offset;
> +} AcpiTable;
> +
> +void acpi_init_table(AcpiTable *desc, GArray *array);
> +void acpi_table_composed(BIOSLinker *linker, AcpiTable *table);
> +
>  void
>  build_header(BIOSLinker *linker, GArray *table_data,
>               AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index d5103e6d7b..c598010144 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -52,6 +52,19 @@ static void build_append_byte(GArray *array, uint8_t val)
>      g_array_append_val(array, val);
>  }
>  
> +static void build_append_padded_str(GArray *array, const char *str,
> +                                    size_t maxlen, char pad)
> +{
> +    size_t i;
> +    size_t len = strlen(str);
> +
> +    g_assert(len <= maxlen);
> +    g_array_append_vals(array, str, len);
> +    for (i = maxlen - len; i > 0; i--) {
> +        g_array_append_val(array, pad);
> +    }
> +}
> +
>  static void build_append_array(GArray *array, GArray *val)
>  {
>      g_array_append_vals(array, val->data, val->len);
> @@ -1692,6 +1705,51 @@ Aml *aml_object_type(Aml *object)
>      return var;
>  }
>  
> +void acpi_init_table(AcpiTable *desc, GArray *array)
> +{
> +
> +    desc->array = array;
> +    desc->table_offset = array->len;
> +
> +    /*
> +     * ACPI spec 1.0b
> +     * 5.2.3 System Description Table Header
> +     */
> +    g_assert(strlen(desc->sig) == 4);
> +    g_array_append_vals(array, desc->sig, 4); /* Signature */
build_append_padded_str?
> +    build_append_int_noprefix(array, 0, 4); /* Length */
> +    build_append_int_noprefix(array, desc->rev, 1); /* Revision */
> +    build_append_int_noprefix(array, 0, 1); /* Checksum */
> +    build_append_padded_str(array, desc->oem_id, 6, ' '); /* OEMID */
> +    /* OEM Table ID */
> +    build_append_padded_str(array, desc->oem_table_id, 8, ' ');
> +    build_append_int_noprefix(array, 1, 4); /* OEM Revision */
> +    g_array_append_vals(array, ACPI_BUILD_APPNAME8, 4); /* Creator ID */
> +    build_append_int_noprefix(array, 1, 4); /* Creator Revision */
> +}
> +
> +void acpi_table_composed(BIOSLinker *linker, AcpiTable *desc)
> +{
> +    /*
> +     * ACPI spec 1.0b
> +     * 5.2.3 System Description Table Header
> +     * Table 5-2 DESCRIPTION_HEADER Fields
> +     */
> +    const unsigned checksum_offset = 9;
> +    uint32_t table_len = desc->array->len - desc->table_offset;
> +    uint32_t table_len_le = cpu_to_le32(table_len);
> +    gchar *len_ptr = &desc->array->data[desc->table_offset + 4];
> +
> +    /* patch "Length" field that has been reserved by acpi_init_table()
> +     * to the actual length, i.e. accumulated table length from
> +     * acpi_init_table() till acpi_table_composed()
> +     */
> +    memcpy(len_ptr, &table_len_le, sizeof table_len_le);
can't you use a garray/build_append function instead to be homogeneous
with the rest of the code?
> +
> +    bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
> +        desc->table_offset, table_len, desc->table_offset + checksum_offset);
> +}
> +
>  void
>  build_header(BIOSLinker *linker, GArray *table_data,
>               AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
> 

Thanks

Eric



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 06/35] acpi: build_tpm2: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 ` [PATCH v2 06/35] acpi: build_tpm2: " Igor Mammedov
@ 2021-09-02 12:59   ` Eric Auger
  0 siblings, 0 replies; 56+ messages in thread
From: Eric Auger @ 2021-09-02 12:59 UTC (permalink / raw)
  To: Igor Mammedov, qemu-devel; +Cc: Stefan Berger, mst, stefanb

Hi Igor,

On 7/8/21 5:45 PM, Igor Mammedov wrote:
> it replaces error-prone pointer arithmetic for build_header() API,
> with 2 calls to start and finish table creation,
> which hides offsets magic from API user.
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> Tested-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric

> ---
> CC: stefanb@linux.vnet.ibm.com
> ---
>  hw/acpi/aml-build.c | 11 +++++------
>  1 file changed, 5 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index 176d086b25..057c64fb48 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -2103,13 +2103,14 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
>                  const char *oem_id, const char *oem_table_id)
>  {
>      uint8_t start_method_params[12] = {};
> -    unsigned log_addr_offset, tpm2_start;
> +    unsigned log_addr_offset;
>      uint64_t control_area_start_address;
>      TPMIf *tpmif = tpm_find();
>      uint32_t start_method;
> +    AcpiTable table = { .sig = "TPM2", .rev = 4,
> +                        .oem_id = oem_id, .oem_table_id = oem_table_id };
>  
> -    tpm2_start = table_data->len;
> -    acpi_data_push(table_data, sizeof(AcpiTableHeader));
> +    acpi_init_table(&table, table_data);
>  
>      /* Platform Class */
>      build_append_int_noprefix(table_data, TPM2_ACPI_CLASS_CLIENT, 2);
> @@ -2147,9 +2148,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
>      bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
>                                     log_addr_offset, 8,
>                                     ACPI_BUILD_TPMLOG_FILE, 0);
> -    build_header(linker, table_data,
> -                 (void *)(table_data->data + tpm2_start),
> -                 "TPM2", table_data->len - tpm2_start, 4, oem_id, oem_table_id);
> +    acpi_table_composed(linker, &table);
>  }
>  #endif
>  
> 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 27/35] acpi: arm: virt: build_dsdt: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:46 ` [PATCH v2 27/35] acpi: arm: virt: build_dsdt: " Igor Mammedov
@ 2021-09-02 15:34   ` Eric Auger
  0 siblings, 0 replies; 56+ messages in thread
From: Eric Auger @ 2021-09-02 15:34 UTC (permalink / raw)
  To: Igor Mammedov, qemu-devel
  Cc: peter.maydell, drjones, qemu-arm, mst, shannon.zhaosl



On 7/8/21 5:46 PM, Igor Mammedov wrote:
> it replaces error-prone pointer arithmetic for build_header() API,
> with 2 calls to start and finish table creation,
> which hides offsets magic from API user.
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
> CC: peter.maydell@linaro.org
> CC: shannon.zhaosl@gmail.com
> CC: qemu-arm@nongnu.org
> CC: drjones@redhat.com
> ---
>  hw/arm/virt-acpi-build.c | 13 ++++++-------
>  1 file changed, 6 insertions(+), 7 deletions(-)
> 
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index dd8011a670..d15e67a39b 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -636,10 +636,11 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>      MachineState *ms = MACHINE(vms);
>      const MemMapEntry *memmap = vms->memmap;
>      const int *irqmap = vms->irqmap;
> +    AcpiTable table = { .sig = "DSDT", .rev = 2, .oem_id = vms->oem_id,
> +                        .oem_table_id = vms->oem_table_id };
>  
> +    acpi_init_table(&table, table_data);
>      dsdt = init_aml_allocator();
> -    /* Reserve space for header */
> -    acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader));
>  
>      /* When booting the VM with UEFI, UEFI takes ownership of the RTC hardware.
>       * While UEFI can use libfdt to disable the RTC device node in the DTB that
> @@ -686,12 +687,10 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>  
>      aml_append(dsdt, scope);
>  
> -    /* copy AML table into ACPI tables blob and patch header there */
> +    /* copy AML table into ACPI tables blob */
>      g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
> -    build_header(linker, table_data,
> -        (void *)(table_data->data + table_data->len - dsdt->buf->len),
> -                 "DSDT", dsdt->buf->len, 2, vms->oem_id,
> -                 vms->oem_table_id);
> +
> +    acpi_table_composed(linker, &table);
>      free_aml_allocator();
>  }
>  
> 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 13/35] acpi: x86: build_dsdt: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:45 ` [PATCH v2 13/35] acpi: x86: build_dsdt: " Igor Mammedov
@ 2021-09-02 15:35   ` Eric Auger
  0 siblings, 0 replies; 56+ messages in thread
From: Eric Auger @ 2021-09-02 15:35 UTC (permalink / raw)
  To: Igor Mammedov, qemu-devel; +Cc: mst



On 7/8/21 5:45 PM, Igor Mammedov wrote:
> it replaces error-prone pointer arithmetic for build_header() API,
> with 2 calls to start and finish table creation,
> which hides offsets magic from API user.
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
> CC: marcel.apfelbaum@gmail.com
> ---
>  hw/i386/acpi-build.c | 10 ++++------
>  1 file changed, 4 insertions(+), 6 deletions(-)
> 
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 796ffc6f5c..538af9d944 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -1380,12 +1380,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>  #endif
>      int i;
>      VMBusBridge *vmbus_bridge = vmbus_bridge_find();
> +    AcpiTable table = { .sig = "DSDT", .rev = 1, .oem_id = x86ms->oem_id,
> +                        .oem_table_id = x86ms->oem_table_id };
>  
> +    acpi_init_table(&table, table_data);
>      dsdt = init_aml_allocator();
>  
> -    /* Reserve space for header */
> -    acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader));
> -
>      build_dbg_aml(dsdt);
>      if (misc->is_piix4) {
>          sb_scope = aml_scope("_SB");
> @@ -1816,9 +1816,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>  
>      /* copy AML table into ACPI tables blob and patch header there */
>      g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
> -    build_header(linker, table_data,
> -        (void *)(table_data->data + table_data->len - dsdt->buf->len),
> -                 "DSDT", dsdt->buf->len, 1, x86ms->oem_id, x86ms->oem_table_id);
> +    acpi_table_composed(linker, &table);
>      free_aml_allocator();
>  }
>  
> 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 31/35] acpi: arm/virt: build_spcr: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:46 ` [PATCH v2 31/35] acpi: arm/virt: build_spcr: use acpi_init_table()/acpi_table_composed() instead of build_header() Igor Mammedov
@ 2021-09-02 15:49   ` Eric Auger
  2021-09-03  7:52     ` Igor Mammedov
  0 siblings, 1 reply; 56+ messages in thread
From: Eric Auger @ 2021-09-02 15:49 UTC (permalink / raw)
  To: Igor Mammedov, qemu-devel
  Cc: peter.maydell, drjones, qemu-arm, mst, shannon.zhaosl

Hi Igor,

On 7/8/21 5:46 PM, Igor Mammedov wrote:
> it replaces error-prone pointer arithmetic for build_header() API,
> with 2 calls to start and finish table creation,
> which hides offsets magic from API user.
> 
> while at it, replace packed structure with endian agnostic
> build_append_FOO() API.
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
> CC: drjones@redhat.com
> CC: peter.maydell@linaro.org
> CC: shannon.zhaosl@gmail.com
> CC: qemu-arm@nongnu.org
> ---
>  include/hw/acpi/acpi-defs.h | 32 -----------------
>  hw/arm/virt-acpi-build.c    | 68 ++++++++++++++++++++++---------------
>  2 files changed, 41 insertions(+), 59 deletions(-)
> 
> diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
> index 6f2f08a9de..012c4ffb3a 100644
> --- a/include/hw/acpi/acpi-defs.h
> +++ b/include/hw/acpi/acpi-defs.h
> @@ -117,38 +117,6 @@ typedef struct AcpiFadtData {
>  #define ACPI_FADT_ARM_PSCI_COMPLIANT  (1 << 0)
>  #define ACPI_FADT_ARM_PSCI_USE_HVC    (1 << 1)
>  
> -/*
> - * Serial Port Console Redirection Table (SPCR), Rev. 1.02
> - *
> - * For .interface_type see Debug Port Table 2 (DBG2) serial port
> - * subtypes in Table 3, Rev. May 22, 2012
> - */
> -struct AcpiSerialPortConsoleRedirection {
> -    ACPI_TABLE_HEADER_DEF
> -    uint8_t  interface_type;
> -    uint8_t  reserved1[3];
> -    struct AcpiGenericAddress base_address;
> -    uint8_t  interrupt_types;
> -    uint8_t  irq;
> -    uint32_t gsi;
> -    uint8_t  baud;
> -    uint8_t  parity;
> -    uint8_t  stopbits;
> -    uint8_t  flowctrl;
> -    uint8_t  term_type;
> -    uint8_t  reserved2;
> -    uint16_t pci_device_id;
> -    uint16_t pci_vendor_id;
> -    uint8_t  pci_bus;
> -    uint8_t  pci_slot;
> -    uint8_t  pci_func;
> -    uint32_t pci_flags;
> -    uint8_t  pci_seg;
> -    uint32_t reserved3;
> -} QEMU_PACKED;
> -typedef struct AcpiSerialPortConsoleRedirection
> -               AcpiSerialPortConsoleRedirection;
> -
>  /*
>   * ACPI 1.0 Firmware ACPI Control Structure (FACS)
>   */
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index a07540affb..e8553dcae5 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -349,39 +349,53 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>      acpi_table_composed(linker, &table);
>  }
>  
> +/*
> + * Serial Port Console Redirection Table (SPCR)
> + * Rev: 1.07
> + */
was
/*
 * Serial Port Console Redirection Table (SPCR), Rev. 1.02
 */

By the way
https://uefi.org/acpi/specs does not list 1.02 nor 1.07
https://docs.microsoft.com/en-us/windows-hardware/drivers/serports/serial-port-console-redirection-table
?

>  static void
>  build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>  {
> -    AcpiSerialPortConsoleRedirection *spcr;
> -    const MemMapEntry *uart_memmap = &vms->memmap[VIRT_UART];
> -    int irq = vms->irqmap[VIRT_UART] + ARM_SPI_BASE;
> -    int spcr_start = table_data->len;
> -
> -    spcr = acpi_data_push(table_data, sizeof(*spcr));
> -
> -    spcr->interface_type = 0x3;    /* ARM PL011 UART */
> -
> -    spcr->base_address.space_id = AML_AS_SYSTEM_MEMORY;
> -    spcr->base_address.bit_width = 8;
> -    spcr->base_address.bit_offset = 0;
> -    spcr->base_address.access_width = 1;
> -    spcr->base_address.address = cpu_to_le64(uart_memmap->base);
> -
> -    spcr->interrupt_types = (1 << 3); /* Bit[3] ARMH GIC interrupt */
> -    spcr->gsi = cpu_to_le32(irq);  /* Global System Interrupt */
> +    AcpiTable table = { .sig = "SPCR", .rev = 2, .oem_id = vms->oem_id,
> +                        .oem_table_id = vms->oem_table_id };
>  
> -    spcr->baud = 3;                /* Baud Rate: 3 = 9600 */
> -    spcr->parity = 0;              /* No Parity */
> -    spcr->stopbits = 1;            /* 1 Stop bit */
> -    spcr->flowctrl = (1 << 1);     /* Bit[1] = RTS/CTS hardware flow control */
> -    spcr->term_type = 0;           /* Terminal Type: 0 = VT100 */
> +    acpi_init_table(&table, table_data);
>  
> -    spcr->pci_device_id = 0xffff;  /* PCI Device ID: not a PCI device */
> -    spcr->pci_vendor_id = 0xffff;  /* PCI Vendor ID: not a PCI device */
> +    /* Interface Type */
> +    build_append_int_noprefix(table_data, 3, 1); /* ARM PL011 UART */
> +    build_append_int_noprefix(table_data, 0, 3); /* Reserved */
> +    /* Base Address */
> +    build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 8, 0, 1,
> +                     vms->memmap[VIRT_UART].base);
> +    /* Interrupt Type */
> +    build_append_int_noprefix(table_data,
> +        (1 << 3) /* Bit[3] ARMH GIC interrupt */, 1);
> +    build_append_int_noprefix(table_data, 0, 1); /* IRQ */
> +    /* Global System Interrupt */
> +    build_append_int_noprefix(table_data,
> +                              vms->irqmap[VIRT_UART] + ARM_SPI_BASE, 4);
> +    build_append_int_noprefix(table_data, 3 /* 9600 */, 1); /* Baud Rate */
> +    build_append_int_noprefix(table_data, 0 /* No Parity */, 1); /* Parity */
> +    /* Stop Bits */
> +    build_append_int_noprefix(table_data, 1 /* 1 Stop bit */, 1);
> +    /* Flow Control */
> +    build_append_int_noprefix(table_data,
> +        (1 << 1) /* RTS/CTS hardware flow control */, 1);
> +    /* Terminal Type */
> +    build_append_int_noprefix(table_data, 0 /* VT100 */, 1);
> +    build_append_int_noprefix(table_data, 0, 1); /* Language */
reserved2 -> language in 1.07? but that's fine
maybe just mention it in the commit msg?
> +    /* PCI Device ID  */
> +    build_append_int_noprefix(table_data, 0xffff /* not a PCI device*/, 2);
> +    /* PCI Vendor ID */
> +    build_append_int_noprefix(table_data, 0xffff /* not a PCI device*/, 2);
> +    build_append_int_noprefix(table_data, 0, 1); /* PCI Bus Number */
> +    build_append_int_noprefix(table_data, 0, 1); /* PCI Device Number */
> +    build_append_int_noprefix(table_data, 0, 1); /* PCI Function Number */
> +    build_append_int_noprefix(table_data, 0, 4); /* PCI Flags */
> +    build_append_int_noprefix(table_data, 0, 1); /* PCI Segment */
> +    build_append_int_noprefix(table_data, 0, 4); /* Reserved */
>  
> -    build_header(linker, table_data, (void *)(table_data->data + spcr_start),
> -                 "SPCR", table_data->len - spcr_start, 2, vms->oem_id,
> -                 vms->oem_table_id);
> +    acpi_table_composed(linker, &table);
>  }
>  
>  /*
> 
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 30/35] acpi: arm/virt: build_spcr: fix invalid cast
  2021-07-08 15:46 ` [PATCH v2 30/35] acpi: arm/virt: build_spcr: fix invalid cast Igor Mammedov
@ 2021-09-02 15:51   ` Eric Auger
  0 siblings, 0 replies; 56+ messages in thread
From: Eric Auger @ 2021-09-02 15:51 UTC (permalink / raw)
  To: Igor Mammedov, qemu-devel
  Cc: peter.maydell, drjones, qemu-arm, mst, shannon.zhaosl



On 7/8/21 5:46 PM, Igor Mammedov wrote:
> implicit cast to structure uint8_t member didn't raise error when
> assigning value from incorrect enum, but when using build_append_gas()
> (next patch) it will error out with (clang):
>   implicit conversion from enumeration type 'AmlRegionSpace'
>   to different enumeration type 'AmlAddressSpace'
> fix cast error by using correct AML_AS_SYSTEM_MEMORY enum
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

> ---
> CC: drjones@redhat.com
> CC: peter.maydell@linaro.org
> CC: shannon.zhaosl@gmail.com
> CC: qemu-arm@nongnu.org
> ---
>  hw/arm/virt-acpi-build.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index b88ea4b70a..a07540affb 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -361,7 +361,7 @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>  
>      spcr->interface_type = 0x3;    /* ARM PL011 UART */
>  
> -    spcr->base_address.space_id = AML_SYSTEM_MEMORY;
> +    spcr->base_address.space_id = AML_AS_SYSTEM_MEMORY;
>      spcr->base_address.bit_width = 8;
>      spcr->base_address.bit_offset = 0;
>      spcr->base_address.access_width = 1;
> 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 32/35] acpi: arm/virt: build_gtdt: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-07-08 15:46 ` [PATCH v2 32/35] acpi: arm/virt: build_gtdt: " Igor Mammedov
@ 2021-09-02 16:07   ` Eric Auger
  0 siblings, 0 replies; 56+ messages in thread
From: Eric Auger @ 2021-09-02 16:07 UTC (permalink / raw)
  To: Igor Mammedov, qemu-devel
  Cc: peter.maydell, drjones, qemu-arm, mst, shannon.zhaosl



On 7/8/21 5:46 PM, Igor Mammedov wrote:
> it replaces error-prone pointer arithmetic for build_header() API,
> with 2 calls to start and finish table creation,
> which hides offsets magic from API user.
> 
> while at it, replace packed structure with endian agnostic
> build_append_FOO() API.
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
> CC: drjones@redhat.com
> CC: peter.maydell@linaro.org
> CC: shannon.zhaosl@gmail.com
> CC: qemu-arm@nongnu.org
> ---
>  include/hw/acpi/acpi-defs.h | 25 -------------
>  hw/arm/virt-acpi-build.c    | 75 ++++++++++++++++++++++++-------------
>  2 files changed, 48 insertions(+), 52 deletions(-)
> 
> diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
> index 012c4ffb3a..0b375e7589 100644
> --- a/include/hw/acpi/acpi-defs.h
> +++ b/include/hw/acpi/acpi-defs.h
> @@ -131,29 +131,4 @@ struct AcpiFacsDescriptorRev1 {
>  } QEMU_PACKED;
>  typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
>  
> -/*
> - * Generic Timer Description Table (GTDT)
> - */
> -#define ACPI_GTDT_INTERRUPT_MODE_LEVEL    (0 << 0)
> -#define ACPI_GTDT_INTERRUPT_MODE_EDGE     (1 << 0)
> -#define ACPI_GTDT_CAP_ALWAYS_ON           (1 << 2)
> -
> -struct AcpiGenericTimerTable {
> -    ACPI_TABLE_HEADER_DEF
> -    uint64_t counter_block_addresss;
> -    uint32_t reserved;
> -    uint32_t secure_el1_interrupt;
> -    uint32_t secure_el1_flags;
> -    uint32_t non_secure_el1_interrupt;
> -    uint32_t non_secure_el1_flags;
> -    uint32_t virtual_timer_interrupt;
> -    uint32_t virtual_timer_flags;
> -    uint32_t non_secure_el2_interrupt;
> -    uint32_t non_secure_el2_flags;
> -    uint64_t counter_read_block_address;
> -    uint32_t platform_timer_count;
> -    uint32_t platform_timer_offset;
> -} QEMU_PACKED;
> -typedef struct AcpiGenericTimerTable AcpiGenericTimerTable;
> -
>  #endif
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index e8553dcae5..8f28e82760 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -455,40 +455,61 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>      acpi_table_composed(linker, &table);
>  }
>  
> -/* GTDT */
> +/*
> + * ACPI spec, Revision 5.1
> + * 5.2.24 Generic Timer Description Table (GTDT)
> + */
>  static void
>  build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>  {
>      VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
> -    int gtdt_start = table_data->len;
> -    AcpiGenericTimerTable *gtdt;
> -    uint32_t irqflags;
> -
> -    if (vmc->claim_edge_triggered_timers) {
> -        irqflags = ACPI_GTDT_INTERRUPT_MODE_EDGE;
> -    } else {
> -        irqflags = ACPI_GTDT_INTERRUPT_MODE_LEVEL;
> -    }
> -
> -    gtdt = acpi_data_push(table_data, sizeof *gtdt);
> -    /* The interrupt values are the same with the device tree when adding 16 */
> -    gtdt->secure_el1_interrupt = cpu_to_le32(ARCH_TIMER_S_EL1_IRQ + 16);
> -    gtdt->secure_el1_flags = cpu_to_le32(irqflags);
> -
> -    gtdt->non_secure_el1_interrupt = cpu_to_le32(ARCH_TIMER_NS_EL1_IRQ + 16);
> -    gtdt->non_secure_el1_flags = cpu_to_le32(irqflags |
> -                                             ACPI_GTDT_CAP_ALWAYS_ON);
> +    /*
> +     * Table 5-117 Flag Definitions
> +     * set only "Timer interrupt Mode" and assume "Timer Interrupt
> +     * polarity" bit as '0: Interrupt is Active high'
> +     */
> +    uint32_t irqflags = vmc->claim_edge_triggered_timers ?
> +        1 : /* Interrupt is Edge triggered */
> +        0;  /* Interrupt is Level triggered  */
> +    AcpiTable table = { .sig = "GTDT", .rev = 2, .oem_id = vms->oem_id,
> +                        .oem_table_id = vms->oem_table_id };
>  
> -    gtdt->virtual_timer_interrupt = cpu_to_le32(ARCH_TIMER_VIRT_IRQ + 16);
> -    gtdt->virtual_timer_flags = cpu_to_le32(irqflags);
> +    acpi_init_table(&table, table_data);
>  
> -    gtdt->non_secure_el2_interrupt = cpu_to_le32(ARCH_TIMER_NS_EL2_IRQ + 16);
> -    gtdt->non_secure_el2_flags = cpu_to_le32(irqflags);
> +    /* CntControlBase Physical Address */
> +    /* FIXME: invalid value, should be 0xFFFFFFFFFFFFFFFF if not impl. ? */
> +    build_append_int_noprefix(table_data, 0, 8);
> +    build_append_int_noprefix(table_data, 0, 4); /* Reserved */
> +    /*
> +     * FIXME: clarify comment:
> +     * The interrupt values are the same with the device tree when adding 16
> +     */
> +    /* Secure EL1 timer GSIV */
> +    build_append_int_noprefix(table_data, ARCH_TIMER_S_EL1_IRQ + 16, 4);
> +    /* Secure EL1 timer Flags */
> +    build_append_int_noprefix(table_data, irqflags, 4);
> +    /* Non-Secure EL1 timer GSIV */
> +    build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL1_IRQ + 16, 4);
> +    /* Non-Secure EL1 timer Flags */
> +    build_append_int_noprefix(table_data, irqflags |
> +                              1UL << 2, /* Always-on Capability */
> +                              4);
> +    /* Virtual timer GSIV */
> +    build_append_int_noprefix(table_data, ARCH_TIMER_VIRT_IRQ + 16, 4);
> +    /* Virtual Timer Flags */
> +    build_append_int_noprefix(table_data, irqflags, 4);
> +    /* Non-Secure EL2 timer GSIV */
> +    build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_IRQ + 16, 4);
> +    /* Non-Secure EL2 timer Flags */
> +    build_append_int_noprefix(table_data, irqflags, 4);
> +    /* CntReadBase Physical address */
> +    build_append_int_noprefix(table_data, 0, 8);
> +    /* Platform Timer Count */
> +    build_append_int_noprefix(table_data, 0, 4);
> +    /* Platform Timer Offset */
> +    build_append_int_noprefix(table_data, 0, 4);
>  
> -    build_header(linker, table_data,
> -                 (void *)(table_data->data + gtdt_start), "GTDT",
> -                 table_data->len - gtdt_start, 2, vms->oem_id,
> -                 vms->oem_table_id);
> +    acpi_table_composed(linker, &table);
>  }
>  
>  /*
> 
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 01/35] acpi: add helper routines to initialize ACPI tables
  2021-09-02 12:56   ` Eric Auger
@ 2021-09-03  7:12     ` Igor Mammedov
  2021-09-03  7:22       ` Eric Auger
  2021-09-04 19:57       ` Michael S. Tsirkin
  0 siblings, 2 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-09-03  7:12 UTC (permalink / raw)
  To: Eric Auger; +Cc: qemu-devel, mst

On Thu, 2 Sep 2021 14:56:00 +0200
Eric Auger <eauger@redhat.com> wrote:

> Hi Igor,
> 
> On 7/8/21 5:45 PM, Igor Mammedov wrote:
> > Patch introduces acpi_init_table()/acpi_table_composed() API
> > that hides pointer/offset arithmetic from user as opposed
> > to build_header(), to prevent errors caused by it [1].
> > 
> >  acpi_init_table():
> >      initializes table header and keeps track of
> >      table data/offsets
> >  acpi_table_composed():
> >      sets actual table length and tells bios loader
> >      where table is for the later initialization on
> >      guest side.  
> might be worth to put those comments in the code as doc comments since
> "_composed" terminology is not self-explanatory?

I'll add doc comments as suggested.
A better idea how to name function is welcome as well?


> > 1) commits
> >    bb9feea43179 x86: acpi: use offset instead of pointer when using build_header()
> >    4d027afeb3a9 Virt: ACPI: fix qemu assert due to re-assigned table data address
> > 
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > ---
> >  include/hw/acpi/aml-build.h | 14 +++++++++
> >  hw/acpi/aml-build.c         | 58 +++++++++++++++++++++++++++++++++++++
> >  2 files changed, 72 insertions(+)
> > 
> > diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> > index 471266d739..d590660bd2 100644
> > --- a/include/hw/acpi/aml-build.h
> > +++ b/include/hw/acpi/aml-build.h
> > @@ -413,6 +413,20 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
> >  Aml *aml_object_type(Aml *object);
> >  
> >  void build_append_int_noprefix(GArray *table, uint64_t value, int size);
> > +
> > +typedef struct AcpiTable {
> > +    const char *sig;
> > +    const uint8_t rev;
> > +    const char *oem_id;
> > +    const char *oem_table_id;
> > +    /* private vars tracking table state */
> > +    GArray *array;
> > +    unsigned table_offset;
> > +} AcpiTable;
> > +
> > +void acpi_init_table(AcpiTable *desc, GArray *array);
> > +void acpi_table_composed(BIOSLinker *linker, AcpiTable *table);
> > +
> >  void
> >  build_header(BIOSLinker *linker, GArray *table_data,
> >               AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
> > diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> > index d5103e6d7b..c598010144 100644
> > --- a/hw/acpi/aml-build.c
> > +++ b/hw/acpi/aml-build.c
> > @@ -52,6 +52,19 @@ static void build_append_byte(GArray *array, uint8_t val)
> >      g_array_append_val(array, val);
> >  }
> >  
> > +static void build_append_padded_str(GArray *array, const char *str,
> > +                                    size_t maxlen, char pad)
> > +{
> > +    size_t i;
> > +    size_t len = strlen(str);
> > +
> > +    g_assert(len <= maxlen);
> > +    g_array_append_vals(array, str, len);
> > +    for (i = maxlen - len; i > 0; i--) {
> > +        g_array_append_val(array, pad);
> > +    }
> > +}
> > +
> >  static void build_append_array(GArray *array, GArray *val)
> >  {
> >      g_array_append_vals(array, val->data, val->len);
> > @@ -1692,6 +1705,51 @@ Aml *aml_object_type(Aml *object)
> >      return var;
> >  }
> >  
> > +void acpi_init_table(AcpiTable *desc, GArray *array)
> > +{
> > +
> > +    desc->array = array;
> > +    desc->table_offset = array->len;
> > +
> > +    /*
> > +     * ACPI spec 1.0b
> > +     * 5.2.3 System Description Table Header
> > +     */
> > +    g_assert(strlen(desc->sig) == 4);
> > +    g_array_append_vals(array, desc->sig, 4); /* Signature */  
> build_append_padded_str?

it will do the job even if it's a bit of overkill,
signature must be 4 characters long so there is nothing to pad here
(at least till this day).
Using padded variant may confuse reader in the future,
so I'd prefer to keep this line as is.


> > +    build_append_int_noprefix(array, 0, 4); /* Length */
> > +    build_append_int_noprefix(array, desc->rev, 1); /* Revision */
> > +    build_append_int_noprefix(array, 0, 1); /* Checksum */
> > +    build_append_padded_str(array, desc->oem_id, 6, ' '); /* OEMID */
> > +    /* OEM Table ID */
> > +    build_append_padded_str(array, desc->oem_table_id, 8, ' ');
> > +    build_append_int_noprefix(array, 1, 4); /* OEM Revision */
> > +    g_array_append_vals(array, ACPI_BUILD_APPNAME8, 4); /* Creator ID */

here we potentially can reuse build_append_padded_str() if we
remove padding in ACPI_BUILD_APPNAME8, but that should wait till
refactoring is complete (to avoid breaking incremental refactoring)

> > +    build_append_int_noprefix(array, 1, 4); /* Creator Revision */
> > +}
> > +
> > +void acpi_table_composed(BIOSLinker *linker, AcpiTable *desc)
> > +{
> > +    /*
> > +     * ACPI spec 1.0b
> > +     * 5.2.3 System Description Table Header
> > +     * Table 5-2 DESCRIPTION_HEADER Fields
> > +     */
> > +    const unsigned checksum_offset = 9;
> > +    uint32_t table_len = desc->array->len - desc->table_offset;
> > +    uint32_t table_len_le = cpu_to_le32(table_len);
> > +    gchar *len_ptr = &desc->array->data[desc->table_offset + 4];
> > +
> > +    /* patch "Length" field that has been reserved by acpi_init_table()
> > +     * to the actual length, i.e. accumulated table length from
> > +     * acpi_init_table() till acpi_table_composed()
> > +     */
> > +    memcpy(len_ptr, &table_len_le, sizeof table_len_le);  
> can't you use a garray/build_append function instead to be homogeneous
> with the rest of the code?
those are for inserting/adding _new_ values, and won't work here,
here we are patching value in place, comment above was supposed
to clarify that (I guess it wasn't sufficient),
Care to suggest a better comment?

> > +
> > +    bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
> > +        desc->table_offset, table_len, desc->table_offset + checksum_offset);
> > +}
> > +
> >  void
> >  build_header(BIOSLinker *linker, GArray *table_data,
> >               AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
> >   
> 
> Thanks
> 
> Eric
> 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 01/35] acpi: add helper routines to initialize ACPI tables
  2021-09-03  7:12     ` Igor Mammedov
@ 2021-09-03  7:22       ` Eric Auger
  2021-09-06 12:17         ` Igor Mammedov
  2021-09-04 19:57       ` Michael S. Tsirkin
  1 sibling, 1 reply; 56+ messages in thread
From: Eric Auger @ 2021-09-03  7:22 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel, mst

Hi Igor,

On 9/3/21 9:12 AM, Igor Mammedov wrote:
> On Thu, 2 Sep 2021 14:56:00 +0200
> Eric Auger <eauger@redhat.com> wrote:
> 
>> Hi Igor,
>>
>> On 7/8/21 5:45 PM, Igor Mammedov wrote:
>>> Patch introduces acpi_init_table()/acpi_table_composed() API
>>> that hides pointer/offset arithmetic from user as opposed
>>> to build_header(), to prevent errors caused by it [1].
>>>
>>>  acpi_init_table():
>>>      initializes table header and keeps track of
>>>      table data/offsets
>>>  acpi_table_composed():
>>>      sets actual table length and tells bios loader
>>>      where table is for the later initialization on
>>>      guest side.  
>> might be worth to put those comments in the code as doc comments since
>> "_composed" terminology is not self-explanatory?
> 
> I'll add doc comments as suggested.
> A better idea how to name function is welcome as well?
acpi_table_build_init()/_complete() or somethink like that giving an
idea of what it does actually. But you would be obliged to revisit all
the patches. I think it is good enough if you add the comment.
> 
> 
>>> 1) commits
>>>    bb9feea43179 x86: acpi: use offset instead of pointer when using build_header()
>>>    4d027afeb3a9 Virt: ACPI: fix qemu assert due to re-assigned table data address
>>>
>>> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
>>> ---
>>>  include/hw/acpi/aml-build.h | 14 +++++++++
>>>  hw/acpi/aml-build.c         | 58 +++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 72 insertions(+)
>>>
>>> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
>>> index 471266d739..d590660bd2 100644
>>> --- a/include/hw/acpi/aml-build.h
>>> +++ b/include/hw/acpi/aml-build.h
>>> @@ -413,6 +413,20 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
>>>  Aml *aml_object_type(Aml *object);
>>>  
>>>  void build_append_int_noprefix(GArray *table, uint64_t value, int size);
>>> +
>>> +typedef struct AcpiTable {
>>> +    const char *sig;
>>> +    const uint8_t rev;
>>> +    const char *oem_id;
>>> +    const char *oem_table_id;
>>> +    /* private vars tracking table state */
>>> +    GArray *array;
>>> +    unsigned table_offset;
>>> +} AcpiTable;
>>> +
>>> +void acpi_init_table(AcpiTable *desc, GArray *array);
>>> +void acpi_table_composed(BIOSLinker *linker, AcpiTable *table);
>>> +
>>>  void
>>>  build_header(BIOSLinker *linker, GArray *table_data,
>>>               AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
>>> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
>>> index d5103e6d7b..c598010144 100644
>>> --- a/hw/acpi/aml-build.c
>>> +++ b/hw/acpi/aml-build.c
>>> @@ -52,6 +52,19 @@ static void build_append_byte(GArray *array, uint8_t val)
>>>      g_array_append_val(array, val);
>>>  }
>>>  
>>> +static void build_append_padded_str(GArray *array, const char *str,
>>> +                                    size_t maxlen, char pad)
>>> +{
>>> +    size_t i;
>>> +    size_t len = strlen(str);
>>> +
>>> +    g_assert(len <= maxlen);
>>> +    g_array_append_vals(array, str, len);
>>> +    for (i = maxlen - len; i > 0; i--) {
>>> +        g_array_append_val(array, pad);
>>> +    }
>>> +}
>>> +
>>>  static void build_append_array(GArray *array, GArray *val)
>>>  {
>>>      g_array_append_vals(array, val->data, val->len);
>>> @@ -1692,6 +1705,51 @@ Aml *aml_object_type(Aml *object)
>>>      return var;
>>>  }
>>>  
>>> +void acpi_init_table(AcpiTable *desc, GArray *array)
>>> +{
>>> +
>>> +    desc->array = array;
>>> +    desc->table_offset = array->len;
>>> +
>>> +    /*
>>> +     * ACPI spec 1.0b
>>> +     * 5.2.3 System Description Table Header
>>> +     */
>>> +    g_assert(strlen(desc->sig) == 4);
>>> +    g_array_append_vals(array, desc->sig, 4); /* Signature */  
>> build_append_padded_str?
> 
> it will do the job even if it's a bit of overkill,
> signature must be 4 characters long so there is nothing to pad here
> (at least till this day).
> Using padded variant may confuse reader in the future,
> so I'd prefer to keep this line as is.

sure it was just a nit
> 
> 
>>> +    build_append_int_noprefix(array, 0, 4); /* Length */
>>> +    build_append_int_noprefix(array, desc->rev, 1); /* Revision */
>>> +    build_append_int_noprefix(array, 0, 1); /* Checksum */
>>> +    build_append_padded_str(array, desc->oem_id, 6, ' '); /* OEMID */
>>> +    /* OEM Table ID */
>>> +    build_append_padded_str(array, desc->oem_table_id, 8, ' ');
>>> +    build_append_int_noprefix(array, 1, 4); /* OEM Revision */
>>> +    g_array_append_vals(array, ACPI_BUILD_APPNAME8, 4); /* Creator ID */
> 
> here we potentially can reuse build_append_padded_str() if we
> remove padding in ACPI_BUILD_APPNAME8, but that should wait till
> refactoring is complete (to avoid breaking incremental refactoring)

OK
> 
>>> +    build_append_int_noprefix(array, 1, 4); /* Creator Revision */
>>> +}
>>> +
>>> +void acpi_table_composed(BIOSLinker *linker, AcpiTable *desc)
>>> +{
>>> +    /*
>>> +     * ACPI spec 1.0b
>>> +     * 5.2.3 System Description Table Header
>>> +     * Table 5-2 DESCRIPTION_HEADER Fields
>>> +     */
>>> +    const unsigned checksum_offset = 9;
>>> +    uint32_t table_len = desc->array->len - desc->table_offset;
>>> +    uint32_t table_len_le = cpu_to_le32(table_len);
>>> +    gchar *len_ptr = &desc->array->data[desc->table_offset + 4];
>>> +
>>> +    /* patch "Length" field that has been reserved by acpi_init_table()
>>> +     * to the actual length, i.e. accumulated table length from
>>> +     * acpi_init_table() till acpi_table_composed()
>>> +     */
>>> +    memcpy(len_ptr, &table_len_le, sizeof table_len_le);  
>> can't you use a garray/build_append function instead to be homogeneous
>> with the rest of the code?
> those are for inserting/adding _new_ values, and won't work here,
> here we are patching value in place, comment above was supposed
> to clarify that (I guess it wasn't sufficient),
> Care to suggest a better comment?

I thought  g_array_insert_vals() could do the job. No the comment was
clear to me actually.      Maybe in acpi_init_table, along with Length
comment you add a comment saying actual value will be set in composed().

Eric
> 
>>> +
>>> +    bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
>>> +        desc->table_offset, table_len, desc->table_offset + checksum_offset);
>>> +}
>>> +
>>>  void
>>>  build_header(BIOSLinker *linker, GArray *table_data,
>>>               AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
>>>   
>>
>> Thanks
>>
>> Eric
>>
> 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 31/35] acpi: arm/virt: build_spcr: use acpi_init_table()/acpi_table_composed() instead of build_header()
  2021-09-02 15:49   ` Eric Auger
@ 2021-09-03  7:52     ` Igor Mammedov
  0 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-09-03  7:52 UTC (permalink / raw)
  To: Eric Auger
  Cc: peter.maydell, drjones, mst, qemu-devel, shannon.zhaosl, qemu-arm

On Thu, 2 Sep 2021 17:49:55 +0200
Eric Auger <eauger@redhat.com> wrote:

> Hi Igor,
> 
> On 7/8/21 5:46 PM, Igor Mammedov wrote:
> > it replaces error-prone pointer arithmetic for build_header() API,
> > with 2 calls to start and finish table creation,
> > which hides offsets magic from API user.
> > 
> > while at it, replace packed structure with endian agnostic
> > build_append_FOO() API.
> > 
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > ---
> > CC: drjones@redhat.com
> > CC: peter.maydell@linaro.org
> > CC: shannon.zhaosl@gmail.com
> > CC: qemu-arm@nongnu.org
> > ---
> >  include/hw/acpi/acpi-defs.h | 32 -----------------
> >  hw/arm/virt-acpi-build.c    | 68 ++++++++++++++++++++++---------------
> >  2 files changed, 41 insertions(+), 59 deletions(-)
> > 
> > diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
> > index 6f2f08a9de..012c4ffb3a 100644
> > --- a/include/hw/acpi/acpi-defs.h
> > +++ b/include/hw/acpi/acpi-defs.h
> > @@ -117,38 +117,6 @@ typedef struct AcpiFadtData {
> >  #define ACPI_FADT_ARM_PSCI_COMPLIANT  (1 << 0)
> >  #define ACPI_FADT_ARM_PSCI_USE_HVC    (1 << 1)
> >  
> > -/*
> > - * Serial Port Console Redirection Table (SPCR), Rev. 1.02
> > - *
> > - * For .interface_type see Debug Port Table 2 (DBG2) serial port
> > - * subtypes in Table 3, Rev. May 22, 2012
> > - */
> > -struct AcpiSerialPortConsoleRedirection {
> > -    ACPI_TABLE_HEADER_DEF
> > -    uint8_t  interface_type;
> > -    uint8_t  reserved1[3];
> > -    struct AcpiGenericAddress base_address;
> > -    uint8_t  interrupt_types;
> > -    uint8_t  irq;
> > -    uint32_t gsi;
> > -    uint8_t  baud;
> > -    uint8_t  parity;
> > -    uint8_t  stopbits;
> > -    uint8_t  flowctrl;
> > -    uint8_t  term_type;
> > -    uint8_t  reserved2;
> > -    uint16_t pci_device_id;
> > -    uint16_t pci_vendor_id;
> > -    uint8_t  pci_bus;
> > -    uint8_t  pci_slot;
> > -    uint8_t  pci_func;
> > -    uint32_t pci_flags;
> > -    uint8_t  pci_seg;
> > -    uint32_t reserved3;
> > -} QEMU_PACKED;
> > -typedef struct AcpiSerialPortConsoleRedirection
> > -               AcpiSerialPortConsoleRedirection;
> > -
> >  /*
> >   * ACPI 1.0 Firmware ACPI Control Structure (FACS)
> >   */
> > diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> > index a07540affb..e8553dcae5 100644
> > --- a/hw/arm/virt-acpi-build.c
> > +++ b/hw/arm/virt-acpi-build.c
> > @@ -349,39 +349,53 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> >      acpi_table_composed(linker, &table);
> >  }
> >  
> > +/*
> > + * Serial Port Console Redirection Table (SPCR)
> > + * Rev: 1.07
> > + */  
> was
> /*
>  * Serial Port Console Redirection Table (SPCR), Rev. 1.02
>  */
> 
> By the way
> https://uefi.org/acpi/specs does not list 1.02 nor 1.07
> https://docs.microsoft.com/en-us/windows-hardware/drivers/serports/serial-port-console-redirection-table
> ?

That's problem with using MS 'specifications', which is a web page
pointing to the current revision only. (I wasn't able to find
1.02 revision to use doc comments).
So I had to use currently available, which is 1.07 currently,
which seems to be binary compatible with our original 1.02
(that's why it passes bios-tables-test).

> 
> >  static void
> >  build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> >  {
> > -    AcpiSerialPortConsoleRedirection *spcr;
> > -    const MemMapEntry *uart_memmap = &vms->memmap[VIRT_UART];
> > -    int irq = vms->irqmap[VIRT_UART] + ARM_SPI_BASE;
> > -    int spcr_start = table_data->len;
> > -
> > -    spcr = acpi_data_push(table_data, sizeof(*spcr));
> > -
> > -    spcr->interface_type = 0x3;    /* ARM PL011 UART */
> > -
> > -    spcr->base_address.space_id = AML_AS_SYSTEM_MEMORY;
> > -    spcr->base_address.bit_width = 8;
> > -    spcr->base_address.bit_offset = 0;
> > -    spcr->base_address.access_width = 1;
> > -    spcr->base_address.address = cpu_to_le64(uart_memmap->base);
> > -
> > -    spcr->interrupt_types = (1 << 3); /* Bit[3] ARMH GIC interrupt */
> > -    spcr->gsi = cpu_to_le32(irq);  /* Global System Interrupt */
> > +    AcpiTable table = { .sig = "SPCR", .rev = 2, .oem_id = vms->oem_id,
> > +                        .oem_table_id = vms->oem_table_id };
> >  
> > -    spcr->baud = 3;                /* Baud Rate: 3 = 9600 */
> > -    spcr->parity = 0;              /* No Parity */
> > -    spcr->stopbits = 1;            /* 1 Stop bit */
> > -    spcr->flowctrl = (1 << 1);     /* Bit[1] = RTS/CTS hardware flow control */
> > -    spcr->term_type = 0;           /* Terminal Type: 0 = VT100 */
> > +    acpi_init_table(&table, table_data);
> >  
> > -    spcr->pci_device_id = 0xffff;  /* PCI Device ID: not a PCI device */
> > -    spcr->pci_vendor_id = 0xffff;  /* PCI Vendor ID: not a PCI device */
> > +    /* Interface Type */
> > +    build_append_int_noprefix(table_data, 3, 1); /* ARM PL011 UART */
> > +    build_append_int_noprefix(table_data, 0, 3); /* Reserved */
> > +    /* Base Address */
> > +    build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 8, 0, 1,
> > +                     vms->memmap[VIRT_UART].base);
> > +    /* Interrupt Type */
> > +    build_append_int_noprefix(table_data,
> > +        (1 << 3) /* Bit[3] ARMH GIC interrupt */, 1);
> > +    build_append_int_noprefix(table_data, 0, 1); /* IRQ */
> > +    /* Global System Interrupt */
> > +    build_append_int_noprefix(table_data,
> > +                              vms->irqmap[VIRT_UART] + ARM_SPI_BASE, 4);
> > +    build_append_int_noprefix(table_data, 3 /* 9600 */, 1); /* Baud Rate */
> > +    build_append_int_noprefix(table_data, 0 /* No Parity */, 1); /* Parity */
> > +    /* Stop Bits */
> > +    build_append_int_noprefix(table_data, 1 /* 1 Stop bit */, 1);
> > +    /* Flow Control */
> > +    build_append_int_noprefix(table_data,
> > +        (1 << 1) /* RTS/CTS hardware flow control */, 1);
> > +    /* Terminal Type */
> > +    build_append_int_noprefix(table_data, 0 /* VT100 */, 1);
> > +    build_append_int_noprefix(table_data, 0, 1); /* Language */  
> reserved2 -> language in 1.07? but that's fine
> maybe just mention it in the commit msg?

sure, I'll add that into commit message.

> > +    /* PCI Device ID  */
> > +    build_append_int_noprefix(table_data, 0xffff /* not a PCI device*/, 2);
> > +    /* PCI Vendor ID */
> > +    build_append_int_noprefix(table_data, 0xffff /* not a PCI device*/, 2);
> > +    build_append_int_noprefix(table_data, 0, 1); /* PCI Bus Number */
> > +    build_append_int_noprefix(table_data, 0, 1); /* PCI Device Number */
> > +    build_append_int_noprefix(table_data, 0, 1); /* PCI Function Number */
> > +    build_append_int_noprefix(table_data, 0, 4); /* PCI Flags */
> > +    build_append_int_noprefix(table_data, 0, 1); /* PCI Segment */
> > +    build_append_int_noprefix(table_data, 0, 4); /* Reserved */
> >  
> > -    build_header(linker, table_data, (void *)(table_data->data + spcr_start),
> > -                 "SPCR", table_data->len - spcr_start, 2, vms->oem_id,
> > -                 vms->oem_table_id);
> > +    acpi_table_composed(linker, &table);
> >  }
> >  
> >  /*
> >   
> Reviewed-by: Eric Auger <eric.auger@redhat.com>
> 
> Eric
> 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 25/35] acpi: arm/virt: madt: use build_append_int_noprefix() API to compose MADT table
  2021-07-08 15:46 ` [PATCH v2 25/35] acpi: arm/virt: " Igor Mammedov
@ 2021-09-03 13:45   ` Eric Auger
  2021-09-06 12:40     ` Igor Mammedov
  0 siblings, 1 reply; 56+ messages in thread
From: Eric Auger @ 2021-09-03 13:45 UTC (permalink / raw)
  To: Igor Mammedov, qemu-devel
  Cc: peter.maydell, drjones, qemu-arm, mst, shannon.zhaosl

Hi Igor,
On 7/8/21 5:46 PM, Igor Mammedov wrote:
> Drop usage of packed structures and explicit endian conversions
> when building MADT table for arm/x86 and use endian agnostic
> build_append_int_noprefix() API to build it.
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
> CC: drjones@redhat.com
> CC: peter.maydell@linaro.org
> CC: shannon.zhaosl@gmail.com
> CC: qemu-arm@nongnu.org
> ---
>  include/hw/acpi/acpi-defs.h |  84 --------------------
>  hw/arm/virt-acpi-build.c    | 149 +++++++++++++++++++++---------------
>  2 files changed, 89 insertions(+), 144 deletions(-)
> 
> diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
> index 3f174ba208..bcada37601 100644
> --- a/include/hw/acpi/acpi-defs.h
> +++ b/include/hw/acpi/acpi-defs.h
> @@ -163,90 +163,6 @@ struct AcpiFacsDescriptorRev1 {
>  } QEMU_PACKED;
>  typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
>  
> -/* Values for Type in APIC sub-headers */
> -
> -#define ACPI_APIC_GENERIC_CPU_INTERFACE 11
> -#define ACPI_APIC_GENERIC_DISTRIBUTOR   12
> -#define ACPI_APIC_GENERIC_MSI_FRAME     13
> -#define ACPI_APIC_GENERIC_REDISTRIBUTOR 14
> -#define ACPI_APIC_GENERIC_TRANSLATOR    15
> -#define ACPI_APIC_RESERVED              16   /* 16 and greater are reserved */
> -
> -/*
> - * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
> - */
> -#define ACPI_SUB_HEADER_DEF   /* Common ACPI sub-structure header */\
> -    uint8_t  type;                               \
> -    uint8_t  length;
> -
> -/* Sub-structures for MADT */
> -
> -struct AcpiMadtGenericCpuInterface {
> -    ACPI_SUB_HEADER_DEF
> -    uint16_t reserved;
> -    uint32_t cpu_interface_number;
> -    uint32_t uid;
> -    uint32_t flags;
> -    uint32_t parking_version;
> -    uint32_t performance_interrupt;
> -    uint64_t parked_address;
> -    uint64_t base_address;
> -    uint64_t gicv_base_address;
> -    uint64_t gich_base_address;
> -    uint32_t vgic_interrupt;
> -    uint64_t gicr_base_address;
> -    uint64_t arm_mpidr;
> -} QEMU_PACKED;
> -
> -typedef struct AcpiMadtGenericCpuInterface AcpiMadtGenericCpuInterface;
> -
> -/* GICC CPU Interface Flags */
> -#define ACPI_MADT_GICC_ENABLED 1
> -
> -struct AcpiMadtGenericDistributor {
> -    ACPI_SUB_HEADER_DEF
> -    uint16_t reserved;
> -    uint32_t gic_id;
> -    uint64_t base_address;
> -    uint32_t global_irq_base;
> -    /* ACPI 5.1 Errata 1228 Present GIC version in MADT table */
> -    uint8_t version;
> -    uint8_t reserved2[3];
> -} QEMU_PACKED;
> -
> -typedef struct AcpiMadtGenericDistributor AcpiMadtGenericDistributor;
> -
> -struct AcpiMadtGenericMsiFrame {
> -    ACPI_SUB_HEADER_DEF
> -    uint16_t reserved;
> -    uint32_t gic_msi_frame_id;
> -    uint64_t base_address;
> -    uint32_t flags;
> -    uint16_t spi_count;
> -    uint16_t spi_base;
> -} QEMU_PACKED;
> -
> -typedef struct AcpiMadtGenericMsiFrame AcpiMadtGenericMsiFrame;
> -
> -struct AcpiMadtGenericRedistributor {
> -    ACPI_SUB_HEADER_DEF
> -    uint16_t reserved;
> -    uint64_t base_address;
> -    uint32_t range_length;
> -} QEMU_PACKED;
> -
> -typedef struct AcpiMadtGenericRedistributor AcpiMadtGenericRedistributor;
> -
> -struct AcpiMadtGenericTranslator {
> -    ACPI_SUB_HEADER_DEF
> -    uint16_t reserved;
> -    uint32_t translation_id;
> -    uint64_t base_address;
> -    uint32_t reserved2;
> -} QEMU_PACKED;
> -
> -typedef struct AcpiMadtGenericTranslator AcpiMadtGenericTranslator;
> -
>  /*
>   * Generic Timer Description Table (GTDT)
>   */
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index cd8b73dde9..dd8011a670 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -476,94 +476,123 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>  }
>  
>  /*
> - * ACPI spec, Revision 5.0
> + * ACPI spec, Revision 5.1 Errata A
It is a bit difficult to follow both the conversion and the upgrade of
the version. May be worth splitting both concerns if sensible.
>   * 5.2.12 Multiple APIC Description Table (MADT)
>   */
> +static void build_append_gicr(GArray *table_data, uint64_t base, uint32_t size)
> +{
> +    build_append_int_noprefix(table_data, 0xE, 1);  /* Type */
> +    build_append_int_noprefix(table_data, 16, 1);   /* Length */
> +    build_append_int_noprefix(table_data, 0, 2);    /* Reserved */
> +    /* Discovery Range Base Addres */
> +    build_append_int_noprefix(table_data, base, 8);
> +    build_append_int_noprefix(table_data, size, 4); /* Discovery Range Length */
> +}
> +
>  static void
>  build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>  {
> +    int i;
>      VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
>      const MemMapEntry *memmap = vms->memmap;
> -    const int *irqmap = vms->irqmap;
> -    AcpiMadtGenericDistributor *gicd;
> -    AcpiMadtGenericMsiFrame *gic_msi;
> -    int i;
>      AcpiTable table = { .sig = "APIC", .rev = 3, .oem_id = vms->oem_id,
>                          .oem_table_id = vms->oem_table_id };
>  
>      acpi_init_table(&table, table_data);
>      /* Local Interrupt Controller Address */
>      build_append_int_noprefix(table_data, 0, 4);
> -    build_append_int_noprefix(table_data, 0, 4); /* Flags */
> -
> -    gicd = acpi_data_push(table_data, sizeof *gicd);
> -    gicd->type = ACPI_APIC_GENERIC_DISTRIBUTOR;
> -    gicd->length = sizeof(*gicd);
> -    gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base);
> -    gicd->version = vms->gic_version;
> +    build_append_int_noprefix(table_data, 0, 4);   /* Flags */
> +
> +    /* 5.2.12.15 GIC Distributor Structure */
> +    build_append_int_noprefix(table_data, 0xC, 1); /* Type */
> +    build_append_int_noprefix(table_data, 24, 1);  /* Length */
> +    build_append_int_noprefix(table_data, 0, 2);   /* Reserved */
> +    build_append_int_noprefix(table_data, 0, 4);   /* GIC ID */
> +    /* Physical Base Address */
> +    build_append_int_noprefix(table_data, memmap[VIRT_GIC_DIST].base, 8);
> +    build_append_int_noprefix(table_data, 0, 4);   /* System Vector Base */
> +    /* GIC version */
> +    build_append_int_noprefix(table_data, vms->gic_version, 1);
> +    build_append_int_noprefix(table_data, 0, 3);   /* Reserved */
>  
>      for (i = 0; i < MACHINE(vms)->smp.cpus; i++) {
> -        AcpiMadtGenericCpuInterface *gicc = acpi_data_push(table_data,
> -                                                           sizeof(*gicc));
>          ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
> +        uint64_t physical_base_address = 0, gich = 0, gicv = 0;
> +        uint32_t vgic_interrupt = vms->virt ? PPI(ARCH_GIC_MAINT_IRQ) : 0;
> +        uint32_t pmu_interrupt = arm_feature(&armcpu->env, ARM_FEATURE_PMU) ?
> +                                             PPI(VIRTUAL_PMU_IRQ) : 0;
>  
> -        gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE;
> -        gicc->length = sizeof(*gicc);
>          if (vms->gic_version == 2) {
> -            gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base);
> -            gicc->gich_base_address = cpu_to_le64(memmap[VIRT_GIC_HYP].base);
> -            gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base);
> +            physical_base_address = memmap[VIRT_GIC_CPU].base;
> +            gicv = memmap[VIRT_GIC_VCPU].base;
> +            gich = memmap[VIRT_GIC_HYP].base;
>          }
> -        gicc->cpu_interface_number = cpu_to_le32(i);
> -        gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity);
> -        gicc->uid = cpu_to_le32(i);
> -        gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED);
>  
> -        if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
> -            gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ));
> -        }
> -        if (vms->virt) {
> -            gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GIC_MAINT_IRQ));
> -        }
> +        /* 5.2.12.14 GIC Structure */
> +        build_append_int_noprefix(table_data, 0xB, 1);  /* Type */
> +        build_append_int_noprefix(table_data, 76, 1);   /* Length */
> +        build_append_int_noprefix(table_data, 0, 2);    /* Reserved */
> +        build_append_int_noprefix(table_data, i, 4);    /* GIC ID */
> +        build_append_int_noprefix(table_data, i, 4);    /* ACPI Processor UID */
> +        /* Flags */
> +        build_append_int_noprefix(table_data, 1, 4);    /* Enabled */
> +        /* Parking Protocol Version */
> +        build_append_int_noprefix(table_data, 0, 4);
> +        /* Performance Interrupt GSIV */
> +        build_append_int_noprefix(table_data, pmu_interrupt, 4);
> +        build_append_int_noprefix(table_data, 0, 8); /* Parked Address */
> +        /* Physical Base Address */
> +        build_append_int_noprefix(table_data, physical_base_address, 8);
> +        build_append_int_noprefix(table_data, gicv, 8); /* GICV */
> +        build_append_int_noprefix(table_data, gich, 8); /* GICH */
> +        /* VGIC Maintenance interrupt */
> +        build_append_int_noprefix(table_data, vgic_interrupt, 4);
> +        build_append_int_noprefix(table_data, 0, 8);    /* GICR Base Address*/
> +        /* MPIDR */
> +        build_append_int_noprefix(table_data, armcpu->mp_affinity, 8);
>      }
>  
>      if (vms->gic_version == 3) {
> -        AcpiMadtGenericTranslator *gic_its;
> -        int nb_redist_regions = virt_gicv3_redist_region_count(vms);
> -        AcpiMadtGenericRedistributor *gicr = acpi_data_push(table_data,
> -                                                         sizeof *gicr);
> -
> -        gicr->type = ACPI_APIC_GENERIC_REDISTRIBUTOR;
> -        gicr->length = sizeof(*gicr);
> -        gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST].base);
> -        gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST].size);
> -
> -        if (nb_redist_regions == 2) {
> -            gicr = acpi_data_push(table_data, sizeof(*gicr));
> -            gicr->type = ACPI_APIC_GENERIC_REDISTRIBUTOR;
> -            gicr->length = sizeof(*gicr);
> -            gicr->base_address =
> -                cpu_to_le64(memmap[VIRT_HIGH_GIC_REDIST2].base);
> -            gicr->range_length =
> -                cpu_to_le32(memmap[VIRT_HIGH_GIC_REDIST2].size);
> +        build_append_gicr(table_data, memmap[VIRT_GIC_REDIST].base,
> +                                      memmap[VIRT_GIC_REDIST].size);
> +        if (virt_gicv3_redist_region_count(vms) == 2) {
> +            build_append_gicr(table_data, memmap[VIRT_HIGH_GIC_REDIST2].base,
> +                                          memmap[VIRT_HIGH_GIC_REDIST2].size);
>          }
>  
>          if (its_class_name() && !vmc->no_its) {
> -            gic_its = acpi_data_push(table_data, sizeof *gic_its);
> -            gic_its->type = ACPI_APIC_GENERIC_TRANSLATOR;
> -            gic_its->length = sizeof(*gic_its);
> -            gic_its->translation_id = 0;
> -            gic_its->base_address = cpu_to_le64(memmap[VIRT_GIC_ITS].base);
> +            /*
> +             * FIXME: Structure is from Revision 6.0 where 'GIC Structure'
> +             * has additional fields on top of implemented 5.1 Errata A
> +             * make it consistent with v6.0 if ITS is present or bump
> +             * everything to v6.0 unconditionally
Do you mean some parts are 5.1 errata A and some others are 6.0 already?
> +             */
> +            /*
> +             * ACPI spec, Revision  6.0
> +             * 5.2.12.18 GIC ITS Structure
> +             */
> +            build_append_int_noprefix(table_data, 0xF, 1);  /* Type */
> +            build_append_int_noprefix(table_data, 16, 1);   /* Length */
this is 20 and not 16. Currently it fails with ITS.

With that fix
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric

> +            build_append_int_noprefix(table_data, 0, 2);    /* Reserved */
> +            build_append_int_noprefix(table_data, 0, 4);    /* GIC ITS ID */
> +            /* Physical Base Address */
> +            build_append_int_noprefix(table_data, memmap[VIRT_GIC_ITS].base, 8);
> +            build_append_int_noprefix(table_data, 0, 4);    /* Reserved */
>          }
>      } else {
> -        gic_msi = acpi_data_push(table_data, sizeof *gic_msi);
> -        gic_msi->type = ACPI_APIC_GENERIC_MSI_FRAME;
> -        gic_msi->length = sizeof(*gic_msi);
> -        gic_msi->gic_msi_frame_id = 0;
> -        gic_msi->base_address = cpu_to_le64(memmap[VIRT_GIC_V2M].base);
> -        gic_msi->flags = cpu_to_le32(1);
> -        gic_msi->spi_count = cpu_to_le16(NUM_GICV2M_SPIS);
> -        gic_msi->spi_base = cpu_to_le16(irqmap[VIRT_GIC_V2M] + ARM_SPI_BASE);
> +        const uint16_t spi_base = vms->irqmap[VIRT_GIC_V2M] + ARM_SPI_BASE;
> +
> +        /* 5.2.12.16 GIC MSI Frame Structure */
> +        build_append_int_noprefix(table_data, 0xD, 1);  /* Type */
> +        build_append_int_noprefix(table_data, 24, 1);   /* Length */
> +        build_append_int_noprefix(table_data, 0, 2);    /* Reserved */
> +        build_append_int_noprefix(table_data, 0, 4);    /* GIC MSI Frame ID */
> +        /* Physical Base Address */
> +        build_append_int_noprefix(table_data, memmap[VIRT_GIC_V2M].base, 8);
> +        build_append_int_noprefix(table_data, 1, 4);    /* Flags */
> +        /* SPI Count */
> +        build_append_int_noprefix(table_data, NUM_GICV2M_SPIS, 2);
> +        build_append_int_noprefix(table_data, spi_base, 2); /* SPI Base */
>      }
>      acpi_table_composed(linker, &table);
>  }
> 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 01/35] acpi: add helper routines to initialize ACPI tables
  2021-09-03  7:12     ` Igor Mammedov
  2021-09-03  7:22       ` Eric Auger
@ 2021-09-04 19:57       ` Michael S. Tsirkin
  2021-09-06 12:14         ` Igor Mammedov
  1 sibling, 1 reply; 56+ messages in thread
From: Michael S. Tsirkin @ 2021-09-04 19:57 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: Eric Auger, qemu-devel

On Fri, Sep 03, 2021 at 09:12:21AM +0200, Igor Mammedov wrote:
> On Thu, 2 Sep 2021 14:56:00 +0200
> Eric Auger <eauger@redhat.com> wrote:
> 
> > Hi Igor,
> > 
> > On 7/8/21 5:45 PM, Igor Mammedov wrote:
> > > Patch introduces acpi_init_table()/acpi_table_composed() API
> > > that hides pointer/offset arithmetic from user as opposed
> > > to build_header(), to prevent errors caused by it [1].
> > > 
> > >  acpi_init_table():
> > >      initializes table header and keeps track of
> > >      table data/offsets
> > >  acpi_table_composed():
> > >      sets actual table length and tells bios loader
> > >      where table is for the later initialization on
> > >      guest side.  
> > might be worth to put those comments in the code as doc comments since
> > "_composed" terminology is not self-explanatory?
> 
> I'll add doc comments as suggested.
> A better idea how to name function is welcome as well?

Aren't these a pair? acpi_init_table is called before you
start composing it, acpi_table_composed after it's composed?

Then one of the classical pairs will work well, e.g.
acpi_table_begin / acpi_table_end or maybe
acpi_table_compose_begin / acpi_table_compose_end .


> 
> > > 1) commits
> > >    bb9feea43179 x86: acpi: use offset instead of pointer when using build_header()
> > >    4d027afeb3a9 Virt: ACPI: fix qemu assert due to re-assigned table data address
> > > 
> > > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > > ---
> > >  include/hw/acpi/aml-build.h | 14 +++++++++
> > >  hw/acpi/aml-build.c         | 58 +++++++++++++++++++++++++++++++++++++
> > >  2 files changed, 72 insertions(+)
> > > 
> > > diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> > > index 471266d739..d590660bd2 100644
> > > --- a/include/hw/acpi/aml-build.h
> > > +++ b/include/hw/acpi/aml-build.h
> > > @@ -413,6 +413,20 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
> > >  Aml *aml_object_type(Aml *object);
> > >  
> > >  void build_append_int_noprefix(GArray *table, uint64_t value, int size);
> > > +
> > > +typedef struct AcpiTable {
> > > +    const char *sig;
> > > +    const uint8_t rev;
> > > +    const char *oem_id;
> > > +    const char *oem_table_id;
> > > +    /* private vars tracking table state */
> > > +    GArray *array;
> > > +    unsigned table_offset;
> > > +} AcpiTable;
> > > +
> > > +void acpi_init_table(AcpiTable *desc, GArray *array);
> > > +void acpi_table_composed(BIOSLinker *linker, AcpiTable *table);
> > > +
> > >  void
> > >  build_header(BIOSLinker *linker, GArray *table_data,
> > >               AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
> > > diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> > > index d5103e6d7b..c598010144 100644
> > > --- a/hw/acpi/aml-build.c
> > > +++ b/hw/acpi/aml-build.c
> > > @@ -52,6 +52,19 @@ static void build_append_byte(GArray *array, uint8_t val)
> > >      g_array_append_val(array, val);
> > >  }
> > >  
> > > +static void build_append_padded_str(GArray *array, const char *str,
> > > +                                    size_t maxlen, char pad)
> > > +{
> > > +    size_t i;
> > > +    size_t len = strlen(str);
> > > +
> > > +    g_assert(len <= maxlen);
> > > +    g_array_append_vals(array, str, len);
> > > +    for (i = maxlen - len; i > 0; i--) {
> > > +        g_array_append_val(array, pad);
> > > +    }
> > > +}
> > > +
> > >  static void build_append_array(GArray *array, GArray *val)
> > >  {
> > >      g_array_append_vals(array, val->data, val->len);
> > > @@ -1692,6 +1705,51 @@ Aml *aml_object_type(Aml *object)
> > >      return var;
> > >  }
> > >  
> > > +void acpi_init_table(AcpiTable *desc, GArray *array)
> > > +{
> > > +
> > > +    desc->array = array;
> > > +    desc->table_offset = array->len;
> > > +
> > > +    /*
> > > +     * ACPI spec 1.0b
> > > +     * 5.2.3 System Description Table Header
> > > +     */
> > > +    g_assert(strlen(desc->sig) == 4);
> > > +    g_array_append_vals(array, desc->sig, 4); /* Signature */  
> > build_append_padded_str?
> 
> it will do the job even if it's a bit of overkill,
> signature must be 4 characters long so there is nothing to pad here
> (at least till this day).
> Using padded variant may confuse reader in the future,
> so I'd prefer to keep this line as is.
> 
> 
> > > +    build_append_int_noprefix(array, 0, 4); /* Length */
> > > +    build_append_int_noprefix(array, desc->rev, 1); /* Revision */
> > > +    build_append_int_noprefix(array, 0, 1); /* Checksum */
> > > +    build_append_padded_str(array, desc->oem_id, 6, ' '); /* OEMID */
> > > +    /* OEM Table ID */
> > > +    build_append_padded_str(array, desc->oem_table_id, 8, ' ');
> > > +    build_append_int_noprefix(array, 1, 4); /* OEM Revision */
> > > +    g_array_append_vals(array, ACPI_BUILD_APPNAME8, 4); /* Creator ID */
> 
> here we potentially can reuse build_append_padded_str() if we
> remove padding in ACPI_BUILD_APPNAME8, but that should wait till
> refactoring is complete (to avoid breaking incremental refactoring)
> 
> > > +    build_append_int_noprefix(array, 1, 4); /* Creator Revision */
> > > +}
> > > +
> > > +void acpi_table_composed(BIOSLinker *linker, AcpiTable *desc)
> > > +{
> > > +    /*
> > > +     * ACPI spec 1.0b
> > > +     * 5.2.3 System Description Table Header
> > > +     * Table 5-2 DESCRIPTION_HEADER Fields
> > > +     */
> > > +    const unsigned checksum_offset = 9;
> > > +    uint32_t table_len = desc->array->len - desc->table_offset;
> > > +    uint32_t table_len_le = cpu_to_le32(table_len);
> > > +    gchar *len_ptr = &desc->array->data[desc->table_offset + 4];
> > > +
> > > +    /* patch "Length" field that has been reserved by acpi_init_table()
> > > +     * to the actual length, i.e. accumulated table length from
> > > +     * acpi_init_table() till acpi_table_composed()
> > > +     */
> > > +    memcpy(len_ptr, &table_len_le, sizeof table_len_le);  
> > can't you use a garray/build_append function instead to be homogeneous
> > with the rest of the code?
> those are for inserting/adding _new_ values, and won't work here,
> here we are patching value in place, comment above was supposed
> to clarify that (I guess it wasn't sufficient),
> Care to suggest a better comment?
> 
> > > +
> > > +    bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
> > > +        desc->table_offset, table_len, desc->table_offset + checksum_offset);
> > > +}
> > > +
> > >  void
> > >  build_header(BIOSLinker *linker, GArray *table_data,
> > >               AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
> > >   
> > 
> > Thanks
> > 
> > Eric
> > 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 01/35] acpi: add helper routines to initialize ACPI tables
  2021-09-04 19:57       ` Michael S. Tsirkin
@ 2021-09-06 12:14         ` Igor Mammedov
  0 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-09-06 12:14 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Eric Auger, qemu-devel

On Sat, 4 Sep 2021 15:57:52 -0400
"Michael S. Tsirkin" <mst@redhat.com> wrote:

> On Fri, Sep 03, 2021 at 09:12:21AM +0200, Igor Mammedov wrote:
> > On Thu, 2 Sep 2021 14:56:00 +0200
> > Eric Auger <eauger@redhat.com> wrote:
> >   
> > > Hi Igor,
> > > 
> > > On 7/8/21 5:45 PM, Igor Mammedov wrote:  
> > > > Patch introduces acpi_init_table()/acpi_table_composed() API
> > > > that hides pointer/offset arithmetic from user as opposed
> > > > to build_header(), to prevent errors caused by it [1].
> > > > 
> > > >  acpi_init_table():
> > > >      initializes table header and keeps track of
> > > >      table data/offsets
> > > >  acpi_table_composed():
> > > >      sets actual table length and tells bios loader
> > > >      where table is for the later initialization on
> > > >      guest side.    
> > > might be worth to put those comments in the code as doc comments since
> > > "_composed" terminology is not self-explanatory?  
> > 
> > I'll add doc comments as suggested.
> > A better idea how to name function is welcome as well?  
> 
> Aren't these a pair? acpi_init_table is called before you
> start composing it, acpi_table_composed after it's composed?
yep, that's the basic idea.

 
> Then one of the classical pairs will work well, e.g.
> acpi_table_begin / acpi_table_end or maybe

I'll use this on respin,
 as more concise compared to _compose_

> acpi_table_compose_begin / acpi_table_compose_end .
> 
> 
> >   
> > > > 1) commits
> > > >    bb9feea43179 x86: acpi: use offset instead of pointer when using build_header()
> > > >    4d027afeb3a9 Virt: ACPI: fix qemu assert due to re-assigned table data address
> > > > 
> > > > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > > > ---
> > > >  include/hw/acpi/aml-build.h | 14 +++++++++
> > > >  hw/acpi/aml-build.c         | 58 +++++++++++++++++++++++++++++++++++++
> > > >  2 files changed, 72 insertions(+)
> > > > 
> > > > diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> > > > index 471266d739..d590660bd2 100644
> > > > --- a/include/hw/acpi/aml-build.h
> > > > +++ b/include/hw/acpi/aml-build.h
> > > > @@ -413,6 +413,20 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
> > > >  Aml *aml_object_type(Aml *object);
> > > >  
> > > >  void build_append_int_noprefix(GArray *table, uint64_t value, int size);
> > > > +
> > > > +typedef struct AcpiTable {
> > > > +    const char *sig;
> > > > +    const uint8_t rev;
> > > > +    const char *oem_id;
> > > > +    const char *oem_table_id;
> > > > +    /* private vars tracking table state */
> > > > +    GArray *array;
> > > > +    unsigned table_offset;
> > > > +} AcpiTable;
> > > > +
> > > > +void acpi_init_table(AcpiTable *desc, GArray *array);
> > > > +void acpi_table_composed(BIOSLinker *linker, AcpiTable *table);
> > > > +
> > > >  void
> > > >  build_header(BIOSLinker *linker, GArray *table_data,
> > > >               AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
> > > > diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> > > > index d5103e6d7b..c598010144 100644
> > > > --- a/hw/acpi/aml-build.c
> > > > +++ b/hw/acpi/aml-build.c
> > > > @@ -52,6 +52,19 @@ static void build_append_byte(GArray *array, uint8_t val)
> > > >      g_array_append_val(array, val);
> > > >  }
> > > >  
> > > > +static void build_append_padded_str(GArray *array, const char *str,
> > > > +                                    size_t maxlen, char pad)
> > > > +{
> > > > +    size_t i;
> > > > +    size_t len = strlen(str);
> > > > +
> > > > +    g_assert(len <= maxlen);
> > > > +    g_array_append_vals(array, str, len);
> > > > +    for (i = maxlen - len; i > 0; i--) {
> > > > +        g_array_append_val(array, pad);
> > > > +    }
> > > > +}
> > > > +
> > > >  static void build_append_array(GArray *array, GArray *val)
> > > >  {
> > > >      g_array_append_vals(array, val->data, val->len);
> > > > @@ -1692,6 +1705,51 @@ Aml *aml_object_type(Aml *object)
> > > >      return var;
> > > >  }
> > > >  
> > > > +void acpi_init_table(AcpiTable *desc, GArray *array)
> > > > +{
> > > > +
> > > > +    desc->array = array;
> > > > +    desc->table_offset = array->len;
> > > > +
> > > > +    /*
> > > > +     * ACPI spec 1.0b
> > > > +     * 5.2.3 System Description Table Header
> > > > +     */
> > > > +    g_assert(strlen(desc->sig) == 4);
> > > > +    g_array_append_vals(array, desc->sig, 4); /* Signature */    
> > > build_append_padded_str?  
> > 
> > it will do the job even if it's a bit of overkill,
> > signature must be 4 characters long so there is nothing to pad here
> > (at least till this day).
> > Using padded variant may confuse reader in the future,
> > so I'd prefer to keep this line as is.
> > 
> >   
> > > > +    build_append_int_noprefix(array, 0, 4); /* Length */
> > > > +    build_append_int_noprefix(array, desc->rev, 1); /* Revision */
> > > > +    build_append_int_noprefix(array, 0, 1); /* Checksum */
> > > > +    build_append_padded_str(array, desc->oem_id, 6, ' '); /* OEMID */
> > > > +    /* OEM Table ID */
> > > > +    build_append_padded_str(array, desc->oem_table_id, 8, ' ');
> > > > +    build_append_int_noprefix(array, 1, 4); /* OEM Revision */
> > > > +    g_array_append_vals(array, ACPI_BUILD_APPNAME8, 4); /* Creator ID */  
> > 
> > here we potentially can reuse build_append_padded_str() if we
> > remove padding in ACPI_BUILD_APPNAME8, but that should wait till
> > refactoring is complete (to avoid breaking incremental refactoring)
> >   
> > > > +    build_append_int_noprefix(array, 1, 4); /* Creator Revision */
> > > > +}
> > > > +
> > > > +void acpi_table_composed(BIOSLinker *linker, AcpiTable *desc)
> > > > +{
> > > > +    /*
> > > > +     * ACPI spec 1.0b
> > > > +     * 5.2.3 System Description Table Header
> > > > +     * Table 5-2 DESCRIPTION_HEADER Fields
> > > > +     */
> > > > +    const unsigned checksum_offset = 9;
> > > > +    uint32_t table_len = desc->array->len - desc->table_offset;
> > > > +    uint32_t table_len_le = cpu_to_le32(table_len);
> > > > +    gchar *len_ptr = &desc->array->data[desc->table_offset + 4];
> > > > +
> > > > +    /* patch "Length" field that has been reserved by acpi_init_table()
> > > > +     * to the actual length, i.e. accumulated table length from
> > > > +     * acpi_init_table() till acpi_table_composed()
> > > > +     */
> > > > +    memcpy(len_ptr, &table_len_le, sizeof table_len_le);    
> > > can't you use a garray/build_append function instead to be homogeneous
> > > with the rest of the code?  
> > those are for inserting/adding _new_ values, and won't work here,
> > here we are patching value in place, comment above was supposed
> > to clarify that (I guess it wasn't sufficient),
> > Care to suggest a better comment?
> >   
> > > > +
> > > > +    bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
> > > > +        desc->table_offset, table_len, desc->table_offset + checksum_offset);
> > > > +}
> > > > +
> > > >  void
> > > >  build_header(BIOSLinker *linker, GArray *table_data,
> > > >               AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
> > > >     
> > > 
> > > Thanks
> > > 
> > > Eric
> > >   
> 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 01/35] acpi: add helper routines to initialize ACPI tables
  2021-09-03  7:22       ` Eric Auger
@ 2021-09-06 12:17         ` Igor Mammedov
  0 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-09-06 12:17 UTC (permalink / raw)
  To: Eric Auger; +Cc: qemu-devel, mst

On Fri, 3 Sep 2021 09:22:10 +0200
Eric Auger <eauger@redhat.com> wrote:

> Hi Igor,
> 
> On 9/3/21 9:12 AM, Igor Mammedov wrote:
> > On Thu, 2 Sep 2021 14:56:00 +0200
> > Eric Auger <eauger@redhat.com> wrote:
> >   
> >> Hi Igor,
> >>
> >> On 7/8/21 5:45 PM, Igor Mammedov wrote:  
> >>> Patch introduces acpi_init_table()/acpi_table_composed() API
> >>> that hides pointer/offset arithmetic from user as opposed
> >>> to build_header(), to prevent errors caused by it [1].
> >>>
> >>>  acpi_init_table():
> >>>      initializes table header and keeps track of
> >>>      table data/offsets
> >>>  acpi_table_composed():
> >>>      sets actual table length and tells bios loader
> >>>      where table is for the later initialization on
> >>>      guest side.    
> >> might be worth to put those comments in the code as doc comments since
> >> "_composed" terminology is not self-explanatory?  
> > 
> > I'll add doc comments as suggested.
> > A better idea how to name function is welcome as well?  
> acpi_table_build_init()/_complete() or somethink like that giving an
> idea of what it does actually. But you would be obliged to revisit all
> the patches. I think it is good enough if you add the comment.

it's fine to rewrite before it's merged, one of the points
of refactoring is to make current code more clear and concise.

I'll use Michael's suggestion
   acpi_table_begin / acpi_table_end 

> > 
> >   
> >>> 1) commits
> >>>    bb9feea43179 x86: acpi: use offset instead of pointer when using build_header()
> >>>    4d027afeb3a9 Virt: ACPI: fix qemu assert due to re-assigned table data address
> >>>
> >>> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> >>> ---
> >>>  include/hw/acpi/aml-build.h | 14 +++++++++
> >>>  hw/acpi/aml-build.c         | 58 +++++++++++++++++++++++++++++++++++++
> >>>  2 files changed, 72 insertions(+)
> >>>
> >>> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> >>> index 471266d739..d590660bd2 100644
> >>> --- a/include/hw/acpi/aml-build.h
> >>> +++ b/include/hw/acpi/aml-build.h
> >>> @@ -413,6 +413,20 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
> >>>  Aml *aml_object_type(Aml *object);
> >>>  
> >>>  void build_append_int_noprefix(GArray *table, uint64_t value, int size);
> >>> +
> >>> +typedef struct AcpiTable {
> >>> +    const char *sig;
> >>> +    const uint8_t rev;
> >>> +    const char *oem_id;
> >>> +    const char *oem_table_id;
> >>> +    /* private vars tracking table state */
> >>> +    GArray *array;
> >>> +    unsigned table_offset;
> >>> +} AcpiTable;
> >>> +
> >>> +void acpi_init_table(AcpiTable *desc, GArray *array);
> >>> +void acpi_table_composed(BIOSLinker *linker, AcpiTable *table);
> >>> +
> >>>  void
> >>>  build_header(BIOSLinker *linker, GArray *table_data,
> >>>               AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
> >>> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> >>> index d5103e6d7b..c598010144 100644
> >>> --- a/hw/acpi/aml-build.c
> >>> +++ b/hw/acpi/aml-build.c
> >>> @@ -52,6 +52,19 @@ static void build_append_byte(GArray *array, uint8_t val)
> >>>      g_array_append_val(array, val);
> >>>  }
> >>>  
> >>> +static void build_append_padded_str(GArray *array, const char *str,
> >>> +                                    size_t maxlen, char pad)
> >>> +{
> >>> +    size_t i;
> >>> +    size_t len = strlen(str);
> >>> +
> >>> +    g_assert(len <= maxlen);
> >>> +    g_array_append_vals(array, str, len);
> >>> +    for (i = maxlen - len; i > 0; i--) {
> >>> +        g_array_append_val(array, pad);
> >>> +    }
> >>> +}
> >>> +
> >>>  static void build_append_array(GArray *array, GArray *val)
> >>>  {
> >>>      g_array_append_vals(array, val->data, val->len);
> >>> @@ -1692,6 +1705,51 @@ Aml *aml_object_type(Aml *object)
> >>>      return var;
> >>>  }
> >>>  
> >>> +void acpi_init_table(AcpiTable *desc, GArray *array)
> >>> +{
> >>> +
> >>> +    desc->array = array;
> >>> +    desc->table_offset = array->len;
> >>> +
> >>> +    /*
> >>> +     * ACPI spec 1.0b
> >>> +     * 5.2.3 System Description Table Header
> >>> +     */
> >>> +    g_assert(strlen(desc->sig) == 4);
> >>> +    g_array_append_vals(array, desc->sig, 4); /* Signature */    
> >> build_append_padded_str?  
> > 
> > it will do the job even if it's a bit of overkill,
> > signature must be 4 characters long so there is nothing to pad here
> > (at least till this day).
> > Using padded variant may confuse reader in the future,
> > so I'd prefer to keep this line as is.  
> 
> sure it was just a nit
> > 
> >   
> >>> +    build_append_int_noprefix(array, 0, 4); /* Length */
> >>> +    build_append_int_noprefix(array, desc->rev, 1); /* Revision */
> >>> +    build_append_int_noprefix(array, 0, 1); /* Checksum */
> >>> +    build_append_padded_str(array, desc->oem_id, 6, ' '); /* OEMID */
> >>> +    /* OEM Table ID */
> >>> +    build_append_padded_str(array, desc->oem_table_id, 8, ' ');
> >>> +    build_append_int_noprefix(array, 1, 4); /* OEM Revision */
> >>> +    g_array_append_vals(array, ACPI_BUILD_APPNAME8, 4); /* Creator ID */  
> > 
> > here we potentially can reuse build_append_padded_str() if we
> > remove padding in ACPI_BUILD_APPNAME8, but that should wait till
> > refactoring is complete (to avoid breaking incremental refactoring)  
> 
> OK
> >   
> >>> +    build_append_int_noprefix(array, 1, 4); /* Creator Revision */
> >>> +}
> >>> +
> >>> +void acpi_table_composed(BIOSLinker *linker, AcpiTable *desc)
> >>> +{
> >>> +    /*
> >>> +     * ACPI spec 1.0b
> >>> +     * 5.2.3 System Description Table Header
> >>> +     * Table 5-2 DESCRIPTION_HEADER Fields
> >>> +     */
> >>> +    const unsigned checksum_offset = 9;
> >>> +    uint32_t table_len = desc->array->len - desc->table_offset;
> >>> +    uint32_t table_len_le = cpu_to_le32(table_len);
> >>> +    gchar *len_ptr = &desc->array->data[desc->table_offset + 4];
> >>> +
> >>> +    /* patch "Length" field that has been reserved by acpi_init_table()
> >>> +     * to the actual length, i.e. accumulated table length from
> >>> +     * acpi_init_table() till acpi_table_composed()
> >>> +     */
> >>> +    memcpy(len_ptr, &table_len_le, sizeof table_len_le);    
> >> can't you use a garray/build_append function instead to be homogeneous
> >> with the rest of the code?  
> > those are for inserting/adding _new_ values, and won't work here,
> > here we are patching value in place, comment above was supposed
> > to clarify that (I guess it wasn't sufficient),
> > Care to suggest a better comment?  
> 
> I thought  g_array_insert_vals() could do the job. No the comment was
> clear to me actually.      Maybe in acpi_init_table, along with Length
> comment you add a comment saying actual value will be set in composed().

sure, I'll add that.

> 
> Eric
> >   
> >>> +
> >>> +    bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
> >>> +        desc->table_offset, table_len, desc->table_offset + checksum_offset);
> >>> +}
> >>> +
> >>>  void
> >>>  build_header(BIOSLinker *linker, GArray *table_data,
> >>>               AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
> >>>     
> >>
> >> Thanks
> >>
> >> Eric
> >>  
> >   
> 



^ permalink raw reply	[flat|nested] 56+ messages in thread

* Re: [PATCH v2 25/35] acpi: arm/virt: madt: use build_append_int_noprefix() API to compose MADT table
  2021-09-03 13:45   ` Eric Auger
@ 2021-09-06 12:40     ` Igor Mammedov
  0 siblings, 0 replies; 56+ messages in thread
From: Igor Mammedov @ 2021-09-06 12:40 UTC (permalink / raw)
  To: Eric Auger
  Cc: peter.maydell, drjones, mst, qemu-devel, shannon.zhaosl, qemu-arm

On Fri, 3 Sep 2021 15:45:00 +0200
Eric Auger <eauger@redhat.com> wrote:

> Hi Igor,
> On 7/8/21 5:46 PM, Igor Mammedov wrote:
> > Drop usage of packed structures and explicit endian conversions
> > when building MADT table for arm/x86 and use endian agnostic
> > build_append_int_noprefix() API to build it.
> > 
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > ---
> > CC: drjones@redhat.com
> > CC: peter.maydell@linaro.org
> > CC: shannon.zhaosl@gmail.com
> > CC: qemu-arm@nongnu.org
> > ---
> >  include/hw/acpi/acpi-defs.h |  84 --------------------
> >  hw/arm/virt-acpi-build.c    | 149 +++++++++++++++++++++---------------
> >  2 files changed, 89 insertions(+), 144 deletions(-)
> > 
> > diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
> > index 3f174ba208..bcada37601 100644
> > --- a/include/hw/acpi/acpi-defs.h
> > +++ b/include/hw/acpi/acpi-defs.h
> > @@ -163,90 +163,6 @@ struct AcpiFacsDescriptorRev1 {
> >  } QEMU_PACKED;
> >  typedef struct AcpiFacsDescriptorRev1 AcpiFacsDescriptorRev1;
> >  
> > -/* Values for Type in APIC sub-headers */
> > -
> > -#define ACPI_APIC_GENERIC_CPU_INTERFACE 11
> > -#define ACPI_APIC_GENERIC_DISTRIBUTOR   12
> > -#define ACPI_APIC_GENERIC_MSI_FRAME     13
> > -#define ACPI_APIC_GENERIC_REDISTRIBUTOR 14
> > -#define ACPI_APIC_GENERIC_TRANSLATOR    15
> > -#define ACPI_APIC_RESERVED              16   /* 16 and greater are reserved */
> > -
> > -/*
> > - * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
> > - */
> > -#define ACPI_SUB_HEADER_DEF   /* Common ACPI sub-structure header */\
> > -    uint8_t  type;                               \
> > -    uint8_t  length;
> > -
> > -/* Sub-structures for MADT */
> > -
> > -struct AcpiMadtGenericCpuInterface {
> > -    ACPI_SUB_HEADER_DEF
> > -    uint16_t reserved;
> > -    uint32_t cpu_interface_number;
> > -    uint32_t uid;
> > -    uint32_t flags;
> > -    uint32_t parking_version;
> > -    uint32_t performance_interrupt;
> > -    uint64_t parked_address;
> > -    uint64_t base_address;
> > -    uint64_t gicv_base_address;
> > -    uint64_t gich_base_address;
> > -    uint32_t vgic_interrupt;
> > -    uint64_t gicr_base_address;
> > -    uint64_t arm_mpidr;
> > -} QEMU_PACKED;
> > -
> > -typedef struct AcpiMadtGenericCpuInterface AcpiMadtGenericCpuInterface;
> > -
> > -/* GICC CPU Interface Flags */
> > -#define ACPI_MADT_GICC_ENABLED 1
> > -
> > -struct AcpiMadtGenericDistributor {
> > -    ACPI_SUB_HEADER_DEF
> > -    uint16_t reserved;
> > -    uint32_t gic_id;
> > -    uint64_t base_address;
> > -    uint32_t global_irq_base;
> > -    /* ACPI 5.1 Errata 1228 Present GIC version in MADT table */
> > -    uint8_t version;
> > -    uint8_t reserved2[3];
> > -} QEMU_PACKED;
> > -
> > -typedef struct AcpiMadtGenericDistributor AcpiMadtGenericDistributor;
> > -
> > -struct AcpiMadtGenericMsiFrame {
> > -    ACPI_SUB_HEADER_DEF
> > -    uint16_t reserved;
> > -    uint32_t gic_msi_frame_id;
> > -    uint64_t base_address;
> > -    uint32_t flags;
> > -    uint16_t spi_count;
> > -    uint16_t spi_base;
> > -} QEMU_PACKED;
> > -
> > -typedef struct AcpiMadtGenericMsiFrame AcpiMadtGenericMsiFrame;
> > -
> > -struct AcpiMadtGenericRedistributor {
> > -    ACPI_SUB_HEADER_DEF
> > -    uint16_t reserved;
> > -    uint64_t base_address;
> > -    uint32_t range_length;
> > -} QEMU_PACKED;
> > -
> > -typedef struct AcpiMadtGenericRedistributor AcpiMadtGenericRedistributor;
> > -
> > -struct AcpiMadtGenericTranslator {
> > -    ACPI_SUB_HEADER_DEF
> > -    uint16_t reserved;
> > -    uint32_t translation_id;
> > -    uint64_t base_address;
> > -    uint32_t reserved2;
> > -} QEMU_PACKED;
> > -
> > -typedef struct AcpiMadtGenericTranslator AcpiMadtGenericTranslator;
> > -
> >  /*
> >   * Generic Timer Description Table (GTDT)
> >   */
> > diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> > index cd8b73dde9..dd8011a670 100644
> > --- a/hw/arm/virt-acpi-build.c
> > +++ b/hw/arm/virt-acpi-build.c
> > @@ -476,94 +476,123 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> >  }
> >  
> >  /*
> > - * ACPI spec, Revision 5.0
> > + * ACPI spec, Revision 5.1 Errata A  
> It is a bit difficult to follow both the conversion and the upgrade of
> the version. May be worth splitting both concerns if sensible.

Change above is correcting stale comment, to document actual state of the code
there is no version upgrade here.

> >   * 5.2.12 Multiple APIC Description Table (MADT)
> >   */
> > +static void build_append_gicr(GArray *table_data, uint64_t base, uint32_t size)
> > +{
> > +    build_append_int_noprefix(table_data, 0xE, 1);  /* Type */
> > +    build_append_int_noprefix(table_data, 16, 1);   /* Length */
> > +    build_append_int_noprefix(table_data, 0, 2);    /* Reserved */
> > +    /* Discovery Range Base Addres */
> > +    build_append_int_noprefix(table_data, base, 8);
> > +    build_append_int_noprefix(table_data, size, 4); /* Discovery Range Length */
> > +}
> > +
> >  static void
> >  build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
> >  {
> > +    int i;
> >      VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
> >      const MemMapEntry *memmap = vms->memmap;
> > -    const int *irqmap = vms->irqmap;
> > -    AcpiMadtGenericDistributor *gicd;
> > -    AcpiMadtGenericMsiFrame *gic_msi;
> > -    int i;
> >      AcpiTable table = { .sig = "APIC", .rev = 3, .oem_id = vms->oem_id,
> >                          .oem_table_id = vms->oem_table_id };
> >  
> >      acpi_init_table(&table, table_data);
> >      /* Local Interrupt Controller Address */
> >      build_append_int_noprefix(table_data, 0, 4);
> > -    build_append_int_noprefix(table_data, 0, 4); /* Flags */
> > -
> > -    gicd = acpi_data_push(table_data, sizeof *gicd);
> > -    gicd->type = ACPI_APIC_GENERIC_DISTRIBUTOR;
> > -    gicd->length = sizeof(*gicd);
> > -    gicd->base_address = cpu_to_le64(memmap[VIRT_GIC_DIST].base);
> > -    gicd->version = vms->gic_version;
> > +    build_append_int_noprefix(table_data, 0, 4);   /* Flags */
> > +
> > +    /* 5.2.12.15 GIC Distributor Structure */
> > +    build_append_int_noprefix(table_data, 0xC, 1); /* Type */
> > +    build_append_int_noprefix(table_data, 24, 1);  /* Length */
> > +    build_append_int_noprefix(table_data, 0, 2);   /* Reserved */
> > +    build_append_int_noprefix(table_data, 0, 4);   /* GIC ID */
> > +    /* Physical Base Address */
> > +    build_append_int_noprefix(table_data, memmap[VIRT_GIC_DIST].base, 8);
> > +    build_append_int_noprefix(table_data, 0, 4);   /* System Vector Base */
> > +    /* GIC version */
> > +    build_append_int_noprefix(table_data, vms->gic_version, 1);
> > +    build_append_int_noprefix(table_data, 0, 3);   /* Reserved */
> >  
> >      for (i = 0; i < MACHINE(vms)->smp.cpus; i++) {
> > -        AcpiMadtGenericCpuInterface *gicc = acpi_data_push(table_data,
> > -                                                           sizeof(*gicc));
> >          ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i));
> > +        uint64_t physical_base_address = 0, gich = 0, gicv = 0;
> > +        uint32_t vgic_interrupt = vms->virt ? PPI(ARCH_GIC_MAINT_IRQ) : 0;
> > +        uint32_t pmu_interrupt = arm_feature(&armcpu->env, ARM_FEATURE_PMU) ?
> > +                                             PPI(VIRTUAL_PMU_IRQ) : 0;
> >  
> > -        gicc->type = ACPI_APIC_GENERIC_CPU_INTERFACE;
> > -        gicc->length = sizeof(*gicc);
> >          if (vms->gic_version == 2) {
> > -            gicc->base_address = cpu_to_le64(memmap[VIRT_GIC_CPU].base);
> > -            gicc->gich_base_address = cpu_to_le64(memmap[VIRT_GIC_HYP].base);
> > -            gicc->gicv_base_address = cpu_to_le64(memmap[VIRT_GIC_VCPU].base);
> > +            physical_base_address = memmap[VIRT_GIC_CPU].base;
> > +            gicv = memmap[VIRT_GIC_VCPU].base;
> > +            gich = memmap[VIRT_GIC_HYP].base;
> >          }
> > -        gicc->cpu_interface_number = cpu_to_le32(i);
> > -        gicc->arm_mpidr = cpu_to_le64(armcpu->mp_affinity);
> > -        gicc->uid = cpu_to_le32(i);
> > -        gicc->flags = cpu_to_le32(ACPI_MADT_GICC_ENABLED);
> >  
> > -        if (arm_feature(&armcpu->env, ARM_FEATURE_PMU)) {
> > -            gicc->performance_interrupt = cpu_to_le32(PPI(VIRTUAL_PMU_IRQ));
> > -        }
> > -        if (vms->virt) {
> > -            gicc->vgic_interrupt = cpu_to_le32(PPI(ARCH_GIC_MAINT_IRQ));
> > -        }
> > +        /* 5.2.12.14 GIC Structure */
> > +        build_append_int_noprefix(table_data, 0xB, 1);  /* Type */
> > +        build_append_int_noprefix(table_data, 76, 1);   /* Length */
> > +        build_append_int_noprefix(table_data, 0, 2);    /* Reserved */
> > +        build_append_int_noprefix(table_data, i, 4);    /* GIC ID */
> > +        build_append_int_noprefix(table_data, i, 4);    /* ACPI Processor UID */
> > +        /* Flags */
> > +        build_append_int_noprefix(table_data, 1, 4);    /* Enabled */
> > +        /* Parking Protocol Version */
> > +        build_append_int_noprefix(table_data, 0, 4);
> > +        /* Performance Interrupt GSIV */
> > +        build_append_int_noprefix(table_data, pmu_interrupt, 4);
> > +        build_append_int_noprefix(table_data, 0, 8); /* Parked Address */
> > +        /* Physical Base Address */
> > +        build_append_int_noprefix(table_data, physical_base_address, 8);
> > +        build_append_int_noprefix(table_data, gicv, 8); /* GICV */
> > +        build_append_int_noprefix(table_data, gich, 8); /* GICH */
> > +        /* VGIC Maintenance interrupt */
> > +        build_append_int_noprefix(table_data, vgic_interrupt, 4);
> > +        build_append_int_noprefix(table_data, 0, 8);    /* GICR Base Address*/
> > +        /* MPIDR */
> > +        build_append_int_noprefix(table_data, armcpu->mp_affinity, 8);
> >      }
> >  
> >      if (vms->gic_version == 3) {
> > -        AcpiMadtGenericTranslator *gic_its;
> > -        int nb_redist_regions = virt_gicv3_redist_region_count(vms);
> > -        AcpiMadtGenericRedistributor *gicr = acpi_data_push(table_data,
> > -                                                         sizeof *gicr);
> > -
> > -        gicr->type = ACPI_APIC_GENERIC_REDISTRIBUTOR;
> > -        gicr->length = sizeof(*gicr);
> > -        gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST].base);
> > -        gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST].size);
> > -
> > -        if (nb_redist_regions == 2) {
> > -            gicr = acpi_data_push(table_data, sizeof(*gicr));
> > -            gicr->type = ACPI_APIC_GENERIC_REDISTRIBUTOR;
> > -            gicr->length = sizeof(*gicr);
> > -            gicr->base_address =
> > -                cpu_to_le64(memmap[VIRT_HIGH_GIC_REDIST2].base);
> > -            gicr->range_length =
> > -                cpu_to_le32(memmap[VIRT_HIGH_GIC_REDIST2].size);
> > +        build_append_gicr(table_data, memmap[VIRT_GIC_REDIST].base,
> > +                                      memmap[VIRT_GIC_REDIST].size);
> > +        if (virt_gicv3_redist_region_count(vms) == 2) {
> > +            build_append_gicr(table_data, memmap[VIRT_HIGH_GIC_REDIST2].base,
> > +                                          memmap[VIRT_HIGH_GIC_REDIST2].size);
> >          }
> >  
> >          if (its_class_name() && !vmc->no_its) {
> > -            gic_its = acpi_data_push(table_data, sizeof *gic_its);
> > -            gic_its->type = ACPI_APIC_GENERIC_TRANSLATOR;
> > -            gic_its->length = sizeof(*gic_its);
> > -            gic_its->translation_id = 0;
> > -            gic_its->base_address = cpu_to_le64(memmap[VIRT_GIC_ITS].base);
> > +            /*
> > +             * FIXME: Structure is from Revision 6.0 where 'GIC Structure'
> > +             * has additional fields on top of implemented 5.1 Errata A
> > +             * make it consistent with v6.0 if ITS is present or bump
> > +             * everything to v6.0 unconditionally  
> Do you mean some parts are 5.1 errata A and some others are 6.0 already?
yep, I'm trying to minimize changes not relevant to refactoring,
so here I basically mark TODO item and document the current state of the code
/some other patches also have similar comments for out of scope thing I noticed/
there is no change to the table contents.

> > +             */
> > +            /*
> > +             * ACPI spec, Revision  6.0
> > +             * 5.2.12.18 GIC ITS Structure
> > +             */
> > +            build_append_int_noprefix(table_data, 0xF, 1);  /* Type */
> > +            build_append_int_noprefix(table_data, 16, 1);   /* Length */  
> this is 20 and not 16. Currently it fails with ITS.

it was yet another Errata, already fixed in current WIP.

comment above now looks like this:


+            /*
+             * FIXME: Structure is from Revision 6.0 where 'GIC Structure'
+             * has additional fields on top of implemented 5.1 Errata A,
+             * to make it consistent with v6.0 we need to bump everything
+             * to v6.0
+             */
+            /*
+             * ACPI spec, Revision 6.0 Errata A
+             * (original 6.0 definition has invalid Length)
+             * 5.2.12.18 GIC ITS Structure
+             */


> With that fix
> Reviewed-by: Eric Auger <eric.auger@redhat.com>
> 
> Thanks
> 
> Eric
> 
> > +            build_append_int_noprefix(table_data, 0, 2);    /* Reserved */
> > +            build_append_int_noprefix(table_data, 0, 4);    /* GIC ITS ID */
> > +            /* Physical Base Address */
> > +            build_append_int_noprefix(table_data, memmap[VIRT_GIC_ITS].base, 8);
> > +            build_append_int_noprefix(table_data, 0, 4);    /* Reserved */
> >          }
> >      } else {
> > -        gic_msi = acpi_data_push(table_data, sizeof *gic_msi);
> > -        gic_msi->type = ACPI_APIC_GENERIC_MSI_FRAME;
> > -        gic_msi->length = sizeof(*gic_msi);
> > -        gic_msi->gic_msi_frame_id = 0;
> > -        gic_msi->base_address = cpu_to_le64(memmap[VIRT_GIC_V2M].base);
> > -        gic_msi->flags = cpu_to_le32(1);
> > -        gic_msi->spi_count = cpu_to_le16(NUM_GICV2M_SPIS);
> > -        gic_msi->spi_base = cpu_to_le16(irqmap[VIRT_GIC_V2M] + ARM_SPI_BASE);
> > +        const uint16_t spi_base = vms->irqmap[VIRT_GIC_V2M] + ARM_SPI_BASE;
> > +
> > +        /* 5.2.12.16 GIC MSI Frame Structure */
> > +        build_append_int_noprefix(table_data, 0xD, 1);  /* Type */
> > +        build_append_int_noprefix(table_data, 24, 1);   /* Length */
> > +        build_append_int_noprefix(table_data, 0, 2);    /* Reserved */
> > +        build_append_int_noprefix(table_data, 0, 4);    /* GIC MSI Frame ID */
> > +        /* Physical Base Address */
> > +        build_append_int_noprefix(table_data, memmap[VIRT_GIC_V2M].base, 8);
> > +        build_append_int_noprefix(table_data, 1, 4);    /* Flags */
> > +        /* SPI Count */
> > +        build_append_int_noprefix(table_data, NUM_GICV2M_SPIS, 2);
> > +        build_append_int_noprefix(table_data, spi_base, 2); /* SPI Base */
> >      }
> >      acpi_table_composed(linker, &table);
> >  }
> >   
> 



^ permalink raw reply	[flat|nested] 56+ messages in thread

end of thread, other threads:[~2021-09-06 12:43 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-08 15:45 [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Igor Mammedov
2021-07-08 15:45 ` [PATCH v2 01/35] acpi: add helper routines to initialize " Igor Mammedov
2021-09-02 12:56   ` Eric Auger
2021-09-03  7:12     ` Igor Mammedov
2021-09-03  7:22       ` Eric Auger
2021-09-06 12:17         ` Igor Mammedov
2021-09-04 19:57       ` Michael S. Tsirkin
2021-09-06 12:14         ` Igor Mammedov
2021-07-08 15:45 ` [PATCH v2 02/35] acpi: build_rsdt: use acpi_init_table()/acpi_table_composed() instead of build_header() Igor Mammedov
2021-07-08 15:45 ` [PATCH v2 03/35] acpi: build_xsdt: " Igor Mammedov
2021-07-08 15:45 ` [PATCH v2 04/35] acpi: build_slit: " Igor Mammedov
2021-07-08 15:45 ` [PATCH v2 05/35] acpi: build_fadt: " Igor Mammedov
2021-07-08 15:45 ` [PATCH v2 06/35] acpi: build_tpm2: " Igor Mammedov
2021-09-02 12:59   ` Eric Auger
2021-07-08 15:45 ` [PATCH v2 07/35] acpi: acpi_build_hest: " Igor Mammedov
2021-07-08 15:45 ` [PATCH v2 08/35] acpi: build_mcfg: " Igor Mammedov
2021-07-08 15:45 ` [PATCH v2 09/35] acpi: build_hmat: " Igor Mammedov
2021-07-08 15:45 ` [PATCH v2 10/35] acpi: nvdimm_build_nfit: " Igor Mammedov
2021-07-08 15:45 ` [PATCH v2 11/35] acpi: nvdimm_build_ssdt: " Igor Mammedov
2021-07-08 15:45 ` [PATCH v2 12/35] acpi: vmgenid_build_acpi: " Igor Mammedov
2021-07-08 15:45 ` [PATCH v2 13/35] acpi: x86: build_dsdt: " Igor Mammedov
2021-09-02 15:35   ` Eric Auger
2021-07-08 15:45 ` [PATCH v2 14/35] acpi: build_hpet: " Igor Mammedov
2021-07-08 15:45 ` [PATCH v2 15/35] acpi: build_tpm_tcpa: " Igor Mammedov
2021-07-08 15:45 ` [PATCH v2 16/35] acpi: arm/x86: build_srat: " Igor Mammedov
2021-07-08 15:45 ` [PATCH v2 17/35] acpi: use build_append_int_noprefix() API to compose SRAT table Igor Mammedov
2021-07-08 15:46 ` [PATCH v2 18/35] acpi: build_dmar_q35: use acpi_init_table()/acpi_table_composed() instead of build_header() Igor Mammedov
2021-07-08 15:46 ` [PATCH v2 19/35] acpi: build_waet: " Igor Mammedov
2021-07-08 15:46 ` [PATCH v2 20/35] acpi: build_amd_iommu: " Igor Mammedov
2021-07-08 15:46 ` [PATCH v2 21/35] acpi: madt: arm/x86: " Igor Mammedov
2021-07-08 15:46 ` [PATCH v2 22/35] acpi: x86: remove dead code Igor Mammedov
2021-07-08 15:46 ` [PATCH v2 23/35] acpi: x86: set enabled when composing _MAT entries Igor Mammedov
2021-07-08 15:46 ` [PATCH v2 24/35] acpi: x86: madt: use build_append_int_noprefix() API to compose MADT table Igor Mammedov
2021-07-08 15:46 ` [PATCH v2 25/35] acpi: arm/virt: " Igor Mammedov
2021-09-03 13:45   ` Eric Auger
2021-09-06 12:40     ` Igor Mammedov
2021-07-08 15:46 ` [PATCH v2 26/35] acpi: build_dsdt_microvm: use acpi_init_table()/acpi_table_composed() instead of build_header() Igor Mammedov
2021-07-08 15:46 ` [PATCH v2 27/35] acpi: arm: virt: build_dsdt: " Igor Mammedov
2021-09-02 15:34   ` Eric Auger
2021-07-08 15:46 ` [PATCH v2 28/35] acpi: arm: virt: build_iort: " Igor Mammedov
2021-07-08 15:46 ` [PATCH v2 29/35] acpi: arm/virt: convert build_iort() to endian agnostic build_append_FOO() API Igor Mammedov
2021-07-09  7:11   ` Michael S. Tsirkin
2021-07-09  8:59     ` Igor Mammedov
2021-07-08 15:46 ` [PATCH v2 30/35] acpi: arm/virt: build_spcr: fix invalid cast Igor Mammedov
2021-09-02 15:51   ` Eric Auger
2021-07-08 15:46 ` [PATCH v2 31/35] acpi: arm/virt: build_spcr: use acpi_init_table()/acpi_table_composed() instead of build_header() Igor Mammedov
2021-09-02 15:49   ` Eric Auger
2021-09-03  7:52     ` Igor Mammedov
2021-07-08 15:46 ` [PATCH v2 32/35] acpi: arm/virt: build_gtdt: " Igor Mammedov
2021-09-02 16:07   ` Eric Auger
2021-07-08 15:46 ` [PATCH v2 33/35] acpi: build_facs: use build_append_int_noprefix() API to compose table Igor Mammedov
2021-07-08 15:46 ` [PATCH v2 34/35] acpi: remove no longer used build_header() Igor Mammedov
2021-07-08 15:46 ` [PATCH v2 35/35] acpi: AcpiGenericAddress no longer used to map/access fields of MMIO, drop packed attribute Igor Mammedov
2021-07-13 15:45 ` [PATCH v2 00/35] acpi: refactor error prone build_header() and packed structures usage in ACPI tables Michael S. Tsirkin
2021-07-14  8:53   ` Igor Mammedov
2021-07-14 10:31     ` Michael S. Tsirkin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.