Skip to main content

vmbus_server/
channels.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4pub mod saved_state;
5#[cfg(test)]
6mod tests;
7
8use crate::Guid;
9use crate::SynicMessage;
10use crate::monitor::AssignedMonitors;
11use crate::protocol::Version;
12use hvdef::Vtl;
13use inspect::Inspect;
14pub use saved_state::RestoreError;
15pub use saved_state::SavedState;
16pub use saved_state::SavedStateData;
17use slab::Slab;
18use std::cmp::min;
19use std::collections::VecDeque;
20use std::collections::hash_map::Entry;
21use std::collections::hash_map::HashMap;
22use std::fmt::Display;
23use std::ops::Index;
24use std::ops::IndexMut;
25use std::task::Poll;
26use std::task::ready;
27use std::time::Duration;
28use thiserror::Error;
29use vmbus_channel::bus::ChannelType;
30use vmbus_channel::bus::GpadlRequest;
31use vmbus_channel::bus::OfferKey;
32use vmbus_channel::bus::OfferParams;
33use vmbus_channel::bus::OpenData;
34use vmbus_channel::bus::RestoredGpadl;
35use vmbus_core::HvsockConnectRequest;
36use vmbus_core::HvsockConnectResult;
37use vmbus_core::MaxVersionInfo;
38use vmbus_core::OutgoingMessage;
39use vmbus_core::VMBUS_SINT;
40use vmbus_core::VersionInfo;
41use vmbus_core::protocol;
42use vmbus_core::protocol::ChannelId;
43use vmbus_core::protocol::ConnectionId;
44use vmbus_core::protocol::FeatureFlags;
45use vmbus_core::protocol::GpadlId;
46use vmbus_core::protocol::Message;
47use vmbus_core::protocol::OfferFlags;
48use vmbus_core::protocol::UserDefinedData;
49use vmbus_ring::gparange;
50use vmcore::monitor::MonitorId;
51use vmcore::synic::MonitorInfo;
52use vmcore::synic::MonitorPageGpas;
53use zerocopy::FromZeros;
54use zerocopy::Immutable;
55use zerocopy::IntoBytes;
56use zerocopy::KnownLayout;
57
58/// An error caused by a channel operation.
59#[derive(Debug, Error)]
60pub enum ChannelError {
61    #[error("unknown channel ID")]
62    UnknownChannelId,
63    #[error("unknown GPADL ID")]
64    UnknownGpadlId,
65    #[error("parse error")]
66    ParseError(#[from] protocol::ParseError),
67    #[error("invalid gpa range")]
68    InvalidGpaRange(#[source] gparange::Error),
69    #[error("duplicate GPADL ID")]
70    DuplicateGpadlId,
71    #[error("GPADL is already complete")]
72    GpadlAlreadyComplete,
73    #[error("GPADL channel ID mismatch")]
74    WrongGpadlChannelId,
75    #[error("trying to open an open channel")]
76    ChannelAlreadyOpen,
77    #[error("trying to close a closed channel")]
78    ChannelNotOpen,
79    #[error("invalid GPADL state for operation")]
80    InvalidGpadlState,
81    #[error("invalid channel state for operation")]
82    InvalidChannelState,
83    #[error("channel ID has already been released")]
84    ChannelReleased,
85    #[error("channel offers have already been sent")]
86    OffersAlreadySent,
87    #[error("invalid operation on reserved channel")]
88    ChannelReserved,
89    #[error("invalid operation on non-reserved channel")]
90    ChannelNotReserved,
91    #[error("received untrusted message for trusted connection")]
92    UntrustedMessage,
93    #[error("received a non-resuming message while paused")]
94    Paused,
95    #[error("invalid target VP")]
96    InvalidTargetVp,
97    #[error("interrupts are disabled for this channel")]
98    InterruptsDisabled,
99}
100
101#[derive(Debug, Error)]
102pub enum OfferError {
103    #[error("the channel ID {} is not valid for this operation", (.0).0)]
104    InvalidChannelId(ChannelId),
105    #[error("the channel ID {} is already in use", (.0).0)]
106    ChannelIdInUse(ChannelId),
107    #[error("offer {0} already exists")]
108    AlreadyExists(OfferKey),
109    #[error("specified resources do not match those of the existing saved or revoked offer")]
110    IncompatibleResources,
111    #[error("too many channels have been offered")]
112    TooManyChannels,
113    #[error("mismatched monitor ID from saved state; expected {0:?}, actual {1:?}")]
114    MismatchedMonitorId(Option<MonitorId>, MonitorId),
115}
116
117/// A unique identifier for an offered channel.
118#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
119pub struct OfferId(usize);
120
121type IncompleteGpadlMap = HashMap<GpadlId, OfferId>;
122
123type GpadlMap = HashMap<(GpadlId, OfferId), Gpadl>;
124
125/// A struct modeling the server side of the VMBus control plane.
126pub struct Server {
127    state: ConnectionState,
128    channels: ChannelList,
129    assigned_channels: AssignedChannels,
130    assigned_monitors: AssignedMonitors,
131    gpadls: GpadlMap,
132    incomplete_gpadls: IncompleteGpadlMap,
133    child_connection_id: u32,
134    /// Limits the protocol version and feature flags that will be accepted for the next connection.
135    max_version: Option<MaxVersionInfo>,
136    /// Version limit that will be applied after the next connection is established. This is used
137    /// for testing scenarios where the first client to connect (usually UEFI) may not be able to
138    /// support the older protocol version being tested.
139    delayed_max_version: Option<MaxVersionInfo>,
140    /// Limits the protocol version and feature flags that will be accepted when restoring from
141    /// saved state.
142    max_restore_version: Option<MaxVersionInfo>,
143    // This must be separate from the connection state because e.g. the UnloadComplete message,
144    // or messages for reserved channels, can be pending even when disconnected.
145    pending_messages: PendingMessages,
146    // If this is set, the server cannot utilize monitor pages provided by the guest. This is
147    // typically the case for OpenHCL in hardware-isolated VMs because the monitor pages must be in
148    // shared memory and we cannot set protections on shared memory.
149    require_server_allocated_mnf: bool,
150    use_absolute_channel_order: bool,
151    support_gpa_pinning: bool,
152}
153
154pub struct ServerWithNotifier<'a, T> {
155    inner: &'a mut Server,
156    notifier: &'a mut T,
157}
158
159impl<T> Drop for ServerWithNotifier<'_, T> {
160    fn drop(&mut self) {
161        self.inner.validate();
162    }
163}
164
165impl<T: Notifier> Inspect for ServerWithNotifier<'_, T> {
166    fn inspect(&self, req: inspect::Request<'_>) {
167        let mut resp = req.respond();
168        let (state, info, next_action) = match &self.inner.state {
169            ConnectionState::Disconnected => ("disconnected", None, None),
170            ConnectionState::Connecting { info, .. } => ("connecting", Some(info), None),
171            ConnectionState::Connected(info) => (
172                if info.offers_sent {
173                    "connected"
174                } else {
175                    "negotiated"
176                },
177                Some(info),
178                None,
179            ),
180            ConnectionState::Disconnecting { next_action, .. } => {
181                ("disconnecting", None, Some(next_action))
182            }
183        };
184
185        resp.field("connection_info", info);
186        let next_action = next_action.map(|a| match a {
187            ConnectionAction::None => "disconnect",
188            ConnectionAction::Reset => "reset",
189            ConnectionAction::SendUnloadComplete => "unload",
190            ConnectionAction::Reconnect { .. } => "reconnect",
191            ConnectionAction::SendFailedVersionResponse => "send_version_response",
192        });
193        resp.field("state", state)
194            .field("next_action", next_action)
195            .field(
196                "assigned_monitors_bitmap",
197                format_args!("{:x}", self.inner.assigned_monitors.bitmap()),
198            )
199            .child("channels", |req| {
200                let mut resp = req.respond();
201                self.inner
202                    .channels
203                    .inspect(self.notifier, self.inner.get_version(), &mut resp);
204                for ((gpadl_id, offer_id), gpadl) in &self.inner.gpadls {
205                    let channel = &self.inner.channels[*offer_id];
206                    resp.field(
207                        &channel_inspect_path(
208                            &channel.offer,
209                            format_args!("/gpadls/{}", gpadl_id.0),
210                        ),
211                        gpadl,
212                    );
213                }
214            });
215    }
216}
217
218/// Stores the monitor page GPAs along with their source.
219#[derive(Debug, Copy, Clone, Inspect)]
220struct MonitorPageGpaInfo {
221    gpas: MonitorPageGpas,
222    server_allocated: bool,
223}
224
225impl MonitorPageGpaInfo {
226    /// Creates a new MonitorPageGpaInfo from guest-provided GPAs.
227    fn from_guest_gpas(gpas: MonitorPageGpas) -> Self {
228        Self {
229            gpas,
230            server_allocated: false,
231        }
232    }
233
234    /// Creates a new MonitorPageGpaInfo from server-allocated GPAs.
235    fn from_server_gpas(gpas: MonitorPageGpas) -> Self {
236        Self {
237            gpas,
238            server_allocated: true,
239        }
240    }
241}
242
243#[derive(Debug, Copy, Clone, Inspect)]
244struct ConnectionInfo {
245    version: VersionInfo,
246    // Indicates if the connection is trusted for the paravisor of a hardware-isolated VM. In other
247    // cases, this value is always false.
248    trusted: bool,
249    offers_sent: bool,
250    interrupt_page: Option<u64>,
251    monitor_page: Option<MonitorPageGpaInfo>,
252    target_message_vp: u32,
253    modifying: bool,
254    client_id: Guid,
255    paused: bool,
256}
257
258/// The state of the VMBus connection.
259#[derive(Debug)]
260enum ConnectionState {
261    Disconnected,
262    Disconnecting {
263        next_action: ConnectionAction,
264        modify_sent: bool,
265    },
266    Connecting {
267        info: ConnectionInfo,
268        next_action: ConnectionAction,
269    },
270    Connected(ConnectionInfo),
271}
272
273impl ConnectionState {
274    /// Checks whether the state is connected using at least the specified version.
275    fn check_version(&self, min_version: Version) -> bool {
276        matches!(self, ConnectionState::Connected(info) if info.version.version >= min_version)
277    }
278
279    /// Checks whether the state is connected and the specified predicate holds for the feature
280    /// flags.
281    fn check_feature_flags(&self, flags: impl Fn(FeatureFlags) -> bool) -> bool {
282        matches!(self, ConnectionState::Connected(info) if flags(info.version.feature_flags))
283    }
284
285    fn get_version(&self) -> Option<VersionInfo> {
286        if let ConnectionState::Connected(info) = self {
287            Some(info.version)
288        } else {
289            None
290        }
291    }
292
293    /// Gets the `ConnectionInfo` if currently connected.
294    fn get_connected_info(&self) -> Option<&ConnectionInfo> {
295        if let ConnectionState::Connected(info) = self {
296            Some(info)
297        } else {
298            None
299        }
300    }
301
302    fn is_trusted(&self) -> bool {
303        match self {
304            ConnectionState::Connected(info) => info.trusted,
305            ConnectionState::Connecting { info, .. } => info.trusted,
306            _ => false,
307        }
308    }
309
310    fn is_paused(&self) -> bool {
311        if let ConnectionState::Connected(info) = self {
312            info.paused
313        } else {
314            false
315        }
316    }
317}
318
319#[derive(Debug, Copy, Clone)]
320enum ConnectionAction {
321    None,
322    Reset,
323    SendUnloadComplete,
324    Reconnect {
325        initiate_contact: InitiateContactRequest,
326    },
327    SendFailedVersionResponse,
328}
329
330#[derive(PartialEq, Eq, Debug, Copy, Clone)]
331pub enum MonitorPageRequest {
332    None,
333    Some(MonitorPageGpas),
334    Invalid,
335}
336
337#[derive(PartialEq, Eq, Debug, Copy, Clone)]
338pub struct InitiateContactRequest {
339    pub version_requested: u32,
340    pub target_message_vp: u32,
341    pub monitor_page: MonitorPageRequest,
342    pub target_sint: u8,
343    pub target_vtl: u8,
344    pub feature_flags: u32,
345    pub interrupt_page: Option<u64>,
346    pub client_id: Guid,
347    pub trusted: bool,
348}
349
350#[derive(Debug, Copy, Clone)]
351pub struct OpenRequest {
352    pub open_id: u32,
353    pub ring_buffer_gpadl_id: GpadlId,
354    pub target_vp: Option<u32>,
355    pub downstream_ring_buffer_page_offset: u32,
356    pub user_data: UserDefinedData,
357    pub guest_specified_interrupt_info: Option<SignalInfo>,
358    pub flags: protocol::OpenChannelFlags,
359}
360
361#[derive(Debug, Copy, Clone, Eq, PartialEq)]
362pub enum Update<T: std::fmt::Debug + Copy + Clone> {
363    Unchanged,
364    Reset,
365    Set(T),
366}
367
368impl<T: std::fmt::Debug + Copy + Clone> From<Option<T>> for Update<T> {
369    fn from(value: Option<T>) -> Self {
370        match value {
371            None => Self::Reset,
372            Some(value) => Self::Set(value),
373        }
374    }
375}
376
377#[derive(Debug, Copy, Clone, Eq, PartialEq)]
378pub struct ModifyConnectionRequest {
379    pub version: Option<VersionInfo>,
380    pub monitor_page: Update<MonitorPageGpas>,
381    pub interrupt_page: Update<u64>,
382    pub target_message_vp: Option<u32>,
383    pub notify_relay: bool,
384}
385
386// Manual implementation because notify_relay should be true by default.
387impl Default for ModifyConnectionRequest {
388    fn default() -> Self {
389        Self {
390            version: None,
391            monitor_page: Update::Unchanged,
392            interrupt_page: Update::Unchanged,
393            target_message_vp: None,
394            notify_relay: true,
395        }
396    }
397}
398
399impl From<protocol::ModifyConnection> for ModifyConnectionRequest {
400    fn from(value: protocol::ModifyConnection) -> Self {
401        let monitor_page = if value.parent_to_child_monitor_page_gpa != 0 {
402            Update::Set(MonitorPageGpas {
403                parent_to_child: value.parent_to_child_monitor_page_gpa,
404                child_to_parent: value.child_to_parent_monitor_page_gpa,
405            })
406        } else {
407            Update::Reset
408        };
409
410        Self {
411            monitor_page,
412            ..Default::default()
413        }
414    }
415}
416
417/// Response to a ModifyConnectionRequest.
418#[derive(Debug, Copy, Clone)]
419pub enum ModifyConnectionResponse {
420    /// The requested version change is supported, and the relay completed the connection
421    /// modification with the specified status and supports the specified feature flags. All of the
422    /// feature flags supported by the relay host are included, regardless of what features were
423    /// requested. If the server allocated monitor pages that are to be used for this connection,
424    /// they will be included as well.
425    Supported(
426        protocol::ConnectionState,
427        FeatureFlags,
428        Option<MonitorPageGpas>,
429    ),
430    /// A version change was requested but the relay host doesn't support that version.
431    Unsupported,
432    /// The connection modification completed with the specified status. This response type must be
433    /// sent if and only if no version change was requested.
434    Modified(protocol::ConnectionState),
435}
436
437#[derive(Debug, Copy, Clone)]
438pub enum ModifyState {
439    NotModifying,
440    Modifying { pending_target_vp: Option<u32> },
441}
442
443impl ModifyState {
444    pub fn is_modifying(&self) -> bool {
445        matches!(self, ModifyState::Modifying { .. })
446    }
447}
448
449#[derive(Debug, Copy, Clone)]
450pub struct SignalInfo {
451    pub event_flag: u16,
452    pub connection_id: u32,
453}
454
455#[derive(Debug, Copy, Clone, PartialEq, Eq)]
456enum RestoreState {
457    /// The channel has been offered newly this session.
458    New,
459    /// The channel was in the saved state and has been re-offered this session,
460    /// but restore_channel has not yet been called on it, and revoke_unclaimed_channels
461    /// has not yet been called.
462    Restoring,
463    /// The channel was in the saved state but has not yet been re-offered this
464    /// session.
465    Unmatched,
466    /// The channel was in the saved state and is now in a fully restored state.
467    Restored,
468}
469
470/// The state of a single vmbus channel.
471#[derive(Debug, Clone)]
472enum ChannelState {
473    /// The device has offered the channel but the offer has not been sent to the
474    /// guest. However, there may still be GPADLs for this channel from a
475    /// previous connection.
476    ClientReleased,
477
478    /// The channel has been offered to the guest.
479    Closed,
480
481    /// The guest has requested to open the channel and the device has been
482    /// notified.
483    Opening {
484        request: OpenRequest,
485        reserved_state: Option<ReservedState>,
486    },
487
488    /// The channel is open by both the guest and the device.
489    Open {
490        params: OpenRequest,
491        modify_state: ModifyState,
492        reserved_state: Option<ReservedState>,
493    },
494
495    /// The device has been notified to close the channel.
496    Closing {
497        params: OpenRequest,
498        reserved_state: Option<ReservedState>,
499    },
500
501    /// The device has been notified to close the channel, and the guest has
502    /// requested to reopen it.
503    ClosingReopen {
504        params: OpenRequest,
505        request: OpenRequest,
506    },
507
508    /// The device has revoked the channel but the guest has not released it yet.
509    Revoked,
510
511    /// The device has been reoffered, but the guest has not released the previous
512    /// offer yet.
513    Reoffered,
514
515    /// The guest has released the channel but there is still a pending close
516    /// request to the device.
517    ClosingClientRelease,
518
519    /// The guest has released the channel, but there is still a pending open
520    /// request to the device.
521    OpeningClientRelease,
522}
523
524impl ChannelState {
525    /// If true, the channel is unreferenced by the guest, and the guest should
526    /// not be able to perform operations on the channel.
527    fn is_released(&self) -> bool {
528        match self {
529            ChannelState::Closed
530            | ChannelState::Opening { .. }
531            | ChannelState::Open { .. }
532            | ChannelState::Closing { .. }
533            | ChannelState::ClosingReopen { .. }
534            | ChannelState::Revoked
535            | ChannelState::Reoffered => false,
536
537            ChannelState::ClientReleased
538            | ChannelState::ClosingClientRelease
539            | ChannelState::OpeningClientRelease => true,
540        }
541    }
542
543    /// If true, the channel has been revoked.
544    fn is_revoked(&self) -> bool {
545        match self {
546            ChannelState::Revoked | ChannelState::Reoffered => true,
547
548            ChannelState::ClientReleased
549            | ChannelState::Closed
550            | ChannelState::Opening { .. }
551            | ChannelState::Open { .. }
552            | ChannelState::Closing { .. }
553            | ChannelState::ClosingReopen { .. }
554            | ChannelState::ClosingClientRelease
555            | ChannelState::OpeningClientRelease => false,
556        }
557    }
558
559    fn is_reserved(&self) -> bool {
560        match self {
561            // TODO: Should closing be included here?
562            ChannelState::Open {
563                reserved_state: Some(_),
564                ..
565            }
566            | ChannelState::Opening {
567                reserved_state: Some(_),
568                ..
569            }
570            | ChannelState::Closing {
571                reserved_state: Some(_),
572                ..
573            } => true,
574
575            ChannelState::Opening { .. }
576            | ChannelState::Open { .. }
577            | ChannelState::Closing { .. }
578            | ChannelState::ClientReleased
579            | ChannelState::Closed
580            | ChannelState::ClosingReopen { .. }
581            | ChannelState::Revoked
582            | ChannelState::Reoffered
583            | ChannelState::ClosingClientRelease
584            | ChannelState::OpeningClientRelease => false,
585        }
586    }
587}
588
589impl Display for ChannelState {
590    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
591        let state = match self {
592            Self::ClientReleased => "ClientReleased",
593            Self::Closed => "Closed",
594            Self::Opening { .. } => "Opening",
595            Self::Open { .. } => "Open",
596            Self::Closing { .. } => "Closing",
597            Self::ClosingReopen { .. } => "ClosingReopen",
598            Self::Revoked => "Revoked",
599            Self::Reoffered => "Reoffered",
600            Self::ClosingClientRelease => "ClosingClientRelease",
601            Self::OpeningClientRelease => "OpeningClientRelease",
602        };
603        write!(f, "{}", state)
604    }
605}
606
607/// Indicates how a MNF (monitored interrupts) should be used for a channel.
608#[derive(Debug, Clone, Default, mesh::MeshPayload)]
609pub enum MnfUsage {
610    /// The channel does not use MNF.
611    #[default]
612    Disabled,
613    /// The channel uses MNF, handled by this server, with the specified interrupt latency.
614    Enabled { latency: Duration },
615    /// The channel uses MNF, handled by the relay host, with the monitor ID specified by the relay
616    /// host.
617    Relayed { monitor_id: u8 },
618}
619
620impl MnfUsage {
621    pub fn is_enabled(&self) -> bool {
622        matches!(self, Self::Enabled { .. })
623    }
624
625    pub fn is_relayed(&self) -> bool {
626        matches!(self, Self::Relayed { .. })
627    }
628
629    pub fn enabled_and_then<T>(&self, f: impl FnOnce(Duration) -> Option<T>) -> Option<T> {
630        if let Self::Enabled { latency } = self {
631            f(*latency)
632        } else {
633            None
634        }
635    }
636}
637
638impl From<Option<Duration>> for MnfUsage {
639    fn from(value: Option<Duration>) -> Self {
640        match value {
641            None => Self::Disabled,
642            Some(latency) => Self::Enabled { latency },
643        }
644    }
645}
646
647#[derive(Debug, Clone, Default, mesh::MeshPayload)]
648pub struct OfferParamsInternal {
649    /// An informational string describing the channel type.
650    pub interface_name: String,
651    pub instance_id: Guid,
652    pub interface_id: Guid,
653    pub mmio_megabytes: u16,
654    pub mmio_megabytes_optional: u16,
655    pub subchannel_index: u16,
656    pub use_mnf: MnfUsage,
657    pub offer_order: Option<u64>,
658    pub flags: OfferFlags,
659    pub user_defined: UserDefinedData,
660}
661
662impl OfferParamsInternal {
663    /// Gets the offer key for this offer.
664    pub fn key(&self) -> OfferKey {
665        OfferKey {
666            interface_id: self.interface_id,
667            instance_id: self.instance_id,
668            subchannel_index: self.subchannel_index,
669        }
670    }
671}
672
673impl From<OfferParams> for OfferParamsInternal {
674    fn from(value: OfferParams) -> Self {
675        let mut user_defined = UserDefinedData::new_zeroed();
676
677        // All non-relay channels are capable of using a confidential ring buffer, but external
678        // memory is dependent on the device.
679        let mut flags = OfferFlags::new()
680            .with_confidential_ring_buffer(true)
681            .with_confidential_external_memory(value.allow_confidential_external_memory);
682
683        match value.channel_type {
684            ChannelType::Device { pipe_packets } => {
685                if pipe_packets {
686                    flags.set_named_pipe_mode(true);
687                    user_defined.as_pipe_params_mut().pipe_type = protocol::PipeType::MESSAGE;
688                }
689            }
690            ChannelType::Interface {
691                user_defined: interface_user_defined,
692            } => {
693                flags.set_enumerate_device_interface(true);
694                user_defined = interface_user_defined;
695            }
696            ChannelType::Pipe {
697                message_mode,
698                user_defined: pipe_user_defined,
699                pipe_flags,
700            } => {
701                flags.set_enumerate_device_interface(true);
702                flags.set_named_pipe_mode(true);
703                *user_defined.as_pipe_params_mut() = protocol::PipeUserDefinedParameters {
704                    pipe_type: if message_mode {
705                        protocol::PipeType::MESSAGE
706                    } else {
707                        protocol::PipeType::BYTE
708                    },
709                    user_defined: pipe_user_defined,
710                    flags: pipe_flags,
711                };
712            }
713            ChannelType::HvSocket {
714                is_connect,
715                is_for_container,
716                silo_id,
717            } => {
718                flags.set_enumerate_device_interface(true);
719                flags.set_tlnpi_provider(true);
720                flags.set_named_pipe_mode(true);
721                *user_defined.as_hvsock_params_mut() = protocol::HvsockUserDefinedParameters::new(
722                    is_connect,
723                    is_for_container,
724                    silo_id,
725                );
726            }
727        };
728
729        Self {
730            interface_name: value.interface_name,
731            instance_id: value.instance_id,
732            interface_id: value.interface_id,
733            mmio_megabytes: value.mmio_megabytes,
734            mmio_megabytes_optional: value.mmio_megabytes_optional,
735            subchannel_index: value.subchannel_index,
736            use_mnf: value.mnf_interrupt_latency.into(),
737            offer_order: value.offer_order,
738            user_defined,
739            flags,
740        }
741    }
742}
743
744#[derive(Debug, Copy, Clone, Inspect, PartialEq, Eq)]
745pub struct ConnectionTarget {
746    pub vp: u32,
747    pub sint: u8,
748}
749
750#[derive(Debug, Copy, Clone, PartialEq, Eq)]
751pub enum MessageTarget {
752    Default,
753    ReservedChannel(OfferId, ConnectionTarget),
754    Custom(ConnectionTarget),
755}
756
757impl MessageTarget {
758    pub fn for_offer(offer_id: OfferId, reserved_state: &Option<ReservedState>) -> Self {
759        if let Some(state) = reserved_state {
760            Self::ReservedChannel(offer_id, state.target)
761        } else {
762            Self::Default
763        }
764    }
765}
766
767#[derive(Debug, Copy, Clone)]
768pub struct ReservedState {
769    version: VersionInfo,
770    target: ConnectionTarget,
771}
772
773/// A VMBus channel.
774#[derive(Debug)]
775struct Channel {
776    info: Option<OfferedInfo>,
777    offer: OfferParamsInternal,
778    state: ChannelState,
779    restore_state: RestoreState,
780}
781
782#[derive(Debug, Copy, Clone)]
783struct OfferedInfo {
784    channel_id: ChannelId,
785    connection_id: u32,
786    monitor_id: Option<MonitorId>,
787}
788
789impl Channel {
790    fn inspect_state(&self, resp: &mut inspect::Response<'_>) {
791        let mut target_vp = None;
792        let mut event_flag = None;
793        let mut connection_id = None;
794        let mut reserved_target = None;
795        let state = match &self.state {
796            ChannelState::ClientReleased => "client_released",
797            ChannelState::Closed => "closed",
798            ChannelState::Opening { reserved_state, .. } => {
799                reserved_target = reserved_state.map(|state| state.target);
800                "opening"
801            }
802            ChannelState::Open {
803                params,
804                reserved_state,
805                ..
806            } => {
807                target_vp = Some(params.target_vp);
808                if let Some(id) = params.guest_specified_interrupt_info {
809                    event_flag = Some(id.event_flag);
810                    connection_id = Some(id.connection_id);
811                }
812                reserved_target = reserved_state.map(|state| state.target);
813                "open"
814            }
815            ChannelState::Closing { reserved_state, .. } => {
816                reserved_target = reserved_state.map(|state| state.target);
817                "closing"
818            }
819            ChannelState::ClosingReopen { .. } => "closing_reopen",
820            ChannelState::Revoked => "revoked",
821            ChannelState::Reoffered => "reoffered",
822            ChannelState::ClosingClientRelease => "closing_client_release",
823            ChannelState::OpeningClientRelease => "opening_client_release",
824        };
825        let restore_state = match self.restore_state {
826            RestoreState::New => "new",
827            RestoreState::Restoring => "restoring",
828            RestoreState::Restored => "restored",
829            RestoreState::Unmatched => "unmatched",
830        };
831        if let Some(info) = &self.info {
832            resp.field("channel_id", info.channel_id.0)
833                .field("offered_connection_id", info.connection_id)
834                .field("monitor_id", info.monitor_id.map(|id| id.0));
835        }
836        resp.field("state", state)
837            .field("restore_state", restore_state)
838            .field("interface_name", self.offer.interface_name.clone())
839            .display("instance_id", &self.offer.instance_id)
840            .display("interface_id", &self.offer.interface_id)
841            .field("mmio_megabytes", self.offer.mmio_megabytes)
842            .field("target_vp", target_vp)
843            .field("guest_specified_event_flag", event_flag)
844            .field("guest_specified_connection_id", connection_id)
845            .field("reserved_connection_target", reserved_target)
846            .binary("offer_flags", self.offer.flags.into_bits());
847    }
848
849    /// Returns the monitor ID and latency only if it's being handled by this server.
850    ///
851    /// The monitor ID can be set while use_mnf is Relayed, which is the case if
852    /// the relay host is handling MNF.
853    ///
854    /// Also returns `None` for reserved channels, since monitored notifications
855    /// are only usable for standard channels. Otherwise, we fail later when we
856    /// try to change the MNF page as part of vmbus protocol renegotiation,
857    /// since the page still appears to be in use by a device.
858    fn handled_monitor_info(&self) -> Option<MonitorInfo> {
859        self.offer.use_mnf.enabled_and_then(|latency| {
860            if self.state.is_reserved() {
861                None
862            } else {
863                self.info.and_then(|info| {
864                    info.monitor_id.map(|monitor_id| MonitorInfo {
865                        monitor_id,
866                        latency,
867                    })
868                })
869            }
870        })
871    }
872
873    /// Prepares a channel to be sent to the guest by allocating a channel ID if
874    /// necessary and filling out channel.info.
875    fn prepare_channel(
876        &mut self,
877        offer_id: OfferId,
878        assigned_channels: &mut AssignedChannels,
879        assigned_monitors: &mut AssignedMonitors,
880    ) {
881        assert!(self.info.is_none());
882
883        // Allocate a channel ID.
884        let entry = assigned_channels
885            .allocate()
886            .expect("there are enough channel IDs for everything in ChannelList");
887
888        let channel_id = entry.id();
889        entry.insert(offer_id);
890        let connection_id = ConnectionId::new(channel_id.0, assigned_channels.vtl, VMBUS_SINT);
891
892        // Allocate a monitor ID if the channel uses MNF.
893        // N.B. If the synic doesn't support MNF or MNF is disabled by the server, use_mnf should
894        //      always be set to Disabled, except if the relay host is handling MnF in which case
895        //      we should use the monitor ID it provided.
896        let monitor_id = match self.offer.use_mnf {
897            MnfUsage::Enabled { .. } => {
898                let monitor_id = assigned_monitors.assign_monitor();
899                if monitor_id.is_none() {
900                    tracelimit::warn_ratelimited!("Out of monitor IDs.");
901                }
902
903                monitor_id
904            }
905            MnfUsage::Relayed { monitor_id } => Some(MonitorId(monitor_id)),
906            MnfUsage::Disabled => None,
907        };
908
909        self.info = Some(OfferedInfo {
910            channel_id,
911            connection_id: connection_id.0,
912            monitor_id,
913        });
914    }
915
916    /// Releases a channel's ID.
917    fn release_channel(
918        &mut self,
919        offer_id: OfferId,
920        assigned_channels: &mut AssignedChannels,
921        assigned_monitors: &mut AssignedMonitors,
922    ) {
923        if let Some(info) = self.info.take() {
924            assigned_channels.free(info.channel_id, offer_id);
925
926            // Only unassign the monitor ID if it was not a relayed ID provided by the offer.
927            if let Some(monitor_id) = info.monitor_id {
928                if self.offer.use_mnf.is_enabled() {
929                    assigned_monitors.release_monitor(monitor_id);
930                }
931            }
932        }
933    }
934}
935
936#[derive(Debug)]
937struct AssignedChannels {
938    assignments: Vec<Option<OfferId>>,
939    vtl: Vtl,
940    reserved_offset: usize,
941    /// The number of assigned channel IDs in the reserved range.
942    count_in_reserved_range: usize,
943}
944
945impl AssignedChannels {
946    fn new(vtl: Vtl, channel_id_offset: u16) -> Self {
947        Self {
948            assignments: vec![None; MAX_CHANNELS],
949            vtl,
950            reserved_offset: channel_id_offset as usize,
951            count_in_reserved_range: 0,
952        }
953    }
954
955    fn allowable_channel_count(&self) -> usize {
956        MAX_CHANNELS - self.reserved_offset + self.count_in_reserved_range
957    }
958
959    fn get(&self, channel_id: ChannelId) -> Option<OfferId> {
960        self.assignments
961            .get(Self::index(channel_id))
962            .copied()
963            .flatten()
964    }
965
966    fn set(&mut self, channel_id: ChannelId) -> Result<AssignmentEntry<'_>, OfferError> {
967        let index = Self::index(channel_id);
968        if self
969            .assignments
970            .get(index)
971            .ok_or(OfferError::InvalidChannelId(channel_id))?
972            .is_some()
973        {
974            return Err(OfferError::ChannelIdInUse(channel_id));
975        }
976        Ok(AssignmentEntry { list: self, index })
977    }
978
979    fn allocate(&mut self) -> Option<AssignmentEntry<'_>> {
980        let index = self.reserved_offset
981            + self.assignments[self.reserved_offset..]
982                .iter()
983                .position(|x| x.is_none())?;
984        Some(AssignmentEntry { list: self, index })
985    }
986
987    fn free(&mut self, channel_id: ChannelId, offer_id: OfferId) {
988        let index = Self::index(channel_id);
989        let slot = &mut self.assignments[index];
990        assert_eq!(slot.take(), Some(offer_id));
991        if index < self.reserved_offset {
992            self.count_in_reserved_range -= 1;
993        }
994    }
995
996    fn index(channel_id: ChannelId) -> usize {
997        channel_id.0.wrapping_sub(1) as usize
998    }
999}
1000
1001struct AssignmentEntry<'a> {
1002    list: &'a mut AssignedChannels,
1003    index: usize,
1004}
1005
1006impl AssignmentEntry<'_> {
1007    pub fn id(&self) -> ChannelId {
1008        ChannelId(self.index as u32 + 1)
1009    }
1010
1011    pub fn insert(self, offer_id: OfferId) {
1012        assert!(
1013            self.list.assignments[self.index]
1014                .replace(offer_id)
1015                .is_none()
1016        );
1017
1018        if self.index < self.list.reserved_offset {
1019            self.list.count_in_reserved_range += 1;
1020        }
1021    }
1022}
1023
1024struct ChannelList {
1025    channels: Slab<Channel>,
1026}
1027
1028fn channel_inspect_path(offer: &OfferParamsInternal, suffix: std::fmt::Arguments<'_>) -> String {
1029    if offer.subchannel_index == 0 {
1030        format!("{}{}", offer.instance_id, suffix)
1031    } else {
1032        format!(
1033            "{}/subchannels/{}{}",
1034            offer.instance_id, offer.subchannel_index, suffix
1035        )
1036    }
1037}
1038
1039impl ChannelList {
1040    fn inspect(
1041        &self,
1042        notifier: &impl Notifier,
1043        version: Option<VersionInfo>,
1044        resp: &mut inspect::Response<'_>,
1045    ) {
1046        for (offer_id, channel) in self.iter() {
1047            resp.child(
1048                &channel_inspect_path(&channel.offer, format_args!("")),
1049                |req| {
1050                    let mut resp = req.respond();
1051                    channel.inspect_state(&mut resp);
1052
1053                    // Merge in the inspection state from outside. Skip this if
1054                    // the channel is revoked (and not reoffered) since in that
1055                    // case the caller won't recognize the channel ID.
1056                    resp.merge(inspect::adhoc(|req| {
1057                        if !matches!(channel.state, ChannelState::Revoked) {
1058                            notifier.inspect(version, offer_id, req);
1059                        }
1060                    }));
1061                },
1062            );
1063        }
1064    }
1065}
1066
1067// This is limited by the size of the synic event flags bitmap (2048 bits per
1068// processor, bit 0 reserved for legacy channel bitmap multiplexing).
1069pub const MAX_CHANNELS: usize = 2047;
1070
1071impl ChannelList {
1072    fn new() -> Self {
1073        Self {
1074            channels: Slab::new(),
1075        }
1076    }
1077
1078    // The number of channels in the list.
1079    fn len(&self) -> usize {
1080        self.channels.len()
1081    }
1082
1083    /// Inserts a channel.
1084    fn offer(&mut self, new_channel: Channel) -> OfferId {
1085        OfferId(self.channels.insert(new_channel))
1086    }
1087
1088    /// Removes a channel by offer ID.
1089    fn remove(&mut self, offer_id: OfferId) {
1090        let channel = self.channels.remove(offer_id.0);
1091        assert!(channel.info.is_none());
1092    }
1093
1094    /// Gets a channel by guest channel ID.
1095    ///
1096    /// It is an error to call this function on a channel that has been released
1097    /// by the guest, since the guest should not be using that ID anymore.
1098    fn get_by_channel_id_mut(
1099        &mut self,
1100        assigned_channels: &AssignedChannels,
1101        channel_id: ChannelId,
1102    ) -> Result<(OfferId, &mut Channel), ChannelError> {
1103        let offer_id = assigned_channels
1104            .get(channel_id)
1105            .ok_or(ChannelError::UnknownChannelId)?;
1106        let channel = &mut self[offer_id];
1107        if channel.state.is_released() {
1108            return Err(ChannelError::ChannelReleased);
1109        }
1110        assert_eq!(
1111            channel.info.as_ref().map(|info| info.channel_id),
1112            Some(channel_id)
1113        );
1114        Ok((offer_id, channel))
1115    }
1116
1117    /// Gets a channel by guest channel ID.
1118    fn get_by_channel_id(
1119        &self,
1120        assigned_channels: &AssignedChannels,
1121        channel_id: ChannelId,
1122    ) -> Result<(OfferId, &Channel), ChannelError> {
1123        let offer_id = assigned_channels
1124            .get(channel_id)
1125            .ok_or(ChannelError::UnknownChannelId)?;
1126        let channel = &self[offer_id];
1127        if channel.state.is_released() {
1128            return Err(ChannelError::ChannelReleased);
1129        }
1130        assert_eq!(
1131            channel.info.as_ref().map(|info| info.channel_id),
1132            Some(channel_id)
1133        );
1134        Ok((offer_id, channel))
1135    }
1136
1137    /// Gets a channel by offer key (interface ID, instance ID, subchannel
1138    /// index).
1139    fn get_by_key_mut(&mut self, key: &OfferKey) -> Option<(OfferId, &mut Channel)> {
1140        for (offer_id, channel) in self.iter_mut() {
1141            if channel.offer.instance_id == key.instance_id
1142                && channel.offer.interface_id == key.interface_id
1143                && channel.offer.subchannel_index == key.subchannel_index
1144            {
1145                return Some((offer_id, channel));
1146            }
1147        }
1148        None
1149    }
1150
1151    /// Returns an iterator over the channels.
1152    fn iter(&self) -> impl Iterator<Item = (OfferId, &Channel)> {
1153        self.channels
1154            .iter()
1155            .map(|(id, channel)| (OfferId(id), channel))
1156    }
1157
1158    /// Returns an iterator over the channels.
1159    fn iter_mut(&mut self) -> impl Iterator<Item = (OfferId, &mut Channel)> {
1160        self.channels
1161            .iter_mut()
1162            .map(|(id, channel)| (OfferId(id), channel))
1163    }
1164
1165    /// Iterates through the channels, retaining those where `f` returns true.
1166    fn retain<F>(&mut self, mut f: F)
1167    where
1168        F: FnMut(OfferId, &mut Channel) -> bool,
1169    {
1170        self.channels.retain(|id, channel| {
1171            let retain = f(OfferId(id), channel);
1172            if !retain {
1173                assert!(channel.info.is_none());
1174            }
1175            retain
1176        })
1177    }
1178}
1179
1180impl Index<OfferId> for ChannelList {
1181    type Output = Channel;
1182
1183    fn index(&self, offer_id: OfferId) -> &Self::Output {
1184        &self.channels[offer_id.0]
1185    }
1186}
1187
1188impl IndexMut<OfferId> for ChannelList {
1189    fn index_mut(&mut self, offer_id: OfferId) -> &mut Self::Output {
1190        &mut self.channels[offer_id.0]
1191    }
1192}
1193
1194/// A GPADL.
1195#[derive(Debug, Inspect)]
1196struct Gpadl {
1197    count: u16,
1198    #[inspect(skip)]
1199    buf: Vec<u64>,
1200    state: GpadlState,
1201}
1202
1203#[derive(Debug, Copy, Clone, PartialEq, Eq, Inspect)]
1204enum GpadlState {
1205    /// The GPADL has not yet been fully sent to the host.
1206    InProgress,
1207    /// The GPADL has been sent to the device but is not yet acknowledged.
1208    Offered,
1209    /// The device has not acknowledged the GPADL but the GPADL is ready to be
1210    /// torn down.
1211    OfferedTearingDown,
1212    /// The device has acknowledged the GPADL.
1213    Accepted,
1214    /// The device has been notified that the GPADL is being torn down.
1215    TearingDown,
1216}
1217
1218impl Gpadl {
1219    /// Creates a new GPADL with `count` ranges and `len * 8` bytes in the range
1220    /// buffer.
1221    fn new(count: u16, len: usize) -> Self {
1222        Self {
1223            state: GpadlState::InProgress,
1224            count,
1225            buf: Vec::with_capacity(len),
1226        }
1227    }
1228
1229    /// Appends `data` to an in-progress GPADL. Returns whether the GPADL is complete.
1230    fn append(&mut self, data: &[u8]) -> Result<bool, ChannelError> {
1231        if self.state == GpadlState::InProgress {
1232            let buf = &mut self.buf;
1233            // data.len() may be longer than is actually valid since some
1234            // clients (e.g. UEFI) always pass the maximum message length. In
1235            // this case, calculate the useful length from the remaining
1236            // capacity instead.
1237            let len = min(data.len() & !7, (buf.capacity() - buf.len()) * 8);
1238            let data = &data[..len];
1239            let start = buf.len();
1240            buf.resize(buf.len() + data.len() / 8, 0);
1241            buf[start..].as_mut_bytes().copy_from_slice(data);
1242            Ok(if buf.len() == buf.capacity() {
1243                gparange::validate_gpa_ranges(self.count as usize, buf)
1244                    .map_err(ChannelError::InvalidGpaRange)?;
1245                self.state = GpadlState::Offered;
1246                true
1247            } else {
1248                false
1249            })
1250        } else {
1251            Err(ChannelError::GpadlAlreadyComplete)
1252        }
1253    }
1254}
1255
1256/// The parameters provided by the guest when the channel is being opened.
1257#[derive(Debug, Copy, Clone)]
1258pub struct OpenParams {
1259    pub open_data: OpenData,
1260    pub connection_id: u32,
1261    pub event_flag: u16,
1262    pub monitor_info: Option<MonitorInfo>,
1263    pub flags: protocol::OpenChannelFlags,
1264    pub reserved_target: Option<ConnectionTarget>,
1265    pub channel_id: ChannelId,
1266}
1267
1268impl OpenParams {
1269    fn from_request(
1270        info: &OfferedInfo,
1271        request: &OpenRequest,
1272        monitor_info: Option<MonitorInfo>,
1273        reserved_target: Option<ConnectionTarget>,
1274    ) -> Self {
1275        // Determine whether to use the alternate IDs.
1276        // N.B. If not specified, the regular IDs are stored as "alternate" in the OpenData.
1277        let (event_flag, connection_id) = if let Some(id) = request.guest_specified_interrupt_info {
1278            (id.event_flag, id.connection_id)
1279        } else {
1280            (info.channel_id.0 as u16, info.connection_id)
1281        };
1282
1283        Self {
1284            open_data: OpenData {
1285                target_vp: request.target_vp,
1286                ring_offset: request.downstream_ring_buffer_page_offset,
1287                ring_gpadl_id: request.ring_buffer_gpadl_id,
1288                user_data: request.user_data,
1289                event_flag,
1290                connection_id,
1291            },
1292            connection_id,
1293            event_flag,
1294            // Only include monitor info if the request has interrupts enabled.
1295            monitor_info: request.target_vp.and(monitor_info),
1296            flags: request.flags.with_unused(0),
1297            reserved_target,
1298            channel_id: info.channel_id,
1299        }
1300    }
1301}
1302
1303/// A channel action, sent to the device when a channel state changes.
1304#[derive(Debug)]
1305pub enum Action {
1306    Open(OpenParams, VersionInfo),
1307    Close,
1308    Gpadl(GpadlId, u16, Vec<u64>),
1309    TeardownGpadl {
1310        gpadl_id: GpadlId,
1311        post_restore: bool,
1312    },
1313    Modify {
1314        target_vp: u32,
1315    },
1316}
1317
1318/// The supported VMBus protocol versions.
1319static SUPPORTED_VERSIONS: &[Version] = &[
1320    Version::V1,
1321    Version::Win7,
1322    Version::Win8,
1323    Version::Win8_1,
1324    Version::Win10,
1325    Version::Win10Rs3_0,
1326    Version::Win10Rs3_1,
1327    Version::Win10Rs4,
1328    Version::Win10Rs5,
1329    Version::Iron,
1330    Version::Copper,
1331];
1332
1333// Feature flags that are always supported.
1334// N.B. Confidential channels are conditionally supported if running in the paravisor.
1335// N.B. GPA pinning is conditionally supported if the server is configured to support it.
1336const SUPPORTED_FEATURE_FLAGS: FeatureFlags = FeatureFlags::new()
1337    .with_guest_specified_signal_parameters(true)
1338    .with_channel_interrupt_redirection(true)
1339    .with_modify_connection(true)
1340    .with_client_id(true)
1341    .with_pause_resume(true)
1342    .with_server_specified_monitor_pages(true);
1343
1344/// Trait for sending requests to devices and the guest.
1345pub trait Notifier: Send {
1346    /// Requests a channel action.
1347    fn notify(&mut self, offer_id: OfferId, action: Action);
1348
1349    /// Forward an unhandled InitiateContact request to an external server.
1350    fn forward_unhandled(&mut self, request: InitiateContactRequest);
1351
1352    /// Update server state with information from the connection, and optionally notify the relay.
1353    ///
1354    /// N.B. If `ModifyConnectionRequest::notify_relay` is true and the function does not return an
1355    /// error, the server expects `Server::complete_modify_connection()` to be called, regardless of
1356    /// whether or not there is a relay.
1357    fn modify_connection(&mut self, request: ModifyConnectionRequest) -> anyhow::Result<()>;
1358
1359    /// Inspects a channel.
1360    fn inspect(&self, version: Option<VersionInfo>, offer_id: OfferId, req: inspect::Request<'_>) {
1361        let _ = (version, offer_id, req);
1362    }
1363
1364    /// Sends a synic message to the guest.
1365    /// Returns true if the message was sent, and false if it must be retried.
1366    #[must_use]
1367    fn send_message(&mut self, message: &OutgoingMessage, target: MessageTarget) -> bool;
1368
1369    /// Used to signal the hvsocket handler that there is a new connection request.
1370    fn notify_hvsock(&mut self, request: &HvsockConnectRequest);
1371
1372    /// Notifies that a requested reset is complete.
1373    fn reset_complete(&mut self);
1374
1375    /// Notifies that a guest-requested unload is complete.
1376    fn unload_complete(&mut self);
1377}
1378
1379impl Server {
1380    /// Creates a new VMBus server.
1381    pub fn new(
1382        vtl: Vtl,
1383        child_connection_id: u32,
1384        channel_id_offset: u16,
1385        use_absolute_channel_order: bool,
1386        support_gpa_pinning: bool,
1387    ) -> Self {
1388        Server {
1389            state: ConnectionState::Disconnected,
1390            channels: ChannelList::new(),
1391            assigned_channels: AssignedChannels::new(vtl, channel_id_offset),
1392            assigned_monitors: AssignedMonitors::new(),
1393            gpadls: Default::default(),
1394            incomplete_gpadls: Default::default(),
1395            child_connection_id,
1396            max_version: None,
1397            delayed_max_version: None,
1398            max_restore_version: None,
1399            pending_messages: PendingMessages(VecDeque::new()),
1400            require_server_allocated_mnf: false,
1401            use_absolute_channel_order,
1402            support_gpa_pinning,
1403        }
1404    }
1405
1406    /// Associates a `Notifier` with the server.
1407    pub fn with_notifier<'a, T: Notifier>(
1408        &'a mut self,
1409        notifier: &'a mut T,
1410    ) -> ServerWithNotifier<'a, T> {
1411        self.validate();
1412        ServerWithNotifier {
1413            inner: self,
1414            notifier,
1415        }
1416    }
1417
1418    /// Requires that the server allocates monitor pages. If this is enabled, the server will ignore
1419    /// guest-specified monitor pages and act as if none of the channels use MNF.
1420    pub fn set_require_server_allocated_mnf(&mut self, require: bool) {
1421        self.require_server_allocated_mnf = require;
1422    }
1423
1424    fn validate(&self) {
1425        #[cfg(debug_assertions)]
1426        for (_, channel) in self.channels.iter() {
1427            let should_have_info = !channel.state.is_released();
1428            if channel.info.is_some() != should_have_info {
1429                panic!("channel invariant violation: {channel:?}");
1430            }
1431        }
1432    }
1433
1434    /// Sets a limit on the version and featuref flags that will be offered to the guest.
1435    ///
1436    /// If `delay` is true, the limit will not apply to the first connection, but to all subsequent
1437    /// connections.
1438    pub fn set_compatibility_version(&mut self, version: MaxVersionInfo, delay: bool) {
1439        if delay {
1440            self.delayed_max_version = Some(version)
1441        } else {
1442            tracing::info!(?version, "Limiting VmBus connections to version");
1443            self.max_version = Some(version);
1444        }
1445    }
1446
1447    /// Indicates the maximum supported version when restoring from saved
1448    /// state. This is configured separately from [`Self::set_compatibility_version`]
1449    /// so that the restore-time limit can be configured independently of the
1450    /// limit used for live negotiation.
1451    ///
1452    /// This allows features to be enabled for rollback scenarios while not yet enabling them for
1453    /// new connections.
1454    pub fn set_restore_compatibility_version(&mut self, version: MaxVersionInfo) {
1455        tracing::info!(?version, "Limiting VmBus restore to version");
1456        self.max_restore_version = Some(version);
1457    }
1458
1459    pub fn channel_gpadls(&self, offer_id: OfferId) -> Vec<RestoredGpadl> {
1460        self.gpadls
1461            .iter()
1462            .filter_map(|(&(gpadl_id, gpadl_offer_id), gpadl)| {
1463                if offer_id != gpadl_offer_id {
1464                    return None;
1465                }
1466                let accepted = match gpadl.state {
1467                    GpadlState::Offered | GpadlState::OfferedTearingDown => false,
1468                    GpadlState::Accepted => true,
1469                    GpadlState::InProgress | GpadlState::TearingDown => return None,
1470                };
1471                Some(RestoredGpadl {
1472                    request: GpadlRequest {
1473                        id: gpadl_id,
1474                        count: gpadl.count,
1475                        buf: gpadl.buf.clone(),
1476                    },
1477                    accepted,
1478                })
1479            })
1480            .collect()
1481    }
1482
1483    pub fn get_version(&self) -> Option<VersionInfo> {
1484        self.state.get_version()
1485    }
1486
1487    pub fn get_restore_open_params(&self, offer_id: OfferId) -> Result<OpenParams, RestoreError> {
1488        let channel = &self.channels[offer_id];
1489
1490        // Check this here to avoid doing unnecessary work.
1491        match channel.restore_state {
1492            RestoreState::New => {
1493                // This channel was never offered, or was released by the guest during the save.
1494                // This is a problem since if this was called the device expects the channel to be
1495                // open.
1496                return Err(RestoreError::MissingChannel(channel.offer.key()));
1497            }
1498            RestoreState::Restoring => {}
1499            RestoreState::Unmatched => unreachable!(),
1500            RestoreState::Restored => {
1501                return Err(RestoreError::AlreadyRestored(channel.offer.key()));
1502            }
1503        }
1504
1505        let info = channel
1506            .info
1507            .ok_or_else(|| RestoreError::MissingChannel(channel.offer.key()))?;
1508
1509        let (request, reserved_state) = match channel.state {
1510            ChannelState::Closed => {
1511                return Err(RestoreError::MismatchedOpenState(channel.offer.key()));
1512            }
1513            ChannelState::Closing { params, .. } | ChannelState::ClosingReopen { params, .. } => {
1514                (params, None)
1515            }
1516            ChannelState::Opening {
1517                request,
1518                reserved_state,
1519            } => (request, reserved_state),
1520            ChannelState::Open {
1521                params,
1522                reserved_state,
1523                ..
1524            } => (params, reserved_state),
1525            ChannelState::ClientReleased | ChannelState::Reoffered => {
1526                return Err(RestoreError::MissingChannel(channel.offer.key()));
1527            }
1528            ChannelState::Revoked
1529            | ChannelState::ClosingClientRelease
1530            | ChannelState::OpeningClientRelease => unreachable!(),
1531        };
1532
1533        Ok(OpenParams::from_request(
1534            &info,
1535            &request,
1536            channel.handled_monitor_info(),
1537            reserved_state.map(|state| state.target),
1538        ))
1539    }
1540
1541    /// Check if there are any messages in the pending queue.
1542    pub fn has_pending_messages(&self) -> bool {
1543        !self.pending_messages.0.is_empty() && !self.state.is_paused()
1544    }
1545
1546    /// Tries to resend pending messages using the provided `send`` function.
1547    pub fn poll_flush_pending_messages(
1548        &mut self,
1549        mut send: impl FnMut(&OutgoingMessage) -> Poll<()>,
1550    ) -> Poll<()> {
1551        if !self.state.is_paused() {
1552            while let Some(message) = self.pending_messages.0.front() {
1553                ready!(send(message));
1554                self.pending_messages.0.pop_front();
1555            }
1556        }
1557
1558        Poll::Ready(())
1559    }
1560}
1561
1562impl<'a, N: 'a + Notifier> ServerWithNotifier<'a, N> {
1563    /// Marks a channel as restored.
1564    ///
1565    /// If this is not called for a channel but vmbus state is restored, then it
1566    /// is assumed that the offer is a fresh one, and the channel will be
1567    /// revoked and reoffered.
1568    pub fn restore_channel(&mut self, offer_id: OfferId, open: bool) -> Result<(), RestoreError> {
1569        let channel = &mut self.inner.channels[offer_id];
1570
1571        // We need to check this here as well, because get_restore_open_params may not have been
1572        // called.
1573        match channel.restore_state {
1574            RestoreState::New => {
1575                // This channel was never offered, or was released by the guest
1576                // during the save. This is fine as long as the device does not
1577                // expect the channel to be open.
1578                if open {
1579                    return Err(RestoreError::MissingChannel(channel.offer.key()));
1580                } else {
1581                    return Ok(());
1582                }
1583            }
1584            RestoreState::Restoring => {}
1585            RestoreState::Unmatched => unreachable!(),
1586            RestoreState::Restored => {
1587                return Err(RestoreError::AlreadyRestored(channel.offer.key()));
1588            }
1589        }
1590
1591        let info = channel
1592            .info
1593            .ok_or_else(|| RestoreError::MissingChannel(channel.offer.key()))?;
1594
1595        if let Some(monitor_info) = channel.handled_monitor_info() {
1596            if !self
1597                .inner
1598                .assigned_monitors
1599                .claim_monitor(monitor_info.monitor_id)
1600            {
1601                return Err(RestoreError::DuplicateMonitorId(monitor_info.monitor_id.0));
1602            }
1603        }
1604
1605        if open {
1606            match channel.state {
1607                ChannelState::Closed => {
1608                    return Err(RestoreError::MismatchedOpenState(channel.offer.key()));
1609                }
1610                ChannelState::Closing { .. } | ChannelState::ClosingReopen { .. } => {
1611                    self.notifier.notify(offer_id, Action::Close);
1612                }
1613                ChannelState::Opening {
1614                    request,
1615                    reserved_state,
1616                } => {
1617                    self.inner
1618                        .pending_messages
1619                        .sender(self.notifier, self.inner.state.is_paused())
1620                        .send_open_result(
1621                            info.channel_id,
1622                            &request,
1623                            protocol::STATUS_SUCCESS,
1624                            MessageTarget::for_offer(offer_id, &reserved_state),
1625                        );
1626                    channel.state = ChannelState::Open {
1627                        params: request,
1628                        modify_state: ModifyState::NotModifying,
1629                        reserved_state,
1630                    };
1631                }
1632                ChannelState::Open { .. } => {}
1633                ChannelState::ClientReleased | ChannelState::Reoffered => {
1634                    return Err(RestoreError::MissingChannel(channel.offer.key()));
1635                }
1636                ChannelState::Revoked
1637                | ChannelState::ClosingClientRelease
1638                | ChannelState::OpeningClientRelease => unreachable!(),
1639            };
1640        } else {
1641            match channel.state {
1642                ChannelState::Closed => {}
1643                // If a channel was reoffered before the save, it was saved as revoked and then
1644                // restored to reoffered if the device is offering it again. If we reach this state,
1645                // the device has offered the channel but we are still waiting for the client to
1646                // release the old revoked channel, so the state must remain reoffered.
1647                ChannelState::Reoffered => {}
1648                ChannelState::Closing { .. } => {
1649                    channel.state = ChannelState::Closed;
1650                }
1651                ChannelState::ClosingReopen { request, .. } => {
1652                    self.notifier.notify(
1653                        offer_id,
1654                        Action::Open(
1655                            OpenParams::from_request(
1656                                &info,
1657                                &request,
1658                                channel.handled_monitor_info(),
1659                                None,
1660                            ),
1661                            self.inner.state.get_version().expect("must be connected"),
1662                        ),
1663                    );
1664                    channel.state = ChannelState::Opening {
1665                        request,
1666                        reserved_state: None,
1667                    };
1668                }
1669                ChannelState::Opening {
1670                    request,
1671                    reserved_state,
1672                } => {
1673                    self.notifier.notify(
1674                        offer_id,
1675                        Action::Open(
1676                            OpenParams::from_request(
1677                                &info,
1678                                &request,
1679                                channel.handled_monitor_info(),
1680                                reserved_state.map(|state| state.target),
1681                            ),
1682                            self.inner.state.get_version().expect("must be connected"),
1683                        ),
1684                    );
1685                }
1686                ChannelState::Open { .. } => {
1687                    return Err(RestoreError::MismatchedOpenState(channel.offer.key()));
1688                }
1689                ChannelState::ClientReleased => {
1690                    return Err(RestoreError::MissingChannel(channel.offer.key()));
1691                }
1692                ChannelState::Revoked
1693                | ChannelState::ClosingClientRelease
1694                | ChannelState::OpeningClientRelease => unreachable!(),
1695            }
1696        }
1697
1698        channel.restore_state = RestoreState::Restored;
1699        Ok(())
1700    }
1701
1702    /// Revoke and reoffer channels to the guest, depending on their `RestoreState.`
1703    /// This function should be called after [`ServerWithNotifier::restore`].
1704    pub fn revoke_unclaimed_channels(&mut self) {
1705        for (offer_id, channel) in self.inner.channels.iter_mut() {
1706            match channel.restore_state {
1707                RestoreState::Restored => {
1708                    // The channel is fully restored. Nothing more to do.
1709                }
1710                RestoreState::New => {
1711                    // This is a fresh channel offer, not in the saved state. Send the offer to the
1712                    // guest if it has not already been sent (which could have happened if the
1713                    // channel was offered after restore() but before revoke_unclaimed_channels()).
1714                    // Offers should only be sent if the guest has already sent RequestOffers.
1715                    if let ConnectionState::Connected(info) = &self.inner.state {
1716                        if info.offers_sent && matches!(channel.state, ChannelState::ClientReleased)
1717                        {
1718                            channel.prepare_channel(
1719                                offer_id,
1720                                &mut self.inner.assigned_channels,
1721                                &mut self.inner.assigned_monitors,
1722                            );
1723                            channel.state = ChannelState::Closed;
1724                            self.inner
1725                                .pending_messages
1726                                .sender(self.notifier, self.inner.state.is_paused())
1727                                .send_offer(channel, info);
1728                        }
1729                    }
1730                }
1731                RestoreState::Restoring => {
1732                    // restore_channel was never called for this, but it was in
1733                    // the saved state. This indicates the offer is meant to be
1734                    // fresh, so revoke and reoffer it.
1735                    let retain = revoke(
1736                        self.inner
1737                            .pending_messages
1738                            .sender(self.notifier, self.inner.state.is_paused()),
1739                        offer_id,
1740                        channel,
1741                        &mut self.inner.gpadls,
1742                    );
1743                    assert!(retain, "channel has not been released");
1744                    channel.state = ChannelState::Reoffered;
1745                }
1746                RestoreState::Unmatched => {
1747                    // offer_channel was never called for this, but it was in
1748                    // the saved state. Revoke it.
1749                    let retain = revoke(
1750                        self.inner
1751                            .pending_messages
1752                            .sender(self.notifier, self.inner.state.is_paused()),
1753                        offer_id,
1754                        channel,
1755                        &mut self.inner.gpadls,
1756                    );
1757                    assert!(retain, "channel has not been released");
1758                }
1759            }
1760        }
1761
1762        // Notify the channels for any GPADLs in progress.
1763        for (&(gpadl_id, offer_id), gpadl) in self.inner.gpadls.iter_mut() {
1764            match gpadl.state {
1765                GpadlState::InProgress | GpadlState::Accepted => {}
1766                GpadlState::Offered => {
1767                    self.notifier.notify(
1768                        offer_id,
1769                        Action::Gpadl(gpadl_id, gpadl.count, gpadl.buf.clone()),
1770                    );
1771                }
1772                GpadlState::TearingDown => {
1773                    self.notifier.notify(
1774                        offer_id,
1775                        Action::TeardownGpadl {
1776                            gpadl_id,
1777                            post_restore: true,
1778                        },
1779                    );
1780                }
1781                GpadlState::OfferedTearingDown => unreachable!(),
1782            }
1783        }
1784
1785        self.check_disconnected();
1786    }
1787
1788    /// Initiates a state reset and a closing of all channels.
1789    ///
1790    /// Only one reset is allowed at a time, and no calls to
1791    /// `handle_synic_message` are allowed during a reset operation.
1792    pub fn reset(&mut self) {
1793        assert!(!self.is_resetting());
1794        if self.request_disconnect(ConnectionAction::Reset) {
1795            self.complete_reset();
1796        }
1797    }
1798
1799    fn complete_reset(&mut self) {
1800        // Reset the restore state since everything is now in a clean state.
1801        for (_, channel) in self.inner.channels.iter_mut() {
1802            channel.restore_state = RestoreState::New;
1803        }
1804        self.inner.pending_messages.0.clear();
1805        self.notifier.reset_complete();
1806    }
1807
1808    /// Creates a new channel, returning its offer ID.
1809    pub fn offer_channel(&mut self, offer: OfferParamsInternal) -> Result<OfferId, OfferError> {
1810        // Ensure no channel with this interface and instance ID exists.
1811        if let Some((offer_id, channel)) = self.inner.channels.get_by_key_mut(&offer.key()) {
1812            // Replace the current offer if this is an unmatched restored
1813            // channel, or if this matching offer has been revoked by the host
1814            // but not yet released by the guest.
1815            if channel.restore_state != RestoreState::Unmatched
1816                && !matches!(channel.state, ChannelState::Revoked)
1817            {
1818                return Err(OfferError::AlreadyExists(offer.key()));
1819            }
1820
1821            let info = channel.info.expect("assigned");
1822            if channel.restore_state == RestoreState::Unmatched {
1823                tracing::debug!(
1824                    offer_id = offer_id.0,
1825                    key = %channel.offer.key(),
1826                    "matched channel"
1827                );
1828
1829                assert!(!matches!(channel.state, ChannelState::Revoked));
1830                // This channel was previously offered to the guest in the saved
1831                // state. Match this back up to handle future calls to
1832                // restore_channel and revoke_unclaimed_channels.
1833                channel.restore_state = RestoreState::Restoring;
1834
1835                // The relay can specify a host-determined monitor ID, which needs to match what's
1836                // in the saved state.
1837                if let MnfUsage::Relayed { monitor_id } = offer.use_mnf {
1838                    if info.monitor_id != Some(MonitorId(monitor_id)) {
1839                        return Err(OfferError::MismatchedMonitorId(
1840                            info.monitor_id,
1841                            MonitorId(monitor_id),
1842                        ));
1843                    }
1844                }
1845            } else {
1846                // The channel has been revoked but the guest still has a
1847                // reference to it. Save the offer for reoffering immediately
1848                // after the child releases it.
1849                channel.state = ChannelState::Reoffered;
1850                tracing::info!(?offer_id, key = %channel.offer.key(), "channel marked for reoffer");
1851            }
1852
1853            channel.offer = offer;
1854            return Ok(offer_id);
1855        }
1856
1857        let mut connected_info = None;
1858        let state = match &self.inner.state {
1859            ConnectionState::Connected(info) => {
1860                if info.offers_sent {
1861                    connected_info = Some(info);
1862                    ChannelState::Closed
1863                } else {
1864                    ChannelState::ClientReleased
1865                }
1866            }
1867            ConnectionState::Connecting { .. }
1868            | ConnectionState::Disconnecting { .. }
1869            | ConnectionState::Disconnected => ChannelState::ClientReleased,
1870        };
1871
1872        // Ensure there will be enough channel IDs for this channel.
1873        if self.inner.channels.len() >= self.inner.assigned_channels.allowable_channel_count() {
1874            return Err(OfferError::TooManyChannels);
1875        }
1876
1877        let key = offer.key();
1878        let confidential_ring_buffer = offer.flags.confidential_ring_buffer();
1879        let confidential_external_memory = offer.flags.confidential_external_memory();
1880        let offer_order = offer.offer_order;
1881        let channel = Channel {
1882            info: None,
1883            offer,
1884            state,
1885            restore_state: RestoreState::New,
1886        };
1887
1888        let offer_id = self.inner.channels.offer(channel);
1889        if let Some(info) = connected_info {
1890            let channel = &mut self.inner.channels[offer_id];
1891            channel.prepare_channel(
1892                offer_id,
1893                &mut self.inner.assigned_channels,
1894                &mut self.inner.assigned_monitors,
1895            );
1896
1897            self.inner
1898                .pending_messages
1899                .sender(self.notifier, self.inner.state.is_paused())
1900                .send_offer(channel, info);
1901        }
1902
1903        tracing::info!(?offer_id, ?offer_order, %key, confidential_ring_buffer, confidential_external_memory, "new channel");
1904        Ok(offer_id)
1905    }
1906
1907    /// Revokes a channel by ID.
1908    pub fn revoke_channel(&mut self, offer_id: OfferId) {
1909        let channel = &mut self.inner.channels[offer_id];
1910        let retain = revoke(
1911            self.inner
1912                .pending_messages
1913                .sender(self.notifier, self.inner.state.is_paused()),
1914            offer_id,
1915            channel,
1916            &mut self.inner.gpadls,
1917        );
1918        if !retain {
1919            self.inner.channels.remove(offer_id);
1920        }
1921
1922        self.check_disconnected();
1923    }
1924
1925    /// Completes an open operation with `result`.
1926    pub fn open_complete(&mut self, offer_id: OfferId, result: i32) {
1927        let channel = &mut self.inner.channels[offer_id];
1928        tracing::debug!(offer_id = offer_id.0, key = %channel.offer.key(), result, "open complete");
1929
1930        match channel.state {
1931            ChannelState::Opening {
1932                request,
1933                reserved_state,
1934            } => {
1935                let channel_id = channel.info.expect("assigned").channel_id;
1936                if result >= 0 {
1937                    tracelimit::info_ratelimited!(
1938                        offer_id = offer_id.0,
1939                        channel_id = channel_id.0,
1940                        key = %channel.offer.key(),
1941                        result,
1942                        "opened channel"
1943                    );
1944                } else {
1945                    // Log channel open failures at error level for visibility.
1946                    tracelimit::error_ratelimited!(
1947                        offer_id = offer_id.0,
1948                        channel_id = channel_id.0,
1949                        key = %channel.offer.key(),
1950                        result,
1951                        "failed to open channel"
1952                    );
1953                }
1954
1955                self.inner
1956                    .pending_messages
1957                    .sender(self.notifier, self.inner.state.is_paused())
1958                    .send_open_result(
1959                        channel_id,
1960                        &request,
1961                        result,
1962                        MessageTarget::for_offer(offer_id, &reserved_state),
1963                    );
1964                channel.state = if result >= 0 {
1965                    ChannelState::Open {
1966                        params: request,
1967                        modify_state: ModifyState::NotModifying,
1968                        reserved_state,
1969                    }
1970                } else {
1971                    ChannelState::Closed
1972                };
1973            }
1974            ChannelState::OpeningClientRelease => {
1975                tracing::info!(
1976                    offer_id = offer_id.0,
1977                    key = %channel.offer.key(),
1978                    result,
1979                    "opened channel (client released)"
1980                );
1981
1982                if result >= 0 {
1983                    channel.state = ChannelState::ClosingClientRelease;
1984                    self.notifier.notify(offer_id, Action::Close);
1985                } else {
1986                    channel.state = ChannelState::ClientReleased;
1987                    self.check_disconnected();
1988                }
1989            }
1990
1991            ChannelState::ClientReleased
1992            | ChannelState::Closed
1993            | ChannelState::Open { .. }
1994            | ChannelState::Closing { .. }
1995            | ChannelState::ClosingReopen { .. }
1996            | ChannelState::Revoked
1997            | ChannelState::Reoffered
1998            | ChannelState::ClosingClientRelease => {
1999                tracing::error!(?offer_id, key = %channel.offer.key(), state = ?channel.state, "invalid open complete")
2000            }
2001        }
2002    }
2003
2004    /// If true, all channels are in a reset state, with no references by the
2005    /// guest. Reserved channels should only be included if the VM is resetting.
2006    fn are_channels_reset(&self, include_reserved: bool) -> bool {
2007        self.inner.gpadls.keys().all(|(_, offer_id)| {
2008            !include_reserved && self.inner.channels[*offer_id].state.is_reserved()
2009        }) && self.inner.channels.iter().all(|(_, channel)| {
2010            matches!(channel.state, ChannelState::ClientReleased)
2011                || (!include_reserved && channel.state.is_reserved())
2012        })
2013    }
2014
2015    /// Checks if the connection state is fully disconnected and advances the
2016    /// connection state machine. Must be called any time a GPADL is deleted or
2017    /// a channel enters the ClientReleased state.
2018    fn check_disconnected(&mut self) {
2019        match self.inner.state {
2020            ConnectionState::Disconnecting {
2021                next_action,
2022                modify_sent: false,
2023            } => {
2024                if self.are_channels_reset(matches!(next_action, ConnectionAction::Reset)) {
2025                    self.notify_disconnect(next_action);
2026                }
2027            }
2028            ConnectionState::Disconnecting {
2029                modify_sent: true, ..
2030            }
2031            | ConnectionState::Disconnected
2032            | ConnectionState::Connected { .. }
2033            | ConnectionState::Connecting { .. } => (),
2034        }
2035    }
2036
2037    /// Informs the notifier to reset the connection state when disconnecting.
2038    fn notify_disconnect(&mut self, next_action: ConnectionAction) {
2039        // Assert this on debug only because it is an expensive check if there are many channels.
2040        debug_assert!(self.are_channels_reset(matches!(next_action, ConnectionAction::Reset)));
2041        self.inner.state = ConnectionState::Disconnecting {
2042            next_action,
2043            modify_sent: true,
2044        };
2045
2046        // Reset server state and disconnect the relay if there is one.
2047        self.notifier
2048            .modify_connection(ModifyConnectionRequest {
2049                monitor_page: Update::Reset,
2050                interrupt_page: Update::Reset,
2051                ..Default::default()
2052            })
2053            .expect("resetting state should not fail");
2054    }
2055
2056    /// If true, the server is mid-reset and cannot take certain actions such
2057    /// as handling synic messages or saving state.
2058    fn is_resetting(&self) -> bool {
2059        matches!(
2060            &self.inner.state,
2061            ConnectionState::Connecting {
2062                next_action: ConnectionAction::Reset,
2063                ..
2064            } | ConnectionState::Disconnecting {
2065                next_action: ConnectionAction::Reset,
2066                ..
2067            }
2068        )
2069    }
2070
2071    /// Completes a channel close operation.
2072    pub fn close_complete(&mut self, offer_id: OfferId) {
2073        let channel = &mut self.inner.channels[offer_id];
2074        tracing::info!(offer_id = offer_id.0, key = %channel.offer.key(), "closed channel");
2075        match channel.state {
2076            ChannelState::Closing {
2077                reserved_state: Some(reserved_state),
2078                ..
2079            } => {
2080                channel.state = ChannelState::Closed;
2081                let channel_id = channel.info.expect("assigned").channel_id;
2082                // Always send the close response to the reserved channel's
2083                // requested target, even while disconnected/ing. Reserved
2084                // channels are independent of the connection state.
2085                self.send_close_reserved_channel_response(
2086                    channel_id,
2087                    offer_id,
2088                    reserved_state.target,
2089                );
2090
2091                if !matches!(self.inner.state, ConnectionState::Connected { .. }) {
2092                    // Re-borrow the channel after the &mut self call above.
2093                    let channel = &mut self.inner.channels[offer_id];
2094                    // Handle closing reserved channels while disconnected/ing. Since we weren't waiting
2095                    // on the channel, no need to call check_disconnected, but we do need to release it.
2096                    if Self::client_release_channel(
2097                        self.inner
2098                            .pending_messages
2099                            .sender(self.notifier, self.inner.state.is_paused()),
2100                        offer_id,
2101                        channel,
2102                        &mut self.inner.gpadls,
2103                        &mut self.inner.incomplete_gpadls,
2104                        &mut self.inner.assigned_channels,
2105                        &mut self.inner.assigned_monitors,
2106                        None,
2107                        false,
2108                    ) {
2109                        self.inner.channels.remove(offer_id);
2110                    }
2111                }
2112            }
2113            ChannelState::Closing { .. } => {
2114                channel.state = ChannelState::Closed;
2115            }
2116            ChannelState::ClosingClientRelease => {
2117                channel.state = ChannelState::ClientReleased;
2118                self.check_disconnected();
2119            }
2120            ChannelState::ClosingReopen { request, .. } => {
2121                channel.state = ChannelState::Closed;
2122                self.open_channel(offer_id, &request, None);
2123            }
2124
2125            ChannelState::Closed
2126            | ChannelState::ClientReleased
2127            | ChannelState::Opening { .. }
2128            | ChannelState::Open { .. }
2129            | ChannelState::Revoked
2130            | ChannelState::Reoffered
2131            | ChannelState::OpeningClientRelease => {
2132                tracing::error!(?offer_id, key = %channel.offer.key(), state = ?channel.state, "invalid close complete")
2133            }
2134        }
2135    }
2136
2137    fn send_close_reserved_channel_response(
2138        &mut self,
2139        channel_id: ChannelId,
2140        offer_id: OfferId,
2141        target: ConnectionTarget,
2142    ) {
2143        self.sender().send_message_with_target(
2144            &protocol::CloseReservedChannelResponse { channel_id },
2145            MessageTarget::ReservedChannel(offer_id, target),
2146        );
2147    }
2148
2149    /// Handles MessageType::INITIATE_CONTACT, which requests version
2150    /// negotiation.
2151    fn handle_initiate_contact(
2152        &mut self,
2153        input: &protocol::InitiateContact2,
2154        message: &SynicMessage,
2155        includes_client_id: bool,
2156    ) -> Result<(), ChannelError> {
2157        let target_info =
2158            protocol::TargetInfo::from(input.initiate_contact.interrupt_page_or_target_info);
2159
2160        let target_sint = if message.multiclient
2161            && input.initiate_contact.version_requested >= Version::Win10Rs3_1 as u32
2162        {
2163            target_info.sint()
2164        } else {
2165            VMBUS_SINT
2166        };
2167
2168        let target_vtl = if message.multiclient
2169            && input.initiate_contact.version_requested >= Version::Win10Rs4 as u32
2170        {
2171            target_info.vtl()
2172        } else {
2173            0
2174        };
2175
2176        let feature_flags = if input.initiate_contact.version_requested >= Version::Copper as u32 {
2177            target_info.feature_flags()
2178        } else {
2179            0
2180        };
2181
2182        // Originally, messages were always sent to processor zero.
2183        // Post-Windows 8, it became necessary to send messages to other
2184        // processors in order to support establishing channel connections
2185        // on arbitrary processors after crashing.
2186        let target_message_vp =
2187            if input.initiate_contact.version_requested >= Version::Win8_1 as u32 {
2188                input.initiate_contact.target_message_vp
2189            } else {
2190                0
2191            };
2192
2193        // Guests can send an interrupt page up to protocol Win10Rs3_1 (at which point the
2194        // interrupt page field was reused), but as of Win8 the host can ignore it as it won't be
2195        // used for channels with dedicated interrupts (which is all channels).
2196        //
2197        // V1 doesn't support dedicated interrupts and Win7 only uses dedicated interrupts for
2198        // guest-to-host, so the interrupt page is still used for host-to-guest.
2199        let interrupt_page = (input.initiate_contact.version_requested < Version::Win8 as u32
2200            && input.initiate_contact.interrupt_page_or_target_info != 0)
2201            .then_some(input.initiate_contact.interrupt_page_or_target_info);
2202
2203        // The guest must specify both monitor pages, or neither. Store this information in the
2204        // request so the response can be sent after the version check, and to the correct VTL.
2205        let monitor_page = if (input.initiate_contact.parent_to_child_monitor_page_gpa == 0)
2206            != (input.initiate_contact.child_to_parent_monitor_page_gpa == 0)
2207        {
2208            MonitorPageRequest::Invalid
2209        } else if input.initiate_contact.parent_to_child_monitor_page_gpa != 0 {
2210            MonitorPageRequest::Some(MonitorPageGpas {
2211                parent_to_child: input.initiate_contact.parent_to_child_monitor_page_gpa,
2212                child_to_parent: input.initiate_contact.child_to_parent_monitor_page_gpa,
2213            })
2214        } else {
2215            MonitorPageRequest::None
2216        };
2217
2218        // We differentiate between InitiateContact and InitiateContact2 only by size, so we need to
2219        // check the feature flags here to ensure the client ID should actually be set to the input GUID.
2220        let client_id = if FeatureFlags::from(feature_flags).client_id() {
2221            if includes_client_id {
2222                input.client_id
2223            } else {
2224                return Err(ChannelError::ParseError(
2225                    protocol::ParseError::MessageTooSmall(Some(
2226                        protocol::MessageType::INITIATE_CONTACT,
2227                    )),
2228                ));
2229            }
2230        } else {
2231            Guid::ZERO
2232        };
2233
2234        let request = InitiateContactRequest {
2235            version_requested: input.initiate_contact.version_requested,
2236            target_message_vp,
2237            monitor_page,
2238            target_sint,
2239            target_vtl,
2240            feature_flags,
2241            interrupt_page,
2242            client_id,
2243            trusted: message.trusted,
2244        };
2245        self.initiate_contact(request);
2246        Ok(())
2247    }
2248
2249    pub fn initiate_contact(&mut self, request: InitiateContactRequest) {
2250        // If the request is not for this server's VTL, inform the notifier it wasn't handled so it
2251        // can be forwarded to the correct server.
2252        let vtl = self.inner.assigned_channels.vtl as u8;
2253        if request.target_vtl != vtl {
2254            // Send a notification to a linked server (which handles a different VTL).
2255            self.notifier.forward_unhandled(request);
2256            return;
2257        }
2258
2259        if request.target_sint != VMBUS_SINT {
2260            tracelimit::warn_ratelimited!(
2261                target_vtl = request.target_vtl,
2262                target_sint = request.target_sint,
2263                version = request.version_requested,
2264                "unsupported multiclient request",
2265            );
2266
2267            // Send an unsupported response to the requested SINT.
2268            self.send_version_response_with_target(
2269                None,
2270                MessageTarget::Custom(ConnectionTarget {
2271                    vp: request.target_message_vp,
2272                    sint: request.target_sint,
2273                }),
2274            );
2275
2276            return;
2277        }
2278
2279        if !self.request_disconnect(ConnectionAction::Reconnect {
2280            initiate_contact: request,
2281        }) {
2282            return;
2283        }
2284
2285        let Some(version) = self.check_version_supported(&request) else {
2286            tracelimit::warn_ratelimited!(
2287                vtl,
2288                version = request.version_requested,
2289                client_id = ?request.client_id,
2290                "Guest requested unsupported version"
2291            );
2292
2293            // Do not notify the relay in this case.
2294            self.send_version_response(None);
2295            return;
2296        };
2297
2298        // Make sure we can receive incoming interrupts on the monitor page. The parent to child
2299        // page is not used as this server doesn't send monitored interrupts.
2300        let monitor_page = match request.monitor_page {
2301            MonitorPageRequest::Some(mp) => {
2302                if self.inner.require_server_allocated_mnf {
2303                    if !version.feature_flags.server_specified_monitor_pages() {
2304                        tracelimit::warn_ratelimited!(
2305                            "guest-supplied monitor pages not supported; MNF will be disabled"
2306                        );
2307                    }
2308
2309                    None
2310                } else {
2311                    Some(mp)
2312                }
2313            }
2314            MonitorPageRequest::None => None,
2315            MonitorPageRequest::Invalid => {
2316                // Do not notify the relay in this case.
2317                self.send_version_response(Some(VersionResponseData::new(
2318                    version,
2319                    protocol::ConnectionState::FAILED_UNKNOWN_FAILURE,
2320                )));
2321
2322                return;
2323            }
2324        };
2325
2326        self.inner.state = ConnectionState::Connecting {
2327            info: ConnectionInfo {
2328                version,
2329                trusted: request.trusted,
2330                interrupt_page: request.interrupt_page,
2331                monitor_page: monitor_page.map(MonitorPageGpaInfo::from_guest_gpas),
2332                target_message_vp: request.target_message_vp,
2333                modifying: false,
2334                offers_sent: false,
2335                client_id: request.client_id,
2336                paused: false,
2337            },
2338            next_action: ConnectionAction::None,
2339        };
2340
2341        // Update server state and notify the relay, if any. When complete,
2342        // complete_initiate_contact will be invoked.
2343        if let Err(err) = self.notifier.modify_connection(ModifyConnectionRequest {
2344            version: Some(version),
2345            monitor_page: monitor_page.into(),
2346            interrupt_page: request.interrupt_page.into(),
2347            target_message_vp: Some(request.target_message_vp),
2348            notify_relay: true,
2349        }) {
2350            tracelimit::error_ratelimited!(?err, "server failed to change state");
2351            self.inner.state = ConnectionState::Disconnected;
2352            self.send_version_response(Some(VersionResponseData::new(
2353                version,
2354                protocol::ConnectionState::FAILED_UNKNOWN_FAILURE,
2355            )));
2356        }
2357    }
2358
2359    pub(crate) fn complete_initiate_contact(&mut self, response: ModifyConnectionResponse) {
2360        let ConnectionState::Connecting {
2361            mut info,
2362            next_action,
2363        } = self.inner.state
2364        else {
2365            panic!("Invalid state for completing InitiateContact.");
2366        };
2367
2368        // Some features are handled locally without needing relay support.
2369        // N.B. Server-specified monitor pages are also handled locally but are only conditionally
2370        //      supported.
2371        const LOCAL_FEATURE_FLAGS: FeatureFlags = FeatureFlags::new()
2372            .with_client_id(true)
2373            .with_confidential_channels(true)
2374            .with_gpa_pinning(true);
2375
2376        let (relay_feature_flags, server_specified_monitor_page) = match response {
2377            // There is no relay, or it successfully processed our request.
2378            ModifyConnectionResponse::Supported(
2379                protocol::ConnectionState::SUCCESSFUL,
2380                feature_flags,
2381                server_specified_monitor_page,
2382            ) => (feature_flags, server_specified_monitor_page),
2383            // The relay supports the requested version, but encountered an error, so pass it
2384            // along to the guest.
2385            ModifyConnectionResponse::Supported(
2386                connection_state,
2387                feature_flags,
2388                server_specified_monitor_page,
2389            ) => {
2390                tracelimit::error_ratelimited!(
2391                    ?connection_state,
2392                    "initiate contact failed because relay request failed"
2393                );
2394
2395                // We still report the supported feature flags with an error, so make sure those
2396                // are correct.
2397                info.version.feature_flags &= (feature_flags | LOCAL_FEATURE_FLAGS)
2398                    .with_server_specified_monitor_pages(server_specified_monitor_page.is_some());
2399
2400                self.send_version_response(Some(VersionResponseData::new(
2401                    info.version,
2402                    connection_state,
2403                )));
2404                self.inner.state = ConnectionState::Disconnected;
2405                return;
2406            }
2407            // The relay doesn't support the requested version, so tell the guest to negotiate a new
2408            // one.
2409            ModifyConnectionResponse::Unsupported => {
2410                self.send_version_response(None);
2411                self.inner.state = ConnectionState::Disconnected;
2412                return;
2413            }
2414            ModifyConnectionResponse::Modified(_) => {
2415                panic!("Invalid response for completing InitiateContact.");
2416            }
2417        };
2418
2419        // The server may not provide its own monitor pages if the guest didn't request them.
2420        assert!(
2421            info.version.feature_flags.server_specified_monitor_pages()
2422                || server_specified_monitor_page.is_none()
2423        );
2424
2425        // The relay responds with all the feature flags it supports, so limit the flags reported to
2426        // the guest to include only those handled by the relay or locally.
2427        info.version.feature_flags &= relay_feature_flags | LOCAL_FEATURE_FLAGS;
2428
2429        // If the server allocated a monitor page, also report that feature is supported, and store
2430        // the server pages. The feature bit must be re-enabled because the relay may not report
2431        // support for it.
2432        if let Some(gpas) = server_specified_monitor_page {
2433            info.monitor_page = Some(MonitorPageGpaInfo::from_server_gpas(gpas));
2434            info.version
2435                .feature_flags
2436                .set_server_specified_monitor_pages(true);
2437        } else {
2438            info.version
2439                .feature_flags
2440                .set_server_specified_monitor_pages(false);
2441        }
2442
2443        tracelimit::info_ratelimited!(
2444            vtl = self.inner.assigned_channels.vtl as u8,
2445            version = ?info.version,
2446            client_id = ?info.client_id,
2447            trusted = info.trusted,
2448            "guest negotiated version"
2449        );
2450
2451        let version = info.version;
2452        self.inner.state = ConnectionState::Connected(info);
2453
2454        self.send_version_response(Some(
2455            VersionResponseData::new(version, protocol::ConnectionState::SUCCESSFUL)
2456                .with_monitor_pages(server_specified_monitor_page),
2457        ));
2458        if !matches!(next_action, ConnectionAction::None) && self.request_disconnect(next_action) {
2459            self.do_next_action(next_action);
2460        }
2461    }
2462
2463    /// Determine if a guest's requested version and feature flags are supported.
2464    fn check_version_supported(&self, request: &InitiateContactRequest) -> Option<VersionInfo> {
2465        let version = SUPPORTED_VERSIONS
2466            .iter()
2467            .find(|v| request.version_requested == **v as u32)
2468            .copied()?;
2469
2470        // The max version may be limited in order to test older protocol versions.
2471        if let Some(max_version) = self.inner.max_version {
2472            if version as u32 > max_version.version {
2473                return None;
2474            }
2475        }
2476
2477        let supported_flags = if version >= Version::Copper {
2478            // Confidential channels should only be enabled if the connection is trusted.
2479            let max_supported_flags = SUPPORTED_FEATURE_FLAGS
2480                .with_confidential_channels(request.trusted)
2481                .with_gpa_pinning(self.inner.support_gpa_pinning);
2482
2483            // The max features may be limited in order to test older protocol versions.
2484            if let Some(max_version) = self.inner.max_version {
2485                max_supported_flags & max_version.feature_flags
2486            } else {
2487                max_supported_flags
2488            }
2489        } else {
2490            FeatureFlags::new()
2491        };
2492
2493        let feature_flags = supported_flags & request.feature_flags.into();
2494
2495        assert!(version >= Version::Copper || feature_flags == FeatureFlags::new());
2496        if feature_flags.into_bits() != request.feature_flags {
2497            // This is a common occurrence, especially with the difference between flags that may
2498            // be supported by Hyper-V, OpenVMM, and OpenHCL, so this does not need to be a warning.
2499            tracelimit::info_ratelimited!(
2500                supported = feature_flags.into_bits(),
2501                requested = request.feature_flags,
2502                "guest requested unsupported feature flags."
2503            );
2504        }
2505
2506        Some(VersionInfo {
2507            version,
2508            feature_flags,
2509        })
2510    }
2511
2512    fn send_version_response(&mut self, data: Option<VersionResponseData>) {
2513        self.send_version_response_with_target(data, MessageTarget::Default);
2514    }
2515
2516    fn send_version_response_with_target(
2517        &mut self,
2518        data: Option<VersionResponseData>,
2519        target: MessageTarget,
2520    ) {
2521        enum VersionResponseType {
2522            PreCopper,
2523            Copper,
2524            CopperWithServerMnf,
2525        }
2526
2527        let mut response_copper_with_mnf = protocol::VersionResponse3::new_zeroed();
2528        let response_copper = &mut response_copper_with_mnf.version_response2;
2529        let response = &mut response_copper.version_response;
2530        let mut response_type = VersionResponseType::PreCopper;
2531        if let Some(data) = data {
2532            // Pre-Win8, there is no way to report failures to the guest, so those should be treated
2533            // as unsupported.
2534            if data.state == protocol::ConnectionState::SUCCESSFUL
2535                || data.version.version >= Version::Win8
2536            {
2537                response.version_supported = 1;
2538                response.connection_state = data.state;
2539                response.selected_version_or_connection_id =
2540                    if data.version.version >= Version::Win10Rs3_1 {
2541                        self.inner.child_connection_id
2542                    } else {
2543                        data.version.version as u32
2544                    };
2545
2546                if data.version.version >= Version::Copper {
2547                    response_copper.supported_features = data.version.feature_flags.into();
2548                    response_type = VersionResponseType::Copper;
2549                    if let Some(monitor_page) = data.monitor_pages {
2550                        assert!(data.version.feature_flags.server_specified_monitor_pages());
2551                        response_copper_with_mnf.child_to_parent_monitor_page_gpa =
2552                            monitor_page.child_to_parent;
2553                        response_copper_with_mnf.parent_to_child_monitor_page_gpa =
2554                            monitor_page.parent_to_child;
2555                        response_type = VersionResponseType::CopperWithServerMnf;
2556                    }
2557                }
2558            }
2559        }
2560
2561        // Send the correct type of response based on the negotiated version and flags.
2562        match response_type {
2563            VersionResponseType::PreCopper => {
2564                self.sender().send_message_with_target(response, target)
2565            }
2566            VersionResponseType::Copper => self
2567                .sender()
2568                .send_message_with_target(response_copper, target),
2569            VersionResponseType::CopperWithServerMnf => self
2570                .sender()
2571                .send_message_with_target(&response_copper_with_mnf, target),
2572        }
2573    }
2574
2575    /// Disconnects the guest, putting the server into `new_state` and returning
2576    /// false if there are channels that are not yet fully reset.
2577    fn request_disconnect(&mut self, new_action: ConnectionAction) -> bool {
2578        assert!(!self.is_resetting());
2579
2580        // Release all channels.
2581        let gpadls = &mut self.inner.gpadls;
2582        let vm_reset = matches!(new_action, ConnectionAction::Reset);
2583        self.inner.channels.retain(|offer_id, channel| {
2584            // Release reserved channels only if the VM is resetting
2585            (!vm_reset && channel.state.is_reserved())
2586                || !Self::client_release_channel(
2587                    self.inner
2588                        .pending_messages
2589                        .sender(self.notifier, self.inner.state.is_paused()),
2590                    offer_id,
2591                    channel,
2592                    gpadls,
2593                    &mut self.inner.incomplete_gpadls,
2594                    &mut self.inner.assigned_channels,
2595                    &mut self.inner.assigned_monitors,
2596                    None,
2597                    vm_reset,
2598                )
2599        });
2600
2601        // Transition to disconnected or one of the pending disconnect states,
2602        // depending on whether there are still GPADLs or channels in use by the
2603        // server.
2604        match &mut self.inner.state {
2605            ConnectionState::Disconnected => {
2606                // Cleanup open reserved channels when doing disconnected VM reset
2607                if vm_reset {
2608                    if !self.are_channels_reset(true) {
2609                        self.inner.state = ConnectionState::Disconnecting {
2610                            next_action: ConnectionAction::Reset,
2611                            modify_sent: false,
2612                        };
2613                    }
2614                } else {
2615                    assert!(self.are_channels_reset(false));
2616                }
2617            }
2618
2619            ConnectionState::Connected { .. } => {
2620                if self.are_channels_reset(vm_reset) {
2621                    self.notify_disconnect(new_action);
2622                } else {
2623                    self.inner.state = ConnectionState::Disconnecting {
2624                        next_action: new_action,
2625                        modify_sent: false,
2626                    };
2627                }
2628            }
2629
2630            ConnectionState::Connecting { next_action, .. }
2631            | ConnectionState::Disconnecting { next_action, .. } => {
2632                *next_action = new_action;
2633            }
2634        }
2635
2636        matches!(self.inner.state, ConnectionState::Disconnected)
2637    }
2638
2639    pub(crate) fn complete_disconnect(&mut self) {
2640        if let ConnectionState::Disconnecting {
2641            next_action,
2642            modify_sent,
2643        } = std::mem::replace(&mut self.inner.state, ConnectionState::Disconnected)
2644        {
2645            assert!(self.are_channels_reset(matches!(next_action, ConnectionAction::Reset)));
2646            if !modify_sent {
2647                tracelimit::warn_ratelimited!("unexpected modify response");
2648            }
2649
2650            self.inner.state = ConnectionState::Disconnected;
2651            self.do_next_action(next_action);
2652        } else {
2653            unreachable!("not ready for disconnect");
2654        }
2655    }
2656
2657    fn do_next_action(&mut self, action: ConnectionAction) {
2658        match action {
2659            ConnectionAction::None => {}
2660            ConnectionAction::Reset => {
2661                self.complete_reset();
2662            }
2663            ConnectionAction::SendUnloadComplete => {
2664                self.complete_unload();
2665            }
2666            ConnectionAction::Reconnect { initiate_contact } => {
2667                self.initiate_contact(initiate_contact);
2668            }
2669            ConnectionAction::SendFailedVersionResponse => {
2670                // Used when the relay didn't support the requested version, so send a failed
2671                // response.
2672                self.send_version_response(None);
2673            }
2674        }
2675    }
2676
2677    /// Handles MessageType::UNLOAD, which disconnects the guest.
2678    fn handle_unload(&mut self) {
2679        tracing::debug!(
2680            vtl = self.inner.assigned_channels.vtl as u8,
2681            state = ?self.inner.state,
2682            "VmBus received unload request from guest",
2683        );
2684
2685        if self.request_disconnect(ConnectionAction::SendUnloadComplete) {
2686            self.complete_unload();
2687        }
2688    }
2689
2690    fn complete_unload(&mut self) {
2691        self.notifier.unload_complete();
2692        if let Some(version) = self.inner.delayed_max_version.take() {
2693            self.inner.set_compatibility_version(version, false);
2694        }
2695
2696        self.sender().send_message(&protocol::UnloadComplete {});
2697        tracelimit::info_ratelimited!("Vmbus disconnected");
2698    }
2699
2700    /// Handles MessageType::REQUEST_OFFERS, which requests a list of channel offers.
2701    fn handle_request_offers(&mut self) -> Result<(), ChannelError> {
2702        let ConnectionState::Connected(info) = &mut self.inner.state else {
2703            unreachable!(
2704                "in unexpected state {:?}, should be prevented by Message::parse()",
2705                self.inner.state
2706            );
2707        };
2708
2709        if info.offers_sent {
2710            return Err(ChannelError::OffersAlreadySent);
2711        }
2712
2713        info.offers_sent = true;
2714
2715        // Some guests expects channel IDs to stay consistent across hibernation and resume, so sort
2716        // the current offers before assigning channel IDs.
2717        let mut sorted_channels: Vec<_> = self
2718            .inner
2719            .channels
2720            .iter_mut()
2721            .filter(|(_, channel)| !channel.state.is_reserved())
2722            .collect();
2723
2724        if self.inner.use_absolute_channel_order {
2725            sorted_channels.sort_unstable_by_key(|(_, channel)| {
2726                (
2727                    channel.offer.offer_order.unwrap_or(u64::MAX),
2728                    channel.offer.interface_id,
2729                    channel.offer.instance_id,
2730                )
2731            });
2732        } else {
2733            sorted_channels.sort_unstable_by_key(|(_, channel)| {
2734                (
2735                    channel.offer.interface_id,
2736                    channel.offer.offer_order.unwrap_or(u64::MAX),
2737                    channel.offer.instance_id,
2738                )
2739            });
2740        }
2741
2742        for (offer_id, channel) in sorted_channels {
2743            assert!(matches!(channel.state, ChannelState::ClientReleased));
2744
2745            channel.prepare_channel(
2746                offer_id,
2747                &mut self.inner.assigned_channels,
2748                &mut self.inner.assigned_monitors,
2749            );
2750
2751            channel.state = ChannelState::Closed;
2752            self.inner
2753                .pending_messages
2754                .sender(self.notifier, info.paused)
2755                .send_offer(channel, info);
2756        }
2757        self.sender().send_message(&protocol::AllOffersDelivered {});
2758
2759        Ok(())
2760    }
2761
2762    /// Sends a GPADL to the device after the full list of ranges was received.
2763    fn gpadl_completed(
2764        mut sender: MessageSender<'_, N>,
2765        offer_id: OfferId,
2766        channel: &Channel,
2767        gpadl_id: GpadlId,
2768        gpadl: &mut Gpadl,
2769    ) {
2770        if channel.state.is_revoked() {
2771            let channel_id = channel.info.as_ref().expect("assigned").channel_id;
2772
2773            // A gpadl for a channel that was revoked but still referenced is
2774            // allowed. In this case there is no channel to notify so
2775            // immediately send a success response.
2776            gpadl.state = GpadlState::Accepted;
2777            sender.send_gpadl_created(channel_id, gpadl_id, protocol::STATUS_SUCCESS);
2778        } else {
2779            // Notify the channel of the completed GPADL.
2780            sender.notifier.notify(
2781                offer_id,
2782                Action::Gpadl(gpadl_id, gpadl.count, gpadl.buf.clone()),
2783            );
2784        }
2785    }
2786
2787    /// Handles MessageType::GPADL_HEADER, which creates a new GPADL.
2788    fn handle_gpadl_header_core(
2789        &mut self,
2790        input: &protocol::GpadlHeader,
2791        range: &[u8],
2792    ) -> Result<(), ChannelError> {
2793        // Validate the channel ID.
2794        let (offer_id, channel) = self
2795            .inner
2796            .channels
2797            .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
2798
2799        // GPADL body messages don't contain the channel ID, so prevent creating new
2800        // GPADLs for reserved channels to avoid GPADL ID conflicts.
2801        if channel.state.is_reserved() {
2802            return Err(ChannelError::ChannelReserved);
2803        }
2804
2805        // Create a new GPADL.
2806        let mut gpadl = Gpadl::new(input.count, input.len as usize / 8);
2807        let done = gpadl.append(range)?;
2808
2809        // Store the GPADL in the table.
2810        let gpadl = match self.inner.gpadls.entry((input.gpadl_id, offer_id)) {
2811            Entry::Vacant(entry) => entry.insert(gpadl),
2812            Entry::Occupied(_) => return Err(ChannelError::DuplicateGpadlId),
2813        };
2814
2815        if done {
2816            Self::gpadl_completed(
2817                self.inner
2818                    .pending_messages
2819                    .sender(self.notifier, self.inner.state.is_paused()),
2820                offer_id,
2821                channel,
2822                input.gpadl_id,
2823                gpadl,
2824            )
2825        } else {
2826            // If we're not done, track the offer ID for GPADL body requests
2827            // N.B. The above only checks if the combination of (gpadl_id, offer_id) is unique,
2828            //      which allows for a guest to reuse a gpadl ID in use by a reserved channel (which
2829            //      it may not know about). But for in-progress GPADLs we need to ensure the gpadl
2830            //      ID itself is unique, since the body message doesn't include a channel ID.
2831            match self.inner.incomplete_gpadls.entry(input.gpadl_id) {
2832                Entry::Vacant(entry) => {
2833                    entry.insert(offer_id);
2834                }
2835                Entry::Occupied(_) => {
2836                    self.inner.gpadls.remove(&(input.gpadl_id, offer_id));
2837                    tracelimit::error_ratelimited!(
2838                        channel_id = ?input.channel_id,
2839                        key = %channel.offer.key(),
2840                        gpadl_id = ?input.gpadl_id,
2841                        "duplicate in-progress gpadl ID",
2842                    );
2843                    return Err(ChannelError::DuplicateGpadlId);
2844                }
2845            }
2846        }
2847        Ok(())
2848    }
2849
2850    /// Handles MessageType::GPADL_HEADER, which creates a new GPADL.
2851    fn handle_gpadl_header(&mut self, input: &protocol::GpadlHeader, range: &[u8]) {
2852        if let Err(err) = self.handle_gpadl_header_core(input, range) {
2853            tracelimit::warn_ratelimited!(
2854                err = &err as &dyn std::error::Error,
2855                channel_id = ?input.channel_id,
2856                key = %self.inner.channels.get_by_channel_id(&self.inner.assigned_channels, input.channel_id).map(|(_, c)| c.offer.key()).unwrap_or_default(),
2857                gpadl_id = ?input.gpadl_id,
2858                "error handling gpadl header"
2859            );
2860
2861            // Inform the guest of any error during the header message.
2862            self.sender().send_gpadl_created(
2863                input.channel_id,
2864                input.gpadl_id,
2865                protocol::STATUS_UNSUCCESSFUL,
2866            );
2867        }
2868    }
2869
2870    /// Handles MessageType::GPADL_BODY, which adds more to an in-progress
2871    /// GPADL.
2872    ///
2873    /// N.B. This function only returns an error if the error was not handled locally by sending an
2874    ///      error response to the guest.
2875    fn handle_gpadl_body(
2876        &mut self,
2877        input: &protocol::GpadlBody,
2878        range: &[u8],
2879    ) -> Result<(), ChannelError> {
2880        // Find and update the GPADL.
2881        // N.B. No error response can be sent to the guest if the gpadl ID is invalid, because the
2882        //      channel ID is not known in that case.
2883        let &offer_id = self
2884            .inner
2885            .incomplete_gpadls
2886            .get(&input.gpadl_id)
2887            .ok_or(ChannelError::UnknownGpadlId)?;
2888        let gpadl = self
2889            .inner
2890            .gpadls
2891            .get_mut(&(input.gpadl_id, offer_id))
2892            .ok_or(ChannelError::UnknownGpadlId)?;
2893        let channel = &mut self.inner.channels[offer_id];
2894
2895        match gpadl.append(range) {
2896            Ok(done) => {
2897                if done {
2898                    self.inner.incomplete_gpadls.remove(&input.gpadl_id);
2899                    Self::gpadl_completed(
2900                        self.inner
2901                            .pending_messages
2902                            .sender(self.notifier, self.inner.state.is_paused()),
2903                        offer_id,
2904                        channel,
2905                        input.gpadl_id,
2906                        gpadl,
2907                    )
2908                }
2909            }
2910            Err(err) => {
2911                self.inner.incomplete_gpadls.remove(&input.gpadl_id);
2912                self.inner.gpadls.remove(&(input.gpadl_id, offer_id));
2913                let channel_id = channel.info.as_ref().expect("assigned").channel_id;
2914                tracelimit::warn_ratelimited!(
2915                    err = &err as &dyn std::error::Error,
2916                    channel_id = channel_id.0,
2917                    key = %channel.offer.key(),
2918                    gpadl_id = input.gpadl_id.0,
2919                    "error handling gpadl body"
2920                );
2921                self.sender().send_gpadl_created(
2922                    channel_id,
2923                    input.gpadl_id,
2924                    protocol::STATUS_UNSUCCESSFUL,
2925                );
2926            }
2927        }
2928
2929        Ok(())
2930    }
2931
2932    /// Handles MessageType::GPADL_TEARDOWN, which tears down a GPADL.
2933    fn handle_gpadl_teardown(
2934        &mut self,
2935        input: &protocol::GpadlTeardown,
2936    ) -> Result<(), ChannelError> {
2937        let (offer_id, channel) = self
2938            .inner
2939            .channels
2940            .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
2941
2942        tracing::debug!(
2943            channel_id = input.channel_id.0,
2944            key = %channel.offer.key(),
2945            gpadl_id = input.gpadl_id.0,
2946            "Received GPADL teardown request"
2947        );
2948
2949        let gpadl = self
2950            .inner
2951            .gpadls
2952            .get_mut(&(input.gpadl_id, offer_id))
2953            .ok_or(ChannelError::UnknownGpadlId)?;
2954
2955        match gpadl.state {
2956            GpadlState::InProgress
2957            | GpadlState::Offered
2958            | GpadlState::OfferedTearingDown
2959            | GpadlState::TearingDown => {
2960                return Err(ChannelError::InvalidGpadlState);
2961            }
2962            GpadlState::Accepted => {
2963                if channel.info.as_ref().map(|info| info.channel_id) != Some(input.channel_id) {
2964                    return Err(ChannelError::WrongGpadlChannelId);
2965                }
2966
2967                // GPADL IDs must be unique during teardown. Disallow reserved
2968                // channels to avoid collisions with non-reserved channel GPADL
2969                // IDs across disconnects.
2970                if channel.state.is_reserved() {
2971                    return Err(ChannelError::ChannelReserved);
2972                }
2973
2974                if channel.state.is_revoked() {
2975                    tracing::trace!(
2976                        channel_id = input.channel_id.0,
2977                        key = %channel.offer.key(),
2978                        gpadl_id = input.gpadl_id.0,
2979                        "Gpadl teardown for revoked channel"
2980                    );
2981
2982                    self.inner.gpadls.remove(&(input.gpadl_id, offer_id));
2983                    self.sender().send_gpadl_torndown(input.gpadl_id);
2984                } else {
2985                    gpadl.state = GpadlState::TearingDown;
2986                    self.notifier.notify(
2987                        offer_id,
2988                        Action::TeardownGpadl {
2989                            gpadl_id: input.gpadl_id,
2990                            post_restore: false,
2991                        },
2992                    );
2993                }
2994            }
2995        }
2996        Ok(())
2997    }
2998
2999    /// Moves a channel from the `Closed` to `Opening` state, notifying the
3000    /// device.
3001    fn open_channel(
3002        &mut self,
3003        offer_id: OfferId,
3004        input: &OpenRequest,
3005        reserved_state: Option<ReservedState>,
3006    ) {
3007        let channel = &mut self.inner.channels[offer_id];
3008        assert!(matches!(channel.state, ChannelState::Closed));
3009
3010        channel.state = ChannelState::Opening {
3011            request: *input,
3012            reserved_state,
3013        };
3014
3015        // Do not update info with the guest-provided connection ID, since the
3016        // value must be remembered if the channel is closed and re-opened.
3017        let info = channel.info.as_ref().expect("assigned");
3018        self.notifier.notify(
3019            offer_id,
3020            Action::Open(
3021                OpenParams::from_request(
3022                    info,
3023                    input,
3024                    channel.handled_monitor_info(),
3025                    reserved_state.map(|state| state.target),
3026                ),
3027                self.inner.state.get_version().expect("must be connected"),
3028            ),
3029        );
3030    }
3031
3032    /// Handles MessageType::OPEN_CHANNEL, which opens a channel.
3033    fn handle_open_channel(&mut self, input: &protocol::OpenChannel2) -> Result<(), ChannelError> {
3034        let (offer_id, channel) = self
3035            .inner
3036            .channels
3037            .get_by_channel_id_mut(&self.inner.assigned_channels, input.open_channel.channel_id)?;
3038
3039        let guest_specified_interrupt_info = self
3040            .inner
3041            .state
3042            .check_feature_flags(|ff| ff.guest_specified_signal_parameters())
3043            .then_some(SignalInfo {
3044                event_flag: input.event_flag,
3045                connection_id: input.connection_id,
3046            });
3047
3048        let flags = if self
3049            .inner
3050            .state
3051            .check_feature_flags(|ff| ff.channel_interrupt_redirection())
3052        {
3053            input.flags
3054        } else {
3055            Default::default()
3056        };
3057
3058        let request = OpenRequest {
3059            open_id: input.open_channel.open_id,
3060            ring_buffer_gpadl_id: input.open_channel.ring_buffer_gpadl_id,
3061            target_vp: protocol::vp_index_if_enabled(input.open_channel.target_vp),
3062            downstream_ring_buffer_page_offset: input
3063                .open_channel
3064                .downstream_ring_buffer_page_offset,
3065            user_data: input.open_channel.user_data,
3066            guest_specified_interrupt_info,
3067            flags,
3068        };
3069
3070        match channel.state {
3071            ChannelState::Closed => self.open_channel(offer_id, &request, None),
3072            ChannelState::Closing { params, .. } => {
3073                // Since there is no close complete message, this can happen
3074                // after the ring buffer GPADL is released but before the server
3075                // completes the close request.
3076                channel.state = ChannelState::ClosingReopen { params, request }
3077            }
3078            ChannelState::Revoked | ChannelState::Reoffered => {}
3079
3080            ChannelState::Open { .. }
3081            | ChannelState::Opening { .. }
3082            | ChannelState::ClosingReopen { .. } => return Err(ChannelError::ChannelAlreadyOpen),
3083
3084            ChannelState::ClientReleased
3085            | ChannelState::ClosingClientRelease
3086            | ChannelState::OpeningClientRelease => unreachable!(),
3087        }
3088        Ok(())
3089    }
3090
3091    /// Handles MessageType::CLOSE_CHANNEL, which closes a channel.
3092    fn handle_close_channel(&mut self, input: &protocol::CloseChannel) -> Result<(), ChannelError> {
3093        let (offer_id, channel) = self
3094            .inner
3095            .channels
3096            .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
3097
3098        match channel.state {
3099            ChannelState::Open {
3100                params,
3101                modify_state,
3102                reserved_state: None,
3103            } => {
3104                if modify_state.is_modifying() {
3105                    tracelimit::warn_ratelimited!(
3106                        key = %channel.offer.key(),
3107                        ?modify_state,
3108                        "Client is closing the channel with a modify in progress"
3109                    )
3110                }
3111
3112                channel.state = ChannelState::Closing {
3113                    params,
3114                    reserved_state: None,
3115                };
3116                self.notifier.notify(offer_id, Action::Close);
3117            }
3118
3119            ChannelState::Open {
3120                reserved_state: Some(_),
3121                ..
3122            } => return Err(ChannelError::ChannelReserved),
3123
3124            ChannelState::Revoked | ChannelState::Reoffered => {}
3125
3126            ChannelState::Closed
3127            | ChannelState::Opening { .. }
3128            | ChannelState::Closing { .. }
3129            | ChannelState::ClosingReopen { .. } => return Err(ChannelError::ChannelNotOpen),
3130
3131            ChannelState::ClientReleased
3132            | ChannelState::ClosingClientRelease
3133            | ChannelState::OpeningClientRelease => unreachable!(),
3134        }
3135
3136        Ok(())
3137    }
3138
3139    /// Handles MessageType::OPEN_RESERVED_CHANNEL, which reserves and opens a channel.
3140    /// The version must have already been validated in parse_message.
3141    fn handle_open_reserved_channel(
3142        &mut self,
3143        input: &protocol::OpenReservedChannel,
3144        version: VersionInfo,
3145    ) -> Result<(), ChannelError> {
3146        let (offer_id, channel) = self
3147            .inner
3148            .channels
3149            .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
3150
3151        let target = ConnectionTarget {
3152            vp: input.target_vp,
3153            sint: input.target_sint as u8,
3154        };
3155
3156        let reserved_state = Some(ReservedState { version, target });
3157
3158        let request = OpenRequest {
3159            ring_buffer_gpadl_id: input.ring_buffer_gpadl,
3160            // Interrupts are disabled for reserved channels; this matches Hyper-V behavior.
3161            target_vp: None,
3162            downstream_ring_buffer_page_offset: input.downstream_page_offset,
3163            open_id: 0,
3164            user_data: UserDefinedData::new_zeroed(),
3165            guest_specified_interrupt_info: None,
3166            flags: Default::default(),
3167        };
3168
3169        match channel.state {
3170            ChannelState::Closed => self.open_channel(offer_id, &request, reserved_state),
3171            ChannelState::Revoked | ChannelState::Reoffered => {}
3172
3173            ChannelState::Open { .. } | ChannelState::Opening { .. } => {
3174                return Err(ChannelError::ChannelAlreadyOpen);
3175            }
3176
3177            ChannelState::Closing { .. } | ChannelState::ClosingReopen { .. } => {
3178                return Err(ChannelError::InvalidChannelState);
3179            }
3180
3181            ChannelState::ClientReleased
3182            | ChannelState::ClosingClientRelease
3183            | ChannelState::OpeningClientRelease => unreachable!(),
3184        }
3185        Ok(())
3186    }
3187
3188    /// Handles MessageType::CLOSE_RESERVED_CHANNEL, which closes a reserved channel. Will send
3189    /// the response to the target provided in the request instead of the current reserved target.
3190    fn handle_close_reserved_channel(
3191        &mut self,
3192        input: &protocol::CloseReservedChannel,
3193    ) -> Result<(), ChannelError> {
3194        let (offer_id, channel) = self
3195            .inner
3196            .channels
3197            .get_by_channel_id_mut(&self.inner.assigned_channels, input.channel_id)?;
3198
3199        match channel.state {
3200            ChannelState::Open {
3201                params,
3202                reserved_state: Some(mut resvd),
3203                ..
3204            } => {
3205                resvd.target.vp = input.target_vp;
3206                resvd.target.sint = input.target_sint as u8;
3207                channel.state = ChannelState::Closing {
3208                    params,
3209                    reserved_state: Some(resvd),
3210                };
3211                self.notifier.notify(offer_id, Action::Close);
3212            }
3213
3214            ChannelState::Open {
3215                reserved_state: None,
3216                ..
3217            } => return Err(ChannelError::ChannelNotReserved),
3218
3219            ChannelState::Revoked | ChannelState::Reoffered => {}
3220
3221            ChannelState::Closed
3222            | ChannelState::Opening { .. }
3223            | ChannelState::Closing { .. }
3224            | ChannelState::ClosingReopen { .. } => return Err(ChannelError::ChannelNotOpen),
3225
3226            ChannelState::ClientReleased
3227            | ChannelState::ClosingClientRelease
3228            | ChannelState::OpeningClientRelease => unreachable!(),
3229        }
3230
3231        Ok(())
3232    }
3233
3234    /// Release all guest references on a channel, including GPADLs that are
3235    /// associated with the channel. Returns true if the channel should be
3236    /// deleted.
3237    #[must_use]
3238    fn client_release_channel(
3239        mut sender: MessageSender<'_, N>,
3240        offer_id: OfferId,
3241        channel: &mut Channel,
3242        gpadls: &mut GpadlMap,
3243        incomplete_gpadls: &mut IncompleteGpadlMap,
3244        assigned_channels: &mut AssignedChannels,
3245        assigned_monitors: &mut AssignedMonitors,
3246        info: Option<&ConnectionInfo>,
3247        vm_reset: bool,
3248    ) -> bool {
3249        tracelimit::info_ratelimited!(?offer_id, key = %channel.offer.key(), "client released channel");
3250        // Release any GPADLs that remain for this channel.
3251        gpadls.retain(|&(gpadl_id, gpadl_offer_id), gpadl| {
3252            if gpadl_offer_id != offer_id {
3253                return true;
3254            }
3255            match gpadl.state {
3256                GpadlState::InProgress => {
3257                    incomplete_gpadls.remove(&gpadl_id);
3258                    false
3259                }
3260                GpadlState::Offered => {
3261                    gpadl.state = GpadlState::OfferedTearingDown;
3262                    true
3263                }
3264                GpadlState::Accepted => {
3265                    if channel.state.is_revoked() {
3266                        // There is no need to tear down the GPADL.
3267                        false
3268                    } else {
3269                        gpadl.state = GpadlState::TearingDown;
3270                        sender.notifier.notify(
3271                            offer_id,
3272                            Action::TeardownGpadl {
3273                                gpadl_id,
3274                                post_restore: false,
3275                            },
3276                        );
3277                        true
3278                    }
3279                }
3280                GpadlState::OfferedTearingDown | GpadlState::TearingDown => true,
3281            }
3282        });
3283
3284        let remove = match &mut channel.state {
3285            ChannelState::Closed => {
3286                channel.state = ChannelState::ClientReleased;
3287                false
3288            }
3289            ChannelState::Reoffered => {
3290                if let Some(info) = info {
3291                    channel.state = ChannelState::Closed;
3292                    channel.restore_state = RestoreState::New;
3293                    sender.send_offer(channel, info);
3294                    // Do not release the channel ID.
3295                    return false;
3296                }
3297                channel.state = ChannelState::ClientReleased;
3298                false
3299            }
3300            ChannelState::Revoked => {
3301                channel.state = ChannelState::ClientReleased;
3302                true
3303            }
3304            ChannelState::Opening { .. } => {
3305                // Normally we transition to `OpeningClientRelease` and wait
3306                // for the device to deliver an `open_complete`, then close
3307                // the channel. During a VM reset, however, channel device
3308                // tasks may already be stopped (state-unit reset stops them
3309                // in reverse-dependency order, before the vmbus unit), in
3310                // which case the in-flight `Action::Open` has been pended
3311                // in the device task's stopped-state queue and will never
3312                // be answered. Waiting would deadlock the vmbus reset,
3313                // which in turn blocks the channel-unit reset that would
3314                // drain the queue.
3315                //
3316                // Force-release directly to `ClientReleased` in that case.
3317                // The device has not opened the channel yet, so there is
3318                // no resource to tear down. Any late `Action::Open`
3319                // response that does arrive (for a still-running device
3320                // that races us) is caught by the `invalid open complete`
3321                // branch of `open_complete` and ignored.
3322                if vm_reset {
3323                    channel.state = ChannelState::ClientReleased;
3324                } else {
3325                    channel.state = ChannelState::OpeningClientRelease;
3326                }
3327                false
3328            }
3329            ChannelState::Open { .. } => {
3330                channel.state = ChannelState::ClosingClientRelease;
3331                sender.notifier.notify(offer_id, Action::Close);
3332                false
3333            }
3334            ChannelState::Closing { .. } | ChannelState::ClosingReopen { .. } => {
3335                channel.state = ChannelState::ClosingClientRelease;
3336                false
3337            }
3338
3339            ChannelState::ClosingClientRelease
3340            | ChannelState::OpeningClientRelease
3341            | ChannelState::ClientReleased => false,
3342        };
3343
3344        assert!(channel.state.is_released());
3345
3346        channel.release_channel(offer_id, assigned_channels, assigned_monitors);
3347        remove
3348    }
3349
3350    /// Handles MessageType::REL_ID_RELEASED, which releases the guest references to a channel.
3351    fn handle_rel_id_released(
3352        &mut self,
3353        input: &protocol::RelIdReleased,
3354    ) -> Result<(), ChannelError> {
3355        let channel_id = input.channel_id;
3356        let (offer_id, channel) = self
3357            .inner
3358            .channels
3359            .get_by_channel_id_mut(&self.inner.assigned_channels, channel_id)?;
3360
3361        match channel.state {
3362            ChannelState::Closed
3363            | ChannelState::Revoked
3364            | ChannelState::Closing { .. }
3365            | ChannelState::Reoffered => {
3366                if Self::client_release_channel(
3367                    self.inner
3368                        .pending_messages
3369                        .sender(self.notifier, self.inner.state.is_paused()),
3370                    offer_id,
3371                    channel,
3372                    &mut self.inner.gpadls,
3373                    &mut self.inner.incomplete_gpadls,
3374                    &mut self.inner.assigned_channels,
3375                    &mut self.inner.assigned_monitors,
3376                    self.inner.state.get_connected_info(),
3377                    false,
3378                ) {
3379                    self.inner.channels.remove(offer_id);
3380                }
3381
3382                self.check_disconnected();
3383            }
3384
3385            ChannelState::Opening { .. }
3386            | ChannelState::Open { .. }
3387            | ChannelState::ClosingReopen { .. } => return Err(ChannelError::InvalidChannelState),
3388
3389            ChannelState::ClientReleased
3390            | ChannelState::OpeningClientRelease
3391            | ChannelState::ClosingClientRelease => unreachable!(),
3392        }
3393        Ok(())
3394    }
3395
3396    /// Handles MessageType::TL_CONNECT_REQUEST, which requests for an hvsocket
3397    /// connection.
3398    fn handle_tl_connect_request(&mut self, request: protocol::TlConnectRequest2) {
3399        let version = self
3400            .inner
3401            .state
3402            .get_version()
3403            .expect("must be connected")
3404            .version;
3405
3406        let hosted_silo_unaware = version < Version::Win10Rs5;
3407        self.notifier
3408            .notify_hvsock(&HvsockConnectRequest::from_message(
3409                request,
3410                hosted_silo_unaware,
3411            ));
3412    }
3413
3414    /// Sends a message to the guest if an hvsocket connect request failed.
3415    pub fn send_tl_connect_result(&mut self, result: HvsockConnectResult) {
3416        // TODO: need save/restore handling for this... probably OK to just drop
3417        // all such requests given hvsock's general lack of save/restore
3418        // support.
3419        if !result.success && self.inner.state.check_version(Version::Win10Rs3_0) {
3420            // Windows guests care about the error code used here; using STATUS_CONNECTION_REFUSED
3421            // ensures a sensible error gets returned to the user that tried to connect to the
3422            // socket.
3423            self.sender().send_message(&protocol::TlConnectResult {
3424                service_id: result.service_id,
3425                endpoint_id: result.endpoint_id,
3426                status: protocol::STATUS_CONNECTION_REFUSED,
3427            })
3428        }
3429    }
3430
3431    /// Handles MessageType::MODIFY_CHANNEL, which allows the guest to request a
3432    /// new target VP for the channel's interrupts.
3433    fn handle_modify_channel(
3434        &mut self,
3435        request: &protocol::ModifyChannel,
3436    ) -> Result<(), ChannelError> {
3437        let result = self.modify_channel(request);
3438        if result.is_err() {
3439            self.send_modify_channel_response(request.channel_id, protocol::STATUS_UNSUCCESSFUL);
3440        }
3441
3442        result
3443    }
3444
3445    /// Modifies a channel's target VP.
3446    fn modify_channel(&mut self, request: &protocol::ModifyChannel) -> Result<(), ChannelError> {
3447        // The ModifyChannel message cannot be used to disable interrupts.
3448        if request.target_vp == protocol::VP_INDEX_DISABLE_INTERRUPT {
3449            return Err(ChannelError::InvalidTargetVp);
3450        }
3451
3452        let (offer_id, channel) = self
3453            .inner
3454            .channels
3455            .get_by_channel_id_mut(&self.inner.assigned_channels, request.channel_id)?;
3456
3457        let (open_request, modify_state) = match &mut channel.state {
3458            ChannelState::Open {
3459                params,
3460                modify_state,
3461                reserved_state: None,
3462            } => (params, modify_state),
3463            _ => return Err(ChannelError::InvalidChannelState),
3464        };
3465
3466        if open_request.target_vp.is_none() {
3467            return Err(ChannelError::InterruptsDisabled);
3468        }
3469
3470        if let ModifyState::Modifying { pending_target_vp } = modify_state {
3471            if self.inner.state.check_version(Version::Iron) {
3472                // On Iron or later, the client isn't allowed to send a ModifyChannel
3473                // request while another one is still in progress.
3474                tracelimit::warn_ratelimited!(
3475                    key = %channel.offer.key(),
3476                    "Client sent new ModifyChannel before receiving ModifyChannelResponse."
3477                );
3478            } else {
3479                // On older versions, the client doesn't know if the operation is complete,
3480                // so store the latest request to execute when the current one completes.
3481                *pending_target_vp = Some(request.target_vp);
3482            }
3483        } else {
3484            self.notifier.notify(
3485                offer_id,
3486                Action::Modify {
3487                    target_vp: request.target_vp,
3488                },
3489            );
3490
3491            // Update the stored open_request so that save/restore will use the new value.
3492            open_request.target_vp = Some(request.target_vp);
3493            *modify_state = ModifyState::Modifying {
3494                pending_target_vp: None,
3495            };
3496        }
3497
3498        Ok(())
3499    }
3500
3501    /// Complete the ModifyChannel message.
3502    ///
3503    /// N.B. The guest expects no further interrupts on the old VP at this point. This
3504    ///      is guaranteed because notify() handles updating the event port synchronously before,
3505    ///      notifying the device/relay, and all types of event port protect their VP settings
3506    ///      with locks.
3507    pub fn modify_channel_complete(&mut self, offer_id: OfferId, status: i32) {
3508        let channel = &mut self.inner.channels[offer_id];
3509
3510        if let ChannelState::Open {
3511            params,
3512            modify_state: ModifyState::Modifying { pending_target_vp },
3513            reserved_state: None,
3514        } = channel.state
3515        {
3516            channel.state = ChannelState::Open {
3517                params,
3518                modify_state: ModifyState::NotModifying,
3519                reserved_state: None,
3520            };
3521
3522            // Send the ModifyChannelResponse message if the protocol supports it.
3523            let channel_id = channel.info.as_ref().expect("assigned").channel_id;
3524            let key = channel.offer.key();
3525            self.send_modify_channel_response(channel_id, status);
3526
3527            // Handle a pending ModifyChannel request if there is one.
3528            if let Some(target_vp) = pending_target_vp {
3529                let request = protocol::ModifyChannel {
3530                    channel_id,
3531                    target_vp,
3532                };
3533
3534                if let Err(error) = self.handle_modify_channel(&request) {
3535                    tracelimit::warn_ratelimited!(?error, %key, "Pending ModifyChannel request failed.")
3536                }
3537            }
3538        }
3539    }
3540
3541    fn send_modify_channel_response(&mut self, channel_id: ChannelId, status: i32) {
3542        if self.inner.state.check_version(Version::Iron) {
3543            self.sender()
3544                .send_message(&protocol::ModifyChannelResponse { channel_id, status });
3545        }
3546    }
3547
3548    fn handle_modify_connection(&mut self, request: protocol::ModifyConnection) {
3549        if let Err(err) = self.modify_connection(request) {
3550            tracelimit::error_ratelimited!(?err, "modifying connection failed");
3551            self.complete_modify_connection(ModifyConnectionResponse::Modified(
3552                protocol::ConnectionState::FAILED_UNKNOWN_FAILURE,
3553            ));
3554        }
3555    }
3556
3557    fn modify_connection(&mut self, request: protocol::ModifyConnection) -> anyhow::Result<()> {
3558        let ConnectionState::Connected(info) = &mut self.inner.state else {
3559            anyhow::bail!(
3560                "Invalid state for ModifyConnection request: {:?}",
3561                self.inner.state
3562            );
3563        };
3564
3565        if info.modifying {
3566            anyhow::bail!(
3567                "Duplicate ModifyConnection request, state: {:?}",
3568                self.inner.state
3569            );
3570        }
3571
3572        if matches!(
3573            info.monitor_page,
3574            Some(MonitorPageGpaInfo {
3575                server_allocated: true,
3576                ..
3577            })
3578        ) {
3579            anyhow::bail!("Cannot modify server-allocated monitor pages");
3580        }
3581
3582        if (request.child_to_parent_monitor_page_gpa == 0)
3583            != (request.parent_to_child_monitor_page_gpa == 0)
3584        {
3585            anyhow::bail!("Guest must specify either both or no monitor pages, {request:?}");
3586        }
3587
3588        let monitor_page = (request.child_to_parent_monitor_page_gpa != 0).then_some(
3589            MonitorPageGpaInfo::from_guest_gpas(MonitorPageGpas {
3590                child_to_parent: request.child_to_parent_monitor_page_gpa,
3591                parent_to_child: request.parent_to_child_monitor_page_gpa,
3592            }),
3593        );
3594
3595        info.modifying = true;
3596        info.monitor_page = monitor_page;
3597        tracing::debug!("modifying connection parameters.");
3598        self.notifier.modify_connection(request.into())?;
3599
3600        Ok(())
3601    }
3602
3603    pub fn complete_modify_connection(&mut self, response: ModifyConnectionResponse) {
3604        tracing::debug!(?response, "modifying connection parameters complete");
3605
3606        // InitiateContact, Unload, and actual ModifyConnection messages are all sent to the relay
3607        // as ModifyConnection requests, so use the server state to determine how to handle the
3608        // response.
3609        match &mut self.inner.state {
3610            ConnectionState::Connecting { .. } => self.complete_initiate_contact(response),
3611            ConnectionState::Disconnecting { .. } => self.complete_disconnect(),
3612            ConnectionState::Connected(info) => {
3613                let ModifyConnectionResponse::Modified(connection_state) = response else {
3614                    panic!(
3615                        "Relay should not return {:?} for a modify request with no version.",
3616                        response
3617                    );
3618                };
3619
3620                if !info.modifying {
3621                    panic!(
3622                        "ModifyConnection response while not modifying, state: {:?}",
3623                        self.inner.state
3624                    );
3625                }
3626
3627                info.modifying = false;
3628                self.sender()
3629                    .send_message(&protocol::ModifyConnectionResponse { connection_state });
3630            }
3631            _ => panic!(
3632                "Invalid state for ModifyConnection response: {:?}",
3633                self.inner.state
3634            ),
3635        }
3636    }
3637
3638    fn handle_pause(&mut self) {
3639        tracelimit::info_ratelimited!("pausing sending messages");
3640        self.sender().send_message(&protocol::PauseResponse {});
3641        let ConnectionState::Connected(info) = &mut self.inner.state else {
3642            unreachable!(
3643                "in unexpected state {:?}, should be prevented by Message::parse()",
3644                self.inner.state
3645            );
3646        };
3647        info.paused = true;
3648    }
3649
3650    /// Processes an incoming message from the guest.
3651    pub fn handle_synic_message(&mut self, message: SynicMessage) -> Result<(), ChannelError> {
3652        assert!(!self.is_resetting());
3653
3654        let version = self.inner.state.get_version();
3655        let msg = Message::parse(&message.data, version)?;
3656        tracing::trace!(?msg, message.trusted, "received vmbus message");
3657        // Do not allow untrusted messages if the connection was established
3658        // using a trusted message.
3659        //
3660        // TODO: Don't allow trusted messages if an untrusted connection was ever used.
3661        if self.inner.state.is_trusted() && !message.trusted {
3662            tracelimit::warn_ratelimited!(?msg, "Received untrusted message");
3663            return Err(ChannelError::UntrustedMessage);
3664        }
3665
3666        // Unpause channel responses if they are paused.
3667        match &mut self.inner.state {
3668            ConnectionState::Connected(info) if info.paused => {
3669                if !matches!(
3670                    msg,
3671                    Message::Resume(..)
3672                        | Message::Unload(..)
3673                        | Message::InitiateContact { .. }
3674                        | Message::InitiateContact2 { .. }
3675                ) {
3676                    tracelimit::warn_ratelimited!(?msg, "Received message while paused");
3677                    return Err(ChannelError::Paused);
3678                }
3679                tracelimit::info_ratelimited!("resuming sending messages");
3680                info.paused = false;
3681            }
3682            _ => {}
3683        }
3684
3685        match msg {
3686            Message::InitiateContact2(input, ..) => {
3687                self.handle_initiate_contact(&input, &message, true)?
3688            }
3689            Message::InitiateContact(input, ..) => {
3690                self.handle_initiate_contact(&input.into(), &message, false)?
3691            }
3692            Message::Unload(..) => self.handle_unload(),
3693            Message::RequestOffers(..) => self.handle_request_offers()?,
3694            Message::GpadlHeader(input, range) => self.handle_gpadl_header(&input, range),
3695            Message::GpadlBody(input, range) => self.handle_gpadl_body(&input, range)?,
3696            Message::GpadlTeardown(input, ..) => self.handle_gpadl_teardown(&input)?,
3697            Message::OpenChannel(input, ..) => self.handle_open_channel(&input.into())?,
3698            Message::OpenChannel2(input, ..) => self.handle_open_channel(&input)?,
3699            Message::CloseChannel(input, ..) => self.handle_close_channel(&input)?,
3700            Message::RelIdReleased(input, ..) => self.handle_rel_id_released(&input)?,
3701            Message::TlConnectRequest(input, ..) => self.handle_tl_connect_request(input.into()),
3702            Message::TlConnectRequest2(input, ..) => self.handle_tl_connect_request(input),
3703            Message::ModifyChannel(input, ..) => self.handle_modify_channel(&input)?,
3704            Message::ModifyConnection(input, ..) => self.handle_modify_connection(input),
3705            Message::OpenReservedChannel(input, ..) => self.handle_open_reserved_channel(
3706                &input,
3707                version.expect("version validated by Message::parse"),
3708            )?,
3709            Message::CloseReservedChannel(input, ..) => {
3710                self.handle_close_reserved_channel(&input)?
3711            }
3712            Message::Pause(protocol::Pause, ..) => self.handle_pause(),
3713            Message::Resume(protocol::Resume, ..) => {}
3714            // Messages that should only be received by a vmbus client.
3715            Message::OfferChannel(..)
3716            | Message::RescindChannelOffer(..)
3717            | Message::AllOffersDelivered(..)
3718            | Message::OpenResult(..)
3719            | Message::GpadlCreated(..)
3720            | Message::GpadlTorndown(..)
3721            | Message::VersionResponse(..)
3722            | Message::VersionResponse2(..)
3723            | Message::VersionResponse3(..)
3724            | Message::UnloadComplete(..)
3725            | Message::CloseReservedChannelResponse(..)
3726            | Message::TlConnectResult(..)
3727            | Message::ModifyChannelResponse(..)
3728            | Message::ModifyConnectionResponse(..)
3729            | Message::PauseResponse(..) => {
3730                unreachable!("Server received client message {:?}", msg);
3731            }
3732        }
3733        Ok(())
3734    }
3735
3736    /// Completes a GPADL creation, accepting it if `status >= 0`, rejecting it otherwise.
3737    pub fn gpadl_create_complete(&mut self, offer_id: OfferId, gpadl_id: GpadlId, status: i32) {
3738        let Some(gpadl) = self.inner.gpadls.get_mut(&(gpadl_id, offer_id)) else {
3739            tracelimit::error_ratelimited!(
3740                ?offer_id,
3741                key = %self.inner.channels[offer_id].offer.key(),
3742                ?gpadl_id,
3743                "invalid gpadl ID for channel"
3744            );
3745            return;
3746        };
3747        let retain = match gpadl.state {
3748            GpadlState::InProgress | GpadlState::TearingDown | GpadlState::Accepted => {
3749                tracelimit::error_ratelimited!(?offer_id, ?gpadl_id, ?gpadl, "invalid gpadl state");
3750                return;
3751            }
3752            GpadlState::Offered => {
3753                let channel_id = self.inner.channels[offer_id]
3754                    .info
3755                    .as_ref()
3756                    .expect("assigned")
3757                    .channel_id;
3758                self.inner
3759                    .pending_messages
3760                    .sender(self.notifier, self.inner.state.is_paused())
3761                    .send_gpadl_created(channel_id, gpadl_id, status);
3762                if status >= 0 {
3763                    gpadl.state = GpadlState::Accepted;
3764                    true
3765                } else {
3766                    false
3767                }
3768            }
3769            GpadlState::OfferedTearingDown => {
3770                if status >= 0 {
3771                    // Tear down the GPADL immediately.
3772                    self.notifier.notify(
3773                        offer_id,
3774                        Action::TeardownGpadl {
3775                            gpadl_id,
3776                            post_restore: false,
3777                        },
3778                    );
3779                    gpadl.state = GpadlState::TearingDown;
3780                    true
3781                } else {
3782                    false
3783                }
3784            }
3785        };
3786        if !retain {
3787            self.inner
3788                .gpadls
3789                .remove(&(gpadl_id, offer_id))
3790                .expect("gpadl validated above");
3791
3792            self.check_disconnected();
3793        }
3794    }
3795
3796    /// Releases a GPADL that is being torn down.
3797    pub fn gpadl_teardown_complete(&mut self, offer_id: OfferId, gpadl_id: GpadlId) {
3798        let channel = &mut self.inner.channels[offer_id];
3799        let Some(gpadl) = self.inner.gpadls.get_mut(&(gpadl_id, offer_id)) else {
3800            tracelimit::error_ratelimited!(
3801                ?offer_id,
3802                key = %channel.offer.key(),
3803                ?gpadl_id,
3804                "invalid gpadl ID for channel"
3805            );
3806            return;
3807        };
3808        tracing::debug!(
3809            offer_id = offer_id.0,
3810            key = %channel.offer.key(),
3811            gpadl_id = gpadl_id.0,
3812            "Gpadl teardown complete"
3813        );
3814        match gpadl.state {
3815            GpadlState::InProgress
3816            | GpadlState::Offered
3817            | GpadlState::OfferedTearingDown
3818            | GpadlState::Accepted => {
3819                tracelimit::error_ratelimited!(?offer_id, key = %channel.offer.key(), ?gpadl_id, ?gpadl, "invalid gpadl state");
3820            }
3821            GpadlState::TearingDown => {
3822                if !channel.state.is_released() {
3823                    self.sender().send_gpadl_torndown(gpadl_id);
3824                }
3825                self.inner
3826                    .gpadls
3827                    .remove(&(gpadl_id, offer_id))
3828                    .expect("gpadl validated above");
3829
3830                self.check_disconnected();
3831            }
3832        }
3833    }
3834
3835    /// Creates a sender, in a convenient way for callers that are able to borrow all of `self`.
3836    ///
3837    /// If you cannot borrow all of `self`, you will need to use the `PendingMessages::sender`
3838    /// method instead.
3839    fn sender(&mut self) -> MessageSender<'_, N> {
3840        self.inner
3841            .pending_messages
3842            .sender(self.notifier, self.inner.state.is_paused())
3843    }
3844}
3845
3846fn revoke<N: Notifier>(
3847    mut sender: MessageSender<'_, N>,
3848    offer_id: OfferId,
3849    channel: &mut Channel,
3850    gpadls: &mut GpadlMap,
3851) -> bool {
3852    let info = match channel.state {
3853        ChannelState::Closed
3854        | ChannelState::Open { .. }
3855        | ChannelState::Opening { .. }
3856        | ChannelState::Closing { .. }
3857        | ChannelState::ClosingReopen { .. } => {
3858            channel.state = ChannelState::Revoked;
3859            Some(channel.info.as_ref().expect("assigned"))
3860        }
3861        ChannelState::Reoffered => {
3862            channel.state = ChannelState::Revoked;
3863            None
3864        }
3865        ChannelState::ClientReleased
3866        | ChannelState::OpeningClientRelease
3867        | ChannelState::ClosingClientRelease => None,
3868        // If the channel is being dropped, it may already have been revoked explicitly.
3869        ChannelState::Revoked => return true,
3870    };
3871    let retain = !channel.state.is_released();
3872
3873    // Release any GPADLs.
3874    gpadls.retain(|&(gpadl_id, gpadl_offer_id), gpadl| {
3875        if gpadl_offer_id != offer_id {
3876            return true;
3877        }
3878
3879        match gpadl.state {
3880            GpadlState::InProgress => true,
3881            GpadlState::Offered => {
3882                if let Some(info) = info {
3883                    sender.send_gpadl_created(
3884                        info.channel_id,
3885                        gpadl_id,
3886                        protocol::STATUS_UNSUCCESSFUL,
3887                    );
3888                }
3889                false
3890            }
3891            GpadlState::OfferedTearingDown => false,
3892            GpadlState::Accepted => true,
3893            GpadlState::TearingDown => {
3894                if info.is_some() {
3895                    sender.send_gpadl_torndown(gpadl_id);
3896                }
3897                false
3898            }
3899        }
3900    });
3901    if let Some(info) = info {
3902        sender.send_rescind(info);
3903    }
3904    // Revoking a channel effectively completes the restore operation for it.
3905    if channel.restore_state != RestoreState::New {
3906        channel.restore_state = RestoreState::Restored;
3907    }
3908    retain
3909}
3910
3911struct PendingMessages(VecDeque<OutgoingMessage>);
3912
3913impl PendingMessages {
3914    /// Creates a sender for the specified notifier.
3915    fn sender<'a, N: Notifier>(
3916        &'a mut self,
3917        notifier: &'a mut N,
3918        is_paused: bool,
3919    ) -> MessageSender<'a, N> {
3920        MessageSender {
3921            notifier,
3922            pending_messages: self,
3923            is_paused,
3924        }
3925    }
3926}
3927
3928/// Wraps the state needed to send messages to the guest through the notifier, and queue them if
3929/// they are not immediately sent.
3930struct MessageSender<'a, N> {
3931    notifier: &'a mut N,
3932    pending_messages: &'a mut PendingMessages,
3933    is_paused: bool,
3934}
3935
3936impl<N: Notifier> MessageSender<'_, N> {
3937    /// Sends a VMBus channel message to the guest.
3938    fn send_message<
3939        T: IntoBytes + protocol::VmbusMessage + std::fmt::Debug + Immutable + KnownLayout,
3940    >(
3941        &mut self,
3942        msg: &T,
3943    ) {
3944        let message = OutgoingMessage::new(msg);
3945
3946        tracing::trace!(typ = ?T::MESSAGE_TYPE, ?msg, "sending message");
3947        // Don't try to send the message if there are already pending messages.
3948        if !self.pending_messages.0.is_empty()
3949            || self.is_paused
3950            || !self.notifier.send_message(&message, MessageTarget::Default)
3951        {
3952            tracing::trace!("message queued");
3953            // Queue the message for retry later.
3954            self.pending_messages.0.push_back(message);
3955        }
3956    }
3957
3958    /// Sends a VMBus channel message to the guest via an alternate port.
3959    fn send_message_with_target<
3960        T: IntoBytes + protocol::VmbusMessage + std::fmt::Debug + Immutable + KnownLayout,
3961    >(
3962        &mut self,
3963        msg: &T,
3964        target: MessageTarget,
3965    ) {
3966        if target == MessageTarget::Default {
3967            self.send_message(msg);
3968        } else {
3969            tracing::trace!(typ = ?T::MESSAGE_TYPE, ?msg, "sending message");
3970            // Messages for other targets are not queued, nor are they affected
3971            // by the paused state.
3972            let message = OutgoingMessage::new(msg);
3973            if !self.notifier.send_message(&message, target) {
3974                tracelimit::warn_ratelimited!(?target, "failed to send message");
3975            }
3976        }
3977    }
3978
3979    /// Sends a channel offer message to the guest.
3980    fn send_offer(&mut self, channel: &mut Channel, connection_info: &ConnectionInfo) {
3981        let info = channel.info.as_ref().expect("assigned");
3982        let mut flags = channel.offer.flags;
3983
3984        // Disable offer flags that are not supported by the current set of feature flags.
3985        if !connection_info
3986            .version
3987            .feature_flags
3988            .confidential_channels()
3989        {
3990            flags.set_confidential_ring_buffer(false);
3991            flags.set_confidential_external_memory(false);
3992        }
3993
3994        if !connection_info.version.feature_flags.gpa_pinning() {
3995            flags.set_require_pinned_external_memory(false);
3996        }
3997
3998        // Send the monitor ID only if the guest supports MNF. MNF may also be disabled if the guest
3999        // provided monitor pages but this server can only use server-allocated monitor pages
4000        // (typically the case for OpenHCL on a hardware-isolated VM), but the guest didn't support
4001        // that. Since we cannot tell the guest to stop using MNF completely, sending the channel
4002        // without a monitor ID will prevent the guest from trying to use MNF to send interrupts for
4003        // it.
4004        let monitor_id = connection_info.monitor_page.and(info.monitor_id);
4005        let msg = protocol::OfferChannel {
4006            interface_id: channel.offer.interface_id,
4007            instance_id: channel.offer.instance_id,
4008            rsvd: [0; 4],
4009            flags,
4010            mmio_megabytes: channel.offer.mmio_megabytes,
4011            user_defined: channel.offer.user_defined,
4012            subchannel_index: channel.offer.subchannel_index,
4013            mmio_megabytes_optional: channel.offer.mmio_megabytes_optional,
4014            channel_id: info.channel_id,
4015            monitor_id: monitor_id.unwrap_or(MonitorId::INVALID).0,
4016            monitor_allocated: monitor_id.is_some().into(),
4017            // All channels are dedicated with Win8+ hosts.
4018            // These fields are sent to V1 guests as well, which will ignore them.
4019            is_dedicated: 1,
4020            connection_id: info.connection_id,
4021        };
4022        tracing::info!(
4023            channel_id = msg.channel_id.0,
4024            connection_id = msg.connection_id,
4025            offer_order = ?channel.offer.offer_order,
4026            key = %channel.offer.key(),
4027            "sending offer to guest"
4028        );
4029
4030        self.send_message(&msg);
4031    }
4032
4033    fn send_open_result(
4034        &mut self,
4035        channel_id: ChannelId,
4036        open_request: &OpenRequest,
4037        result: i32,
4038        target: MessageTarget,
4039    ) {
4040        self.send_message_with_target(
4041            &protocol::OpenResult {
4042                channel_id,
4043                open_id: open_request.open_id,
4044                status: result as u32,
4045            },
4046            target,
4047        );
4048    }
4049
4050    fn send_gpadl_created(&mut self, channel_id: ChannelId, gpadl_id: GpadlId, status: i32) {
4051        self.send_message(&protocol::GpadlCreated {
4052            channel_id,
4053            gpadl_id,
4054            status,
4055        });
4056    }
4057
4058    fn send_gpadl_torndown(&mut self, gpadl_id: GpadlId) {
4059        self.send_message(&protocol::GpadlTorndown { gpadl_id });
4060    }
4061
4062    fn send_rescind(&mut self, info: &OfferedInfo) {
4063        tracing::info!(
4064            channel_id = info.channel_id.0,
4065            "rescinding channel from guest"
4066        );
4067
4068        self.send_message(&protocol::RescindChannelOffer {
4069            channel_id: info.channel_id,
4070        });
4071    }
4072}
4073
4074/// Provides information needed to send a VersionResponse message for a supported version.
4075struct VersionResponseData {
4076    version: VersionInfo,
4077    state: protocol::ConnectionState,
4078    monitor_pages: Option<MonitorPageGpas>,
4079}
4080
4081impl VersionResponseData {
4082    /// Creates a new `VersionResponseData` with the negotiated version and connection state.
4083    fn new(version: VersionInfo, state: protocol::ConnectionState) -> Self {
4084        VersionResponseData {
4085            version,
4086            state,
4087            monitor_pages: None,
4088        }
4089    }
4090
4091    /// Attaches server-allocated monitor pages to be sent with the response.
4092    fn with_monitor_pages(mut self, monitor_pages: Option<MonitorPageGpas>) -> Self {
4093        self.monitor_pages = monitor_pages;
4094        self
4095    }
4096}