Skip to content

Commit 3850835

Browse files
committed
vmbfs: Implement SaveRestore (#4072)
The hope is this will fix some UEFI flakiness, as our UEFI is not tolerant of vmbfs getting revoked and reoffered, which is the fallback behavior for vmbus devices that don't implement SaveRestore. (cherry picked from commit 59dd998)
1 parent 14ad42d commit 3850835

3 files changed

Lines changed: 65 additions & 7 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9932,6 +9932,7 @@ dependencies = [
99329932
"guestmem",
99339933
"guid",
99349934
"inspect",
9935+
"mesh",
99359936
"open_enum",
99369937
"task_control",
99379938
"thiserror 2.0.16",

vm/devices/vmbus/vmbfs/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ vmcore.workspace = true
1717

1818
guid.workspace = true
1919
inspect = { workspace = true, features = ["filepath"] }
20+
mesh.workspace = true
2021
open_enum.workspace = true
2122
task_control.workspace = true
2223

vm/devices/vmbus/vmbfs/src/lib.rs

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ use thiserror::Error;
3030
use vmbus_async::async_dgram::AsyncRecvExt;
3131
use vmbus_channel::bus::OfferParams;
3232
use vmbus_channel::gpadl_ring::GpadlRingMem;
33+
use vmbus_channel::simple::SaveRestoreSimpleVmbusDevice;
3334
use vmbus_channel::simple::SimpleVmbusDevice;
34-
use vmcore::save_restore::SavedStateNotSupported;
3535
use zerocopy::FromBytes;
3636
use zerocopy::IntoBytes;
3737

@@ -51,7 +51,7 @@ impl VmbfsDevice {
5151

5252
#[async_trait]
5353
impl SimpleVmbusDevice for VmbfsDevice {
54-
type SavedState = SavedStateNotSupported;
54+
type SavedState = save_restore::state::SavedState;
5555
type Runner = VmbfsChannel;
5656

5757
fn offer(&self) -> OfferParams {
@@ -93,12 +93,9 @@ impl SimpleVmbusDevice for VmbfsDevice {
9393
fn supports_save_restore(
9494
&mut self,
9595
) -> Option<
96-
&mut dyn vmbus_channel::simple::SaveRestoreSimpleVmbusDevice<
97-
SavedState = Self::SavedState,
98-
Runner = Self::Runner,
99-
>,
96+
&mut dyn SaveRestoreSimpleVmbusDevice<SavedState = Self::SavedState, Runner = Self::Runner>,
10097
> {
101-
None
98+
Some(self)
10299
}
103100
}
104101

@@ -108,6 +105,8 @@ pub struct VmbfsChannel {
108105
state: State,
109106
#[inspect(mut)]
110107
pipe: vmbus_async::pipe::MessagePipe<GpadlRingMem>,
108+
// A scratch buffer for reading messages. This is allocated once and reused for each message.
109+
// It does not hold any meaningful state.
111110
buf: Vec<u8>,
112111
}
113112

@@ -327,3 +326,60 @@ enum DeviceError {
327326
#[error("read too large")]
328327
ReadTooLarge,
329328
}
329+
330+
mod save_restore {
331+
use super::*;
332+
333+
pub mod state {
334+
use mesh::payload::Protobuf;
335+
use vmcore::save_restore::SavedStateRoot;
336+
337+
#[derive(Copy, Clone, Protobuf)]
338+
#[mesh(package = "vmbfs")]
339+
pub enum State {
340+
#[mesh(1)]
341+
VersionRequest,
342+
#[mesh(2)]
343+
Ready,
344+
}
345+
346+
#[derive(Protobuf, SavedStateRoot)]
347+
#[mesh(package = "vmbfs")]
348+
pub struct SavedState {
349+
#[mesh(1)]
350+
pub state: State,
351+
}
352+
}
353+
354+
impl SaveRestoreSimpleVmbusDevice for VmbfsDevice {
355+
fn save_open(&mut self, runner: &Self::Runner) -> state::SavedState {
356+
let Self::Runner {
357+
state,
358+
pipe: _,
359+
buf: _,
360+
} = runner;
361+
state::SavedState {
362+
state: match state {
363+
State::VersionRequest => state::State::VersionRequest,
364+
State::Ready => state::State::Ready,
365+
},
366+
}
367+
}
368+
369+
fn restore_open(
370+
&mut self,
371+
saved_state: Self::SavedState,
372+
channel: vmbus_channel::RawAsyncChannel<GpadlRingMem>,
373+
) -> Result<Self::Runner, vmbus_channel::channel::ChannelOpenError> {
374+
let Self::SavedState { state } = saved_state;
375+
Ok(VmbfsChannel {
376+
state: match state {
377+
state::State::VersionRequest => State::VersionRequest,
378+
state::State::Ready => State::Ready,
379+
},
380+
pipe: vmbus_async::pipe::MessagePipe::new(channel)?,
381+
buf: vec![0; protocol::MAX_MESSAGE_SIZE],
382+
})
383+
}
384+
}
385+
}

0 commit comments

Comments
 (0)