virtio: Add a virtio RTC driver
v7 cover virtio: Add a virtio RTC driver
QEMU v11.1.0 added a virtio RTC device (virtio-rtc-pci and virtio-rtc-device), but U-Boot has no driver for it. This series adds one, so U-Boot can read the time from it through the RTC uclass.
Patch 1 adds the driver, patch 2 updates the virtio documentation and patch 3 adds a MAINTAINERS entry. Patch 4 lets sandbox tests answer virtqueue requests as the device would, which patch 5 uses to test the driver. Patch 6 documents how to reach the virtio RTC.
Changes in v7:
- Patch 6: drop the claim that QEMU x86 does not enable DM_RTC. X86 implies DM_RTC, so the driver is already built there (Simon).
- Cover letter: no longer claim that "date" reads the virtio RTC on any QEMU target, which patch 6 explains is not the case (Simon, v5).
- Rebase onto main. Patches 1-5 are unchanged.
Tested with qemu-riscv64_smode_defconfig and RTC_GOLDFISH disabled, on QEMU v11.1.2, which reports a UTC clock, and on QEMU master, which reports a smeared UTC clock:
- With -device virtio-rtc-pci and with -device virtio-rtc-device, "date" reads the host time and advances between reads.
- Setting the time fails, as the clocks are read-only.
- With no virtio RTC device, "date" fails cleanly with err=-19.
With qemu-x86_64_defconfig on QEMU v11.1.2, "dm uclass rtc" shows the CMOS RTC at sequence 0 and the virtio RTC at 1; with RTC_MC146818 disabled, the virtio RTC is sequence 0 and "date" reads it.
On sandbox, "ut dm virtio_rtc*" passes.
Hung-Chun Tseng (6):
virtio: rtc: Add virtio RTC driver
doc: virtio: List the supported device types
MAINTAINERS: Add entry for virtio RTC
virtio: sandbox: Let tests emulate the device side of a virtqueue
test: dm: Add tests for the virtio RTC driver
doc: virtio: Explain how to reach the virtio RTC
MAINTAINERS | 6 + arch/sandbox/dts/test.dts | 5 + arch/sandbox/include/asm/test.h | 25 +++ doc/develop/driver-model/virtio.rst | 25 ++- drivers/virtio/Kconfig | 11 + drivers/virtio/Makefile | 1 + drivers/virtio/virtio-uclass.c | 1 + drivers/virtio/virtio_rtc.c | 244 ++++++++++++++++++++++ drivers/virtio/virtio_sandbox.c | 15 ++ include/virtio.h | 4 +- test/dm/Makefile | 1 + test/dm/virtio_rtc.c | 306 ++++++++++++++++++++++++++++ 12 files changed, 639 insertions(+), 5 deletions(-) create mode 100644 drivers/virtio/virtio_rtc.c create mode 100644 test/dm/virtio_rtc.c
Signature · 1 line
2.43.0
PATCH v7 1/6 virtio: rtc: Add virtio RTC driver
QEMU provides a virtio RTC device (virtio-rtc-pci, virtio-rtc-device) since v11.1.0, but U-Boot has no driver for it.
The virtqueue must not be used before the virtio uclass sets DRIVER_OK, which happens after probe(), so the clock is looked up on the first read.
Like Linux, the driver prefers a VIRTIO_RTC_CLOCK_UTC_SMEARED clock, as it never steps on leap seconds. QEMU master reports such a clock since "virtio-rtc: Report smeared UTC clock type", but v11.1 reports VIRTIO_RTC_CLOCK_UTC, so the driver falls back to another UTC clock rather than leave U-Boot without an RTC there.
The set of clocks never changes, so if none of them is UTC, the driver remembers it and fails later reads at once.
--- drivers/virtio/Kconfig | 11 ++ drivers/virtio/Makefile | 1 + drivers/virtio/virtio-uclass.c | 1 + drivers/virtio/virtio_rtc.c | 244 +++++++++++++++++++++++++++++++++ include/virtio.h | 4 +- 5 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 drivers/virtio/virtio_rtc.c
drivers/virtio/Kconfig +11 -0
@@ -84,4 +84,15 @@ config VIRTIO_9P help This enables the 9P transport driver over virtio. It can be used with QEMU based targets. + +config VIRTIO_RTC + bool "virtio RTC driver" + depends on DM_RTC + depends on VIRTIO + default y + help + This enables the virtio RTC driver, which reads the UTC clock + exposed by a virtio RTC device. QEMU v11.1.0 or later provides + it as virtio-rtc-pci and virtio-rtc-device. The clocks are + read-only, so the time cannot be set. endmenu
drivers/virtio/Makefile +1 -0
@@ -12,3 +12,4 @@ obj-$(CONFIG_VIRTIO_NET) += virtio_net.o obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o obj-$(CONFIG_VIRTIO_RNG) += virtio_rng.o obj-$(CONFIG_VIRTIO_9P) += virtio_9p.o +obj-$(CONFIG_VIRTIO_RTC) += virtio_rtc.o
drivers/virtio/virtio-uclass.c +1 -0
@@ -32,6 +32,7 @@ static const char *const virtio_drv_name[VIRTIO_ID_MAX_NUM] = { [VIRTIO_ID_BLOCK] = VIRTIO_BLK_DRV_NAME, [VIRTIO_ID_RNG] = VIRTIO_RNG_DRV_NAME, [VIRTIO_ID_9P] = VIRTIO_9P_DRV_NAME, + [VIRTIO_ID_CLOCK] = VIRTIO_RTC_DRV_NAME, }; int virtio_get_config(struct udevice *vdev, unsigned int offset,
drivers/virtio/virtio_rtc.c new file +244 -0
244 lines not on this page · raw message
include/virtio.h +3 -1
@@ -32,12 +32,14 @@#define VIRTIO_ID_BLOCK 2/* virtio block */ #define VIRTIO_ID_RNG 4/* virtio rng */ #define VIRTIO_ID_9P 9/* virtio 9p */ -#define VIRTIO_ID_MAX_NUM 10 +#define VIRTIO_ID_CLOCK 17/* virtio clock/timer (rtc) */ +#define VIRTIO_ID_MAX_NUM 18#define VIRTIO_NET_DRV_NAME "virtio-net"#define VIRTIO_BLK_DRV_NAME "virtio-blk"#define VIRTIO_RNG_DRV_NAME "virtio-rng"#define VIRTIO_9P_DRV_NAME "virtio-9p" +#define VIRTIO_RTC_DRV_NAME "virtio-rtc"/* Feature bits for virtio 9P */ #define VIRTIO_9P_MOUNT_TAG 0
Signature · 1 line
2.43.0
PATCH v7 2/6 doc: virtio: List the supported device types
In reply to Hung-Chun TsengThe list of supported device types still only named network and block devices. Turn it into a bulleted list, which is easier to extend, and add the entropy, 9P and RTC devices. Also note that the virtio RTC device needs QEMU v11.1.0 or later.
The Development Flow section repeated the old list; point it to the one at the top instead.
--- doc/develop/driver-model/virtio.rst | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
doc/develop/driver-model/virtio.rst +11 -4
@@ -28,7 +28,13 @@ queues configuration and buffer transfers are nearly identical. Both MMIO and PCI transport options are supported in U-Boot. The VirtIO spec defines a lots of VirtIO device types, however at present only -network and block device, the most two commonly used devices, are supported. +the following devices are supported. + + - network + - block + - entropy (rng) + - 9P transport + - RTC The following QEMU targets are supported.
@@ -72,6 +78,8 @@ Requirements ------------ It is required that QEMU v2.5.0+ should be used to test U-Boot VirtIO support on QEMU ARM and x86, and v2.12.0+ on QEMU RISC-V. +The VirtIO RTC device (``-device virtio-rtc-pci`` or +``-device virtio-rtc-device``) requires QEMU v11.1.0+. Testing -------
@@ -246,9 +254,8 @@ So it's easy to tell which device these functions are operating on. Development Flow ---------------- -At present only VirtIO network card (device ID 1) and block device (device -ID 2) are supported. If you want to develop new driver for new devices, -please follow the guideline below. +The supported devices are listed at the top of this document. If you want +to develop new driver for new devices, please follow the guideline below. 1. add new device ID in virtio.h
Signature · 1 line
2.43.0
PATCH v7 3/6 MAINTAINERS: Add entry for virtio RTC
In reply to Hung-Chun TsengAdd myself as the maintainer of the virtio RTC driver.
--- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+)
MAINTAINERS +5 -0
@@ -1889,6 +1889,11 @@ F: include/virtio*.h F: test/dm/virtio*.c F: doc/develop/driver-model/virtio.rst +VIRTIO RTC +M: Hung-Chun Tseng <[email protected]> +S: Maintained +F: drivers/virtio/virtio_rtc.c + WATCHDOG M: Stefan Roese <[email protected]> S: Maintained
Signature · 1 line
2.43.0
PATCH v7 4/6 virtio: sandbox: Let tests emulate the device side of a virtqueue
In reply to Hung-Chun TsengThe sandbox virtio transport ignores notifications, so a driver that waits for the device to answer a request cannot be tested beyond its probe. The virtio-rng test works around this by writing to the used ring of the driver's virtqueue before reading.
Add sandbox_virtio_set_notify() so that a test can install a handler which is called when the driver kicks a virtqueue. The handler can then process the available ring and fill in the used ring, as a real device would. Without a handler, notifications are still ignored.
--- arch/sandbox/include/asm/test.h | 25 +++++++++++++++++++++++++ drivers/virtio/virtio_sandbox.c | 15 +++++++++++++++ 2 files changed, 40 insertions(+)
arch/sandbox/include/asm/test.h +25 -0
@@ -11,6 +11,8 @@#include <pci_ids.h> struct unit_test_state ; +struct udevice ; +struct virtqueue ;/* The sandbox driver always permits an I2C device with this address */ #define SANDBOX_I2C_TEST_ADDR 0x59
@@ -369,4 +371,27 @@ bool sandbox_sf_bootdev_enabled(void);*/ void sandbox_sf_set_enable_bootdevs (bool enable); +/** +* typedef sandbox_virtio_notify_t - Emulate the device side of a virtqueue +* +* @dev: sandbox virtio transport device +* @vq: virtqueue that was kicked +* Returns: 0 on success, or -ve error code +*/ +typedef int (*sandbox_virtio_notify_t )(struct udevice *dev, +struct virtqueue *vq); + +/** +* sandbox_virtio_set_notify() - Set a handler for virtqueue notifications +* +* The sandbox virtio transport ignores notifications by default. A test can +* set a handler here to process the buffers the driver adds, like a real +* device would. +* +* @dev: sandbox virtio transport device +* @notify: handler to call, or NULL to ignore notifications again +*/ +void sandbox_virtio_set_notify (struct udevice *dev, +sandbox_virtio_notify_t notify); +#endif
drivers/virtio/virtio_sandbox.c +15 -0
@@ -13,6 +13,7 @@#include <linux/compat.h> #include <linux/err.h> #include <linux/io.h> +#include <asm/test.h> struct virtio_sandbox_priv {u8 id;
@@ -22,6 +23,7 @@ struct virtio_sandbox_priv {ulong queue_desc;ulong queue_available;ulong queue_used; +sandbox_virtio_notify_t notify; }; static int virtio_sandbox_get_config(struct udevice *udev, unsigned int offset,
@@ -150,9 +152,22 @@ static int virtio_sandbox_find_vqs(struct udevice *udev, unsigned int nvqs,static int virtio_sandbox_notify (struct udevice *udev,struct virtqueue *vq) { +struct virtio_sandbox_priv *priv =dev_get_priv (udev); + +if (priv->notify) +return priv->notify (udev, vq); +return 0 ; } +void sandbox_virtio_set_notify (struct udevice *udev, +sandbox_virtio_notify_t notify) +{ +struct virtio_sandbox_priv *priv =dev_get_priv (udev); + + priv->notify = notify; +} +static int virtio_sandbox_probe (struct udevice *udev) {struct virtio_sandbox_priv *priv =dev_get_priv (udev);
Signature · 1 line
2.43.0
PATCH v7 5/6 test: dm: Add tests for the virtio RTC driver
In reply to Hung-Chun TsengAdd a virtio RTC device to the sandbox test device tree and emulate it through the sandbox virtio transport. The emulated device answers the VIRTIO_RTC_REQ_CFG, VIRTIO_RTC_REQ_CLOCK_CAP and VIRTIO_RTC_REQ_READ requests from a configurable list of clocks.
The tests check that the driver:
- does not use the virtqueue in probe()
- reads the time from the first UTC clock and looks it up only once
- remembers that there is no UTC clock and does not ask again
- reports a failed request and looks for the clock again next time
- gives up with -ETIMEDOUT when the device does not answer
--- MAINTAINERS | 1 + arch/sandbox/dts/test.dts | 5 + test/dm/Makefile | 1 + test/dm/virtio_rtc.c | 306 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 313 insertions(+) create mode 100644 test/dm/virtio_rtc.c
MAINTAINERS +1 -0
@@ -1893,6 +1893,7 @@ VIRTIO RTC M: Hung-Chun Tseng <[email protected]> S: Maintained F: drivers/virtio/virtio_rtc.c +F: test/dm/virtio_rtc.c WATCHDOG M: Stefan Roese <[email protected]>
arch/sandbox/dts/test.dts +5 -0
@@ -1996,6 +1996,11 @@ virtio-type = <2>; /* block */ }; + sandbox-virtio-rtc { + compatible = "sandbox,virtio1"; + virtio-type = <17>; /* clock */ + }; + sandbox_scmi { compatible = "sandbox,scmi-devices"; power-domains = <&pwrdom_scmi 2>;
test/dm/Makefile +1 -0
@@ -155,6 +155,7 @@ ifeq ($(CONFIG_VIRTIO_SANDBOX),y) obj-y += virtio.o obj-$(CONFIG_VIRTIO_RNG) += virtio_device.o obj-$(CONFIG_VIRTIO_RNG) += virtio_rng.o +obj-$(CONFIG_VIRTIO_RTC) += virtio_rtc.o endif ifeq ($(CONFIG_WDT_GPIO)$(CONFIG_WDT_SANDBOX),yy) obj-y += wdt.o
test/dm/virtio_rtc.c new file +306 -0
306 lines not on this page · raw message
Signature · 1 line
2.43.0
PATCH v7 6/6 doc: virtio: Explain how to reach the virtio RTC
In reply to Hung-Chun TsengThe date command only uses RTC sequence 0. On the QEMU ARM, RISC-V and x86 machines that is the PL031, Goldfish or MC146818 RTC, so date never reads the virtio RTC unless that driver is disabled. rtc dev does not help, as rtc read reads raw registers, which the virtio RTC does not have.
Give the virtio RTC its own section and say this there, along with the QEMU version it needs.
--- doc/develop/driver-model/virtio.rst | 10 ++++++++++ 1 file changed, 10 insertions(+)
doc/develop/driver-model/virtio.rst +10 -0
@@ -78,9 +78,19 @@ Requirements ------------ It is required that QEMU v2.5.0+ should be used to test U-Boot VirtIO support on QEMU ARM and x86, and v2.12.0+ on QEMU RISC-V. + +VirtIO RTC +---------- The VirtIO RTC device (``-device virtio-rtc-pci`` or ``-device virtio-rtc-device``) requires QEMU v11.1.0+. +The ``date`` command only uses RTC sequence 0. The QEMU ARM, RISC-V and x86 +machines also have a PL031, Goldfish or MC146818 RTC, which gets sequence 0, +so ``date`` reads the VirtIO RTC only if ``CONFIG_RTC_PL031``, +``CONFIG_RTC_GOLDFISH`` or ``CONFIG_RTC_MC146818`` is disabled. +``dm uclass rtc`` shows the sequence numbers. ``rtc dev`` does not help, as +``rtc read`` reads raw registers, which the VirtIO RTC does not have. + Testing ------- The following QEMU command line is used to get U-Boot up and running with
Signature · 1 line
2.43.0
Am 9. November 2026 00:34:00 MEZ schrieb Hung-Chun Tseng <[email protected]>:
Quoted 16 lines
QEMU v11.1.0 added a virtio RTC device (virtio-rtc-pci and virtio-rtc-device), but U-Boot has no driver for it. This series adds one, so U-Boot can read the time from it through the RTC uclass.
Patch 1 adds the driver, patch 2 updates the virtio documentation and patch 3 adds a
MAINTAINERSentry. Patch 4 lets sandbox tests answer virtqueue requests as the device would, which patch 5 uses to test the driver. Patch 6 documents how to reach the virtio RTC.Changes in v7:
- Patch 6: drop the claim that QEMU x86 does not enableDM_RTC. X86 impliesDM_RTC, so the driver is already built there (Simon).
- Cover letter: no longer claim that "date" reads the virtio RTC on any QEMU target, which patch 6 explains is not the case (Simon, v5).
- Rebase onto main. Patches 1-5 are unchanged.
Quoted 3 lines
Tested with qemu-riscv64_smode_defconfig and
RTC_GOLDFISHdisabled, on QEMU v11.1.2, which reports a UTC clock, and on QEMU master, which reports a smeared UTC clock:
I was not able to set the time with the date command using the prior version (v6). Is this a deficiency of the virtio RTC or of the U-Boot implementation?
Best regards
Heinrich
Quoted 36 lines
- With -device virtio-rtc-pci and with -device virtio-rtc-device, "date" reads the host time and advances between reads.
- Setting the time fails, as the clocks are read-only.
- With no virtio RTC device, "date" fails cleanly with err=-19.With qemu-x86_64_defconfig on QEMU v11.1.2, "dm uclass rtc" shows the CMOS RTC at sequence 0 and the virtio RTC at 1; with
RTC_MC146818disabled, the virtio RTC is sequence 0 and "date" reads it.On sandbox, "ut dm virtio_rtc*" passes.
Hung-Chun Tseng (6):
virtio: rtc: Add virtio RTC driver
doc: virtio: List the supported device types
MAINTAINERS: Add entry for virtio RTC
virtio: sandbox: Let tests emulate the device side of a virtqueue
test: dm: Add tests for the virtio RTC driver
doc: virtio: Explain how to reach the virtio RTCMAINTAINERS | 6 + arch/sandbox/dts/test.dts | 5 + arch/sandbox/include/asm/test.h | 25 +++ doc/develop/driver-model/virtio.rst | 25 ++- drivers/virtio/Kconfig | 11 + drivers/virtio/Makefile | 1 + drivers/virtio/virtio-uclass.c | 1 + drivers/virtio/virtio_rtc.c | 244 ++++++++++++++++++++++ drivers/virtio/virtio_sandbox.c | 15 ++ include/virtio.h | 4 +- test/dm/Makefile | 1 + test/dm/virtio_rtc.c | 306 ++++++++++++++++++++++++++++ 12 files changed, 639 insertions(+), 5 deletions(-)create mode 100644
drivers/virtio/virtio_rtc.c
create mode 100644test/dm/virtio_rtc.c
Hi Heinrich,
Quoted 3 lines · Heinrich Schuchardt
I was not able to set the time with the date command using the prior version (v6). Is this a deficiency of the virtio RTC or of the U-Boot implementation?
It is the device. The virtio RTC spec has no request to set a clock:
besides reading the time and the clock capabilities, the only requests are for alarms (VIRTIO_RTC_F_ALARM). The clocks follow the host clock and are read-only to the guest, so the driver only implements .get and "date reset" / "date YYMMDD..." fail with -ENOSYS.
Best regards,
Hung-Chun