[prev in list] [next in list] [prev in thread] [next in thread]
List: fwts-devel
Subject: ACK: [PATCH] hpet: hpetcheck: add ACPI HPET table check
From: Alex Hung <alex.hung () canonical ! com>
Date: 2012-12-21 6:11:08
Message-ID: 50D3FD7C.3070506 () canonical ! com
[Download RAW message or body]
On 12/12/2012 07:35 AM, Colin King wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> The original test has some notion of checking the HPET table
> but this was #ifdef'd out from the original Linux Firmware
> Developer Kit code and never implemented in fwts. Remove the
> old legacy code and fully implement a HPET table validation.
>
> Since we want to sanity check where the kernel's view of where
> the HPET is located and what the HPET table states, I've re-ordered
> the sub-tests to ensure the new test runs 2nd.
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> ---
> src/hpet/hpet_check/hpet_check.c | 224 ++++++++++++++++++++++++++++++++-------
> 1 file changed, 186 insertions(+), 38 deletions(-)
>
> diff --git a/src/hpet/hpet_check/hpet_check.c b/src/hpet/hpet_check/hpet_check.c
> index 399bde2..9b8eac6 100644
> --- a/src/hpet/hpet_check/hpet_check.c
> +++ b/src/hpet/hpet_check/hpet_check.c
> @@ -34,28 +34,6 @@ static fwts_list *klog;
> static uint64_t hpet_base_p = 0;
> static void *hpet_base_v = 0;
>
> -#if 0
> -/* check_hpet_base_hpet() -- used to parse the HPET Table for HPET base info */
> -static void check_hpet_base_hpet(void)
> -{
> - unsigned long address = 0;
> - unsigned long size = 0;
> - struct hpet_table *table;
> - char *table_ptr;
> -
> - if (locate_acpi_table("HPET", &address, &size))
> - return;
> -
> - if (address == 0 || address == -1)
> - return;
> -
> - table = (struct hpet_table *) address;
> -
> - hpet_base_p = table->base_address.address;
> - free((void *) address);
> -}
> -#endif
> -
> static void hpet_parse_check_base(fwts_framework *fw,
> const char *table, fwts_list_link *item)
> {
> @@ -74,14 +52,14 @@ static void hpet_parse_check_base(fwts_framework *fw,
> fwts_failed(fw, LOG_LEVEL_MEDIUM,
> "HPETBaseMismatch",
> "Mismatched HPET base between %s (%" PRIx64 ") "
> - "and the kernel (%" PRIx64 ").",
> + "and the kernel (0x%" PRIx64 ").",
> table,
> hpet_base_p,
> address_base);
> else
> fwts_passed(fw,
> "HPET base matches that between %s and "
> - "the kernel (%" PRIx64 ").",
> + "the kernel (0x%" PRIx64 ").",
> table,
> hpet_base_p);
> }
> @@ -185,7 +163,7 @@ static int hpet_check_test1(fwts_framework *fw)
> if (str) {
> hpet_base_p = strtoul(str+6, NULL, 0x10);
> fwts_passed(fw,
> - "Found HPET base %" PRIx64 " in kernel log.",
> + "Found HPET base 0x%" PRIx64 " in kernel log.",
> hpet_base_p);
> break;
> }
> @@ -198,7 +176,7 @@ static int hpet_check_test1(fwts_framework *fw)
> if (str) {
> hpet_base_p = strtoul(str+8, NULL, 0x10);
> fwts_passed(fw,
> - "Found HPET base %" PRIx64 " in kernel log.",
> + "Found HPET base 0x%" PRIx64 " in kernel log.",
> hpet_base_p);
> break;
> }
> @@ -213,8 +191,187 @@ static int hpet_check_test1(fwts_framework *fw)
> return FWTS_OK;
> }
>
> +/*
> + * Sanity check HPET table, see:
> + * http://www.intel.co.uk/content/www/uk/en/software-developers/software-developers-hpet-spec-1-0a.html
> + */
> static int hpet_check_test2(fwts_framework *fw)
> {
> + fwts_acpi_table_info *table;
> + fwts_acpi_table_hpet *hpet;
> + bool passed = true;
> + char *page_prot;
> +
> + if (fwts_acpi_find_table(fw, "HPET", 0, &table) != FWTS_OK) {
> + fwts_log_error(fw, "Cannot read ACPI table HPET.");
> + return FWTS_ERROR;
> + }
> +
> + if (table == NULL) {
> + fwts_log_error(fw, "ACPI table HPET does not exist!");
> + return FWTS_ERROR;
> + }
> +
> + if (table->length < sizeof(fwts_acpi_table_hpet)) {
> + fwts_failed(fw, LOG_LEVEL_HIGH, "HPETAcpiTableTooSmall",
> + "HPET ACPI table is %zd bytes long which is smaller "
> + "than the expected size of %zd bytes.",
> + table->length, sizeof(fwts_acpi_table_hpet));
> + return FWTS_ERROR;
> + }
> +
> + hpet = (fwts_acpi_table_hpet *)table->data;
> +
> + if (hpet->base_address.address == 0) {
> + fwts_failed(fw, LOG_LEVEL_HIGH, "HPETAcpiBaseAddressNull",
> + "HPET base address in ACPI HPET table is null.");
> + passed = false;
> + }
> +
> + /*
> + * If we've already figured out the HPET base address then
> + * sanity check it against HPET. This should never happen.
> + */
> + if ((hpet_base_p != 0) &&
> + (hpet_base_p != hpet->base_address.address)) {
> + fwts_failed(fw, LOG_LEVEL_MEDIUM,
> + "HPETAcpiBaseAddressDifferFromKernel",
> + "HPET base address in ACPI HPET table "
> + "is 0x%" PRIx64 " which is different from "
> + "the kernel HPET base address of "
> + "0x%" PRIx64 ".",
> + hpet->base_address.address, hpet_base_p);
> + passed = false;
> + }
> +
> +#if 0
> + /*
> + * The Intel spec states that the address space ID
> + * must be memory or I/O space.
> + */
> + if ((hpet->base_address.address_space_id != 0) &&
> + (hpet->base_address.address_space_id != 1)) {
> + fwts_failed(fw, LOG_LEVEL_HIGH,
> + "HPETAcpiBaseAddressSpaceId",
> + "The HPET base address space ID was 0x%" PRIx8
> + ", was expecting 0 (System Memory) or "
> + "1 (System I/O).",
> + hpet->base_address.address_space_id);
> + passed = false;
> + }
> +#endif
> + /*
> + * The kernel expects the HPET address space ID
> + * to be memory.
> + */
> + if (hpet->base_address.address_space_id != 0) {
> + fwts_failed(fw, LOG_LEVEL_HIGH,
> + "HPETAcpiBaseAddressSpaceIdNotMemory",
> + "The HPET base address space ID was 0x%" PRIx8
> + ", however, the Kernel expects the HPET address "
> + "space ID to be 0 (System Memory). The kernel "
> + "will not parse this and the HPET configuration "
> + "will be ignored.",
> + hpet->base_address.address_space_id);
> + }
> +
> + /*
> + * Some broken firmware advertises the HPET at
> + * 0xfed0000000000000 instead of 0xfed00000. The kernel
> + * detects this and fixes it, but even so, it is wrong
> + * so lets check for this.
> + */
> + if ((hpet->base_address.address >> 32) != 0) {
> + fwts_failed(fw, LOG_LEVEL_CRITICAL,
> + "HPETAcpiBaseAddressBogus",
> + "The HPET base address is bogus: 0x%" PRIx64 ".",
> + hpet->base_address.address);
> + fwts_advice(fw,
> + "Bogus HPET base address can be worked around "
> + "by using the kernel parameter 'hpet=force' if "
> + "the base addess is 0xfed0000000000000. "
> + "This will make the kernel shift the address "
> + "down 32 bits to 0xfed00000.");
> + passed = false;
> + }
> +
> + /*
> + * We don't need to check for GAS address space widths etc
> + * since the kernel does not care and the spec doesn't
> + * stipulate these need to be sane
> + */
> +
> + /*
> + * Dump out HPET
> + */
> + fwts_log_info_verbatum(fw, "Hardware ID of Event Block:");
> + fwts_log_info_verbatum(fw, " PCI Vendor ID : 0x%" PRIx32,
> + (hpet->event_timer_block_id >> 16) & 0xffff);
> + fwts_log_info_verbatum(fw, " Legacy IRQ Routing Capable : %" PRIu32,
> + (hpet->event_timer_block_id >> 15) & 1);
> + fwts_log_info_verbatum(fw, " COUNT_SIZE_CAP counter size: %" PRIu32,
> + (hpet->event_timer_block_id >> 13) & 1);
> + fwts_log_info_verbatum(fw, " Number of comparitors : %" PRIu32,
> + (hpet->event_timer_block_id >> 8) & 0x1f);
> + fwts_log_info_verbatum(fw, " Hardwre Revision ID : 0x%" PRIx8,
> + hpet->event_timer_block_id & 0xff);
> +
> + fwts_log_info_verbatum(fw, "Lower 32 bit base Address : 0x%" PRIx64,
> + hpet->base_address.address);
> + fwts_log_info_verbatum(fw, " Address Space ID : 0x%" PRIx8,
> + hpet->base_address.address_space_id);
> + fwts_log_info_verbatum(fw, " Register Bit Width : 0x%" PRIx8,
> + hpet->base_address.register_bit_width);
> + fwts_log_info_verbatum(fw, " Register Bit Offset : 0x%" PRIx8,
> + hpet->base_address.register_bit_offset);
> + fwts_log_info_verbatum(fw, " Address Width : 0x%" PRIx8,
> + hpet->base_address.access_width);
> + fwts_log_info_verbatum(fw, "HPET sequence number : 0x%" PRIx8,
> + hpet->hpet_number);
> + fwts_log_info_verbatum(fw, "Minimum clock tick : 0x%" PRIx16,
> + hpet->main_counter_minimum);
> +
> + switch (hpet->page_prot_and_oem_attribute & 0xf) {
> + case 0:
> + page_prot = "No guaranteed protection";
> + break;
> + case 1:
> + page_prot = "4K page protected";
> + break;
> + case 2:
> + page_prot = "64K page protected";
> + break;
> + default:
> + page_prot = "Reserved";
> + break;
> + }
> + fwts_log_info_verbatum(fw, "Page Protection : 0x%" PRIx8 " (%s)",
> + hpet->page_prot_and_oem_attribute & 0xf,
> + page_prot);
> + fwts_log_info_verbatum(fw, "OEM attributes : 0x%" PRIx8,
> + (hpet->page_prot_and_oem_attribute >> 4) & 0xf);
> +
> + if (passed)
> + fwts_passed(fw, "HPET looks sane.");
> +
> + return FWTS_OK;
> +}
> +
> +static int hpet_check_test3(fwts_framework *fw)
> +{
> + int i;
> +
> + hpet_check_base_acpi_table(fw, "DSDT", 0);
> +
> + for (i=0;i<11;i++) {
> + hpet_check_base_acpi_table(fw, "SSDT", i);
> + }
> + return FWTS_OK;
> +}
> +
> +
> +static int hpet_check_test4(fwts_framework *fw)
> +{
> uint64_t hpet_id;
> uint32_t vendor_id;
> uint32_t clk_period;
> @@ -238,7 +395,7 @@ static int hpet_check_test2(fwts_framework *fw)
> "Invalid Vendor ID: %04" PRIx32 " - this should be configured.",
> vendor_id);
> else
> - fwts_passed(fw, "Vendor ID looks sane: %04" PRIx32 ".", vendor_id);
> + fwts_passed(fw, "Vendor ID looks sane: 0x%04" PRIx32 ".", vendor_id);
>
> clk_period = hpet_id >> 32;
> if ((clk_period > MAX_CLK_PERIOD) || (clk_period == 0))
> @@ -253,21 +410,12 @@ static int hpet_check_test2(fwts_framework *fw)
> return FWTS_OK;
> }
>
> -static int hpet_check_test3(fwts_framework *fw)
> -{
> - int i;
> -
> - hpet_check_base_acpi_table(fw, "DSDT", 0);
> - for (i=0;i<11;i++) {
> - hpet_check_base_acpi_table(fw, "SSDT", i);
> - }
> - return FWTS_OK;
> -}
>
> static fwts_framework_minor_test hpet_check_tests[] = {
> { hpet_check_test1, "Check HPET base in kernel log." },
> - { hpet_check_test2, "Sanity check HPET configuration." },
> + { hpet_check_test2, "Check HPET base in HPET table. "},
> { hpet_check_test3, "Check HPET base in DSDT and/or SSDT. "},
> + { hpet_check_test4, "Sanity check HPET configuration." },
> { NULL, NULL }
> };
>
>
Acked-by: Alex Hung <alex.hung@canonical.com>
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic