Skip to content
Open
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
13 changes: 12 additions & 1 deletion boards/qemu_arm64/board_qemu_arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "board_qemu_arm64.h"
#include "eos_board_registry.h"
#include "qemu_arm64_timer.h"
#include <string.h>

static int qemu_flash_read(uint32_t addr, void *buf, size_t len)
Expand Down Expand Up @@ -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,
Expand Down
20 changes: 20 additions & 0 deletions boards/qemu_arm64/qemu_arm64_timer.h
Original file line number Diff line number Diff line change
@@ -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 <stdint.h>

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 */
11 changes: 9 additions & 2 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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(
Expand Down
38 changes: 38 additions & 0 deletions tests/unit/test_qemu_arm64_timer.c
Original file line number Diff line number Diff line change
@@ -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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#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;
}