From d6a9378f47515c6d70dbff4912c5740c98709880 Mon Sep 17 00:00:00 2001 From: Stefano Garzarella Date: Tue, 21 Sep 2021 18:16:41 +0200 Subject: vhost-vsock: fix migration issue when seqpacket is supported Commit 1e08fd0a46 ("vhost-vsock: SOCK_SEQPACKET feature bit support") enabled the SEQPACKET feature bit. This commit is released with QEMU 6.1, so if we try to migrate a VM where the host kernel supports SEQPACKET but machine type version is less than 6.1, we get the following errors: Features 0x130000002 unsupported. Allowed features: 0x179000000 Failed to load virtio-vhost_vsock:virtio error while loading state for instance 0x0 of device '0000:00:05.0/virtio-vhost_vsock' load of migration failed: Operation not permitted Let's disable the feature bit for machine types < 6.1. We add a new OnOffAuto property for this, called `seqpacket`. When it is `auto` (default), QEMU behaves as before, trying to enable the feature, when it is `on` QEMU will fail if the backend (vhost-vsock kernel module) doesn't support it. Fixes: 1e08fd0a46 ("vhost-vsock: SOCK_SEQPACKET feature bit support") Cc: qemu-stable@nongnu.org Reported-by: Jiang Wang Signed-off-by: Stefano Garzarella Message-Id: <20210921161642.206461-2-sgarzare@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/virtio/vhost-vsock.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/hw/virtio/vhost-vsock.h b/include/hw/virtio/vhost-vsock.h index 84f4e727c7..3f121a624f 100644 --- a/include/hw/virtio/vhost-vsock.h +++ b/include/hw/virtio/vhost-vsock.h @@ -30,6 +30,9 @@ struct VHostVSock { VHostVSockCommon parent; VHostVSockConf conf; + /* features */ + OnOffAuto seqpacket; + /*< public >*/ }; -- cgit v1.2.3-55-g7522 From 46ce017167d800c5d96104a88cfaed9949c4a3b6 Mon Sep 17 00:00:00 2001 From: Stefano Garzarella Date: Tue, 21 Sep 2021 18:16:42 +0200 Subject: vhost-vsock: handle common features in vhost-vsock-common virtio-vsock features, like VIRTIO_VSOCK_F_SEQPACKET, can be handled by vhost-vsock-common parent class. In this way, we can reuse the same code for all virtio-vsock backends (i.e. vhost-vsock, vhost-user-vsock). Let's move `seqpacket` property to vhost-vsock-common class, add vhost_vsock_common_get_features() used by children, and disable `seqpacket` for vhost-user-vsock device for machine types < 6.2. The behavior of vhost-vsock device doesn't change; vhost-user-vsock device now supports `seqpacket` property. Signed-off-by: Stefano Garzarella Message-Id: <20210921161642.206461-3-sgarzare@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/core/machine.c | 4 +++- hw/virtio/vhost-user-vsock.c | 4 +++- hw/virtio/vhost-vsock-common.c | 31 +++++++++++++++++++++++++++++++ hw/virtio/vhost-vsock.c | 24 +----------------------- include/hw/virtio/vhost-vsock-common.h | 5 +++++ include/hw/virtio/vhost-vsock.h | 3 --- 6 files changed, 43 insertions(+), 28 deletions(-) (limited to 'include') diff --git a/hw/core/machine.c b/hw/core/machine.c index 74f2a9a984..b8d95eec32 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -37,7 +37,9 @@ #include "hw/virtio/virtio.h" #include "hw/virtio/virtio-pci.h" -GlobalProperty hw_compat_6_1[] = {}; +GlobalProperty hw_compat_6_1[] = { + { "vhost-user-vsock-device", "seqpacket", "off" }, +}; const size_t hw_compat_6_1_len = G_N_ELEMENTS(hw_compat_6_1); GlobalProperty hw_compat_6_0[] = { diff --git a/hw/virtio/vhost-user-vsock.c b/hw/virtio/vhost-user-vsock.c index 6095ed7349..52bd682c34 100644 --- a/hw/virtio/vhost-user-vsock.c +++ b/hw/virtio/vhost-user-vsock.c @@ -81,7 +81,9 @@ static uint64_t vuv_get_features(VirtIODevice *vdev, { VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); - return vhost_get_features(&vvc->vhost_dev, user_feature_bits, features); + features = vhost_get_features(&vvc->vhost_dev, user_feature_bits, features); + + return vhost_vsock_common_get_features(vdev, features, errp); } static const VMStateDescription vuv_vmstate = { diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c index 4ad6e234ad..3f3771274e 100644 --- a/hw/virtio/vhost-vsock-common.c +++ b/hw/virtio/vhost-vsock-common.c @@ -18,6 +18,30 @@ #include "qemu/iov.h" #include "monitor/monitor.h" +const int feature_bits[] = { + VIRTIO_VSOCK_F_SEQPACKET, + VHOST_INVALID_FEATURE_BIT +}; + +uint64_t vhost_vsock_common_get_features(VirtIODevice *vdev, uint64_t features, + Error **errp) +{ + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); + + if (vvc->seqpacket != ON_OFF_AUTO_OFF) { + virtio_add_feature(&features, VIRTIO_VSOCK_F_SEQPACKET); + } + + features = vhost_get_features(&vvc->vhost_dev, feature_bits, features); + + if (vvc->seqpacket == ON_OFF_AUTO_ON && + !virtio_has_feature(features, VIRTIO_VSOCK_F_SEQPACKET)) { + error_setg(errp, "vhost-vsock backend doesn't support seqpacket"); + } + + return features; +} + int vhost_vsock_common_start(VirtIODevice *vdev) { VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); @@ -231,11 +255,18 @@ void vhost_vsock_common_unrealize(VirtIODevice *vdev) virtio_cleanup(vdev); } +static Property vhost_vsock_common_properties[] = { + DEFINE_PROP_ON_OFF_AUTO("seqpacket", VHostVSockCommon, seqpacket, + ON_OFF_AUTO_AUTO), + DEFINE_PROP_END_OF_LIST(), +}; + static void vhost_vsock_common_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + device_class_set_props(dc, vhost_vsock_common_properties); set_bit(DEVICE_CATEGORY_MISC, dc->categories); vdc->guest_notifier_mask = vhost_vsock_common_guest_notifier_mask; vdc->guest_notifier_pending = vhost_vsock_common_guest_notifier_pending; diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c index dade0da031..478c0c9a87 100644 --- a/hw/virtio/vhost-vsock.c +++ b/hw/virtio/vhost-vsock.c @@ -21,11 +21,6 @@ #include "hw/virtio/vhost-vsock.h" #include "monitor/monitor.h" -const int feature_bits[] = { - VIRTIO_VSOCK_F_SEQPACKET, - VHOST_INVALID_FEATURE_BIT -}; - static void vhost_vsock_get_config(VirtIODevice *vdev, uint8_t *config) { VHostVSock *vsock = VHOST_VSOCK(vdev); @@ -113,22 +108,7 @@ static uint64_t vhost_vsock_get_features(VirtIODevice *vdev, uint64_t requested_features, Error **errp) { - VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); - VHostVSock *vsock = VHOST_VSOCK(vdev); - - if (vsock->seqpacket != ON_OFF_AUTO_OFF) { - virtio_add_feature(&requested_features, VIRTIO_VSOCK_F_SEQPACKET); - } - - requested_features = vhost_get_features(&vvc->vhost_dev, feature_bits, - requested_features); - - if (vsock->seqpacket == ON_OFF_AUTO_ON && - !virtio_has_feature(requested_features, VIRTIO_VSOCK_F_SEQPACKET)) { - error_setg(errp, "vhost-vsock backend doesn't support seqpacket"); - } - - return requested_features; + return vhost_vsock_common_get_features(vdev, requested_features, errp); } static const VMStateDescription vmstate_virtio_vhost_vsock = { @@ -229,8 +209,6 @@ static void vhost_vsock_device_unrealize(DeviceState *dev) static Property vhost_vsock_properties[] = { DEFINE_PROP_UINT64("guest-cid", VHostVSock, conf.guest_cid, 0), DEFINE_PROP_STRING("vhostfd", VHostVSock, conf.vhostfd), - DEFINE_PROP_ON_OFF_AUTO("seqpacket", VHostVSock, seqpacket, - ON_OFF_AUTO_AUTO), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/virtio/vhost-vsock-common.h b/include/hw/virtio/vhost-vsock-common.h index e412b5ee98..d8b565b4da 100644 --- a/include/hw/virtio/vhost-vsock-common.h +++ b/include/hw/virtio/vhost-vsock-common.h @@ -35,6 +35,9 @@ struct VHostVSockCommon { VirtQueue *trans_vq; QEMUTimer *post_load_timer; + + /* features */ + OnOffAuto seqpacket; }; int vhost_vsock_common_start(VirtIODevice *vdev); @@ -43,5 +46,7 @@ int vhost_vsock_common_pre_save(void *opaque); int vhost_vsock_common_post_load(void *opaque, int version_id); void vhost_vsock_common_realize(VirtIODevice *vdev, const char *name); void vhost_vsock_common_unrealize(VirtIODevice *vdev); +uint64_t vhost_vsock_common_get_features(VirtIODevice *vdev, uint64_t features, + Error **errp); #endif /* _QEMU_VHOST_VSOCK_COMMON_H */ diff --git a/include/hw/virtio/vhost-vsock.h b/include/hw/virtio/vhost-vsock.h index 3f121a624f..84f4e727c7 100644 --- a/include/hw/virtio/vhost-vsock.h +++ b/include/hw/virtio/vhost-vsock.h @@ -30,9 +30,6 @@ struct VHostVSock { VHostVSockCommon parent; VHostVSockConf conf; - /* features */ - OnOffAuto seqpacket; - /*< public >*/ }; -- cgit v1.2.3-55-g7522 From c151fd87102cbb4082ac5dbcd704196b0495d28a Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:28 -0400 Subject: acpi: add helper routines to initialize ACPI tables Patch introduces acpi_table_begin()/ acpi_table_end() API that hides pointer/offset arithmetic from user as opposed to build_header(), to prevent errors caused by it [1]. acpi_table_begin(): initializes table header and keeps track of table data/offsets acpi_table_end(): 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 Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-2-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Tested-by: Stefan Berger Tested-by: Yanan Wang --- hw/acpi/aml-build.c | 62 +++++++++++++++++++++++++++++++++++++++++++++ include/hw/acpi/aml-build.h | 31 +++++++++++++++++++++++ 2 files changed, 93 insertions(+) (limited to 'include') diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index d5103e6d7b..229a3eb654 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,55 @@ Aml *aml_object_type(Aml *object) return var; } +void acpi_table_begin(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 */ + /* + * reserve space for Length field, which will be patched by + * acpi_table_end() when the table creation is finished. + */ + 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_end(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_table_begin() + * to the actual length, i.e. accumulated table length from + * acpi_table_begin() till acpi_table_end() + */ + 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, diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index 471266d739..4242382399 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -413,6 +413,37 @@ 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; + +/** + * acpi_table_begin: + * initializes table header and keeps track of + * table data/offsets + * @desc: ACPI table descriptor + * @array: blob where the ACPI table will be composed/stored. + */ +void acpi_table_begin(AcpiTable *desc, GArray *array); + +/** + * acpi_table_end: + * sets actual table length and tells bios loader + * where table is for the later initialization on + * guest side. + * @linker: reference to BIOSLinker object to use for the table + * @table: ACPI table descriptor that was used with @acpi_table_begin + * counterpart + */ +void acpi_table_end(BIOSLinker *linker, AcpiTable *table); + void build_header(BIOSLinker *linker, GArray *table_data, AcpiTableHeader *h, const char *sig, int len, uint8_t rev, -- cgit v1.2.3-55-g7522 From ea298e83a7fb435e57913dd755b53e6b2264feed Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:29 -0400 Subject: acpi: build_rsdt: use acpi_table_begin()/acpi_table_end() instead of build_header() 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 Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-3-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/aml-build.c | 31 +++++++++++++++---------------- include/hw/acpi/acpi-defs.h | 10 ---------- 2 files changed, 15 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index 229a3eb654..616a292229 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -1884,33 +1884,32 @@ build_rsdp(GArray *tbl, BIOSLinker *linker, AcpiRsdpData *rsdp_data) 32); } -/* Build rsdt table */ +/* + * ACPI 1.0 Root System Description Table (RSDT) + */ void 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_table_begin(&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; - /* rsdt->table_offset_entry to be filled by Guest linker */ + /* reserve space for entry */ + build_append_int_noprefix(table.array, 0, 4); + + /* 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_end(linker, &table); } /* Build xsdt table */ 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) */ -- cgit v1.2.3-55-g7522 From f497b7cae1cd052fdbc023f02d37921c4069f7e6 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:30 -0400 Subject: acpi: build_xsdt: use acpi_table_begin()/acpi_table_end() instead of build_header() 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 Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-4-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/aml-build.c | 31 +++++++++++++++---------------- include/hw/acpi/acpi-defs.h | 10 ---------- 2 files changed, 15 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index 616a292229..86b8322ee1 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -1912,33 +1912,32 @@ build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, acpi_table_end(linker, &table); } -/* Build xsdt table */ +/* + * ACPI 2.0 eXtended System Description Table (XSDT) + */ void 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_table_begin(&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_end(linker, &table); } void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, 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) */ -- cgit v1.2.3-55-g7522 From 43dde1705c610710389491e5989ae6f5b5cf6fb9 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:41 -0400 Subject: acpi: build_hpet: use acpi_table_begin()/acpi_table_end() instead of build_header() 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 Message-Id: <20210924122802.1455362-15-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 26 ++++++++++++++++++-------- include/hw/acpi/acpi-defs.h | 13 ------------- 2 files changed, 18 insertions(+), 21 deletions(-) (limited to 'include') diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index e17451bc6d..12d743d529 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1871,22 +1871,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_table_begin(&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_end(linker, &table); } #ifdef CONFIG_TPM 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 */ -- cgit v1.2.3-55-g7522 From 57cb8cfbf2cda59fe829fee54115f72dd7998645 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:42 -0400 Subject: acpi: build_tpm_tcpa: use acpi_table_begin()/acpi_table_end() instead of build_header() 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 Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-16-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 38 +++++++++++++++++++++++--------------- include/hw/acpi/acpi-defs.h | 14 -------------- 2 files changed, 23 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 12d743d529..3310a3efc3 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1900,31 +1900,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_table_begin(&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); + /* 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); + 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 + tcpa_start), - "TCPA", sizeof(*tcpa), 2, oem_id, oem_table_id); + acpi_table_end(linker, &table); } #endif 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 -- cgit v1.2.3-55-g7522 From 255bf20f2e047be1068f90cf8eaf3fc07cbba7d5 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:43 -0400 Subject: acpi: arm/x86: build_srat: use acpi_table_begin()/acpi_table_end() instead of build_header() 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 Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-17-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/arm/virt-acpi-build.c | 15 +++++++-------- hw/i386/acpi-build.c | 18 +++++++----------- include/hw/acpi/acpi-defs.h | 11 ----------- 3 files changed, 14 insertions(+), 30 deletions(-) (limited to 'include') diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 037cc1fd82..21efe7fe34 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -477,18 +477,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_table_begin(&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)); @@ -522,9 +523,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_end(linker, &table); } /* GTDT */ diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 3310a3efc3..1ce808c576 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1942,11 +1942,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); @@ -1957,11 +1956,12 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) ram_addr_t hotpluggable_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_table_begin(&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; @@ -2067,11 +2067,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_end(linker, &table); } /* 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 -- cgit v1.2.3-55-g7522 From e5b6d55a6e5e13002cf79a42a0b78b3188e88a1f Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:44 -0400 Subject: acpi: use build_append_int_noprefix() API to compose SRAT table 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 Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-18-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/aml-build.c | 24 ++++++++++---- hw/acpi/nvdimm.c | 4 +-- hw/arm/virt-acpi-build.c | 29 ++++++++++------- hw/i386/acpi-build.c | 78 +++++++++++++++++++++++++-------------------- include/hw/acpi/acpi-defs.h | 49 ---------------------------- include/hw/acpi/aml-build.h | 2 +- 6 files changed, 80 insertions(+), 106 deletions(-) (limited to 'include') diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index 23cda45ee0..c0f339847a 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -1940,15 +1940,25 @@ build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, acpi_table_end(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 a7539cfe89..5f9b552d6a 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 21efe7fe34..6ba02cf281 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -474,11 +474,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); @@ -492,19 +494,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; @@ -516,8 +522,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 1ce808c576..078097a060 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1939,13 +1939,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); @@ -1968,34 +1970,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 < nb_numa_nodes + 1; ++i) { mem_base = next_base; @@ -2007,8 +2016,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); } @@ -2026,8 +2034,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; @@ -2036,8 +2043,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); } } @@ -2046,10 +2052,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 < nb_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); } /* @@ -2061,8 +2072,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) * providing _PXM method if necessary. */ if (hotpluggable_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, hotpluggable_address_space_size, nb_numa_nodes - 1, MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); } 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 4242382399..6e1f42e119 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -487,7 +487,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, -- cgit v1.2.3-55-g7522 From 91a6b9756970f70d933ea3c01fb5306ea6e5b331 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:45 -0400 Subject: acpi: build_dmar_q35: use acpi_table_begin()/acpi_table_end() instead of build_header() 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 Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-19-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 87 +++++++++++++++++++++++++-------------------- include/hw/acpi/acpi-defs.h | 68 ----------------------------------- 2 files changed, 48 insertions(+), 107 deletions(-) (limited to 'include') diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 078097a060..c65ab1d6a5 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2086,8 +2086,9 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) static void insert_scope(PCIBus *bus, PCIDevice *dev, void *opaque) { + const size_t device_scope_size = 6 /* device scope structure */ + + 2 /* 1 path entry */; GArray *scope_blob = opaque; - AcpiDmarDeviceScope *scope = NULL; if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) { /* Dmar Scope Type: 0x02 for PCI Bridge */ @@ -2098,8 +2099,7 @@ insert_scope(PCIBus *bus, PCIDevice *dev, void *opaque) } /* length */ - build_append_int_noprefix(scope_blob, - sizeof(*scope) + sizeof(scope->path[0]), 1); + build_append_int_noprefix(scope_blob, device_scope_size, 1); /* reserved */ build_append_int_noprefix(scope_blob, 0, 2); /* enumeration_id */ @@ -2131,26 +2131,26 @@ dmar_host_bridges(Object *obj, void *opaque) } /* - * 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); GArray *scope_blob = g_array_new(false, true, 1); + AcpiTable table = { .sig = "DMAR", .rev = 1, .oem_id = oem_id, + .oem_table_id = oem_table_id }; + /* * A PCI bus walk, for each PCI host bridge. * Insert scope for each PCI bridge and endpoint device which @@ -2164,43 +2164,52 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker, const char *oem_id, 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 + scope_blob->len); - drhd->flags = 0; /* Don't include all pci device */ - drhd->pci_segment = cpu_to_le16(0); - drhd->address = cpu_to_le64(Q35_HOST_BRIDGE_IOMMU_ADDR); + acpi_table_begin(&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 + scope_blob->len, 2); + /* Flags */ + build_append_int_noprefix(table_data, 0 /* Don't include all pci device */ , + 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); /* Add scope found above */ g_array_append_vals(table_data, scope_blob->data, scope_blob->len); g_array_free(scope_blob, true); 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_end(linker, &table); } /* 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", -- cgit v1.2.3-55-g7522 From 99a7545f92378765ca98eb1b54b1087c9d2567ec Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:48 -0400 Subject: acpi: madt: arm/x86: use acpi_table_begin()/acpi_table_end() instead of build_header() 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 Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-22-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/arm/virt-acpi-build.c | 19 +++++++++++-------- hw/i386/acpi-common.c | 19 +++++++++++-------- include/hw/acpi/acpi-defs.h | 9 --------- 3 files changed, 22 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 6ba02cf281..e3bdcd44e8 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -567,19 +567,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_table_begin(&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; @@ -650,11 +657,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_end(linker, &table); } /* FADT */ diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c index 1f5947fcf9..a0cde1d874 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_table_begin(&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_end(linker, &table); } 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 -- cgit v1.2.3-55-g7522 From b10e7f4f8f05b3956eabf0661320c71f1e3bab10 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:49 -0400 Subject: acpi: x86: remove dead code Signed-off-by: Igor Mammedov Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-23-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/acpi/acpi-defs.h | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'include') 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 -- cgit v1.2.3-55-g7522 From d0aa026a498cdd4e082f12618767f19a2532712a Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:50 -0400 Subject: acpi: x86: set enabled when composing _MAT entries 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 Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-24-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/acpi-x86-stub.c | 3 ++- hw/acpi/cpu.c | 17 ++--------------- hw/i386/acpi-common.c | 18 ++++++------------ include/hw/acpi/acpi_dev_interface.h | 3 ++- include/hw/i386/pc.h | 6 +++--- 5 files changed, 15 insertions(+), 32 deletions(-) (limited to 'include') diff --git a/hw/acpi/acpi-x86-stub.c b/hw/acpi/acpi-x86-stub.c index e9e46c5c5f..3df1e090f4 100644 --- a/hw/acpi/acpi-x86-stub.c +++ b/hw/acpi/acpi-x86-stub.c @@ -3,7 +3,8 @@ #include "hw/i386/acpi-build.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 a0cde1d874..7983a13a93 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; } 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 5748d7c55f..11426e26dc 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -190,10 +190,10 @@ bool pc_system_ovmf_table_find(const char *entry, uint8_t **data, int *data_len); void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size); - -/* 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); /* sgx.c */ void pc_machine_init_sgx_epc(PCMachineState *pcms); -- cgit v1.2.3-55-g7522 From dd092b9c6008149785d7789c729f468fb762aa0b Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:51 -0400 Subject: acpi: x86: madt: use build_append_int_noprefix() API to compose MADT table 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 Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-25-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-common.c | 129 +++++++++++++++++++++++--------------------- include/hw/acpi/acpi-defs.h | 64 ---------------------- 2 files changed, 67 insertions(+), 126 deletions(-) (limited to 'include') diff --git a/hw/i386/acpi-common.c b/hw/i386/acpi-common.c index 7983a13a93..4aaafbdd7b 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,15 @@ 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 /* Flags: Conforms to the specifications of the bus */); } for (i = 1; i < 16; i++) { @@ -127,32 +134,30 @@ 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 /* Flags: Active high, Level Triggered */); } 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 LINT# */ + build_append_int_noprefix(table_data, 1 /* ACPI_LINT1 */, 1); + build_append_int_noprefix(table_data, 0, 3); /* Reserved */ } 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_end(linker, &table); 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; -- cgit v1.2.3-55-g7522 From 37f33084ed2eb0867e3a3f501c6279c7c5f666c6 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:52 -0400 Subject: acpi: arm/virt: madt: use build_append_int_noprefix() API to compose MADT table 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 Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-26-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/arm/virt-acpi-build.c | 150 ++++++++++++++++++++++++++------------------ include/hw/acpi/acpi-defs.h | 84 ------------------------- 2 files changed, 90 insertions(+), 144 deletions(-) (limited to 'include') diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index e3bdcd44e8..a9a78d904a 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -568,94 +568,124 @@ 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_table_begin(&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, + * 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 + */ + build_append_int_noprefix(table_data, 0xF, 1); /* Type */ + build_append_int_noprefix(table_data, 20, 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_end(linker, &table); } 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) */ -- cgit v1.2.3-55-g7522 From 3548494e49dacd33bbd610876d1ac38f8f8b94bc Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:55 -0400 Subject: acpi: arm: virt: build_iort: use acpi_table_begin()/acpi_table_end() instead of build_header() 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 Reviewed-by: Eric Auger Tested-by: Eric Auger Message-Id: <20210924122802.1455362-29-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/arm/virt-acpi-build.c | 44 ++++++++++++++++++-------------------------- include/hw/acpi/acpi-defs.h | 14 -------------- 2 files changed, 18 insertions(+), 40 deletions(-) (limited to 'include') diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 4b9687439d..42ea460313 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -273,20 +273,26 @@ static int iort_idmap_compare(gconstpointer a, gconstpointer b) return idmap_a->input_base - idmap_b->input_base; } +/* + * 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 i, nb_nodes, rc_mapping_count, iort_start = table_data->len; + int i, nb_nodes, rc_mapping_count; AcpiIortIdMapping *idmap; AcpiIortItsGroup *its; - AcpiIortTable *iort; AcpiIortSmmu3 *smmu; - size_t node_size, iort_node_offset, iort_length, smmu_offset = 0; AcpiIortRC *rc; + const uint32_t iort_node_offset = 48; + size_t node_size, smmu_offset = 0; GArray *smmu_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping)); GArray *its_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping)); - 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) { AcpiIortIdMapping next_range = {0}; @@ -325,18 +331,16 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) rc_mapping_count = 1; } - 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_table_begin(&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; @@ -350,7 +354,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; @@ -375,7 +378,6 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) /* Root Complex Node */ node_size = sizeof(*rc) + sizeof(*idmap) * rc_mapping_count; - iort_length += node_size; rc = acpi_data_push(table_data, node_size); rc->type = ACPI_IORT_NODE_PCI_ROOT_COMPLEX; @@ -424,19 +426,9 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) idmap->output_reference = cpu_to_le32(iort_node_offset); } + acpi_table_end(linker, &table); g_array_free(smmu_idmaps, true); g_array_free(its_idmaps, true); - - /* - * 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); } static void 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 */ -- cgit v1.2.3-55-g7522 From 271cbb2f2bfecfbb31175645f4e3da7ec626b810 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:56 -0400 Subject: acpi: arm/virt: convert build_iort() to endian agnostic build_append_FOO() API Drop usage of packed structures and explicit endian conversions when building IORT table use endian agnostic build_append_int_noprefix() API to build it. Signed-off-by: Igor Mammedov Message-Id: <20210924122802.1455362-30-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Eric Auger Tested-by: Eric Auger --- hw/arm/virt-acpi-build.c | 164 +++++++++++++++++++++++++------------------- include/hw/acpi/acpi-defs.h | 71 ------------------- 2 files changed, 93 insertions(+), 142 deletions(-) (limited to 'include') diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 42ea460313..8c382915a9 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -240,6 +240,28 @@ 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 input_base, + uint32_t id_count, uint32_t out_ref) +{ + /* Identity RID mapping covering the whole input RID range */ + build_append_int_noprefix(table_data, input_base, 4); /* Input base */ + build_append_int_noprefix(table_data, id_count, 4); /* Number of IDs */ + build_append_int_noprefix(table_data, input_base, 4); /* Output base */ + build_append_int_noprefix(table_data, out_ref, 4); /* Output Reference */ + build_append_int_noprefix(table_data, 0, 4); /* Flags */ +} + +struct AcpiIortIdMapping { + uint32_t input_base; + uint32_t id_count; +}; +typedef struct AcpiIortIdMapping AcpiIortIdMapping; + /* Build the iort ID mapping to SMMUv3 for a given PCI host bridge */ static int iort_host_bridges(Object *obj, void *opaque) @@ -282,17 +304,16 @@ static void build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) { int i, nb_nodes, rc_mapping_count; - AcpiIortIdMapping *idmap; - AcpiIortItsGroup *its; - AcpiIortSmmu3 *smmu; - AcpiIortRC *rc; - const uint32_t iort_node_offset = 48; + const uint32_t iort_node_offset = IORT_NODE_OFFSET; size_t node_size, smmu_offset = 0; + AcpiIortIdMapping *idmap; GArray *smmu_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping)); GArray *its_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping)); AcpiTable table = { .sig = "IORT", .rev = 0, .oem_id = vms->oem_id, .oem_table_id = vms->oem_table_id }; + /* Table 2 The IORT */ + acpi_table_begin(&table, table_data); if (vms->iommu == VIRT_IOMMU_SMMUV3) { AcpiIortIdMapping next_range = {0}; @@ -330,100 +351,101 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) nb_nodes = 2; /* RC, ITS */ rc_mapping_count = 1; } - - /* Table 2 The IORT */ - acpi_table_begin(&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, 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; + 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 */ + /* 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, 0, 0xFFFF, IORT_NODE_OFFSET); } - /* Root Complex Node */ - node_size = sizeof(*rc) + sizeof(*idmap) * rc_mapping_count; - 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(rc_mapping_count); - rc->mapping_offset = cpu_to_le32(sizeof(*rc)); - - /* 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 */ - + /* 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 * rc_mapping_count; + 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 */ + /* Number of ID mappings */ + build_append_int_noprefix(table_data, rc_mapping_count, 4); + /* Reference to ID Array */ + build_append_int_noprefix(table_data, ROOT_COMPLEX_ENTRY_SIZE, 4); + + /* Table 13 Memory access properties */ + /* CCA: Cache Coherent Attribute */ + build_append_int_noprefix(table_data, 1 /* fully coherent */, 4); + build_append_int_noprefix(table_data, 0, 1); /* AH: Note Allocation Hints */ + build_append_int_noprefix(table_data, 0, 2); /* Reserved */ + /* MAF: Note Memory Access Flags */ + build_append_int_noprefix(table_data, 0x3 /* CCA = CPM = DCAS = 1 */, 1); + + 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) { AcpiIortIdMapping *range; /* translated RIDs connect to SMMUv3 node: RC -> SMMUv3 -> ITS */ for (i = 0; i < smmu_idmaps->len; i++) { - idmap = &rc->id_mapping_array[i]; range = &g_array_index(smmu_idmaps, AcpiIortIdMapping, i); - - idmap->input_base = cpu_to_le32(range->input_base); - idmap->id_count = cpu_to_le32(range->id_count); - idmap->output_base = cpu_to_le32(range->input_base); /* output IORT node is the smmuv3 node */ - idmap->output_reference = cpu_to_le32(smmu_offset); + build_iort_id_mapping(table_data, range->input_base, + range->id_count, smmu_offset); } /* bypassed RIDs connect to ITS group node directly: RC -> ITS */ for (i = 0; i < its_idmaps->len; i++) { - idmap = &rc->id_mapping_array[smmu_idmaps->len + i]; range = &g_array_index(its_idmaps, AcpiIortIdMapping, i); - - idmap->input_base = cpu_to_le32(range->input_base); - idmap->id_count = cpu_to_le32(range->id_count); - idmap->output_base = cpu_to_le32(range->input_base); /* 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, range->input_base, + range->id_count, iort_node_offset); } } else { - /* Identity RID mapping covering the whole input RID range */ - idmap = &rc->id_mapping_array[0]; - idmap->input_base = cpu_to_le32(0); - idmap->id_count = cpu_to_le32(0xFFFF); - idmap->output_base = cpu_to_le32(0); /* 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, 0, 0xFFFF, IORT_NODE_OFFSET); } acpi_table_end(linker, &table); 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 -- cgit v1.2.3-55-g7522 From a86d86ac0ae39b7e8fcce08fffd2e0ab5aa287df Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:58 -0400 Subject: acpi: arm/virt: build_spcr: use acpi_table_begin()/acpi_table_end() instead of build_header() 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. PS: Spec is Microsoft hosted, however 1.02 is no where to be found (MS lists only the current revision) and the current revision is 1.07, so bring comments in line with 1.07 as this is the only available spec. There is no content change between originally implemented 1.02 (using QEMU code as reference) and 1.07. The only change is renaming 'Reserved2' field to 'Language', with the same 0 value. Signed-off-by: Igor Mammedov Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-32-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/arm/virt-acpi-build.c | 68 +++++++++++++++++++++++++++------------------ include/hw/acpi/acpi-defs.h | 32 --------------------- 2 files changed, 41 insertions(+), 59 deletions(-) (limited to 'include') diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 7b8706b305..7b79fae0ad 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -453,39 +453,53 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) g_array_free(its_idmaps, true); } +/* + * 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_table_begin(&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_end(linker, &table); } /* 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) */ -- cgit v1.2.3-55-g7522 From 41041e57085a9454c45a6a751babfca70306f361 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:27:59 -0400 Subject: acpi: arm/virt: build_gtdt: use acpi_table_begin()/acpi_table_end() instead of build_header() 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 Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-33-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/arm/virt-acpi-build.c | 75 +++++++++++++++++++++++++++++---------------- include/hw/acpi/acpi-defs.h | 25 --------------- 2 files changed, 48 insertions(+), 52 deletions(-) (limited to 'include') diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 7b79fae0ad..6cec97352b 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -559,40 +559,61 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) acpi_table_end(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_table_begin(&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_end(linker, &table); } /* 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 -- cgit v1.2.3-55-g7522 From cf68410bc98914ee9be5cb5a127a1212056ab83a Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:28:00 -0400 Subject: acpi: build_facs: use build_append_int_noprefix() API to compose table 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 Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-34-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 18 ++++++++++++++---- include/hw/acpi/acpi-defs.h | 14 -------------- 2 files changed, 14 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index d9e2b5dc30..81418b7911 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -345,13 +345,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) 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 -- cgit v1.2.3-55-g7522 From 538c2ecf1ab73fb2ecc2d50ef23b116e634b5392 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:28:01 -0400 Subject: acpi: remove no longer used build_header() Signed-off-by: Igor Mammedov Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-35-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/aml-build.c | 23 ----------------------- include/hw/acpi/acpi-defs.h | 25 ------------------------- include/hw/acpi/aml-build.h | 4 ---- 3 files changed, 52 deletions(-) (limited to 'include') diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index c0f339847a..76af0ebaf9 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -1754,29 +1754,6 @@ void acpi_table_end(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; 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 6e1f42e119..3cf6f2c1b9 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -444,10 +444,6 @@ void acpi_table_begin(AcpiTable *desc, GArray *array); */ void acpi_table_end(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); -- cgit v1.2.3-55-g7522 From a8a5768786f4182cb4f4b08e830150dc93d51964 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 24 Sep 2021 08:28:02 -0400 Subject: acpi: AcpiGenericAddress no longer used to map/access fields of MMIO, drop packed attribute Signed-off-by: Igor Mammedov Reviewed-by: Eric Auger Message-Id: <20210924122802.1455362-36-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/acpi/acpi-defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') 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 */ -- cgit v1.2.3-55-g7522 From 0e780da76a6fe283a20283856718bca3986c104f Mon Sep 17 00:00:00 2001 From: Ani Sinha Date: Thu, 16 Sep 2021 18:58:37 +0530 Subject: hw/i386/acpi: fix conflicting IO address range for acpi pci hotplug in q35 Change caf108bc58790 ("hw/i386/acpi-build: Add ACPI PCI hot-plug methods to Q35") selects an IO address range for acpi based PCI hotplug for q35 arbitrarily. It starts at address 0x0cc4 and ends at 0x0cdb. At the time when the patch was written but the final version of the patch was not yet pushed upstream, this address range was free and did not conflict with any other IO address ranges. However, with the following change, this address range was no longer conflict free as in this change, the IO address range (value of ACPI_PCIHP_SIZE) was incremented by four bytes: b32bd763a1ca92 ("pci: introduce acpi-index property for PCI device") This can be seen from the output of QMP command 'info mtree' : 0000000000000600-0000000000000603 (prio 0, i/o): acpi-evt 0000000000000604-0000000000000605 (prio 0, i/o): acpi-cnt 0000000000000608-000000000000060b (prio 0, i/o): acpi-tmr 0000000000000620-000000000000062f (prio 0, i/o): acpi-gpe0 0000000000000630-0000000000000637 (prio 0, i/o): acpi-smi 0000000000000cc4-0000000000000cdb (prio 0, i/o): acpi-pci-hotplug 0000000000000cd8-0000000000000ce3 (prio 0, i/o): acpi-cpu-hotplug It shows that there is a region of conflict between IO regions of acpi pci hotplug and acpi cpu hotplug. Unfortunately, the change caf108bc58790 did not update the IO address range appropriately before it was pushed upstream to accommodate the increased length of the IO address space introduced in change b32bd763a1ca92. Due to this bug, windows guests complain 'This device cannot find enough free resources it can use' in the device manager panel for extended IO buses. This issue also breaks the correct functioning of pci hotplug as the following shows that the IO space for pci hotplug has been truncated: (qemu) info mtree -f FlatView #0 AS "I/O", root: io Root memory region: io 0000000000000cc4-0000000000000cd7 (prio 0, i/o): acpi-pci-hotplug 0000000000000cd8-0000000000000cf7 (prio 0, i/o): acpi-cpu-hotplug Therefore, in this fix, we adjust the IO address range for the acpi pci hotplug so that it does not conflict with cpu hotplug and there is no truncation of IO spaces. The starting IO address of PCI hotplug region has been decremented by four bytes in order to accommodate four byte increment in the IO address space introduced by change b32bd763a1ca92 ("pci: introduce acpi-index property for PCI device") After fixing, the following are the corrected IO ranges: 0000000000000600-0000000000000603 (prio 0, i/o): acpi-evt 0000000000000604-0000000000000605 (prio 0, i/o): acpi-cnt 0000000000000608-000000000000060b (prio 0, i/o): acpi-tmr 0000000000000620-000000000000062f (prio 0, i/o): acpi-gpe0 0000000000000630-0000000000000637 (prio 0, i/o): acpi-smi 0000000000000cc0-0000000000000cd7 (prio 0, i/o): acpi-pci-hotplug 0000000000000cd8-0000000000000ce3 (prio 0, i/o): acpi-cpu-hotplug This change has been tested using a Windows Server 2019 guest VM. Windows no longer complains after this change. Fixes: caf108bc58790 ("hw/i386/acpi-build: Add ACPI PCI hot-plug methods to Q35") Resolves: https://gitlab.com/qemu-project/qemu/-/issues/561 Signed-off-by: Ani Sinha Reviewed-by: Igor Mammedov Reviewed-by: Julia Suvorova Message-Id: <20210916132838.3469580-3-ani@anisinha.ca> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/acpi/ich9.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h index a329ce43ab..f04f1791bd 100644 --- a/include/hw/acpi/ich9.h +++ b/include/hw/acpi/ich9.h @@ -29,7 +29,7 @@ #include "hw/acpi/acpi_dev_interface.h" #include "hw/acpi/tco.h" -#define ACPI_PCIHP_ADDR_ICH9 0x0cc4 +#define ACPI_PCIHP_ADDR_ICH9 0x0cc0 typedef struct ICH9LPCPMRegs { /* -- cgit v1.2.3-55-g7522