@@ -17,6 +17,8 @@
#if defined(FWTS_HAS_ACPI)
+#include "fwts_acpi_object_eval.h"
+
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
@@ -203,6 +205,95 @@ static fwts_acpi_table_info *ftable;
static fwts_list msi_frame_ids;
static fwts_list its_ids;
+static fwts_list processor_uids;
+
+struct acpi_processor {
+ ACPI_OBJECT_TYPE type;
+ uint32_t proc_id;
+ ACPI_IO_ADDRESS pblk_address;
+ uint32_t pblk_length;
+};
+
+struct acpi_integer {
+ ACPI_OBJECT_TYPE type;
+ uint64_t value;
+};
+
+struct list_integer {
+ uint64_t value;
+};
+
+static ACPI_STATUS madt_processor_handler(ACPI_HANDLE ObjHandle, uint32_t level,
+ void *context, void **returnvalue)
+{
+ ACPI_OBJECT_TYPE acpi_type;
+ ACPI_STATUS status;
+ struct acpi_processor processor;
+ struct acpi_integer integer;
+ struct acpi_buffer pbuf = {sizeof(struct acpi_processor), &processor};
+ struct acpi_buffer ibuf = {sizeof(struct acpi_integer), &integer};
+ struct list_integer *listint;
+
+ /* Prevent -Werror=unused-parameter from complaining */
+ FWTS_UNUSED(level);
+ FWTS_UNUSED(context);
+ FWTS_UNUSED(returnvalue);
+
+ listint = malloc(sizeof(struct list_integer));
+ if (!listint)
+ return (!AE_OK);
+
+ status = AcpiGetType(ObjHandle, &acpi_type);
+ if (ACPI_FAILURE(status))
+ return (!AE_OK);
+
+ switch(acpi_type) {
+ case ACPI_TYPE_PROCESSOR:
+ status = AcpiEvaluateObject(ObjHandle, NULL, NULL,
+ &pbuf);
+ if (ACPI_FAILURE(status))
+ return status;
+ listint->value = processor.proc_id;
+ break;
+ case ACPI_TYPE_DEVICE:
+ status = AcpiEvaluateObject(ObjHandle, "_UID", NULL,
+ &ibuf);
+ if (ACPI_FAILURE(status))
+ return status;
+ listint->value = integer.value;
+ break;
+ default:
+ return (!AE_OK);
+ }
+ fwts_list_append(&processor_uids, listint);
+
+ return (AE_OK);
+}
+
+static void madt_find_processor_uid(fwts_framework *fw, uint64_t uid,
+ char *table_name)
+{
+ char table_label[64];
+ fwts_list_link *item;
+ struct list_integer *listint;
+
+ /* TODO: is UID = 0 an error? */
+
+ fwts_list_foreach(item, &processor_uids) {
+ listint = fwts_list_data(struct list_integer *, item);
+ if (uid == listint->value) {
+ fwts_passed(fw, "MADT %s has matching processor "
+ "UID %lu.", table_name, uid);
+ return;
+ }
+ }
+
+ sprintf(table_label, "MADT%sUidMismatch", table_name);
+ fwts_failed(fw, LOG_LEVEL_MEDIUM,
+ table_label, "%s has no matching processor UID %lu",
+ table_name, uid);
+ return;
+}
static int madt_init(fwts_framework *fw)
{
@@ -270,6 +361,14 @@ static int madt_init(fwts_framework *fw)
*/
fwts_list_init(&msi_frame_ids);
fwts_list_init(&its_ids);
+ fwts_list_init(&processor_uids);
+
+ if (fwts_acpica_init(fw) != FWTS_OK)
+ return FWTS_ERROR;
+
+ AcpiWalkNamespace(0x0c, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+ madt_processor_handler, NULL, NULL, NULL);
+ AcpiGetDevices("ACPI0007", madt_processor_handler, NULL, NULL);
return (spec_data) ? FWTS_OK : FWTS_ERROR;
}
@@ -412,11 +511,7 @@ static int madt_local_apic(fwts_framework *fw,
fwts_acpi_madt_processor_local_apic *lapic =
(fwts_acpi_madt_processor_local_apic *)data;
- /*
- * TODO: verify UID field has a corresponding
- * Processor device object with a matching
- * _UID result
- */
+ madt_find_processor_uid(fw, lapic->acpi_processor_id, "LAPIC");
if (lapic->flags & 0xfffffffe)
fwts_failed(fw, LOG_LEVEL_MEDIUM,
@@ -527,11 +622,7 @@ static int madt_local_apic_nmi(fwts_framework *fw,
fwts_acpi_madt_local_apic_nmi *nmi =
(fwts_acpi_madt_local_apic_nmi *)data;
- /*
- * TODO: verify UID field has a corresponding
- * Processor device object with a matching
- * _UID result
- */
+ madt_find_processor_uid(fw, nmi->acpi_processor_id, "LAPICNMI");
if (nmi->flags & 0xfffffff0)
fwts_failed(fw, LOG_LEVEL_MEDIUM,
@@ -693,11 +784,7 @@ static int madt_local_sapic(fwts_framework *fw,
"reserved and properly set to zero.",
madt_sub_names[hdr->type]);
- /*
- * TODO: verify UID field has a corresponding
- * Processor device object with a matching
- * _UID result (or Processor object ID?)
- */
+ madt_find_processor_uid(fw, lsapic->acpi_processor_id, "LSAPIC");
for (tmp = 0, ii = 0; ii < (int)strlen(lsapic->uid_string); ii++)
if (isascii(lsapic->uid_string[ii]))
@@ -817,11 +904,7 @@ static int madt_local_x2apic(fwts_framework *fw,
"reserved and properly set to zero.",
madt_sub_names[hdr->type]);
- /*
- * TODO: verify UID field has a corresponding
- * Processor device object with a matching
- * _UID result
- */
+ madt_find_processor_uid(fw, lx2apic->processor_uid, "X2APIC");
return (hdr->length - sizeof(fwts_acpi_madt_sub_table_header));
}
@@ -869,11 +952,7 @@ static int madt_gicc(fwts_framework *fw,
"MADT %s reserved field properly set to zero.",
madt_sub_names[hdr->type]);
- /*
- * TODO: verify UID field has a corresponding
- * Processor device object with a matching
- * _UID result
- */
+ madt_find_processor_uid(fw, gic->processor_uid, "GICC");
mask = 0xfffffffc;
start = 2;
@@ -1395,9 +1474,12 @@ static int madt_subtables(fwts_framework *fw)
static int madt_deinit(fwts_framework *fw)
{
+ fwts_acpica_deinit();
+
/* only minor clean up needed */
fwts_list_free_items(&msi_frame_ids, NULL);
fwts_list_free_items(&its_ids, NULL);
+ fwts_list_free_items(&processor_uids, NULL);
return (fw) ? FWTS_ERROR : FWTS_OK;
}
The current madt test does not do any processor UID comparisons. They are marked as TODOs in the file. This patchset implements two ACPI searches (one for old-style Processor Declaration operator, and another for the new Processor Device operator) that populate a list of UID entries, which can be queried for each MADT struct's UID. Signed-off-by: Prarit Bhargava <prarit@redhat.com> --- src/acpi/madt/madt.c | 132 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 107 insertions(+), 25 deletions(-)