From 7c6307bebf6c81055b5bc9bb12bb23f1e0fdb17b Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Thu, 8 Oct 2026 21:57:36 +0200 Subject: [PATCH] arch/arm64/qemu: Use the PL031 RTC of the virt machine. The QEMU virt machine has a PL031 RTC at 0x09010000 (SPI 2), which QEMU sets from the host clock. qemu-armv8a did not register it, so the system time started at CONFIG_START_YEAR, and files on a host share (v9fs, hostfs) had times years in the future. With CONFIG_RTC_PL031, up_rtc_initialize() now registers the PL031 as the RTC, so the system time starts at the host's time. The new option QEMU_RTC_PL031_SYNC makes the boot wait (up to a second) for the RTC second to change. The PL031 counts whole seconds, so without the wait the time starts up to a second behind the host. Assisted-by: Claude Code:claude-opus-5-5 Signed-off-by: Marco Casaroli --- arch/arm64/src/qemu/CMakeLists.txt | 3 ++ arch/arm64/src/qemu/Kconfig | 25 +++++++++++ arch/arm64/src/qemu/Make.defs | 4 ++ arch/arm64/src/qemu/qemu_rtc.c | 69 ++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+) create mode 100644 arch/arm64/src/qemu/qemu_rtc.c diff --git a/arch/arm64/src/qemu/CMakeLists.txt b/arch/arm64/src/qemu/CMakeLists.txt index 141673930a1..05c43928518 100644 --- a/arch/arm64/src/qemu/CMakeLists.txt +++ b/arch/arm64/src/qemu/CMakeLists.txt @@ -30,4 +30,7 @@ endif() if(CONFIG_PM) list(APPEND SRCS qemu_initialize.c) endif() +if(CONFIG_RTC_PL031) + list(APPEND SRCS qemu_rtc.c) +endif() target_sources(arch PRIVATE ${SRCS}) diff --git a/arch/arm64/src/qemu/Kconfig b/arch/arm64/src/qemu/Kconfig index 668b9c564d9..89e0b4b6b2a 100644 --- a/arch/arm64/src/qemu/Kconfig +++ b/arch/arm64/src/qemu/Kconfig @@ -47,4 +47,29 @@ config ARCH_CHIP_QEMU_WITH_HV endmenu # "Qemu Chip Selection" +config QEMU_RTC_PL031_BASE + hex "PL031 RTC base address" + default 0x09010000 + depends on RTC_PL031 + ---help--- + Physical address of the PL031 RTC of the QEMU virt machine. + +config QEMU_RTC_PL031_IRQ + int "PL031 RTC interrupt" + default 34 + depends on RTC_PL031 + ---help--- + Interrupt of the PL031 RTC of the QEMU virt machine (SPI 2). + +config QEMU_RTC_PL031_SYNC + bool "Start the system time at an RTC second boundary" + default n + depends on RTC_PL031 + ---help--- + The PL031 counts whole seconds, so the system time starts up to a + second behind the host. Files that the host writes then look + up to a second in the future, and make warns about clock skew. + With this option the boot waits (up to a second) for the RTC + second to change, so the time is correct to a few milliseconds. + endif # ARCH_CHIP_QEMU diff --git a/arch/arm64/src/qemu/Make.defs b/arch/arm64/src/qemu/Make.defs index 83c77512f22..da73b158d87 100644 --- a/arch/arm64/src/qemu/Make.defs +++ b/arch/arm64/src/qemu/Make.defs @@ -36,3 +36,7 @@ endif ifeq ($(CONFIG_PM),y) CHIP_CSRCS += qemu_initialize.c endif + +ifeq ($(CONFIG_RTC_PL031),y) +CHIP_CSRCS += qemu_rtc.c +endif diff --git a/arch/arm64/src/qemu/qemu_rtc.c b/arch/arm64/src/qemu/qemu_rtc.c new file mode 100644 index 00000000000..6c91e317f33 --- /dev/null +++ b/arch/arm64/src/qemu/qemu_rtc.c @@ -0,0 +1,69 @@ +/**************************************************************************** + * arch/arm64/src/qemu/qemu_rtc.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include "arm64_internal.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_rtc_initialize + * + * Description: + * Register the PL031 RTC of the QEMU virt machine. QEMU sets it from the + * host clock (-rtc base=utc by default), so the system time starts at the + * host's time. + * + ****************************************************************************/ + +int up_rtc_initialize(void) +{ + FAR struct rtc_lowerhalf_s *lower; + +#ifdef CONFIG_QEMU_RTC_PL031_SYNC + /* The PL031 counts whole seconds, so the system time would start up to a + * second late. Wait until the second changes: the time read next is + * then correct to a few milliseconds. Register 0 is the data register. + */ + + uint32_t second = getreg32(CONFIG_QEMU_RTC_PL031_BASE); + + while (getreg32(CONFIG_QEMU_RTC_PL031_BASE) == second); +#endif + + lower = pl031_initialize(CONFIG_QEMU_RTC_PL031_BASE, + CONFIG_QEMU_RTC_PL031_IRQ); + up_rtc_set_lowerhalf(lower, true); + return rtc_initialize(0, lower); +}