From patchwork Fri Feb 19 23:39:52 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Stone X-Patchwork-Id: 62432 Delivered-To: patches@linaro.org Received: by 10.112.43.199 with SMTP id y7csp78684lbl; Fri, 19 Feb 2016 15:41:09 -0800 (PST) X-Received: by 10.182.68.74 with SMTP id u10mr2488439obt.25.1455925269771; Fri, 19 Feb 2016 15:41:09 -0800 (PST) Return-Path: Received: from mail-oi0-x234.google.com (mail-oi0-x234.google.com. [2607:f8b0:4003:c06::234]) by mx.google.com with ESMTPS id r66si2647896oih.68.2016.02.19.15.41.09 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 19 Feb 2016 15:41:09 -0800 (PST) Received-SPF: pass (google.com: domain of al.stone@linaro.org designates 2607:f8b0:4003:c06::234 as permitted sender) client-ip=2607:f8b0:4003:c06::234; Authentication-Results: mx.google.com; spf=pass (google.com: domain of al.stone@linaro.org designates 2607:f8b0:4003:c06::234 as permitted sender) smtp.mailfrom=al.stone@linaro.org; dkim=pass header.i=@linaro.org Received: by mail-oi0-x234.google.com with SMTP id j125so23004956oih.0 for ; Fri, 19 Feb 2016 15:41:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=sYRBMNIl+J8IcOOE14r36bF8MncSf+qVI+gTlk7jZFA=; b=YhiL/3+R2Vr5ZxnKMdCXjlGA8vrnDuCLIg5QUJ1Tl/f60OY8si8HVXbxOGzLIK7Efb KkmPopMbmPG0jLWKJLA6g6Nhei09k1SB65U/leV1KB2YFpyy/g3/syhd2aJOmRmdhNaJ m0DQy+dQ8Ea9lG9IJQ0ROPmaEn2u9R7YlHEp0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=sYRBMNIl+J8IcOOE14r36bF8MncSf+qVI+gTlk7jZFA=; b=KTS0Siealt4U0Autur9C+ed9JV8p/Ph6nzZgJIGhM8WN5EdUXh5iSO7cXJn7KLQZ+C prl4Oiz9ZYtPVwhcR22CoOQ0roZ6kRmVtPYau0LypIRkp4Pl/0yyTHF0CTPZFpfFhRa2 cCZ1N3Nwba8J+eYm2jH2Om0JnloANiqc13oMlmKKcGtutNxLUmg5ivURJeWAd9AYKLWw pZn0nALCgtL8ouIt7ZvXg7XU0Bmgwq/dBfPrXeCXCi6OW6l76fyJ1+QjX6xDuPBc4akP FYX7SbzvcRECF689MsmE/o3AeM2CPVR1e1kt+VKUPEYsaHwUKLNwTxSfu4uRLVqmiun2 8Nhw== X-Gm-Message-State: AG10YORx0Qpk99p9Svq96iui9QNTHFdk4Qk7GKdFfJHhtX0QaWf4rbLgOR3wNdWszcfUZC7+iQo= X-Received: by 10.202.200.88 with SMTP id y85mr8490088oif.92.1455925269455; Fri, 19 Feb 2016 15:41:09 -0800 (PST) Return-Path: Received: from fidelio.ahs3.com (c-50-134-239-249.hsd1.co.comcast.net. [50.134.239.249]) by smtp.googlemail.com with ESMTPSA id kg7sm8655217obb.27.2016.02.19.15.41.07 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 19 Feb 2016 15:41:08 -0800 (PST) From: Al Stone To: fwts-devel@lists.ubuntu.com Cc: linaro-acpi@lists.linaro.org, patches@linaro.org, Al Stone Subject: [PATCH v2 16/23] FADT: extend and add PM address block compliance tests Date: Fri, 19 Feb 2016 16:39:52 -0700 Message-Id: <1455925199-8587-17-git-send-email-al.stone@linaro.org> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1455925199-8587-1-git-send-email-al.stone@linaro.org> References: <1455925199-8587-1-git-send-email-al.stone@linaro.org> There are several address fields for power management in the FADT: PM1A_EVT_BLK PM1B_EVT_BLK PM1A_CNT_BLK PM1B_CNT_BLK PM2_CNT_BLK PM_TMR_BLK PM1_EVT_LEN PM1_CNT_LEN PM2_CNT_LEN PM_TMR_LEN The tests that existed before only touched a few of these, so extend the tests so that now all of them are checked for proper values. Most of the tests are very similar, hence they are grouped together into this one patch. Signed-off-by: Al Stone Acked-by: Colin Ian King Acked-by: Alex Hung --- src/acpi/fadt/fadt.c | 397 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 336 insertions(+), 61 deletions(-) -- 2.5.0 diff --git a/src/acpi/fadt/fadt.c b/src/acpi/fadt/fadt.c index 94a166c..7c9401c 100644 --- a/src/acpi/fadt/fadt.c +++ b/src/acpi/fadt/fadt.c @@ -908,20 +908,336 @@ static void acpi_table_check_fadt_pstate_cnt(fwts_framework *fw) return; } -static void acpi_table_check_fadt_pm_tmr( - fwts_framework *fw, - const fwts_acpi_table_fadt *fadt, - bool *passed) +static void acpi_table_check_fadt_pm1a_evt_blk(fwts_framework *fw) { - if (fwts_acpi_is_reduced_hardware(fadt)) { - if (fadt->pm_tmr_len != 0) - fwts_warning(fw, "FADT PM_TMR_LEN is not zero " - "but should be in reduced hardware mode."); + bool both_zero; + bool both_nonzero; + + if (fadt->pm1a_evt_blk == 0 && fadt->x_pm1a_evt_blk.address == 0) { + both_zero = true; + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPm1aEvtBlkNotSet", + "FADT PM1A_EVT_BLK is a required field and must " + "have either a 32-bit or 64-bit address set."); + } else { + both_zero = false; + fwts_passed(fw, + "FADT required PM1A_EVT_BLK field is non-zero"); + } + + if (fadt->pm1a_evt_blk != 0 && fadt->x_pm1a_evt_blk.address != 0) { + both_nonzero = true; + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPm1aEvtBlkBothtSet", + "FADT PM1A_EVT_BLK has both a 32-bit and a " + "64-bit address set; only one should be used."); + } else { + both_nonzero = false; + if (!both_zero) + fwts_passed(fw, + "FADT one required PM1A_EVT_BLK field " + "is non-zero"); + } + + if (both_nonzero && + ((uint64_t)fadt->pm1a_evt_blk == fadt->x_pm1a_evt_blk.address)) { + fwts_passed(fw, + "FADT 32- and 64-bit PM1A_EVT_BLK fields are " + "at least equal."); + fwts_advice(fw, + "Both FADT 32- and 64-bit PM1A_EVT_BLK " + "fields are being used, but only one should be " + "non-zero. However, they are at least equal so " + "the kernel will at least have a usable value."); + } else { + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPm1aEvtBlkNotSet", + "FADT PM1A_EVT_BLK is a required field and must " + "have either a 32-bit or 64-bit address set."); + if (!both_zero) + fwts_advice(fw, + "Both FADT 32- and 64-bit PM1A_EVT_BLK " + "fields are being used, but only one " + "should be non-zero. Since the fields " + "value are not equal the kernel cannot " + "unambiguously determine which value " + "is the correct one."); + } +} + +static void acpi_table_check_fadt_pm1b_evt_blk(fwts_framework *fw) +{ + if (fadt->pm1b_evt_blk == 0 && fadt->x_pm1b_evt_blk.address == 0) { + fwts_skipped(fw, "FADT PM1B_EVT_BLK not being used."); return; } - if (fadt->pm_tmr_len != 4) { - *passed = false; + if ((fadt->pm1b_evt_blk != 0 && fadt->x_pm1b_evt_blk.address == 0) || + (fadt->pm1b_evt_blk == 0 && fadt->x_pm1b_evt_blk.address != 0)) + fwts_passed(fw, + "FADT only one of the 32-bit or 64-bit " + "PM1B_EVT_BLK fields is being used."); + else + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPm1bEvtBlkOnlyOneField", + "FADT PM1B_EVT_BLK field has both the 32-bit " + "and the 64-bit field set."); + + if ((uint64_t)fadt->pm1b_evt_blk == fadt->x_pm1b_evt_blk.address) { + fwts_passed(fw, + "FADT 32- and 64-bit PM1B_EVT_BLK fields are " + "at least equal."); + fwts_advice(fw, + "Both FADT 32- and 64-bit PM1B_EVT_BLK " + "fields are being used, but only one should be " + "non-zero. However, they are at least equal so " + "the kernel will at least have a usable value."); + } else { + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPm1bEvtBlkNotSet", + "FADT PM1A_EVT_BLK is a required field and must " + "have either a 32-bit or 64-bit address set."); + fwts_advice(fw, + "Both FADT 32- and 64-bit PM1B_EVT_BLK " + "fields are being used, but only one should be " + "non-zero. Since the fields value are not equal " + "the kernel cannot unambiguously determine which " + "value is the correct one."); + } +} + +static void acpi_table_check_fadt_pm1a_cnt_blk(fwts_framework *fw) +{ + if (fadt->pm1a_cnt_blk != 0 || fadt->x_pm1a_cnt_blk.address != 0) + fwts_passed(fw, + "FADT required PM1A_CNT_BLK field is non-zero"); + else + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPm1aCntBlkNotSet", + "FADT PM1A_CNT_BLK is a required field and must " + "have either a 32-bit or 64-bit address set."); + + if ((fadt->pm1a_cnt_blk != 0 && fadt->x_pm1a_cnt_blk.address == 0) || + (fadt->pm1a_cnt_blk == 0 && fadt->x_pm1a_cnt_blk.address != 0)) + fwts_passed(fw, + "FADT only one of the 32-bit or 64-bit " + "PM1A_CNT_BLK fields is being used."); + else + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPm1aCntBlkOnlyOneField", + "FADT PM1A_CNT_BLK field has both the 32-bit " + "and the 64-bit field set."); + + if ((uint64_t)fadt->pm1a_cnt_blk == fadt->x_pm1a_cnt_blk.address) { + fwts_passed(fw, + "FADT 32- and 64-bit PM1A_CNT_BLK fields are " + "at least equal."); + fwts_advice(fw, + "Both FADT 32- and 64-bit PM1A_CNT_BLK " + "fields are being used, but only one should be " + "non-zero. However, they are at least equal so " + "the kernel will at least have a usable value."); + } else { + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPm1aCntBlkNotSet", + "FADT PM1A_CNT_BLK is a required field and must " + "have either a 32-bit or 64-bit address set."); + fwts_advice(fw, + "Both FADT 32- and 64-bit PM1A_CNT_BLK " + "fields are being used, but only one should be " + "non-zero. Since the fields value are not equal " + "the kernel cannot unambiguously determine which " + "value is the correct one."); + } +} + +static void acpi_table_check_fadt_pm1b_cnt_blk(fwts_framework *fw) +{ + if (fadt->pm1b_cnt_blk == 0 && fadt->x_pm1b_cnt_blk.address == 0) { + fwts_skipped(fw, "FADT PM1B_CNT_BLK not being used."); + return; + } + + if ((fadt->pm1b_cnt_blk != 0 && fadt->x_pm1b_cnt_blk.address == 0) || + (fadt->pm1b_cnt_blk == 0 && fadt->x_pm1b_cnt_blk.address != 0)) + fwts_passed(fw, + "FADT only one of the 32-bit or 64-bit " + "PM1B_CNT_BLK fields is being used."); + else + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPm1bCntBlkOnlyOneField", + "FADT PM1B_CNT_BLK field has both the 32-bit " + "and the 64-bit field set."); + + if ((uint64_t)fadt->pm1b_cnt_blk == fadt->x_pm1b_cnt_blk.address) { + fwts_passed(fw, + "FADT 32- and 64-bit PM1B_CNT_BLK fields are " + "at least equal."); + fwts_advice(fw, + "Both FADT 32- and 64-bit PM1B_CNT_BLK " + "fields are being used, but only one should be " + "non-zero. However, they are at least equal so " + "the kernel will at least have a usable value."); + } else { + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPm1bCntBlkNotSet", + "FADT PM1A_CNT_BLK is a required field and must " + "have either a 32-bit or 64-bit address set."); + fwts_advice(fw, + "Both FADT 32- and 64-bit PM1B_CNT_BLK " + "fields are being used, but only one should be " + "non-zero. Since the fields value are not equal " + "the kernel cannot unambiguously determine which " + "value is the correct one."); + } +} + +static void acpi_table_check_fadt_pm2_cnt_blk(fwts_framework *fw) +{ + if (fadt->pm2_cnt_blk == 0 && fadt->x_pm2_cnt_blk.address == 0) { + fwts_skipped(fw, "FADT PM2_CNT_BLK not being used."); + return; + } + + if ((fadt->pm2_cnt_blk != 0 && fadt->x_pm2_cnt_blk.address == 0) || + (fadt->pm2_cnt_blk == 0 && fadt->x_pm2_cnt_blk.address != 0)) + fwts_passed(fw, + "FADT only one of the 32-bit or 64-bit " + "PM2_CNT_BLK fields is being used."); + else + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPm2CntBlkOnlyOneField", + "FADT PM2_CNT_BLK field has both the 32-bit " + "and the 64-bit field set."); + + if ((uint64_t)fadt->pm2_cnt_blk == fadt->x_pm2_cnt_blk.address) { + fwts_passed(fw, + "FADT 32- and 64-bit PM2_CNT_BLK fields are " + "at least equal."); + fwts_advice(fw, + "Both FADT 32- and 64-bit PM2_CNT_BLK " + "fields are being used, but only one should be " + "non-zero. However, they are at least equal so " + "the kernel will at least have a usable value."); + } else { + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPm2CntBlkNotSet", + "FADT PM2_CNT_BLK is a required field and must " + "have either a 32-bit or 64-bit address set."); + fwts_advice(fw, + "Both FADT 32- and 64-bit PM2_CNT_BLK " + "fields are being used, but only one should be " + "non-zero. Since the fields value are not equal " + "the kernel cannot unambiguously determine which " + "value is the correct one."); + } +} + +static void acpi_table_check_fadt_pm_tmr_blk(fwts_framework *fw) +{ + if (fadt->pm_tmr_blk == 0 && fadt->x_pm_tmr_blk.address == 0) { + fwts_skipped(fw, "FADT PM_TMR_BLK not being used."); + return; + } + + if ((fadt->pm_tmr_blk != 0 && fadt->x_pm_tmr_blk.address == 0) || + (fadt->pm_tmr_blk == 0 && fadt->x_pm_tmr_blk.address != 0)) + fwts_passed(fw, + "FADT only one of the 32-bit or 64-bit " + "PM_TMR_BLK fields is being used."); + else + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPm2CntBlkOnlyOneField", + "FADT PM_TMR_BLK field has both the 32-bit " + "and the 64-bit field set."); + + if ((uint64_t)fadt->pm_tmr_blk == fadt->x_pm_tmr_blk.address) { + fwts_passed(fw, + "FADT 32- and 64-bit PM_TMR_BLK fields are " + "at least equal."); + fwts_advice(fw, + "Both FADT 32- and 64-bit PM_TMR_BLK " + "fields are being used, but only one should be " + "non-zero. However, they are at least equal so " + "the kernel will at least have a usable value."); + } else { + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPm2CntBlkNotSet", + "FADT PM1A_CNT_BLK is a required field and must " + "have either a 32-bit or 64-bit address set."); + fwts_advice(fw, + "Both FADT 32- and 64-bit PM_TMR_BLK " + "fields are being used, but only one should be " + "non-zero. Since the fields value are not equal " + "the kernel cannot unambiguously determine which " + "value is the correct one."); + } +} + +static void acpi_table_check_fadt_pm1_evt_len(fwts_framework *fw) +{ + if (fadt->pm1_evt_len >= 4) + fwts_passed(fw, "FADT PM1_EVT_LEN >= 4."); + else + fwts_failed(fw, LOG_LEVEL_MEDIUM, "FADTPm1EvtLenTooSmall", + "FADT PM1_EVT_LEN must be >= 4, but is %d.", + fadt->pm1_evt_len); + return; +} + +static void acpi_table_check_fadt_pm1_cnt_len(fwts_framework *fw) +{ + if (fadt->pm1_cnt_len >= 2) + fwts_passed(fw, "FADT PM1_CNT_LEN >= 2."); + else + fwts_failed(fw, LOG_LEVEL_MEDIUM, "FADTPm1CntLenTooSmall", + "FADT PM1_CNT_LEN must be >= 2, but is %d.", + fadt->pm1_cnt_len); + return; +} + +static void acpi_table_check_fadt_pm2_cnt_len(fwts_framework *fw) +{ + if (fadt->pm2_cnt_blk == 0) { + if (fadt->pm2_cnt_len == 0) + fwts_passed(fw, "FADT PM2_CNT_LEN is zero and " + "PM2_CNT_BLK is not supported."); + else + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPm2CntLenInconsistent", + "FADT PM2_CNT_LEN must be zero because " + "PM2_CNT_BLK is not supported, but is %d.", + fadt->pm2_cnt_len); + return; + } + + if (fadt->pm2_cnt_len >= 1) + fwts_passed(fw, "FADT PM2_CNT_LEN >= 1."); + else + fwts_failed(fw, LOG_LEVEL_MEDIUM, "FADTPm2CntLenTooSmall", + "FADT PM2_CNT_LEN must be >= 1, but is %d.", + fadt->pm2_cnt_len); + return; +} + +static void acpi_table_check_fadt_pm_tmr_len(fwts_framework *fw) +{ + if (fadt->pm_tmr_len == 0) { + if (fadt->pm_tmr_blk == 0) + fwts_passed(fw, "FADT PM_TMR_LEN is zero and " + "PM_TMR_BLK is not supported."); + else + fwts_failed(fw, LOG_LEVEL_MEDIUM, + "FADTPmTmrLenInconsistent", + "FADT PM_TMR_LEN must be zero because " + "PM_TMR_BLK is not supported, but is %d.", + fadt->pm_tmr_len); + return; + } + + if (fadt->pm_tmr_len == 4) + fwts_passed(fw, "FADT PM_TMR_LEN is 4."); + else { fwts_failed(fw, LOG_LEVEL_MEDIUM, "FADTBadPMTMRLEN", "FADT PM_TMR_LEN is %" PRIu8 @@ -982,55 +1298,6 @@ static void acpi_table_check_fadt_gpe( } } -static void acpi_table_check_fadt_addr( - fwts_framework *fw, - const char *name, - const uint32_t addr32, - const fwts_acpi_gas *addr64, - bool *passed) -{ - /* Don't compare if addresses are zero */ - if ((addr32 == 0) || (addr64->address == 0)) - return; - if (addr32 == addr64->address) - return; - - *passed = false; - /* - * Since this can cause systems to misbehave - * if the kernel uses the incorrect address we - * make this LOG_LEVEL_HIGH - */ - fwts_failed(fw, LOG_LEVEL_HIGH, - "FADTPmAddr32Addr64Different", - "FADT %s (32 bit address) 0x%" PRIx32 " is different from " - "X_%s (64 bit address) 0x%" PRIx64 ".", - name, addr32, name, addr64->address); -} - -static void acpi_table_check_fadt_pm_addr( - fwts_framework *fw, - const fwts_acpi_table_fadt *fadt, - bool *passed) -{ - if (fadt->header.length < 148) { - /* No 64 bit PM addresses to sanity check */ - return; - } - acpi_table_check_fadt_addr(fw, "PM1a_EVT_BLK", fadt->pm1a_evt_blk, - &fadt->x_pm1a_evt_blk, passed); - acpi_table_check_fadt_addr(fw, "PM1b_EVT_BLK", fadt->pm1b_evt_blk, - &fadt->x_pm1b_evt_blk, passed); - acpi_table_check_fadt_addr(fw, "PM1a_CNT_BLK", fadt->pm1a_cnt_blk, - &fadt->x_pm1a_cnt_blk, passed); - acpi_table_check_fadt_addr(fw, "PM1b_CNT_BLK", fadt->pm1b_cnt_blk, - &fadt->x_pm1b_cnt_blk, passed); - acpi_table_check_fadt_addr(fw, "PM2_CNT_BLK", fadt->pm2_cnt_blk, - &fadt->x_pm2_cnt_blk, passed); - acpi_table_check_fadt_addr(fw, "PM_TMR_BLK", fadt->pm_tmr_blk, - &fadt->x_pm_tmr_blk, passed); -} - static int fadt_test1(fwts_framework *fw) { bool passed = true; @@ -1055,9 +1322,17 @@ static int fadt_test1(fwts_framework *fw) acpi_table_check_fadt_acpi_disable(fw); acpi_table_check_fadt_s4bios_req(fw); acpi_table_check_fadt_pstate_cnt(fw); - acpi_table_check_fadt_pm_tmr(fw, fadt, &passed); + acpi_table_check_fadt_pm1a_evt_blk(fw); + acpi_table_check_fadt_pm1b_evt_blk(fw); + acpi_table_check_fadt_pm1a_cnt_blk(fw); + acpi_table_check_fadt_pm1b_cnt_blk(fw); + acpi_table_check_fadt_pm2_cnt_blk(fw); + acpi_table_check_fadt_pm_tmr_blk(fw); + acpi_table_check_fadt_pm1_evt_len(fw); + acpi_table_check_fadt_pm1_cnt_len(fw); + acpi_table_check_fadt_pm2_cnt_len(fw); + acpi_table_check_fadt_pm_tmr_len(fw); acpi_table_check_fadt_gpe(fw, fadt, &passed); - acpi_table_check_fadt_pm_addr(fw, fadt, &passed); fwts_log_info(fw, "FADT GPE1_BASE is %" PRIu8, fadt->gpe1_base); fwts_log_info(fw, "FADT FLUSH_SIZE is %" PRIu16,