drivers/char/hw_random/virtio-rng.c
Source file repositories/reference/linux-study-clean/drivers/char/hw_random/virtio-rng.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/char/hw_random/virtio-rng.c- Extension
.c- Size
- 6227 bytes
- Lines
- 282
- Domain
- Driver Families
- Bucket
- drivers/char
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
asm/barrier.hlinux/err.hlinux/hw_random.hlinux/nospec.hlinux/scatterlist.hlinux/spinlock.hlinux/virtio.hlinux/virtio_rng.hlinux/dma-mapping.hlinux/module.hlinux/slab.h
Detected Declarations
struct virtrng_infofunction random_recv_donefunction request_entropyfunction copy_datafunction virtio_readfunction virtio_cleanupfunction probe_commonfunction remove_commonfunction virtrng_probefunction virtrng_removefunction virtrng_scanfunction virtrng_freezefunction virtrng_restore
Annotated Snippet
struct virtrng_info {
struct hwrng hwrng;
struct virtqueue *vq;
char name[25];
int index;
bool hwrng_register_done;
bool hwrng_removed;
/* data transfer */
struct completion have_data;
unsigned int data_avail;
unsigned int data_idx;
/* minimal size returned by rng_buffer_size() */
__dma_from_device_group_begin();
#if SMP_CACHE_BYTES < 32
u8 data[32];
#else
u8 data[SMP_CACHE_BYTES];
#endif
__dma_from_device_group_end();
};
static void random_recv_done(struct virtqueue *vq)
{
struct virtrng_info *vi = vq->vdev->priv;
unsigned int len;
/* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */
if (!virtqueue_get_buf(vi->vq, &len))
return;
smp_store_release(&vi->data_avail, len);
complete(&vi->have_data);
}
static void request_entropy(struct virtrng_info *vi)
{
struct scatterlist sg;
reinit_completion(&vi->have_data);
vi->data_idx = 0;
sg_init_one(&sg, vi->data, sizeof(vi->data));
/* There should always be room for one buffer. */
virtqueue_add_inbuf(vi->vq, &sg, 1, vi->data, GFP_KERNEL);
virtqueue_kick(vi->vq);
}
static unsigned int copy_data(struct virtrng_info *vi, void *buf,
unsigned int size)
{
unsigned int idx, avail;
/*
* vi->data_avail was set from the device-reported used.len and
* vi->data_idx was advanced by previous copy_data() calls. A
* malicious or buggy virtio-rng backend can drive either past
* sizeof(vi->data). Clamp at point of use and harden the index
* with array_index_nospec() so the memcpy() below cannot be
* steered into adjacent slab memory, including under
* speculation.
*/
avail = min_t(unsigned int, vi->data_avail, sizeof(vi->data));
if (vi->data_idx >= avail) {
vi->data_avail = 0;
request_entropy(vi);
return 0;
}
size = min_t(unsigned int, size, avail - vi->data_idx);
idx = array_index_nospec(vi->data_idx, sizeof(vi->data));
memcpy(buf, vi->data + idx, size);
vi->data_idx += size;
vi->data_avail -= size;
if (vi->data_avail == 0)
request_entropy(vi);
return size;
}
static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
{
int ret;
struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
unsigned int chunk;
size_t read;
if (vi->hwrng_removed)
return -ENODEV;
read = 0;
Annotation
- Immediate include surface: `asm/barrier.h`, `linux/err.h`, `linux/hw_random.h`, `linux/nospec.h`, `linux/scatterlist.h`, `linux/spinlock.h`, `linux/virtio.h`, `linux/virtio_rng.h`.
- Detected declarations: `struct virtrng_info`, `function random_recv_done`, `function request_entropy`, `function copy_data`, `function virtio_read`, `function virtio_cleanup`, `function probe_common`, `function remove_common`, `function virtrng_probe`, `function virtrng_remove`.
- Atlas domain: Driver Families / drivers/char.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.