diff --git a/boards/qemu_arm64/board_qemu_arm64.c b/boards/qemu_arm64/board_qemu_arm64.c index 4a6386c..d9c814d 100644 --- a/boards/qemu_arm64/board_qemu_arm64.c +++ b/boards/qemu_arm64/board_qemu_arm64.c @@ -9,6 +9,7 @@ #include "board_qemu_arm64.h" #include "eos_board_registry.h" +#include "qemu_arm64_timer.h" #include static int qemu_flash_read(uint32_t addr, void *buf, size_t len) @@ -50,7 +51,17 @@ static void qemu_jump(uint32_t vector_addr) entry(); } -static uint32_t qemu_get_tick_ms(void) { return 0; } +static uint32_t qemu_get_tick_ms(void) +{ + uint64_t counter; + uint64_t frequency; + + /* QEMU virt exposes the AArch64 Generic Timer at EL1. */ + __asm volatile ("mrs %0, cntfrq_el0" : "=r" (frequency)); + __asm volatile ("isb\n\tmrs %0, cntvct_el0" : "=r" (counter) :: "memory"); + + return qemu_arm64_counter_to_ms(counter, (uint32_t)frequency); +} static const eos_board_ops_t qemu_arm64_ops = { .flash_base = QEMU_ARM64_FLASH_BASE, diff --git a/boards/qemu_arm64/qemu_arm64_timer.h b/boards/qemu_arm64/qemu_arm64_timer.h new file mode 100644 index 0000000..5fc1ab0 --- /dev/null +++ b/boards/qemu_arm64/qemu_arm64_timer.h @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2026 EoS Project +// ISO/IEC 25000 | ISO/IEC/IEEE 15288:2023 + +#ifndef QEMU_ARM64_TIMER_H +#define QEMU_ARM64_TIMER_H + +#include + +static inline uint32_t qemu_arm64_counter_to_ms(uint64_t counter, + uint32_t frequency) +{ + uint32_t milliseconds = (uint32_t)(counter / frequency) * 1000U; + uint64_t remainder = counter % frequency; + + milliseconds += (uint32_t)((remainder * 1000U) / frequency); + return milliseconds; +} + +#endif /* QEMU_ARM64_TIMER_H */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b394f24..803229d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -65,6 +65,13 @@ add_executable(eboot_test_multicore unit/test_multicore.c) target_link_libraries(eboot_test_multicore PRIVATE eboot_core) add_test(NAME test_multicore COMMAND eboot_test_multicore) +# --- test_qemu_arm64_timer: Generic timer conversion --- +add_executable(eboot_test_qemu_arm64_timer unit/test_qemu_arm64_timer.c) +target_include_directories(eboot_test_qemu_arm64_timer PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/../boards/qemu_arm64 +) +add_test(NAME test_qemu_arm64_timer COMMAND eboot_test_qemu_arm64_timer) + # --- test_board_registry: Runtime board selection --- add_executable(eboot_test_board_registry unit/test_board_registry.c) target_link_libraries(eboot_test_board_registry PRIVATE eboot_core) @@ -116,8 +123,8 @@ if(VALGRIND) set(VALGRIND_OPTS --leak-check=full --error-exitcode=1 --quiet) foreach(TEST_NAME test_bootctl test_crypto test_ed25519 test_keystore test_device_table test_runtime_svc test_board_config - test_multicore test_board_registry test_slot_manager - test_boot_log test_image_verify test_image_abi + test_multicore test_qemu_arm64_timer test_board_registry + test_slot_manager test_boot_log test_image_verify test_image_abi test_recovery test_slot_size_bounds test_fw_transport test_tlv_auth) add_test( diff --git a/tests/unit/test_qemu_arm64_timer.c b/tests/unit/test_qemu_arm64_timer.c new file mode 100644 index 0000000..ede5c41 --- /dev/null +++ b/tests/unit/test_qemu_arm64_timer.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2026 EoS Project +// ISO/IEC 25000 | ISO/IEC/IEEE 15288:2023 + +/** + * @file test_qemu_arm64_timer.c + * @brief Unit tests for QEMU ARM64 generic timer conversion + */ + +#include "qemu_arm64_timer.h" +#include +#include +#include + +#define ASSERT_EQ(expected, actual) do { \ + uint32_t expected_value = (expected); \ + uint32_t actual_value = (actual); \ + if (expected_value != actual_value) { \ + printf("[FAIL] %s:%d: expected %u, got %u\n", \ + __FILE__, __LINE__, expected_value, actual_value); \ + exit(1); \ + } \ +} while (0) + +int main(void) +{ + printf("=== eBootloader: QEMU ARM64 Timer Unit Tests ===\n\n"); + + ASSERT_EQ(0U, qemu_arm64_counter_to_ms(0U, 1000000U)); + ASSERT_EQ(1500U, qemu_arm64_counter_to_ms(1500000U, 1000000U)); + ASSERT_EQ(1271310319U, + qemu_arm64_counter_to_ms(UINT64_MAX, 1000000U)); + ASSERT_EQ(123U, + qemu_arm64_counter_to_ms(4294967296123ULL, 1000U)); + + printf("4/4 tests passed\n"); + return 0; +}