underhill_core/emuplat/
watchdog.rs1use cvm_tracing::CVM_ALLOWED;
5use vmcore::non_volatile_store::NonVolatileStore;
6use watchdog_core::platform::WatchdogPlatform;
7use watchdog_vmgs_format::WatchdogVmgsFormatStore;
8use watchdog_vmgs_format::WatchdogVmgsFormatStoreError;
9
10pub struct UnderhillWatchdog {
13 store: WatchdogVmgsFormatStore,
14 get: guest_emulation_transport::GuestEmulationTransportClient,
15 hook: Box<dyn WatchdogTimeout>,
16}
17
18#[async_trait::async_trait]
19pub trait WatchdogTimeout: Send + Sync {
20 async fn on_timeout(&self);
21}
22
23impl UnderhillWatchdog {
24 pub async fn new(
25 store: Box<dyn NonVolatileStore>,
26 get: guest_emulation_transport::GuestEmulationTransportClient,
27 hook: Box<dyn WatchdogTimeout>,
28 ) -> Result<Self, WatchdogVmgsFormatStoreError> {
29 Ok(UnderhillWatchdog {
30 store: WatchdogVmgsFormatStore::new(store).await?,
31 get,
32 hook,
33 })
34 }
35}
36
37#[async_trait::async_trait]
38impl WatchdogPlatform for UnderhillWatchdog {
39 async fn on_timeout(&mut self) {
40 let res = self.store.set_boot_failure().await;
41 if let Err(e) = res {
42 tracing::error!(
43 CVM_ALLOWED,
44 error = &e as &dyn std::error::Error,
45 "error persisting watchdog status"
46 );
47 }
48
49 self.hook.on_timeout().await;
52
53 self.get
56 .event_log_fatal(get_protocol::EventLogId::WATCHDOG_TIMEOUT_RESET)
57 .await;
58 }
59
60 async fn read_and_clear_boot_status(&mut self) -> bool {
61 let res = self.store.read_and_clear_boot_status().await;
62 match res {
63 Ok(status) => status,
64 Err(e) => {
65 tracing::error!(
66 CVM_ALLOWED,
67 error = &e as &dyn std::error::Error,
68 "error reading watchdog status"
69 );
70 false
72 }
73 }
74 }
75}