ACK: [PATCH] bios: mpcheck: reduce error level if ACPI is being used (LP: #1373340)

Alex Hung alex.hung at canonical.com
Thu Sep 25 02:17:23 UTC 2014


On 14-09-24 07:39 PM, Colin King wrote:
> From: Colin Ian King <colin.king at canonical.com>
>
> http://en.wikipedia.org/wiki/MultiProcessor_Specification states:
>
> "Since most newer machines support Advanced Configuration and Power
> Interface (ACPI) which subsumes the MPS functionality, MPS has for
> the most part been supplanted by ACPI. MPS can still be useful on
> machines or with operating systems that do not support ACPI."
>
> fwts should therefore indicate that any errors in the mptables on an
> ACPI compliant system should be LOW (ignored) if the ACPI LAPIC or
> IOAPIC configurations are being used.
>
> The best we can do for now is to check this by searching the kernel log
> to see if ACPI is being used and providing more useful information
> on the mpcheck if MP tables are not being used.  If this is so, we
> also lower the error level to LOW for any MP table issues since they
> are not critical on an ACPI based system.
>
> Signed-off-by: Colin Ian King <colin.king at canonical.com>
> ---
>   src/bios/multiproc/mpcheck.c | 102 +++++++++++++++++++++++++++++++------------
>   1 file changed, 75 insertions(+), 27 deletions(-)
>
> diff --git a/src/bios/multiproc/mpcheck.c b/src/bios/multiproc/mpcheck.c
> index 99118f3..3e34636 100644
> --- a/src/bios/multiproc/mpcheck.c
> +++ b/src/bios/multiproc/mpcheck.c
> @@ -23,6 +23,9 @@
>   #ifdef FWTS_ARCH_INTEL
>   
>   static fwts_mp_data mp_data;
> +static bool fwts_mp_not_used = false;
> +
> +#define LEVEL(level)	fwts_mp_not_used ? LOG_LEVEL_LOW : level
>   
>   static bool mpcheck_find_bus(uint8_t id, int depth)
>   {
> @@ -81,7 +84,7 @@ static int mpcheck_test_cpu_entries(fwts_framework *fw)
>   							fwts_list_data(fwts_mp_processor_entry *, entry2);
>   
>   						if (cpu_entry1->local_apic_id == cpu_entry2->local_apic_id) {
> -							fwts_failed(fw, LOG_LEVEL_HIGH,
> +							fwts_failed(fw, LEVEL(LOG_LEVEL_HIGH),
>   								"MPCPUEntryLAPICId",
>   								"CPU Entry %d (@0x%8.8" PRIx32 ")"
>   								" and %d (@0x%8.8" PRIx32 ") "
> @@ -100,7 +103,7 @@ static int mpcheck_test_cpu_entries(fwts_framework *fw)
>   			/*
>   			if ((cpu_entry1->local_apic_version != 0x11) &&
>   			    (cpu_entry1->local_apic_version != 0x14)) {
> -				fwts_failed(fw, LOG_LEVEL_HIGH,
> +				fwts_failed(fw, LEVEL(LOG_LEVEL_HIGH),
>   					"MPCPUEntryLAPICVersion",
>   					"CPU Entry %d (@0x%8.8" PRIx32 ") has an "
>   					"invalid Local APIC Version %2.2x, should be "
> @@ -115,7 +118,7 @@ static int mpcheck_test_cpu_entries(fwts_framework *fw)
>   
>   			if ((cpu_entry1->cpu_flags >> 1) & 1) {
>   				if (bootstrap_cpu != -1) {
> -					fwts_failed(fw, LOG_LEVEL_HIGH,
> +					fwts_failed(fw, LEVEL(LOG_LEVEL_HIGH),
>   						"MPCPUEntryBootCPU",
>   						"CPU Entry %d (@0x%8.8" PRIx32 ") "
>   						"is marked as a boot CPU but CPU entry "
> @@ -130,7 +133,7 @@ static int mpcheck_test_cpu_entries(fwts_framework *fw)
>   	}
>   
>   	if (!usable_cpu_found) {
> -		fwts_failed(fw, LOG_LEVEL_HIGH,
> +		fwts_failed(fw, LEVEL(LOG_LEVEL_HIGH),
>   			"MPCPUEntryUsable",
>   			"CPU entries 0..%d were not marked as usable. "
>   			"There should be at least one usable CPU.",
> @@ -187,7 +190,7 @@ static int mpcheck_test_bus_entries(fwts_framework *fw)
>   					break;
>   			}
>   			if (bus_types[i] == NULL) {
> -				fwts_failed(fw, LOG_LEVEL_HIGH,
> +				fwts_failed(fw, LEVEL(LOG_LEVEL_HIGH),
>   					"MPBusEntryBusType",
>   					"Bus Entry %d (@0x%8.8" PRIx32 ") has an "
>   					"unrecognised bus type: %6.6s",
> @@ -196,7 +199,7 @@ static int mpcheck_test_bus_entries(fwts_framework *fw)
>   			if (prev_bus_id == -1) {
>   				prev_bus_id = bus_entry->bus_id;
>   				if (prev_bus_id != 0) {
> -					fwts_failed(fw, LOG_LEVEL_HIGH,
> +					fwts_failed(fw, LEVEL(LOG_LEVEL_HIGH),
>   						"MPBusEntryLAPICId",
>   						"Bus Entry %d (@0x%8.8" PRIx32 ") has a "
>   						"Local APIC ID 0x%2.2x and should be 0x00.",
> @@ -206,7 +209,7 @@ static int mpcheck_test_bus_entries(fwts_framework *fw)
>   				}
>   			} else {
>   				if (bus_entry->bus_id < prev_bus_id) {
> -					fwts_failed(fw, LOG_LEVEL_HIGH,
> +					fwts_failed(fw, LEVEL(LOG_LEVEL_HIGH),
>   						"MPBusEntryBusId",
>   						"Bus Entry %d (@0x%8.8" PRIx32 ") has a "
>   						"Bus ID 0x%2.2x and should be greater "
> @@ -240,7 +243,8 @@ static int mpcheck_test_io_apic_entries(fwts_framework *fw)
>   			fwts_mp_io_apic_entry *io_apic_entry = fwts_list_data(fwts_mp_io_apic_entry *, entry);
>   
>   			if (io_apic_entry->address == 0) {
> -				fwts_failed(fw, LOG_LEVEL_HIGH, "MPIOAPICNullAddr",
> +				fwts_failed(fw, LEVEL(LOG_LEVEL_HIGH),
> +					"MPIOAPICNullAddr",
>   					"IO APIC Entry %d (@0x%8.8" PRIx32 ") has an "
>   					"invalid NULL address, should be non-zero.",
>   					n, phys_addr);
> @@ -254,7 +258,8 @@ static int mpcheck_test_io_apic_entries(fwts_framework *fw)
>   	}
>   
>   	if (!enabled) {
> -		fwts_failed(fw, LOG_LEVEL_HIGH, "MPIOAPICEnabled",
> +		fwts_failed(fw, LEVEL(LOG_LEVEL_HIGH),
> +			"MPIOAPICEnabled",
>   			"None of the %d IO APIC entries were enabled, "
>   			"at least one must be enabled.", n);
>   		failed = true;
> @@ -307,7 +312,7 @@ static int mpcheck_test_io_interrupt_entries(fwts_framework *fw)
>   				fwts_list_data(fwts_mp_io_interrupt_entry *, entry);
>   
>   			if (io_interrupt_entry->type > 3) {
> -				fwts_failed(fw, LOG_LEVEL_HIGH,
> +				fwts_failed(fw, LEVEL(LOG_LEVEL_HIGH),
>   					"MPIOIRQType",
>   					"IO Interrupt Entry %d (@0x%8.8" PRIx32 ") has a "
>   					"Type 0x%2.2" PRIx8 " and should be 0x00..0x03.",
> @@ -316,7 +321,7 @@ static int mpcheck_test_io_interrupt_entries(fwts_framework *fw)
>   				failed = true;
>   			}
>   			if (!mpcheck_find_io_apic(io_interrupt_entry->destination_io_apic_id)) {
> -				fwts_failed(fw, LOG_LEVEL_HIGH,
> +				fwts_failed(fw, LEVEL(LOG_LEVEL_HIGH),
>   					"MPIOAPICId",
>   					"IO Interrupt Entry %d (@0x%8.8" PRIx32 ") has a "
>   					"Destination IO APIC ID 0x%2.2" PRIx8 " "
> @@ -348,7 +353,7 @@ static int mpcheck_test_local_interrupt_entries(fwts_framework *fw)
>   			fwts_mp_local_interrupt_entry *local_interrupt_entry =
>   				fwts_list_data(fwts_mp_local_interrupt_entry *, entry);
>   			if (local_interrupt_entry->type > 3) {
> -				fwts_failed(fw, LOG_LEVEL_HIGH,
> +				fwts_failed(fw, LEVEL(LOG_LEVEL_HIGH),
>   					"MPLocalIRQType",
>   					"Local Interrupt Entry %d (@0x%8.8" PRIx32 ") has a "
>   					"Type 0x%2.2" PRIx8 " and should be 0x00..0x03.",
> @@ -358,7 +363,7 @@ static int mpcheck_test_local_interrupt_entries(fwts_framework *fw)
>   			}
>   #if 0
>   			if (!mpcheck_find_io_apic(local_interrupt_entry->destination_local_apic_id)) {
> -				fwts_failed(fw, LOG_LEVEL_HIGH,
> +				fwts_failed(fw, LEVEL(LOG_LEVEL_HIGH),
>   					"MPLocalIRQDestIRQAPIDId",
>   					"Local Interrupt Entry %d (@0x%8.8" PRIx32 ") has a"
>   					"Destination IO APIC ID 0x%2.2" PRIx8 " "
> @@ -392,7 +397,7 @@ static int mpcheck_test_sys_addr_entries(fwts_framework *fw)
>   				fwts_list_data(fwts_mp_system_address_space_entry *, entry);
>   
>   			if (!mpcheck_find_bus(sys_addr_entry->bus_id, 0)) {
> -				fwts_failed(fw, LOG_LEVEL_MEDIUM,
> +				fwts_failed(fw, LEVEL(LOG_LEVEL_MEDIUM),
>   					"MPSysAddrSpaceBusId",
>   					"System Address Space Mapping Entry %d (@0x%8.8" PRIx32 ") "
>   					"has an Bus ID 0x%2.2" PRIx8 " "
> @@ -401,7 +406,7 @@ static int mpcheck_test_sys_addr_entries(fwts_framework *fw)
>   				failed = true;
>   			}
>   			if (sys_addr_entry->address_type > 3) {
> -				fwts_failed(fw, LOG_LEVEL_MEDIUM,
> +				fwts_failed(fw, LEVEL(LOG_LEVEL_MEDIUM),
>   					"MPSysAddrSpaceType",
>   					"System Address Space Mapping Entry %d (@0x%8.8" PRIx32 ") "
>   					"has an incorrect Address Type: %2.2" PRIx8 ", "
> @@ -411,7 +416,7 @@ static int mpcheck_test_sys_addr_entries(fwts_framework *fw)
>   				failed = true;
>   			}
>   			if (sys_addr_entry->address_length == 0) {
> -				fwts_failed(fw, LOG_LEVEL_MEDIUM,
> +				fwts_failed(fw, LEVEL(LOG_LEVEL_MEDIUM),
>   					"MPSysAddrSpaceAddrLength",
>   					"System Address Space Mapping Entry %d "
>   					"(@0x%8.8" PRIx32 ") has a "
> @@ -442,7 +447,7 @@ static int mpcheck_test_bus_hierarchy_entries(fwts_framework *fw)
>   			fwts_mp_bus_hierarchy_entry *bus_hierarchy_entry =
>   				fwts_list_data(fwts_mp_bus_hierarchy_entry *, entry);
>   			if (bus_hierarchy_entry->length != 8) {
> -				fwts_failed(fw, LOG_LEVEL_MEDIUM,
> +				fwts_failed(fw, LEVEL(LOG_LEVEL_MEDIUM),
>   					"MPBusHieraracyLength",
>   					"Bus Hierarchy Entry %d (@x%8.8" PRIx32 ") "
>   					"length was 0x%2.2" PRIx8 ", it should be 0x08.",
> @@ -451,7 +456,7 @@ static int mpcheck_test_bus_hierarchy_entries(fwts_framework *fw)
>   				failed = true;
>   			}
>   			if (!mpcheck_find_bus(bus_hierarchy_entry->parent_bus, 0)) {
> -				fwts_failed(fw, LOG_LEVEL_MEDIUM,
> +				fwts_failed(fw, LEVEL(LOG_LEVEL_MEDIUM),
>   					"MPBusHierarchyParents",
>   					"Bus Hierarchy Entry %d (@x%8.8" PRIx32 ") "
>   					"did not have parents that "
> @@ -483,7 +488,7 @@ static int mpcheck_test_compat_bus_address_space_entries(fwts_framework *fw)
>   				fwts_list_data(fwts_mp_compat_bus_address_space_entry*, entry);
>   
>   			if (compat_bus_entry->length != 8) {
> -				fwts_failed(fw, LOG_LEVEL_MEDIUM,
> +				fwts_failed(fw, LEVEL(LOG_LEVEL_MEDIUM),
>   					"MPCompatBusLength",
>   					"Compatible Bus Address Space Entry %d "
>   					"(@x%8.8" PRIx32 ") "
> @@ -493,7 +498,7 @@ static int mpcheck_test_compat_bus_address_space_entries(fwts_framework *fw)
>   				failed = true;
>   			}
>   			if (compat_bus_entry->range_list > 1) {
> -				fwts_failed(fw, LOG_LEVEL_MEDIUM,
> +				fwts_failed(fw, LEVEL(LOG_LEVEL_MEDIUM),
>   					"MPCompatBusRangeList",
>   					"Compatible Bus Address Space Entry %d "
>   					"(@x%8.8" PRIx32 ") Range List was 0x%8.8" PRIx32
> @@ -511,13 +516,53 @@ static int mpcheck_test_compat_bus_address_space_entries(fwts_framework *fw)
>   	return FWTS_OK;
>   }
>   
> +static void mpcheck_mp_used(fwts_framework *fw)
> +{
> +	fwts_list *klog;
> +
> +	/* Can't read kernel log, not fatal */
> +	if ((klog = fwts_klog_read()) == NULL)
> +		return;
> +
> +	/*
> +	 * Kernel reported that MADT is being used, so MP tables are ignored,
> +	 * this is only issues when the ACPI LAPIC is being used AND the
> +	 * ACPI IOAPIC is used too.
> +	 */
> +	if (fwts_klog_regex_find(fw, klog,
> +		"Using ACPI \\(MADT\\) for SMP configuration information") > 0) {
> +		fwts_mp_not_used = true;
> +		fwts_log_info(fw,
> +			"The kernel is using the ACPI MADT for SMP "
> +			"configuration information, so the Multiprocessor Tables "
> +			"are not used by the kernel. Any errors in the tables "
> +			"will not affect the operation of Linux unless it is "
> +			"booted with ACPI disabled.");
> +		fwts_log_nl(fw);
> +		fwts_log_info(fw,
> +			"NOTE: Since ACPI is being used in preference to the "
> +			"Multiprocessor Tables, any errors found in the mpcheck "
> +			"tests will be tagged as LOW errors.");
> +		fwts_log_nl(fw);
> +	}
> +
> +	fwts_klog_free(klog);
> +}
>   
>   static int mpcheck_init(fwts_framework *fw)
>   {
> +	mpcheck_mp_used(fw);
> +
>   	if (fwts_mp_data_get(&mp_data) != FWTS_OK) {
> -		fwts_log_error(fw, "Failed to get _MP_ data from firmware.");
> +		fwts_log_info(fw,
> +			"Failed to find the Multiprocessor Table data, skipping mpcheck test.");
> +		if (fwts_mp_not_used)
> +			fwts_log_info(fw,
> +				"NOTE: Since the ACPI MADT is being used instead for "
> +				"SMP configuration, this is not a problem.");
>   		return FWTS_SKIP;
>   	}
> +
>   	return FWTS_OK;
>   }
>   
> @@ -533,21 +578,24 @@ static int mpcheck_test_header(fwts_framework *fw)
>   	bool failed = false;
>   
>   	if (strncmp((char*)mp_data.header->signature, FWTS_MP_HEADER_SIGNATURE, 4)) {
> -		fwts_failed(fw, LOG_LEVEL_MEDIUM, "MPHeaderSig",
> +		fwts_failed(fw, LEVEL(LOG_LEVEL_MEDIUM),
> +			"MPHeaderSig",
>   			"MP header signature should be %s, got %4.4s.",
>   			FWTS_MP_HEADER_SIGNATURE, mp_data.header->signature);
>   		failed = true;
>   	}
>   
>   	if ((mp_data.header->spec_rev != 1) && (mp_data.header->spec_rev != 4)) {
> -		fwts_failed(fw, LOG_LEVEL_MEDIUM, "MPHeaderRevision",
> -		"MP header spec revision should be 1 or 4, got %" PRIx8 ".",
> -		mp_data.header->spec_rev);
> +		fwts_failed(fw, LEVEL(LOG_LEVEL_MEDIUM),
> +			"MPHeaderRevision",
> +			"MP header spec revision should be 1 or 4, got %" PRIx8 ".",
> +			mp_data.header->spec_rev);
>   		failed = true;
>   	}
>   	if (mp_data.header->lapic_address == 0) {
> -		fwts_failed(fw, LOG_LEVEL_MEDIUM, "MPHeaderLAPICAddrNull",
> -		"MP header LAPIC address is NULL.");
> +		fwts_failed(fw, LEVEL(LOG_LEVEL_MEDIUM),
> +			"MPHeaderLAPICAddrNull",
> +			"MP header LAPIC address is NULL.");
>   		failed = true;
>   	}
>   	if (!failed)
Thanks Colin. This should solve many false positives we are seeing.

Acked-by: Alex Hung <alex.hung at canonical.com>



More information about the fwts-devel mailing list