virtio/devices/
virtio_rng.rs1use core::cell::Cell;
6
7use kernel::deferred_call::{DeferredCall, DeferredCallClient};
8use kernel::hil::rng::{Client as RngClient, Continue as RngCont, Rng};
9use kernel::utilities::cells::OptionalCell;
10use kernel::ErrorCode;
11
12use super::super::devices::{VirtIODeviceDriver, VirtIODeviceType};
13use super::super::queues::split_queue::{SplitVirtqueue, SplitVirtqueueClient, VirtqueueBuffer};
14
15pub struct VirtIORng<'a, 'b> {
16 virtqueue: &'a SplitVirtqueue<'a, 'b, 1>,
17 buffer_capacity: Cell<usize>,
18 callback_pending: Cell<bool>,
19 deferred_call: DeferredCall,
20 client: OptionalCell<&'a dyn RngClient>,
21}
22
23impl<'a, 'b> VirtIORng<'a, 'b> {
24 pub fn new(virtqueue: &'a SplitVirtqueue<'a, 'b, 1>) -> VirtIORng<'a, 'b> {
25 VirtIORng {
26 virtqueue,
27 buffer_capacity: Cell::new(0),
28 callback_pending: Cell::new(false),
29 deferred_call: DeferredCall::new(),
30 client: OptionalCell::empty(),
31 }
32 }
33
34 pub fn provide_buffer(&self, buf: &'b mut [u8]) -> Result<usize, (&'b mut [u8], ErrorCode)> {
35 let len = buf.len();
36 if len < 4 {
37 return Err((buf, ErrorCode::INVAL));
43 }
44
45 let mut buffer_chain = [Some(VirtqueueBuffer {
46 buf,
47 len,
48 device_writeable: true,
49 })];
50
51 let res = self.virtqueue.provide_buffer_chain(&mut buffer_chain);
52
53 match res {
54 Err(ErrorCode::NOMEM) => {
55 let buf = buffer_chain[0].take().unwrap().buf;
58 Err((buf, ErrorCode::NOMEM))
59 }
60 Err(e) => panic!("Unexpected error {:?}", e),
61 Ok(()) => {
62 let mut cap = self.buffer_capacity.get();
63 cap += len;
64 self.buffer_capacity.set(cap);
65 Ok(cap)
66 }
67 }
68 }
69
70 fn buffer_chain_callback(
71 &self,
72 buffer_chain: &mut [Option<VirtqueueBuffer<'b>>],
73 bytes_used: usize,
74 ) {
75 self.virtqueue.disable_used_callbacks();
80
81 let buf = buffer_chain[0].take().unwrap().buf;
83
84 assert!(self.buffer_capacity.get() >= buf.len());
86
87 let cont = if self.callback_pending.get() {
90 self.callback_pending.set(false);
92
93 let mut u32randiter = buf[0..bytes_used].chunks(4).filter_map(|slice| {
94 if slice.len() < 4 {
95 None
96 } else {
97 Some(u32::from_le_bytes([slice[0], slice[1], slice[2], slice[3]]))
98 }
99 });
100
101 self.client
104 .map(|client| client.randomness_available(&mut u32randiter, Ok(())))
105 .unwrap_or(RngCont::Done)
106 } else {
107 RngCont::Done
108 };
109
110 if let RngCont::More = cont {
111 let _ = self.get();
116 }
117
118 self.provide_buffer(buf).expect("Buffer reinsertion failed");
120 }
121}
122
123impl<'a> Rng<'a> for VirtIORng<'a, '_> {
124 fn get(&self) -> Result<(), ErrorCode> {
125 if self.buffer_capacity.get() < 4 {
128 Err(ErrorCode::FAIL)
129 } else if self.client.is_none() {
130 Err(ErrorCode::FAIL)
131 } else if self.callback_pending.get() {
132 Err(ErrorCode::OFF)
133 } else if self.virtqueue.used_descriptor_chains_count() < 1 {
134 self.callback_pending.set(true);
138 self.virtqueue.enable_used_callbacks();
139 Ok(())
140 } else {
141 self.callback_pending.set(true);
144 self.deferred_call.set();
145 Ok(())
146 }
147 }
148
149 fn cancel(&self) -> Result<(), ErrorCode> {
150 self.callback_pending.set(false);
153
154 self.virtqueue.disable_used_callbacks();
158
159 Ok(())
160 }
161
162 fn set_client(&self, client: &'a dyn RngClient) {
163 self.client.set(client);
164 }
165}
166
167impl<'b> SplitVirtqueueClient<'b> for VirtIORng<'_, 'b> {
168 fn buffer_chain_ready(
169 &self,
170 _queue_number: u32,
171 buffer_chain: &mut [Option<VirtqueueBuffer<'b>>],
172 bytes_used: usize,
173 ) {
174 self.buffer_chain_callback(buffer_chain, bytes_used)
175 }
176}
177
178impl DeferredCallClient for VirtIORng<'_, '_> {
179 fn register(&'static self) {
180 self.deferred_call.register(self);
181 }
182
183 fn handle_deferred_call(&self) {
184 if let Some((mut chain, bytes_used)) = self.virtqueue.pop_used_buffer_chain() {
186 self.buffer_chain_callback(&mut chain, bytes_used)
187 } else {
188 panic!("VirtIO RNG: deferred call callback with empty queue");
195 }
196 }
197}
198
199impl VirtIODeviceDriver for VirtIORng<'_, '_> {
200 fn negotiate_features(&self, _offered_features: u64) -> Option<u64> {
201 Some(0)
204 }
205
206 fn device_type(&self) -> VirtIODeviceType {
207 VirtIODeviceType::EntropySource
208 }
209}