From 286c890aa043d2b79edbfa4cab32fb42ca51626d Mon Sep 17 00:00:00 2001 From: Srikar Josyula Date: Thu, 23 Apr 2026 11:21:44 +0530 Subject: [PATCH 1/2] fix(timer): remove obselete counter frequency tests - CNTFRQ_EL0 cannot be relied on to determine the base frequency - Drop timer tests t006 and t007 along with their declarations and entry IDs. - Remove the related rule-to-test mappings and direct execution hooks from BSA/SBSA paths. - Clean up UEFI/CMake build inputs so the deleted timer tests are no longer referenced. - Update the testcase checklist and test scenario documents Signed-off-by: Srikar Josyula Change-Id: Ib0a1822db4d569829132d2adf68998770b0c47ef --- apps/uefi/Bsa.inf | 1 - apps/uefi/Sbsa.inf | 1 - apps/uefi/SbsaNist.inf | 1 - apps/uefi/Vbsa.inf | 1 - apps/uefi/pc_bsa.inf | 1 - apps/uefi/xbsa_acpi.inf | 1 - docs/bsa/arm_bsa_testcase_checklist.md | 10 +-- docs/sbsa/arm_sbsa_testcase_checklist.md | 10 +-- ...a_architecture_compliance_test_scenario.md | 3 +- docs/vbsa/arm_vbsa_testcase_checklist.md | 8 +- test_pool/timer/t001.c | 65 ---------------- test_pool/timer/t006.c | 76 ------------------- tools/cmake/infra/sbsa_test.txt | 1 - val/include/acs_timer.h | 2 - val/include/rule_based_execution_enum.h | 2 - val/src/bsa_execute_test.c | 1 - val/src/rule_metadata.c | 39 +++------- val/src/sbsa_execute_test.c | 4 +- 18 files changed, 26 insertions(+), 201 deletions(-) delete mode 100644 test_pool/timer/t006.c diff --git a/apps/uefi/Bsa.inf b/apps/uefi/Bsa.inf index d9a4d5b5..fb4e64e0 100644 --- a/apps/uefi/Bsa.inf +++ b/apps/uefi/Bsa.inf @@ -83,7 +83,6 @@ ../../test_pool/timer/t003.c ../../test_pool/timer/t004.c ../../test_pool/timer/t005.c - ../../test_pool/timer/t006.c ../../test_pool/timer/t008.c ../../test_pool/watchdog/w001.c ../../test_pool/watchdog/w002.c diff --git a/apps/uefi/Sbsa.inf b/apps/uefi/Sbsa.inf index 7a90174e..02787ae5 100644 --- a/apps/uefi/Sbsa.inf +++ b/apps/uefi/Sbsa.inf @@ -86,7 +86,6 @@ ../../test_pool/timer/t003.c ../../test_pool/timer/t004.c ../../test_pool/timer/t005.c - ../../test_pool/timer/t006.c ../../test_pool/timer/t008.c ../../test_pool/watchdog/w001.c ../../test_pool/watchdog/w002.c diff --git a/apps/uefi/SbsaNist.inf b/apps/uefi/SbsaNist.inf index a2156207..7baf1b05 100644 --- a/apps/uefi/SbsaNist.inf +++ b/apps/uefi/SbsaNist.inf @@ -80,7 +80,6 @@ ../../test_pool/gic/g014.c ../../test_pool/gic/g015.c ../../test_pool/gic/g016.c - ../../test_pool/timer/t006.c ../../test_pool/watchdog/w003.c ../../test_pool/smmu/i008.c ../../test_pool/smmu/i009.c diff --git a/apps/uefi/Vbsa.inf b/apps/uefi/Vbsa.inf index 96cb286a..b94f3477 100644 --- a/apps/uefi/Vbsa.inf +++ b/apps/uefi/Vbsa.inf @@ -85,7 +85,6 @@ ../../test_pool/timer/t003.c ../../test_pool/timer/t004.c ../../test_pool/timer/t005.c - ../../test_pool/timer/t006.c ../../test_pool/timer/t008.c ../../test_pool/watchdog/w001.c ../../test_pool/watchdog/w002.c diff --git a/apps/uefi/pc_bsa.inf b/apps/uefi/pc_bsa.inf index 3dab32e6..88b17e9e 100644 --- a/apps/uefi/pc_bsa.inf +++ b/apps/uefi/pc_bsa.inf @@ -86,7 +86,6 @@ ../../test_pool/timer/t003.c ../../test_pool/timer/t004.c ../../test_pool/timer/t005.c - ../../test_pool/timer/t006.c ../../test_pool/timer/t008.c ../../test_pool/watchdog/w001.c ../../test_pool/watchdog/w002.c diff --git a/apps/uefi/xbsa_acpi.inf b/apps/uefi/xbsa_acpi.inf index a68840ec..c636329a 100644 --- a/apps/uefi/xbsa_acpi.inf +++ b/apps/uefi/xbsa_acpi.inf @@ -192,7 +192,6 @@ ../../test_pool/gic/g014.c ../../test_pool/gic/g015.c ../../test_pool/gic/g016.c - ../../test_pool/timer/t006.c ../../test_pool/timer/t008.c ../../test_pool/watchdog/w003.c ../../test_pool/smmu/i008.c diff --git a/docs/bsa/arm_bsa_testcase_checklist.md b/docs/bsa/arm_bsa_testcase_checklist.md index 8b0a6149..1d0fd854 100644 --- a/docs/bsa/arm_bsa_testcase_checklist.md +++ b/docs/bsa/arm_bsa_testcase_checklist.md @@ -630,11 +630,11 @@ The checklist provides information about: L1 B_TIME_02 B_TIME_02 - 407 - Check System Counter Frequency - Yes - Yes - No + Not Covered + + + + diff --git a/docs/sbsa/arm_sbsa_testcase_checklist.md b/docs/sbsa/arm_sbsa_testcase_checklist.md index d502f9ce..8ed184b4 100644 --- a/docs/sbsa/arm_sbsa_testcase_checklist.md +++ b/docs/sbsa/arm_sbsa_testcase_checklist.md @@ -3266,11 +3266,11 @@ The checklist provides information about: Version 8.0 S_L8TI_01 S_L8TI_01 - 406 - Check Minimum Counter Frequency 50MHz - Yes - Yes - No + Not Covered + + + + diff --git a/docs/vbsa/arm_vbsa_architecture_compliance_test_scenario.md b/docs/vbsa/arm_vbsa_architecture_compliance_test_scenario.md index 087e938c..0986d00c 100644 --- a/docs/vbsa/arm_vbsa_architecture_compliance_test_scenario.md +++ b/docs/vbsa/arm_vbsa_architecture_compliance_test_scenario.md @@ -176,8 +176,7 @@ Purpose: capture ACS scenario outlines for each VBSA rule. Each section: ### V_L1TM_02 — Check Virt and Phy counter min freq **Rationale**: Virtual Counter (CNTVCT_EL0) = Physical counter (CNTPCT_EL0) - Virtual offset (CNTVOFF_EL2). As the offset is a constant provided by the hypervisor, the virtual counter advances at the same effective frequency as the physical counter. -**Scenario**: Execute the same test used to validate B_TIME_02, which verifies physical counter runs at atleast 10MHz. -- see section 2.6 in [BSA ACS Scenario Document](../bsa/arm_bsa_architecture_compliance_test_scenario.pdf#page18&search=B_TIME_02) +**Rationale for not implementing** - The base frequency should be obtained from the CNTFID registers, which are implemented in Secure space. At present, ACS does not provide a mechanism for accessing Secure registers from Non-secure (NS) space. --- diff --git a/docs/vbsa/arm_vbsa_testcase_checklist.md b/docs/vbsa/arm_vbsa_testcase_checklist.md index f3a321c4..783d19ed 100644 --- a/docs/vbsa/arm_vbsa_testcase_checklist.md +++ b/docs/vbsa/arm_vbsa_testcase_checklist.md @@ -347,10 +347,10 @@ The checklist provides information about: L1 V_L1TM_02 - 402 - Check Virt and Phy counter min freq - ✅ - ❌ + Not Covered + + + Related rules from other specifications: B_TIME_02 (BSA) diff --git a/test_pool/timer/t001.c b/test_pool/timer/t001.c index 9c08d1c4..cc081cbd 100644 --- a/test_pool/timer/t001.c +++ b/test_pool/timer/t001.c @@ -22,10 +22,6 @@ #define TEST_RULE "B_TIME_01" #define TEST_DESC "Check for Generic System Counter " -#define TEST_NUM1 (ACS_TIMER_TEST_NUM_BASE + 7) -#define TEST_RULE1 "B_TIME_02" -#define TEST_DESC1 "Check System Counter Frequency " - /* This test checks for presence of Generic System Counter */ static void @@ -49,46 +45,6 @@ payload_check_system_counter_presence() } } -/* This test checks if Generic System Counter frequency is greater than 10Mhz */ -static -void -payload_check_system_timer_freq() -{ - uint64_t counter_freq, print_freq = 0; - uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); - uint32_t print_mhz = 0; - - /* Read CNTFRQ_EL0 register for counter frequency */ - counter_freq = val_timer_get_info(TIMER_INFO_CNTFREQ, 0); - - /* Convert frequency into MHz or KHz unit */ - print_freq = counter_freq/1000; - if (print_freq > 1000) { - print_freq = print_freq/1000; - print_mhz = 1; - } - - /* Print counter frequency in DEBUG verbosity */ - if (print_mhz) - val_print(DEBUG, "\n Counter frequency is %ld MHz", print_freq); - else - val_print(DEBUG, "\n Counter frequency is %ld KHz", print_freq); - - /* Check if Generic system counter frequency is greater than 10MHz */ - if (counter_freq > 10*1000*1000) { - val_set_status(index, RESULT_PASS); - return; - } - - /* If 10Mhz check fails, print frequency in ERROR verbosity */ - if (print_mhz) - val_print(ERROR, "\n Counter frequency is %ld MHz", print_freq); - else - val_print(ERROR, "\n Counter frequency is %ld KHz", print_freq); - - val_set_status(index, RESULT_FAIL(1)); -} - uint32_t t001_entry(uint32_t num_pe) { @@ -109,24 +65,3 @@ t001_entry(uint32_t num_pe) return status; } - -uint32_t -t007_entry(uint32_t num_pe) -{ - - uint32_t status = ACS_STATUS_FAIL; - - num_pe = 1; //This Timer test is run on single processor - - val_log_context((char8_t *)__FILE__, (char8_t *)__func__, __LINE__); - status = val_initialize_test(TEST_NUM1, TEST_DESC1, num_pe); - if (status != ACS_STATUS_SKIP) - val_run_test_payload(TEST_NUM1, num_pe, payload_check_system_timer_freq, 0); - - /* get the result from all PE and check for failure */ - status = val_check_for_error(TEST_NUM1, num_pe, TEST_RULE1); - - val_report_status(0, ACS_END(TEST_NUM1), NULL); - - return status; -} diff --git a/test_pool/timer/t006.c b/test_pool/timer/t006.c deleted file mode 100644 index b54e1a05..00000000 --- a/test_pool/timer/t006.c +++ /dev/null @@ -1,76 +0,0 @@ -/** @file - * Copyright (c) 2025-2026, Arm Limited or its affiliates. All rights reserved. - * SPDX-License-Identifier : Apache-2.0 - - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ - -#include "acs_val.h" -#include "acs_timer.h" - -#define TEST_NUM (ACS_TIMER_TEST_NUM_BASE + 6) -#define TEST_RULE "S_L8TI_01" -#define TEST_DESC "Check Minimum Counter Frequency 50MHz " - -static -void -payload() -{ - - uint64_t counter_freq, print_freq; - uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); - uint32_t print_mhz = 0; - - - counter_freq = val_timer_get_info(TIMER_INFO_CNTFREQ, 0); - - if (counter_freq != 0) { - print_freq = counter_freq/1000; - if (print_freq > 1000) { - print_freq = print_freq/1000; - print_mhz = 1; - } - } - - if (print_mhz) - val_print(ERROR, "\n Counter frequency is %ld MHz", print_freq); - else - val_print(ERROR, "\n Counter frequency is %ld KHz", print_freq); - - if (counter_freq >= 50*1000*1000) { - val_set_status(index, RESULT_PASS); - return; - } - - val_set_status(index, RESULT_FAIL(1)); -} - -uint32_t -t006_entry(uint32_t num_pe) -{ - - uint32_t status = ACS_STATUS_FAIL; - - num_pe = 1; //This Timer test is run on single processor - - val_log_context((char8_t *)__FILE__, (char8_t *)__func__, __LINE__); - status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); - if (status != ACS_STATUS_SKIP) - val_run_test_payload(TEST_NUM, num_pe, payload, 0); - - /* get the result from all PE and check for failure */ - status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); - - val_report_status(0, ACS_END(TEST_NUM), TEST_RULE); - return status; -} diff --git a/tools/cmake/infra/sbsa_test.txt b/tools/cmake/infra/sbsa_test.txt index c66576ef..7a5be126 100644 --- a/tools/cmake/infra/sbsa_test.txt +++ b/tools/cmake/infra/sbsa_test.txt @@ -41,7 +41,6 @@ g013.c g014.c g015.c g016.c -t006.c w003.c i008.c i009.c diff --git a/val/include/acs_timer.h b/val/include/acs_timer.h index f2c8dd82..5b1e1328 100644 --- a/val/include/acs_timer.h +++ b/val/include/acs_timer.h @@ -47,7 +47,5 @@ uint32_t t002_entry(uint32_t num_pe); uint32_t t003_entry(uint32_t num_pe); uint32_t t004_entry(uint32_t num_pe); uint32_t t005_entry(uint32_t num_pe); -uint32_t t006_entry(uint32_t num_pe); -uint32_t t007_entry(uint32_t num_pe); uint32_t t008_entry(uint32_t num_pe); #endif // __ACS_TIMER_H__ diff --git a/val/include/rule_based_execution_enum.h b/val/include/rule_based_execution_enum.h index 71528fdb..2cc0e801 100644 --- a/val/include/rule_based_execution_enum.h +++ b/val/include/rule_based_execution_enum.h @@ -759,12 +759,10 @@ typedef enum { I028_ENTRY, I031_ENTRY, T001_ENTRY, - T007_ENTRY, T002_ENTRY, T003_ENTRY, T004_ENTRY, T005_ENTRY, - T006_ENTRY, T008_ENTRY, W001_ENTRY, W002_ENTRY, diff --git a/val/src/bsa_execute_test.c b/val/src/bsa_execute_test.c index 0b28886d..97046c8a 100644 --- a/val/src/bsa_execute_test.c +++ b/val/src/bsa_execute_test.c @@ -352,7 +352,6 @@ val_bsa_timer_execute_tests(uint32_t num_pe, uint32_t *g_sw_view) status |= t003_entry(num_pe); status |= t004_entry(num_pe); status |= t005_entry(num_pe); - status |= t007_entry(num_pe); } } diff --git a/val/src/rule_metadata.c b/val/src/rule_metadata.c index 6de48e97..316b002f 100644 --- a/val/src/rule_metadata.c +++ b/val/src/rule_metadata.c @@ -1404,14 +1404,6 @@ rule_test_map_t rule_test_map[RULE_ID_SENTINEL] = { .flag = BASE_RULE, .test_num = ACS_TIMER_TEST_NUM_BASE + 1, }, - [B_TIME_02] = { - .test_entry_id = T007_ENTRY, - .module_id = TIMER, - .rule_desc = "Check System Counter Frequency", - .platform_bitmask = PLATFORM_BAREMETAL | PLATFORM_UEFI, - .flag = BASE_RULE, - .test_num = ACS_TIMER_TEST_NUM_BASE + 7, - }, [B_TIME_06] = { .test_entry_id = T002_ENTRY, .module_id = TIMER, @@ -1444,14 +1436,6 @@ rule_test_map_t rule_test_map[RULE_ID_SENTINEL] = { .flag = BASE_RULE, .test_num = ACS_TIMER_TEST_NUM_BASE + 5, }, - [S_L8TI_01] = { - .test_entry_id = T006_ENTRY, - .module_id = TIMER, - .rule_desc = "Check Minimum Counter Frequency 50MHz", - .platform_bitmask = PLATFORM_BAREMETAL | PLATFORM_UEFI, - .flag = BASE_RULE, - .test_num = ACS_TIMER_TEST_NUM_BASE + 6, - }, /* WATCHDOG */ [B_WD_00] = { .test_entry_id = NULL_ENTRY, @@ -2611,14 +2595,7 @@ rule_test_map_t rule_test_map[RULE_ID_SENTINEL] = { .flag = BASE_RULE, .test_num = ACS_TIMER_TEST_NUM_BASE + 1, }, - [V_L1TM_02] = { - .test_entry_id = T007_ENTRY, - .module_id = TIMER, - .rule_desc = "Check Virt and Phy counter min freq", - .platform_bitmask = PLATFORM_UEFI, - .flag = BASE_RULE, - .test_num = ACS_TIMER_TEST_NUM_BASE + 7, - }, + [V_L1TM_04] = { .test_entry_id = T008_ENTRY, .module_id = TIMER, @@ -3131,6 +3108,9 @@ rule_test_map_t rule_test_map[RULE_ID_SENTINEL] = { [P_L1SM_01] = { .module_id = SMMU, }, + [B_TIME_02] = { + .module_id = TIMER, + }, [B_TIME_03] = { .module_id = TIMER, }, @@ -3146,6 +3126,12 @@ rule_test_map_t rule_test_map[RULE_ID_SENTINEL] = { [S_L5TI_01] = { .module_id = TIMER, }, + [S_L8TI_01] = { + .module_id = TIMER, + }, + [V_L1TM_02] = { + .module_id = TIMER, + }, [B_WD_04] = { .module_id = WATCHDOG, }, @@ -3809,8 +3795,6 @@ test_entry_fn_t test_entry_func_table[TEST_ENTRY_SENTINEL] = { [T003_ENTRY] = t003_entry, [T004_ENTRY] = t004_entry, [T005_ENTRY] = t005_entry, - [T006_ENTRY] = t006_entry, - [T007_ENTRY] = t007_entry, [T008_ENTRY] = t008_entry, [U001_ENTRY] = u001_entry, // used in wrapper. [U002_ENTRY] = u002_entry, // used in wrapper. @@ -3926,7 +3910,6 @@ test_entry_fn_t test_entry_func_table[TEST_ENTRY_SENTINEL] = { [T003_ENTRY] = t003_entry, [T004_ENTRY] = t004_entry, [T005_ENTRY] = t005_entry, - [T007_ENTRY] = t007_entry, [W001_ENTRY] = w001_entry, [W002_ENTRY] = w002_entry, [D001_ENTRY] = d001_entry, @@ -4063,7 +4046,6 @@ test_entry_fn_t test_entry_func_table[TEST_ENTRY_SENTINEL] = { [PE065_ENTRY] = pe065_entry, [M005_ENTRY] = m005_entry, [M008_ENTRY] = m008_entry, - [T006_ENTRY] = t006_entry, [ETE008_ENTRY] = ete008_entry, [ETE007_ENTRY] = ete007_entry, [ETE002_ENTRY] = ete002_entry, @@ -4299,7 +4281,6 @@ test_entry_fn_t test_entry_func_table[TEST_ENTRY_SENTINEL] = { [T003_ENTRY] = t003_entry, [T004_ENTRY] = t004_entry, [T001_ENTRY] = t001_entry, - [T007_ENTRY] = t007_entry, [T002_ENTRY] = t002_entry, [E039_ENTRY] = e039_entry, // used in wrapper. [E035_ENTRY] = e035_entry, diff --git a/val/src/sbsa_execute_test.c b/val/src/sbsa_execute_test.c index db1de534..23276543 100644 --- a/val/src/sbsa_execute_test.c +++ b/val/src/sbsa_execute_test.c @@ -239,6 +239,7 @@ uint32_t val_sbsa_timer_execute_tests(uint32_t level, uint32_t num_pe) { uint32_t status = ACS_STATUS_PASS, i; + (void) num_pe; if (!(((level > 7) && (g_sbsa_only_level == 0)) || (g_sbsa_only_level == 8))) return ACS_STATUS_SKIP; @@ -260,9 +261,6 @@ val_sbsa_timer_execute_tests(uint32_t level, uint32_t num_pe) val_print_test_start("Timer"); g_curr_module = 1 << TIMER_MODULE; - if (((level > 7) && (g_sbsa_only_level == 0)) || (g_sbsa_only_level == 8)) - status |= t006_entry(num_pe); - val_print_test_end(status, "Timer"); return status; From 3a529f07406c8d036cf6ed429d2d6ecb56103189 Mon Sep 17 00:00:00 2001 From: Srikar Josyula Date: Tue, 28 Apr 2026 11:26:44 +0530 Subject: [PATCH 2/2] dev(timer): add S_L5TI_01 timer frequency test - Add timer test t006 for S_L5TI_01 to verify that the OS-visible generic counter reports a 1GHz frequency through CNTFRQ_EL0 - Add a platform time API for an independent timer source and use it as a sanity check against CNTPCT_EL0 progression - Include the new test into SBSA rule metadata, timer execution, UEFI build files, CMake test lists, and the SBSA checklist - Add UEFI ACPI/DT implementations using GetTime and baremetal stubs for RD platforms Signed-off-by: Srikar Josyula Change-Id: I553fbdde5804312ba556601d4d4dce3421d2068f --- apps/uefi/Bsa.inf | 1 + apps/uefi/Sbsa.inf | 1 + apps/uefi/SbsaNist.inf | 1 + apps/uefi/Vbsa.inf | 1 + apps/uefi/pc_bsa.inf | 1 + apps/uefi/xbsa_acpi.inf | 1 + docs/sbsa/arm_sbsa_testcase_checklist.md | 10 +- pal/baremetal/target/RDN2/src/pal_sbsa.c | 13 ++ pal/baremetal/target/RDV3/src/pal_sbsa.c | 13 ++ pal/baremetal/target/RDV3CFG1/src/pal_sbsa.c | 13 ++ pal/uefi_acpi/src/pal_timer_wd.c | 22 +++ pal/uefi_dt/src/pal_timer_wd.c | 22 +++ test_pool/timer/t006.c | 145 +++++++++++++++++++ tools/cmake/infra/sbsa_test.txt | 1 + val/include/acs_timer.h | 1 + val/include/pal_interface.h | 2 + val/include/rule_based_execution_enum.h | 1 + val/include/val_interface.h | 1 + val/src/acs_test_infra.c | 6 + val/src/rule_metadata.c | 13 +- val/src/sbsa_execute_test.c | 6 +- 21 files changed, 265 insertions(+), 10 deletions(-) create mode 100644 test_pool/timer/t006.c diff --git a/apps/uefi/Bsa.inf b/apps/uefi/Bsa.inf index fb4e64e0..d9a4d5b5 100644 --- a/apps/uefi/Bsa.inf +++ b/apps/uefi/Bsa.inf @@ -83,6 +83,7 @@ ../../test_pool/timer/t003.c ../../test_pool/timer/t004.c ../../test_pool/timer/t005.c + ../../test_pool/timer/t006.c ../../test_pool/timer/t008.c ../../test_pool/watchdog/w001.c ../../test_pool/watchdog/w002.c diff --git a/apps/uefi/Sbsa.inf b/apps/uefi/Sbsa.inf index 02787ae5..7a90174e 100644 --- a/apps/uefi/Sbsa.inf +++ b/apps/uefi/Sbsa.inf @@ -86,6 +86,7 @@ ../../test_pool/timer/t003.c ../../test_pool/timer/t004.c ../../test_pool/timer/t005.c + ../../test_pool/timer/t006.c ../../test_pool/timer/t008.c ../../test_pool/watchdog/w001.c ../../test_pool/watchdog/w002.c diff --git a/apps/uefi/SbsaNist.inf b/apps/uefi/SbsaNist.inf index 7baf1b05..a2156207 100644 --- a/apps/uefi/SbsaNist.inf +++ b/apps/uefi/SbsaNist.inf @@ -80,6 +80,7 @@ ../../test_pool/gic/g014.c ../../test_pool/gic/g015.c ../../test_pool/gic/g016.c + ../../test_pool/timer/t006.c ../../test_pool/watchdog/w003.c ../../test_pool/smmu/i008.c ../../test_pool/smmu/i009.c diff --git a/apps/uefi/Vbsa.inf b/apps/uefi/Vbsa.inf index b94f3477..96cb286a 100644 --- a/apps/uefi/Vbsa.inf +++ b/apps/uefi/Vbsa.inf @@ -85,6 +85,7 @@ ../../test_pool/timer/t003.c ../../test_pool/timer/t004.c ../../test_pool/timer/t005.c + ../../test_pool/timer/t006.c ../../test_pool/timer/t008.c ../../test_pool/watchdog/w001.c ../../test_pool/watchdog/w002.c diff --git a/apps/uefi/pc_bsa.inf b/apps/uefi/pc_bsa.inf index 88b17e9e..3dab32e6 100644 --- a/apps/uefi/pc_bsa.inf +++ b/apps/uefi/pc_bsa.inf @@ -86,6 +86,7 @@ ../../test_pool/timer/t003.c ../../test_pool/timer/t004.c ../../test_pool/timer/t005.c + ../../test_pool/timer/t006.c ../../test_pool/timer/t008.c ../../test_pool/watchdog/w001.c ../../test_pool/watchdog/w002.c diff --git a/apps/uefi/xbsa_acpi.inf b/apps/uefi/xbsa_acpi.inf index c636329a..a68840ec 100644 --- a/apps/uefi/xbsa_acpi.inf +++ b/apps/uefi/xbsa_acpi.inf @@ -192,6 +192,7 @@ ../../test_pool/gic/g014.c ../../test_pool/gic/g015.c ../../test_pool/gic/g016.c + ../../test_pool/timer/t006.c ../../test_pool/timer/t008.c ../../test_pool/watchdog/w003.c ../../test_pool/smmu/i008.c diff --git a/docs/sbsa/arm_sbsa_testcase_checklist.md b/docs/sbsa/arm_sbsa_testcase_checklist.md index 8ed184b4..e3e55f90 100644 --- a/docs/sbsa/arm_sbsa_testcase_checklist.md +++ b/docs/sbsa/arm_sbsa_testcase_checklist.md @@ -474,11 +474,11 @@ The checklist provides information about: L5 S_L5TI_01 S_L5TI_01 - Not Covered - - - - + 406 + Check OS visible counter reports 1GHz + Yes + Yes + No diff --git a/pal/baremetal/target/RDN2/src/pal_sbsa.c b/pal/baremetal/target/RDN2/src/pal_sbsa.c index ff30020c..efe5ef81 100644 --- a/pal/baremetal/target/RDN2/src/pal_sbsa.c +++ b/pal/baremetal/target/RDN2/src/pal_sbsa.c @@ -32,6 +32,19 @@ extern const PLATFORM_OVERRIDE_MEMORY_INFO_TABLE platform_mem_cfg; extern const PCIE_INFO_TABLE platform_pcie_cfg; extern const WD_INFO_TABLE platform_wd_cfg; +/** Timer API **/ +/** + @brief Platform defined method to read time in microseconds from an independent timer source + + @return PAL_STATUS_NOT_IMPLEMENTED - API not implemented, Other values - Success +**/ +uint64_t +pal_get_platform_time_us(void) +{ + pal_warn_not_implemented(__func__); + return PAL_STATUS_NOT_IMPLEMENTED; +} + /** SMMU API's **/ /** @brief Platform defined method to check if CATU is behind an ETR device diff --git a/pal/baremetal/target/RDV3/src/pal_sbsa.c b/pal/baremetal/target/RDV3/src/pal_sbsa.c index 6faf8400..59002c21 100644 --- a/pal/baremetal/target/RDV3/src/pal_sbsa.c +++ b/pal/baremetal/target/RDV3/src/pal_sbsa.c @@ -32,6 +32,19 @@ extern const PLATFORM_OVERRIDE_MEMORY_INFO_TABLE platform_mem_cfg; extern const PCIE_INFO_TABLE platform_pcie_cfg; extern const WD_INFO_TABLE platform_wd_cfg; +/** Timer API **/ +/** + @brief Platform defined method to read time in microseconds from an independent timer source + + @return PAL_STATUS_NOT_IMPLEMENTED - API not implemented, Other values - Success +**/ +uint64_t +pal_get_platform_time_us(void) +{ + pal_warn_not_implemented(__func__); + return PAL_STATUS_NOT_IMPLEMENTED; +} + /** SMMU API's **/ /** @brief Platform defined method to check if CATU is behind an ETR device diff --git a/pal/baremetal/target/RDV3CFG1/src/pal_sbsa.c b/pal/baremetal/target/RDV3CFG1/src/pal_sbsa.c index 6faf8400..59002c21 100644 --- a/pal/baremetal/target/RDV3CFG1/src/pal_sbsa.c +++ b/pal/baremetal/target/RDV3CFG1/src/pal_sbsa.c @@ -32,6 +32,19 @@ extern const PLATFORM_OVERRIDE_MEMORY_INFO_TABLE platform_mem_cfg; extern const PCIE_INFO_TABLE platform_pcie_cfg; extern const WD_INFO_TABLE platform_wd_cfg; +/** Timer API **/ +/** + @brief Platform defined method to read time in microseconds from an independent timer source + + @return PAL_STATUS_NOT_IMPLEMENTED - API not implemented, Other values - Success +**/ +uint64_t +pal_get_platform_time_us(void) +{ + pal_warn_not_implemented(__func__); + return PAL_STATUS_NOT_IMPLEMENTED; +} + /** SMMU API's **/ /** @brief Platform defined method to check if CATU is behind an ETR device diff --git a/pal/uefi_acpi/src/pal_timer_wd.c b/pal/uefi_acpi/src/pal_timer_wd.c index f5be4e29..d02257d4 100644 --- a/pal/uefi_acpi/src/pal_timer_wd.c +++ b/pal/uefi_acpi/src/pal_timer_wd.c @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -31,6 +32,27 @@ static EFI_ACPI_6_1_GENERIC_TIMER_DESCRIPTION_TABLE *gGtdtHdr; UINT64 pal_get_gtdt_ptr(); +UINT64 +pal_get_platform_time_us ( + VOID + ) +{ + EFI_STATUS Status; + EFI_TIME Time; + UINT64 TimeUs; + + Status = gRT->GetTime(&Time, NULL); + if (EFI_ERROR(Status)) { + pal_print_msg(ACS_PRINT_WARN, " GetTime failed: %x\n", Status); + return ~0ULL; + } + + TimeUs = (((UINT64)Time.Hour * 60 + Time.Minute) * 60 + Time.Second) * 1000000ULL; + TimeUs += (UINT64)Time.Nanosecond / 1000ULL; + + return TimeUs; +} + /** @brief This API overrides the timer specified by TimerTable Note: Information about only one timer can be mentioned as an Override diff --git a/pal/uefi_dt/src/pal_timer_wd.c b/pal/uefi_dt/src/pal_timer_wd.c index 212ad8a3..fdc57f4a 100644 --- a/pal/uefi_dt/src/pal_timer_wd.c +++ b/pal/uefi_dt/src/pal_timer_wd.c @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -48,6 +49,27 @@ static char wd_dt_arr[][WD_COMPATIBLE_STR_LEN] = { UINT64 pal_get_gtdt_ptr(); +UINT64 +pal_get_platform_time_us ( + VOID + ) +{ + EFI_STATUS Status; + EFI_TIME Time; + UINT64 TimeUs; + + Status = gRT->GetTime(&Time, NULL); + if (EFI_ERROR(Status)) { + pal_print_msg(ACS_PRINT_WARN, " GetTime failed: %x\n", Status); + return ~0ULL; + } + + TimeUs = (((UINT64)Time.Hour * 60 + Time.Minute) * 60 + Time.Second) * 1000000ULL; + TimeUs += (UINT64)Time.Nanosecond / 1000ULL; + + return TimeUs; +} + /** @brief This API overrides the timer specified by TimerTable Note: Information about only one timer can be mentioned as an Override diff --git a/test_pool/timer/t006.c b/test_pool/timer/t006.c new file mode 100644 index 00000000..31585151 --- /dev/null +++ b/test_pool/timer/t006.c @@ -0,0 +1,145 @@ +/** @file + * Copyright (c) 2026, Arm Limited or its affiliates. All rights reserved. + * SPDX-License-Identifier : Apache-2.0 + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include "acs_val.h" +#include "acs_timer.h" +#include "acs_timer_support.h" + +#define TEST_NUM (ACS_TIMER_TEST_NUM_BASE + 6) +#define TEST_RULE "S_L5TI_01" +#define TEST_DESC "Check OS visible counter reports 1GHz " + +#define MICROSECONDS_PER_SECOND 1000000ULL +#define MAX_DELTA_PERCENT 1ULL + +static +void +payload() +{ + uint64_t counter_freq, print_freq = 0; + uint64_t counter_start_value, counter_end_value; + uint64_t time_start_us, time_end_us; + uint64_t counter_delta, elapsed_time_us; + uint64_t est_freq_hz, freq_delta_hz; + uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid()); + uint32_t print_mhz = 0; + uint32_t iter; + + counter_freq = val_timer_get_info(TIMER_INFO_CNTFREQ, 0); + + if (counter_freq != 0) { + print_freq = counter_freq/1000; + if (print_freq > 1000) { + print_freq = print_freq/1000; + print_mhz = 1; + } + } + + if (print_mhz) + val_print(INFO, "\n Counter frequency is %ld MHz", print_freq); + else + val_print(INFO, "\n Counter frequency is %ld KHz", print_freq); + + /* Acc to S_L5TI_01, the OS visible counter should be able to count in nanosecond units. + That means the reported effective freq by CNTFRQ_EL0 should be exactly 1GHz, + consistent with post Armv8.6 systems that mandate a fixed 1GHz counter freq */ + if (counter_freq == (1000 * 1000 * 1000)) + val_set_status(index, RESULT_PASS); + else + val_set_status(index, RESULT_FAIL(1)); + + /* The test below is only a sanity check. It will not measure the compliance of the system against + S_L5TI_01. + + Sanity Check: CNTFRQ_EL0 is programmed by the firmware and software relies on it to derive the + timer resolution. CNTPCT_EL0 is a hardware managed physical counter which progresses at the + rate mentioned by CNTFID and if scaling is implemented the counter increments based on the + scale value mentioned in CNTSCR.ScaleVal. + + The purpose of this check is to verify that the observed progression of CNTPCT_EL0 is + consistent with the frequency reported to software through CNTFRQ_EL0. + */ + + /* Algorithm: Sample CNTPCT_EL0 at two points separated by 1000 ms while tracking the same + interval with an independent timer source. Use the elapsed counter delta + and the independent time delta to estimate the effective frequency of CNTPCT_EL0. + */ + + for (iter = 0; iter < 5; iter++) { + isb(); + counter_start_value = read_cntpct_el0(); + time_start_us = val_get_platform_time_us(); + if ((time_start_us == PAL_TIME_US_INVALID) || + (time_start_us == ACS_STATUS_PAL_NOT_IMPLEMENTED)) { + val_print(DEBUG, "\n Platform time source unavailable; skipping sanity check"); + return; + } + + val_time_delay_ms(1000 * ONE_MILLISECOND); + + isb(); + counter_end_value = read_cntpct_el0(); + time_end_us = val_get_platform_time_us(); + if (time_end_us == PAL_TIME_US_INVALID) { + val_print(DEBUG, "\n Platform time source unavailable; skipping sanity check"); + return; + } + + counter_delta = counter_end_value - counter_start_value; + elapsed_time_us = time_end_us - time_start_us; + + if (elapsed_time_us == 0) { + val_print(DEBUG, "\n Platform time delta is zero; skipping sanity check"); + return; + } + + est_freq_hz = (counter_delta * MICROSECONDS_PER_SECOND) / elapsed_time_us; + val_print(DEBUG, "\n Estimated CNTPCT_EL0 frequency is %ld Hz", est_freq_hz); + + if (est_freq_hz >= counter_freq) + freq_delta_hz = est_freq_hz - counter_freq; + else + freq_delta_hz = counter_freq - est_freq_hz; + + if (((freq_delta_hz * 100ULL) / counter_freq) > MAX_DELTA_PERCENT) + val_print(WARN, "\n Sanity check: CNTPCT_EL0 progression is not consistent with" + " CNTFRQ_EL0"); + else + val_print(DEBUG, "\n Sanity check: CNTPCT_EL0 progression is consistent with" + " CNTFRQ_EL0"); + } +} + +uint32_t +t006_entry(uint32_t num_pe) +{ + + uint32_t status = ACS_STATUS_FAIL; + + num_pe = 1; //This Timer test is run on single processor + + val_log_context((char8_t *)__FILE__, (char8_t *)__func__, __LINE__); + status = val_initialize_test(TEST_NUM, TEST_DESC, num_pe); + if (status != ACS_STATUS_SKIP) + val_run_test_payload(TEST_NUM, num_pe, payload, 0); + + /* get the result from all PE and check for failure */ + status = val_check_for_error(TEST_NUM, num_pe, TEST_RULE); + + val_report_status(0, ACS_END(TEST_NUM), TEST_RULE); + return status; +} diff --git a/tools/cmake/infra/sbsa_test.txt b/tools/cmake/infra/sbsa_test.txt index 7a5be126..c66576ef 100644 --- a/tools/cmake/infra/sbsa_test.txt +++ b/tools/cmake/infra/sbsa_test.txt @@ -41,6 +41,7 @@ g013.c g014.c g015.c g016.c +t006.c w003.c i008.c i009.c diff --git a/val/include/acs_timer.h b/val/include/acs_timer.h index 5b1e1328..d4f41076 100644 --- a/val/include/acs_timer.h +++ b/val/include/acs_timer.h @@ -47,5 +47,6 @@ uint32_t t002_entry(uint32_t num_pe); uint32_t t003_entry(uint32_t num_pe); uint32_t t004_entry(uint32_t num_pe); uint32_t t005_entry(uint32_t num_pe); +uint32_t t006_entry(uint32_t num_pe); uint32_t t008_entry(uint32_t num_pe); #endif // __ACS_TIMER_H__ diff --git a/val/include/pal_interface.h b/val/include/pal_interface.h index 1eca6e83..1f9bdacc 100644 --- a/val/include/pal_interface.h +++ b/val/include/pal_interface.h @@ -126,6 +126,7 @@ /* The following are common across all platform unless guarded explicitly */ #define ONE_MILLISECOND 1000 +#define PAL_TIME_US_INVALID (~0ULL) #define PCIE_SUCCESS 0x00000000 /* Operation completed successfully */ #define PCIE_NO_MAPPING 0x10000001 /* A mapping to a Function does not exist */ @@ -805,6 +806,7 @@ void *pal_mem_virt_to_phys(void *va); void *pal_mem_phys_to_virt(uint64_t pa); uint64_t pal_time_delay_ms(uint64_t time_ms); +uint64_t pal_get_platform_time_us(void); void pal_mem_allocate_shared(uint32_t num_pe, uint32_t sizeofentry); void pal_mem_free_shared(void); uint64_t pal_mem_get_shared_addr(void); diff --git a/val/include/rule_based_execution_enum.h b/val/include/rule_based_execution_enum.h index 2cc0e801..0a94d1eb 100644 --- a/val/include/rule_based_execution_enum.h +++ b/val/include/rule_based_execution_enum.h @@ -763,6 +763,7 @@ typedef enum { T003_ENTRY, T004_ENTRY, T005_ENTRY, + T006_ENTRY, T008_ENTRY, W001_ENTRY, W002_ENTRY, diff --git a/val/include/val_interface.h b/val/include/val_interface.h index cb1c27cb..6d930f9b 100644 --- a/val/include/val_interface.h +++ b/val/include/val_interface.h @@ -111,6 +111,7 @@ void val_print_acs_test_status_summary(void); uint32_t execute_tests(void); uint64_t val_time_delay_ms(uint64_t time_ms); +uint64_t val_get_platform_time_us(void); /* VAL PE APIs */ typedef enum { diff --git a/val/src/acs_test_infra.c b/val/src/acs_test_infra.c index f94341bd..8b90947b 100644 --- a/val/src/acs_test_infra.c +++ b/val/src/acs_test_infra.c @@ -862,6 +862,12 @@ val_time_delay_ms(uint64_t timer_ms) return pal_time_delay_ms(timer_ms); } +uint64_t +val_get_platform_time_us(void) +{ + return pal_get_platform_time_us(); +} + /** Calls pal API to dump dtb diff --git a/val/src/rule_metadata.c b/val/src/rule_metadata.c index 316b002f..159c8435 100644 --- a/val/src/rule_metadata.c +++ b/val/src/rule_metadata.c @@ -1436,6 +1436,14 @@ rule_test_map_t rule_test_map[RULE_ID_SENTINEL] = { .flag = BASE_RULE, .test_num = ACS_TIMER_TEST_NUM_BASE + 5, }, + [S_L5TI_01] = { + .test_entry_id = T006_ENTRY, + .module_id = TIMER, + .rule_desc = "Check OS visible counter reports 1GHz", + .platform_bitmask = PLATFORM_BAREMETAL | PLATFORM_UEFI, + .flag = BASE_RULE, + .test_num = ACS_TIMER_TEST_NUM_BASE + 6, + }, /* WATCHDOG */ [B_WD_00] = { .test_entry_id = NULL_ENTRY, @@ -3123,9 +3131,6 @@ rule_test_map_t rule_test_map[RULE_ID_SENTINEL] = { [B_TIME_10] = { .module_id = TIMER, }, - [S_L5TI_01] = { - .module_id = TIMER, - }, [S_L8TI_01] = { .module_id = TIMER, }, @@ -3552,6 +3557,7 @@ test_entry_fn_t test_entry_func_table[TEST_ENTRY_SENTINEL] = { [CXL_11_ENTRY] = cxl_11_entry, [CXL_12_ENTRY] = cxl_12_entry, [CXL_13_ENTRY] = cxl013_entry, + [T006_ENTRY] = t006_entry, [G013_ENTRY] = g013_entry, [G014_ENTRY] = g014_entry, [G015_ENTRY] = g015_entry, @@ -4006,6 +4012,7 @@ test_entry_fn_t test_entry_func_table[TEST_ENTRY_SENTINEL] = { #else /* Drop compiling entries not required for Bare Metal BSA compliance */ #ifndef BAREMETAL_BSA_BUILD + [T006_ENTRY] = t006_entry, [G012_ENTRY] = g012_entry, [G013_ENTRY] = g013_entry, [G016_ENTRY] = g016_entry, diff --git a/val/src/sbsa_execute_test.c b/val/src/sbsa_execute_test.c index 23276543..8aaddadd 100644 --- a/val/src/sbsa_execute_test.c +++ b/val/src/sbsa_execute_test.c @@ -239,9 +239,8 @@ uint32_t val_sbsa_timer_execute_tests(uint32_t level, uint32_t num_pe) { uint32_t status = ACS_STATUS_PASS, i; - (void) num_pe; - if (!(((level > 7) && (g_sbsa_only_level == 0)) || (g_sbsa_only_level == 8))) + if (!(((level > 4) && (g_sbsa_only_level == 0)) || (g_sbsa_only_level == 5))) return ACS_STATUS_SKIP; for (i = 0; i < g_num_skip; i++) { @@ -261,6 +260,9 @@ val_sbsa_timer_execute_tests(uint32_t level, uint32_t num_pe) val_print_test_start("Timer"); g_curr_module = 1 << TIMER_MODULE; + if (((level > 4) && (g_sbsa_only_level == 0)) || (g_sbsa_only_level == 5)) + status |= t006_entry(num_pe); + val_print_test_end(status, "Timer"); return status;