Skip to contentSkip to conversation

virtio: Add a virtio RTC driver

PATCH In review Hung-Chun Tseng 2 participants 9 messages Nov 8 – Nov 9 virtio core

lore
Share & tools
lore
#0 lore raw

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
#1 lore raw

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
index 55b444280..48ab669f3 100644
@@ -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
index 6e7bcfc8e..ddb5ce4eb 100644
@@ -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
index 978ef0d1c..75c234a89 100644
@@ -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
index 30e5005e9..fb8b396d8 100644
@@ -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
#2 lore raw

PATCH v7 2/6 doc: virtio: List the supported device types

In reply to Hung-Chun Tseng

The 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
index e5da9f430..30df0e944 100644
@@ -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
#3 lore raw

PATCH v7 3/6 MAINTAINERS: Add entry for virtio RTC

In reply to Hung-Chun Tseng

Add myself as the maintainer of the virtio RTC driver.

---
 MAINTAINERS | 5 +++++
 1 file changed, 5 insertions(+)
MAINTAINERS +5 -0
index b6ce499d0..106218f0a 100644
@@ -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
#4 lore raw

PATCH v7 4/6 virtio: sandbox: Let tests emulate the device side of a virtqueue

In reply to Hung-Chun Tseng

The 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
index 043879002..d95de1095 100644
@@ -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
index 0f1ebef22..3b8a4d5a6 100644
@@ -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
#5 lore raw

PATCH v7 5/6 test: dm: Add tests for the virtio RTC driver

In reply to Hung-Chun Tseng

Add 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
index 106218f0a..08172cf7a 100644
@@ -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
index 02a9ca29b..405f6921e 100644
@@ -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
index 1b3a20aa9..d4a112c32 100644
@@ -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
#6 lore raw

PATCH v7 6/6 doc: virtio: Explain how to reach the virtio RTC

In reply to Hung-Chun Tseng

The 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
index 30df0e944..05204b5f4 100644
@@ -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
#7 lore raw
In reply to Hung-Chun Tseng

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 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.

Quoted 3 lines

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:

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_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

#8 lore raw

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