vmm/devices/virtio/rng/
event_handler.rs

1// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use event_manager::{EventOps, Events, MutEventSubscriber};
5use vmm_sys_util::epoll::EventSet;
6
7use super::{Entropy, RNG_QUEUE};
8use crate::devices::virtio::device::VirtioDevice;
9use crate::logger::{error, warn};
10
11impl Entropy {
12    const PROCESS_ACTIVATE: u32 = 0;
13    const PROCESS_ENTROPY_QUEUE: u32 = 1;
14    const PROCESS_RATE_LIMITER: u32 = 2;
15
16    fn register_runtime_events(&self, ops: &mut EventOps) {
17        if let Err(err) = ops.add(Events::with_data(
18            &self.queue_events()[RNG_QUEUE],
19            Self::PROCESS_ENTROPY_QUEUE,
20            EventSet::IN,
21        )) {
22            error!("entropy: Failed to register queue event: {err}");
23        }
24        if let Err(err) = ops.add(Events::with_data(
25            self.rate_limiter(),
26            Self::PROCESS_RATE_LIMITER,
27            EventSet::IN,
28        )) {
29            error!("entropy: Failed to register rate-limiter event: {err}");
30        }
31    }
32
33    fn register_activate_event(&self, ops: &mut EventOps) {
34        if let Err(err) = ops.add(Events::with_data(
35            self.activate_event(),
36            Self::PROCESS_ACTIVATE,
37            EventSet::IN,
38        )) {
39            error!("entropy: Failed to register activate event: {err}");
40        }
41    }
42
43    fn process_activate_event(&self, ops: &mut EventOps) {
44        if let Err(err) = self.activate_event().read() {
45            error!("entropy: Failed to consume activate event: {err}");
46        }
47
48        // Register runtime events
49        self.register_runtime_events(ops);
50
51        // Remove activate event
52        if let Err(err) = ops.remove(Events::with_data(
53            self.activate_event(),
54            Self::PROCESS_ACTIVATE,
55            EventSet::IN,
56        )) {
57            error!("entropy: Failed to un-register activate event: {err}");
58        }
59    }
60}
61
62impl MutEventSubscriber for Entropy {
63    fn init(&mut self, ops: &mut event_manager::EventOps) {
64        // This function can be called during different points in the device lifetime:
65        //  - shortly after device creation,
66        //  - on device activation (is-activated already true at this point),
67        //  - on device restore from snapshot.
68        if self.is_activated() {
69            self.register_runtime_events(ops);
70        } else {
71            self.register_activate_event(ops);
72        }
73    }
74
75    fn process(&mut self, events: event_manager::Events, ops: &mut event_manager::EventOps) {
76        let event_set = events.event_set();
77        let source = events.data();
78
79        if !event_set.contains(EventSet::IN) {
80            warn!("entropy: Received unknown event: {event_set:?} from source {source}");
81            return;
82        }
83
84        if !self.is_activated() {
85            warn!("entropy: The device is not activated yet. Spurious event received: {source}");
86            return;
87        }
88
89        match source {
90            Self::PROCESS_ACTIVATE => self.process_activate_event(ops),
91            Self::PROCESS_ENTROPY_QUEUE => self.process_entropy_queue_event(),
92            Self::PROCESS_RATE_LIMITER => self.process_rate_limiter_event(),
93            _ => {
94                warn!("entropy: Unknown event received: {source}");
95            }
96        }
97    }
98}