From 52c6b05e8e22ba4ac06d192050df61c06b6afc7b Mon Sep 17 00:00:00 2001 From: Kuan-Wei Chiu Date: Sat, 25 Apr 2026 18:52:14 +0000 Subject: [PATCH 1/4] [dev][virtio-rng] Introduce virtio-rng driver Introduces a new virtio-rng driver to fetch entropy from the host in virtualized environments. Additionally, an early boot hook (LK_INIT_LEVEL_TARGET + 1) is added to automatically seed the system's PRNG via srand() when the device is initialized. Signed-off-by: Kuan-Wei Chiu --- dev/virtio/rng/include/dev/virtio/rng.h | 15 ++++ dev/virtio/rng/rules.mk | 8 ++ dev/virtio/rng/virtio-rng.cpp | 114 ++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 dev/virtio/rng/include/dev/virtio/rng.h create mode 100644 dev/virtio/rng/rules.mk create mode 100644 dev/virtio/rng/virtio-rng.cpp diff --git a/dev/virtio/rng/include/dev/virtio/rng.h b/dev/virtio/rng/include/dev/virtio/rng.h new file mode 100644 index 000000000..3a0dff604 --- /dev/null +++ b/dev/virtio/rng/include/dev/virtio/rng.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2026 Kuan-Wei Chiu + * + * Use of this source code is governed by a MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT + */ +#pragma once + +#include + +struct virtio_device; + +status_t virtio_rng_init(virtio_device *dev); +ssize_t virtio_rng_read(void *buf, size_t len); diff --git a/dev/virtio/rng/rules.mk b/dev/virtio/rng/rules.mk new file mode 100644 index 000000000..e9a801802 --- /dev/null +++ b/dev/virtio/rng/rules.mk @@ -0,0 +1,8 @@ +LOCAL_DIR := $(GET_LOCAL_DIR) + +MODULE := $(LOCAL_DIR) + +MODULE_SRCS += \ + $(LOCAL_DIR)/virtio-rng.cpp + +include make/module.mk diff --git a/dev/virtio/rng/virtio-rng.cpp b/dev/virtio/rng/virtio-rng.cpp new file mode 100644 index 000000000..a69025dd2 --- /dev/null +++ b/dev/virtio/rng/virtio-rng.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2026 Kuan-Wei Chiu + * + * Use of this source code is governed by a MIT-style + * license that can be found in the LICENSE file or at + * https://opensource.org/licenses/MIT + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOCAL_TRACE 0 + +constexpr uint16_t RNG_QUEUE_INDEX = 0; + +struct virtio_rng_state { + virtio_device *dev; + bool initialized; + volatile size_t last_rx_len; +}; + +static virtio_rng_state rng; + +static enum handler_return virtio_rng_irq(virtio_device *dev, uint ring_index, const vring_used_elem *e) { + if (ring_index == RNG_QUEUE_INDEX && e) + rng.last_rx_len = e->len; + + return INT_NO_RESCHEDULE; +} + +status_t virtio_rng_init(virtio_device *dev) { + LTRACE_ENTRY; + + rng.dev = dev; + rng.initialized = false; + rng.last_rx_len = 0; + + dev->set_irq_callbacks(virtio_rng_irq, nullptr); + + status_t err = dev->virtio_alloc_ring(RNG_QUEUE_INDEX, 32); + if (err != NO_ERROR) { + TRACEF("virtio-rng: Failed to allocate virtqueue\n"); + return err; + } + + dev->bus()->virtio_status_driver_ok(); + rng.initialized = true; + + LTRACEF("virtio-rng: initialized successfully\n"); + return NO_ERROR; +} + +ssize_t virtio_rng_read(void *buf, size_t len) { + if (!rng.initialized || len == 0) return ERR_NOT_CONFIGURED; + + vaddr_t v_start = (vaddr_t)buf; + vaddr_t v_end = v_start + len - 1; + if ((v_start / PAGE_SIZE) != (v_end / PAGE_SIZE)) + return ERR_INVALID_ARGS; + + paddr_t paddr = vaddr_to_paddr(buf); + if (!paddr) return ERR_INVALID_ARGS; + + uint16_t desc_idx = rng.dev->virtio_alloc_desc(RNG_QUEUE_INDEX); + if (desc_idx == 0xffff) return ERR_NO_MEMORY; + + vring_desc *desc = rng.dev->virtio_desc_index_to_desc(RNG_QUEUE_INDEX, desc_idx); + desc->addr = paddr; + desc->len = (uint32_t)len; + desc->flags = VRING_DESC_F_WRITE; + + rng.last_rx_len = 0; + rng.dev->virtio_submit_chain(RNG_QUEUE_INDEX, desc_idx); + rng.dev->bus()->virtio_kick(RNG_QUEUE_INDEX); + + while (rng.last_rx_len == 0) { + rng.dev->handle_queue_interrupt(); + thread_yield(); + } + + size_t rx_len = rng.last_rx_len; + rng.last_rx_len = 0; + + rng.dev->virtio_free_desc(RNG_QUEUE_INDEX, desc_idx); + return rx_len; +} + +static void seed_system_prng(uint level) { + unsigned int seed = 0; + ssize_t bytes_read; + + if (!rng.initialized) + return; + + bytes_read = virtio_rng_read(&seed, sizeof(seed)); + + if (bytes_read == sizeof(seed)) { + srand(seed); + dprintf(INFO, "virtio-rng: System PRNG seeded with hardware entropy\n"); + } else { + dprintf(INFO, "virtio-rng: Failed to seed system PRNG\n"); + } +} + +LK_INIT_HOOK(virtio_rng_seed, seed_system_prng, LK_INIT_LEVEL_TARGET + 1); From 194815abdcdb6191938d393c1d4659b20916ed2c Mon Sep 17 00:00:00 2001 From: Kuan-Wei Chiu Date: Sat, 25 Apr 2026 18:53:19 +0000 Subject: [PATCH 2/4] [dev][virtio-pci] Wire up virtio-rng to PCI bus Add initialization dispatch for the virtio-rng device. This registers the transitional (0x1005) and non-transitional (0x1044) virtio-rng device IDs to the virtio PCI bus driver, allowing the bus to probe and initialize the device when discovered. Signed-off-by: Kuan-Wei Chiu --- dev/virtio/virtio-pci-bus.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/dev/virtio/virtio-pci-bus.cpp b/dev/virtio/virtio-pci-bus.cpp index e0153ae3e..5ca9a7fa2 100644 --- a/dev/virtio/virtio-pci-bus.cpp +++ b/dev/virtio/virtio-pci-bus.cpp @@ -32,6 +32,9 @@ #if WITH_DEV_VIRTIO_GPU #include #endif +#if WITH_DEV_VIRTIO_RNG +#include +#endif #define LOCAL_TRACE 0 @@ -465,6 +468,32 @@ static status_t init_gpu(pci_location_t loc, const virtio_pci_devices &dev_table #endif } +static status_t init_rng(pci_location_t loc, const virtio_pci_devices &dev_table_entry, size_t index) { + LTRACE_ENTRY; + +#if WITH_DEV_VIRTIO_RNG + auto *bus = new virtio_pci_bus(); + auto *dev = new virtio_device(bus); + + auto err = bus->init(dev, loc, index); + if (err != NO_ERROR) { + delete bus; + return err; + } + + dev->set_config_ptr(bus->device_config()); + + err = virtio_rng_init(dev); + if (err != NO_ERROR) { + PANIC_UNIMPLEMENTED; + } + + return err; +#else + return ERR_NOT_FOUND; +#endif +} + int virtio_pci_init() { LTRACE_ENTRY; @@ -472,10 +501,12 @@ int virtio_pci_init() { constexpr virtio_pci_devices devices[] = { { 0x1000, true, &init_net }, // transitional network { 0x1001, true, &init_block }, // transitional block + { 0x1005, true, &init_rng }, // transitional rng { 0x1009, true, nullptr }, // legacy virtio 9p { 0x1041, false, &init_net }, // non-transitional network { 0x1042, false, &init_block }, // non-transitional block { 0x1043, false, nullptr }, // non-transitional console + { 0x1044, false, &init_rng }, // non-transitional rng { 0x1050, false, &init_gpu }, // non-transitional gpu { 0x1052, false, nullptr }, // non-transitional input }; From 4cc6201ae69521278c2c6ce28159940e9100e9b7 Mon Sep 17 00:00:00 2001 From: Kuan-Wei Chiu Date: Wed, 29 Apr 2026 18:01:03 +0000 Subject: [PATCH 3/4] [dev][virtio-mmio] Wire up virtio-rng to MMIO Add initialization dispatch for the virtio-rng device on the MMIO. This registers the virtio-rng subsystem device ID (4) to the virtio MMIO driver, allowing platforms that default to MMIO to probe and initialize the hardware entropy source. Signed-off-by: Kuan-Wei Chiu --- dev/virtio/virtio-mmio-bus.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/dev/virtio/virtio-mmio-bus.cpp b/dev/virtio/virtio-mmio-bus.cpp index 3b3776ea8..7ae8bae05 100644 --- a/dev/virtio/virtio-mmio-bus.cpp +++ b/dev/virtio/virtio-mmio-bus.cpp @@ -34,6 +34,9 @@ #if WITH_DEV_VIRTIO_9P #include #endif +#if WITH_DEV_VIRTIO_RNG +#include +#endif #define LOCAL_TRACE 0 @@ -237,6 +240,16 @@ int virtio_mmio_detect(void *ptr, uint count, const uint irqs[], size_t stride) } } #endif // WITH_DEV_VIRTIO_NET +#if WITH_DEV_VIRTIO_RNG + if (mmio->device_id == 4) { // virtio-rng + LTRACEF("found rng device\n"); + + status_t err = virtio_rng_init(dev); + if (err >= 0) { + found++; + } + } +#endif // WITH_DEV_VIRTIO_RNG #if WITH_DEV_VIRTIO_9P if (mmio->device_id == 9) { // 9p device LTRACEF("found 9p device\n"); From 96b5782c71a6f7bc7fda7ba06ae2dd6f041da18a Mon Sep 17 00:00:00 2001 From: Kuan-Wei Chiu Date: Sat, 25 Apr 2026 18:54:15 +0000 Subject: [PATCH 4/4] [platform][qemu-arm] Enable virtio-rng module Add dev/virtio/rng to the module dependencies for the qemu-virt-arm platform. This allows the system to automatically fetch hardware entropy and seed the PRNG during the early boot process. Signed-off-by: Kuan-Wei Chiu --- platform/qemu-virt-arm/rules.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/qemu-virt-arm/rules.mk b/platform/qemu-virt-arm/rules.mk index 99da19dd2..feb01040b 100644 --- a/platform/qemu-virt-arm/rules.mk +++ b/platform/qemu-virt-arm/rules.mk @@ -34,6 +34,7 @@ MODULE_DEPS += \ dev/virtio/block \ dev/virtio/gpu \ dev/virtio/net \ + dev/virtio/rng \ lib/cbuf \ lib/fdtwalk \ lib/fs/9p \