Alioth Code Coverage

entropy.rs85.06%

1// Copyright 2024 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::fmt::Debug;
16use std::fs::{File, OpenOptions};
17use std::os::unix::prelude::OpenOptionsExt;
18use std::path::Path;
19use std::sync::Arc;
20use std::sync::mpsc::Receiver;
21use std::thread::JoinHandle;
22
23use libc::O_NONBLOCK;
24use mio::Registry;
25use mio::event::Event;
26use serde::Deserialize;
27use serde_aco::Help;
28use snafu::ResultExt;
29
30use crate::hv::IoeventFd;
31use crate::mem::emulated::{Action, Mmio};
32use crate::mem::mapped::RamBus;
33use crate::sync::notifier::Notifier;
34use crate::virtio::dev::{DevParam, DeviceId, Virtio, WakeEvent};
35use crate::virtio::queue::{QueueReg, VirtQueue, copy_from_reader};
36use crate::virtio::worker::mio::{ActiveMio, Mio, VirtioMio};
37use crate::virtio::{FEATURE_BUILT_IN, IrqSender, Result, error};
38use crate::{bitflags, mem};
39
40#[derive(Debug, Clone)]
41pub struct EntropyConfig;
42
43impl Mmio for EntropyConfig {
44 fn size(&self) -> u64 {3x
45 03x
46 }3x
47
48 fn read(&self, _offset: u64, _size: u8) -> mem::Result<u64> {3x
49 Ok(0)3x
50 }3x
51
52 fn write(&self, _offset: u64, _size: u8, _val: u64) -> mem::Result<Action> {3x
53 Ok(Action::None)3x
54 }3x
55}
56
57bitflags! {
58 pub struct EntropyFeature(u128) { }
59}
60
61#[derive(Debug)]
62pub struct Entropy {
63 name: Arc<str>,
64 source: File,
65 config: Arc<EntropyConfig>,
66}
67
68impl Entropy {
69 pub fn new(param: EntropyParam, name: impl Into<Arc<str>>) -> Result<Self> {3x
70 let name = name.into();3x
71 let mut options = OpenOptions::new();3x
72 options.custom_flags(O_NONBLOCK).read(true);3x
73 let path = param.source.as_deref().unwrap_or(Path::new("/dev/urandom"));3x
74 let file = options.open(path).context(error::AccessFile { path })?;3x
75 Ok(Entropy {3x
76 name,3x
77 source: file,3x
78 config: Arc::new(EntropyConfig),3x
79 })3x
80 }3x
81}
82
83impl Virtio for Entropy {
84 type Config = EntropyConfig;
85 type Feature = EntropyFeature;
86
87 fn id(&self) -> DeviceId {3x
88 DeviceId::ENTROPY3x
89 }3x
90
91 fn name(&self) -> &str {12x
92 &self.name12x
93 }12x
94
95 fn spawn_worker<S, E>(3x
96 self,3x
97 event_rx: Receiver<WakeEvent<S, E>>,3x
98 memory: Arc<RamBus>,3x
99 queue_regs: Arc<[QueueReg]>,3x
100 ) -> Result<(JoinHandle<()>, Arc<Notifier>)>3x
101 where3x
102 S: IrqSender,3x
103 E: IoeventFd,3x
104 {
105 Mio::spawn_worker(self, event_rx, memory, queue_regs)3x
106 }3x
107
108 fn num_queues(&self) -> u16 {3x
109 13x
110 }3x
111
112 fn config(&self) -> Arc<EntropyConfig> {3x
113 self.config.clone()3x
114 }3x
115
116 fn feature(&self) -> u128 {3x
117 FEATURE_BUILT_IN3x
118 }3x
119}
120
121impl VirtioMio for Entropy {
122 fn activate<'m, Q, S, E>(3x
123 &mut self,3x
124 _feature: u128,3x
125 _active_mio: &mut ActiveMio<'_, '_, 'm, Q, S, E>,3x
126 ) -> Result<()>3x
127 where3x
128 Q: VirtQueue<'m>,3x
129 S: IrqSender,3x
130 E: IoeventFd,3x
131 {
132 Ok(())3x
133 }3x
134
135 fn handle_queue<'m, Q, S, E>(9x
136 &mut self,9x
137 index: u16,9x
138 active_mio: &mut ActiveMio<'_, '_, 'm, Q, S, E>,9x
139 ) -> Result<()>9x
140 where9x
141 Q: VirtQueue<'m>,9x
142 S: IrqSender,9x
143 E: IoeventFd,9x
144 {
145 let Some(Some(queue)) = active_mio.queues.get_mut(index as usize) else {9x
146 log::error!("{}: invalid queue index {index}", self.name);
147 return Ok(());
148 };
149 queue.handle_desc(index, active_mio.irq_sender, copy_from_reader(&self.source))9x
150 }9x
151
152 fn handle_event<'a, 'm, Q, S, E>(
153 &mut self,
154 _event: &Event,
155 _active_mio: &mut ActiveMio<'_, '_, 'm, Q, S, E>,
156 ) -> Result<()>
157 where
158 Q: VirtQueue<'m>,
159 S: IrqSender,
160 E: IoeventFd,
161 {
162 Ok(())
163 }
164
165 fn reset(&mut self, _registry: &Registry) {}3x
166}
167
168#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Help)]
169pub struct EntropyParam {
170 /// Source of entropy [default: /dev/urandom]
171 pub source: Option<Box<Path>>,
172}
173
174impl DevParam for EntropyParam {
175 type Device = Entropy;
176
177 fn build(self, name: impl Into<Arc<str>>) -> Result<Self::Device> {3x
178 Entropy::new(self, name)3x
179 }3x
180}
181
182#[cfg(test)]
183#[path = "entropy_test.rs"]
184mod tests;
185