Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/uefi/Bsa.inf
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
../../test_pool/timer/t005.c
../../test_pool/timer/t006.c
../../test_pool/timer/t008.c
../../test_pool/timer/t009.c
../../test_pool/watchdog/w001.c
../../test_pool/watchdog/w002.c
../../test_pool/peripherals/d001.c
Expand Down
1 change: 1 addition & 0 deletions apps/uefi/Sbsa.inf
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
../../test_pool/timer/t005.c
../../test_pool/timer/t006.c
../../test_pool/timer/t008.c
../../test_pool/timer/t009.c
../../test_pool/watchdog/w001.c
../../test_pool/watchdog/w002.c
../../test_pool/peripherals/d001.c
Expand Down
1 change: 1 addition & 0 deletions apps/uefi/Vbsa.inf
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
../../test_pool/timer/t005.c
../../test_pool/timer/t006.c
../../test_pool/timer/t008.c
../../test_pool/timer/t009.c
../../test_pool/watchdog/w001.c
../../test_pool/watchdog/w002.c
../../test_pool/peripherals/d001.c
Expand Down
1 change: 1 addition & 0 deletions apps/uefi/pc_bsa.inf
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
../../test_pool/timer/t005.c
../../test_pool/timer/t006.c
../../test_pool/timer/t008.c
../../test_pool/timer/t009.c
../../test_pool/watchdog/w001.c
../../test_pool/watchdog/w002.c
../../test_pool/peripherals/d001.c
Expand Down
1 change: 1 addition & 0 deletions apps/uefi/xbsa_acpi.inf
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@
../../test_pool/gic/g016.c
../../test_pool/timer/t006.c
../../test_pool/timer/t008.c
../../test_pool/timer/t009.c
../../test_pool/watchdog/w003.c
../../test_pool/smmu/i008.c
../../test_pool/smmu/i009.c
Expand Down
20 changes: 10 additions & 10 deletions docs/bsa/arm_bsa_testcase_checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -663,11 +663,11 @@ The checklist provides information about:
<td>L1</td>
<td>B_TIME_05</td>
<td>B_TIME_05</td>
<td>Not Covered</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>501,502,503,504,505</td>
<td>Check sys cnt visible to PE timers</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td></td>
</tr>
<tr>
Expand Down Expand Up @@ -718,11 +718,11 @@ The checklist provides information about:
<td>L1</td>
<td>B_TIME_10</td>
<td>B_TIME_10</td>
<td>Not Covered</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>410</td>
<td>Check Non-secure timer frame access</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td></td>
</tr>
<tr>
Expand Down
165 changes: 165 additions & 0 deletions test_pool/timer/t009.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/** @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 "val_interface.h"
#include "acs_pe.h"
#include "acs_timer.h"

#define TEST_NUM (ACS_TIMER_TEST_NUM_BASE + 10)
#define TEST_RULE "B_TIME_10"
#define TEST_DESC "Check Non-secure timer frame access "

#define ACCESS_CNTTIDR 1
#define ACCESS_CNTPCT 2

static void *branch_to_test;
static uint64_t fault_timer_index;
static uint32_t fault_access_type;

static
void
esr(uint64_t interrupt_type, void *context)
{
uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid());

val_pe_update_elr(context, (uint64_t)branch_to_test);

val_print(ERROR, "\n Received exception type %d", interrupt_type);
if (fault_access_type == ACCESS_CNTTIDR)
val_print(ERROR, " during CNTCTLBase.CNTTIDR read for timer %llx", fault_timer_index);
else if (fault_access_type == ACCESS_CNTPCT)
val_print(ERROR, " during CNTBaseN.CNTPCT read for timer %llx", fault_timer_index);
val_set_status(index, RESULT_FAIL(1));
}

static
void
payload()
{
uint32_t index = val_pe_get_index_mpid(val_pe_get_mpid());
uint32_t status;
uint32_t ns_timer = 0;
uint32_t readable_timer = 0;
uint32_t cnttidr;
uint64_t cnt_ctl_base;
uint64_t cnt_base_n;
uint64_t cntpct;
uint64_t timer_num = val_timer_get_info(TIMER_INFO_NUM_PLATFORM_TIMERS, 0);

branch_to_test = &&exception_taken;
status = val_pe_install_esr(EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS, esr);
status |= val_pe_install_esr(EXCEPT_AARCH64_SERROR, esr);
if (status) {
val_print(ERROR, "\n Failed to install exception handlers");
val_set_status(index, RESULT_FAIL(2));
return;
}

if (!timer_num) {
val_print(DEBUG, "\n No System timers are defined");
val_set_status(index, RESULT_SKIP(1));
return;
}

while (timer_num) {
--timer_num;

/* Skip secure timers */
if (val_timer_get_info(TIMER_INFO_IS_PLATFORM_TIMER_SECURE, timer_num))
continue;

ns_timer++;
cnt_ctl_base = val_timer_get_info(TIMER_INFO_SYS_CNTL_BASE, timer_num);
cnt_base_n = val_timer_get_info(TIMER_INFO_SYS_CNT_BASE_N, timer_num);

/*
* Firmware should expose non-zero base addresses for usable Non-secure
* timer frames. Keep scanning other frames so one bad descriptor does not
* hide a later usable frame.
*/
if (cnt_ctl_base == 0)
val_print(WARN, "\n CNTCTL BASE is zero for timer %llx", timer_num);

if (cnt_base_n == 0)
val_print(WARN, "\n CNT_BASE_N is zero for timer %llx", timer_num);

if ((cnt_ctl_base == 0) || (cnt_base_n == 0))
continue;

