hvlite_helpers/
underhill.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Helpers for managing the Underhill firmware.
5
6use anyhow::Context;
7use get_resources::ged::GuestEmulationRequest;
8use get_resources::ged::GuestServicingFlags;
9use hvlite_defs::rpc::VmRpc;
10use mesh::rpc::RpcSend;
11
12/// Replace the running version of Underhill.
13pub async fn service_underhill(
14    vm_send: &mesh::Sender<VmRpc>,
15    send: &mesh::Sender<GuestEmulationRequest>,
16    flags: GuestServicingFlags,
17    file: std::fs::File,
18) -> anyhow::Result<()> {
19    // Stage the IGVM file in the VM worker.
20    tracing::debug!("staging new IGVM file");
21    vm_send
22        .call_failable(VmRpc::StartReloadIgvm, file)
23        .await
24        .context("failed to stage new IGVM file")?;
25
26    // Block waiting for the guest to send saved state.
27    //
28    // TODO: make this event driven instead so that other operations are not
29    // blocked while waiting for the guest.
30    tracing::debug!("waiting for guest to send saved state");
31    let r = send
32        .call_failable(GuestEmulationRequest::SaveGuestVtl2State, flags)
33        .await
34        .context("failed to save VTL2 state");
35
36    if r.is_err() {
37        // Clear the staged IGVM file.
38        tracing::debug!(?r, "save state failed, clearing staged IGVM file");
39        let _ = vm_send.call(VmRpc::CompleteReloadIgvm, false).await;
40        return r;
41    }
42
43    // Reload the IGVM file and reset VTL2 state.
44    tracing::debug!("reloading IGVM file");
45    vm_send
46        .call_failable(VmRpc::CompleteReloadIgvm, true)
47        .await
48        .context("failed to reload VTL2 firmware")?;
49
50    // Wait for VTL0 to start.
51    //
52    // TODO: event driven, cancellable.
53    tracing::debug!("waiting for VTL0 to start");
54    send.call_failable(GuestEmulationRequest::WaitForVtl0Start, ())
55        .await
56        .context("vtl0 start failed")?;
57
58    Ok(())
59}