diff mbox series

acpi: madt: handle GICR and ITS flags for ACPI 6.6 (mantis 2422)

Message ID 20251112072819.275903-1-ivan.hu@canonical.com
State Accepted
Headers show
Series acpi: madt: handle GICR and ITS flags for ACPI 6.6 (mantis 2422) | expand

Commit Message

Ivan Hu Nov. 12, 2025, 7:28 a.m. UTC
BugLink: https://bugs.launchpad.net/fwts/+bug/2131128

ACPI 6.6 splits the first word of the GICR and GIC ITS nodes into a flag byte.
This should be checked after checking the madt revision >= 7.

Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
---
 src/acpi/madt/madt.c        | 97 ++++++++++++++++++++++++++++---------
 src/lib/include/fwts_acpi.h | 16 +++++-
 2 files changed, 89 insertions(+), 24 deletions(-)
diff mbox series

Patch

diff --git a/src/acpi/madt/madt.c b/src/acpi/madt/madt.c
index caa4b96c..3b574b6e 100644
--- a/src/acpi/madt/madt.c
+++ b/src/acpi/madt/madt.c
@@ -1368,23 +1368,50 @@  static int madt_gicr(fwts_framework *fw,
 {
 	/* specific checks for subtable type 0xe: GICR */
 	fwts_acpi_madt_gicr *gicr = (fwts_acpi_madt_gicr *)data;
+	fwts_acpi_table_madt *madt = (fwts_acpi_table_madt *)mtable->data;
 
 	/*
 	 * TODO: GICR structures should only be used when GICs implement
 	 * version 3 or higher.
 	 */
 
-	if (gicr->reserved)
-		fwts_failed(fw, LOG_LEVEL_LOW,
-			    "MADTGICRReservedNonZero",
-			    "MADT %s reserved field should be zero, "
-			    "instead got 0x%" PRIx32 ".",
-			    madt_sub_names[hdr->type],
-			    gicr->reserved);
-	else
-		fwts_passed(fw,
-			    "MADT %s reserved field properly set to zero.",
-			    madt_sub_names[hdr->type]);
+	if (madt && madt->header.revision >= 7) {
+		if (gicr->gicr.flags & ~0x1) {
+			fwts_failed(fw, LOG_LEVEL_LOW,
+				    "MADTGICRReservedFlags",
+				    "MADT %s flags bits 1..7 are reserved and should "
+				    "be zero, but 0x%" PRIx8 " was reported.",
+				    madt_sub_names[hdr->type], gicr->gicr.flags);
+		} else {
+			fwts_passed(fw,
+				    "MADT %s reserved flag bits are properly cleared.",
+				    madt_sub_names[hdr->type]);
+		}
+
+		if (gicr->gicr.reserved)
+			fwts_failed(fw, LOG_LEVEL_LOW,
+				    "MADTGICRReservedNonZero",
+				    "MADT %s reserved byte should be zero, "
+				    "instead got 0x%" PRIx8 ".",
+				    madt_sub_names[hdr->type],
+				    gicr->gicr.reserved);
+		else
+			fwts_passed(fw,
+				    "MADT %s reserved byte properly set to zero.",
+				    madt_sub_names[hdr->type]);
+	} else {
+		if (gicr->reserved)
+			fwts_failed(fw, LOG_LEVEL_LOW,
+				    "MADTGICRReservedNonZero",
+				    "MADT %s reserved field should be zero, "
+				    "instead got 0x%" PRIx16 ".",
+				    madt_sub_names[hdr->type],
+				    gicr->reserved);
+		else
+			fwts_passed(fw,
+				    "MADT %s reserved field properly set to zero.",
+				    madt_sub_names[hdr->type]);
+	}
 
 	/*
 	 * TODO: can Discovery Range Base Address ever be zero?
@@ -1411,20 +1438,46 @@  static int madt_gic_its(fwts_framework *fw,
 {
 	/* specific checks for subtable type 0xf: GIC ITS */
 	fwts_acpi_madt_gic_its *gic_its = (fwts_acpi_madt_gic_its *)data;
+	fwts_acpi_table_madt *madt = (fwts_acpi_table_madt *)mtable->data;
 	fwts_list_link *item;
 	bool found;
 
-	if (gic_its->reserved)
-		fwts_failed(fw, LOG_LEVEL_LOW,
-			    "SPECMADTGICITSReservedNonZero",
-			    "MADT %s first reserved field should be zero, "
-			    "instead got 0x%" PRIx32 ".",
-			    madt_sub_names[hdr->type], gic_its->reserved);
-	else
-		fwts_passed(fw,
-			    "MADT %s first reserved field is properly set "
-			    "to zero.",
-			    madt_sub_names[hdr->type]);
+	if (madt && madt->header.revision >= 7) {
+		if (gic_its->gic_its.flags & ~0x1)
+			fwts_failed(fw, LOG_LEVEL_LOW,
+				    "SPECMADTGICITSReservedFlags",
+				    "MADT %s flags bits 1..7 are reserved and should "
+				    "be zero, but 0x%" PRIx8 " was reported.",
+				    madt_sub_names[hdr->type], gic_its->gic_its.flags);
+		else
+			fwts_passed(fw,
+				    "MADT %s reserved flag bits are properly cleared.",
+				    madt_sub_names[hdr->type]);
+
+		if (gic_its->gic_its.reserved)
+			fwts_failed(fw, LOG_LEVEL_LOW,
+				    "SPECMADTGICITSReservedNonZero",
+				    "MADT %s reserved byte should be zero, "
+				    "instead got 0x%" PRIx8 ".",
+				    madt_sub_names[hdr->type], gic_its->gic_its.reserved);
+		else
+			fwts_passed(fw,
+				    "MADT %s reserved byte is properly set "
+				    "to zero.",
+				    madt_sub_names[hdr->type]);
+	} else {
+		if (gic_its->reserved)
+			fwts_failed(fw, LOG_LEVEL_LOW,
+				    "SPECMADTGICITSReservedNonZero",
+				    "MADT %s reserved field should be zero, "
+				    "instead got 0x%" PRIx16 ".",
+				    madt_sub_names[hdr->type], gic_its->reserved);
+		else
+			fwts_passed(fw,
+				    "MADT %s reserved field is properly set "
+				    "to zero.",
+				    madt_sub_names[hdr->type]);
+	}
 
 	/*
 	 * Check ITS ID against previously found IDs to see if it
diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h
index 025127dd..a47dd107 100644
--- a/src/lib/include/fwts_acpi.h
+++ b/src/lib/include/fwts_acpi.h
@@ -697,7 +697,13 @@  typedef struct {
 /* New in ACPI 5.1, GICR structure, 5.2.12.17 */
 /* Type 14, FWTS_MADT_GIC_R_REDISTRIBUTOR */
 typedef struct {
-	uint16_t	reserved;
+	union {
+		uint16_t	reserved;
+		struct {
+			uint8_t	flags;
+			uint8_t	reserved;
+		} __attribute__ ((packed)) gicr;
+	};
 	uint64_t	discovery_range_base_address;
 	uint32_t	discovery_range_length;
 } __attribute__ ((packed)) fwts_acpi_madt_gicr;
@@ -705,7 +711,13 @@  typedef struct {
 /* New in ACPI 6.0, GIC ITS structure, 5.2.12.18 */
 /* Type 15, FWTS_MADT_GIC_ITS */
 typedef struct {
-	uint16_t	reserved;
+	union {
+		uint16_t	reserved;
+		struct {
+			uint8_t	flags;
+			uint8_t	reserved;
+		} __attribute__ ((packed)) gic_its;
+	};
 	uint32_t	its_id;
 	uint64_t	physical_base_address;
 	uint32_t	reserved2;