/*
* The payload checks Non-secure memory access of CNTCTLBase and CNTBaseN,
* not register behavior. Do read probes only: no writes, no read-only/RW
* validation, and no CNTACR permission interpretation.
*/
fault_timer_index = timer_num;
fault_access_type = ACCESS_CNTTIDR;
cnttidr = val_mmio_read(cnt_ctl_base + CNTTIDR);
val_print(DEBUG, "\n CNTTIDR Read value = 0x%x", cnttidr);

/*
* CNTPCT may legally read as RAZ/WI if CNTACR<n>.RPCT is clear. That is
* acceptable here because CNTACR/CNTNSAR policy is Secure-state owned;
* this test only requires that the Non-secure read access itself does
* not fault.
*/
fault_access_type = ACCESS_CNTPCT;
cntpct = val_mmio_read64(cnt_base_n + CNTPCT_LOWER);
val_print(DEBUG, "\n CNTPCT Read value = 0x%llx", cntpct);

readable_timer++;
}

/* Report fail if OS visible platform timers exists, but non of them are non-secure access */
if (!ns_timer) {
val_print(ERROR, "\n No non-secure systimer implemented");
val_set_status(index, RESULT_FAIL(3));
return;
}

if (!readable_timer) {
val_print(ERROR, "\n No usable non-secure systimer frame found");
val_set_status(index, RESULT_FAIL(4));
return;
}

val_set_status(index, RESULT_PASS);

exception_taken:
return;
}

uint32_t
t009_entry(uint32_t num_pe)
{
uint32_t status = ACS_STATUS_FAIL;

num_pe = 1;

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), NULL);

return status;
}
1 change: 1 addition & 0 deletions tools/cmake/infra/bsa_test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ t002.c
t003.c
t004.c
t005.c
t009.c
w001.c
w002.c
d001.c
Expand Down
1 change: 1 addition & 0 deletions tools/cmake/infra/pc_bsa_test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ t002.c
t003.c
t004.c
t005.c
t009.c
tpm001.c
tpm002.c
e001.c
Expand Down
1 change: 1 addition & 0 deletions val/include/acs_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@ 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);
uint32_t t009_entry(uint32_t num_pe);
#endif // __ACS_TIMER_H__
1 change: 1 addition & 0 deletions val/include/rule_based_execution_enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,7 @@ typedef enum {
T005_ENTRY,
T006_ENTRY,
T008_ENTRY,
T009_ENTRY,
W001_ENTRY,
W002_ENTRY,
W003_ENTRY,
Expand Down
24 changes: 18 additions & 6 deletions val/src/rule_metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -1404,6 +1404,13 @@ rule_test_map_t rule_test_map[RULE_ID_SENTINEL] = {
.flag = BASE_RULE,
.test_num = ACS_TIMER_TEST_NUM_BASE + 1,
},
[B_TIME_05] = {
.test_entry_id = B_WAK_03_07_ENTRY,
.module_id = TIMER,
.rule_desc = "Check sys cnt visible to PE timers",
.platform_bitmask = PLATFORM_BAREMETAL | PLATFORM_UEFI,
.flag = BASE_RULE,
},
[B_TIME_06] = {
.test_entry_id = T002_ENTRY,
.module_id = TIMER,
Expand Down Expand Up @@ -1436,6 +1443,14 @@ rule_test_map_t rule_test_map[RULE_ID_SENTINEL] = {
.flag = BASE_RULE,
.test_num = ACS_TIMER_TEST_NUM_BASE + 5,
},
[B_TIME_10] = {
.test_entry_id = T009_ENTRY,
.module_id = TIMER,
.rule_desc = "Check Non-secure timer frame access",
.platform_bitmask = PLATFORM_BAREMETAL | PLATFORM_UEFI,
.flag = BASE_RULE,
.test_num = ACS_TIMER_TEST_NUM_BASE + 10,
},
[S_L5TI_01] = {
.test_entry_id = T006_ENTRY,
.module_id = TIMER,
Expand Down Expand Up @@ -3125,12 +3140,6 @@ rule_test_map_t rule_test_map[RULE_ID_SENTINEL] = {
[B_TIME_04] = {
.module_id = TIMER,
},
[B_TIME_05] = {
.module_id = TIMER,
},
[B_TIME_10] = {
.module_id = TIMER,
},
[S_L8TI_01] = {
.module_id = TIMER,
},
Expand Down Expand Up @@ -3803,6 +3812,7 @@ test_entry_fn_t test_entry_func_table[TEST_ENTRY_SENTINEL] = {
[T004_ENTRY] = t004_entry,
[T005_ENTRY] = t005_entry,
[T008_ENTRY] = t008_entry,
[T009_ENTRY] = t009_entry,
[U001_ENTRY] = u001_entry, // used in wrapper.
[U002_ENTRY] = u002_entry, // used in wrapper.
[U003_ENTRY] = u003_entry, // used in wrapper.
Expand Down Expand Up @@ -3917,6 +3927,7 @@ test_entry_fn_t test_entry_func_table[TEST_ENTRY_SENTINEL] = {
[T003_ENTRY] = t003_entry,
[T004_ENTRY] = t004_entry,
[T005_ENTRY] = t005_entry,
[T009_ENTRY] = t009_entry,
[W001_ENTRY] = w001_entry,
[W002_ENTRY] = w002_entry,
[D001_ENTRY] = d001_entry,
Expand Down Expand Up @@ -4290,6 +4301,7 @@ test_entry_fn_t test_entry_func_table[TEST_ENTRY_SENTINEL] = {
[T004_ENTRY] = t004_entry,
[T001_ENTRY] = t001_entry,
[T002_ENTRY] = t002_entry,
[T009_ENTRY] = t009_entry,
[E039_ENTRY] = e039_entry, // used in wrapper.
[E035_ENTRY] = e035_entry,
[E013_ENTRY] = e013_entry,
Expand Down
Loading