vmm_core/partition_unit/
vp_set.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Virtual processor state management.
5
6use super::HaltReason;
7use super::HaltReasonReceiver;
8use super::InternalHaltReason;
9#[cfg(feature = "gdb")]
10use anyhow::Context as _;
11use async_trait::async_trait;
12use futures::FutureExt;
13use futures::StreamExt;
14use futures::future::JoinAll;
15use futures::future::TryJoinAll;
16use futures::stream::select_with_strategy;
17use futures_concurrency::future::Race;
18use futures_concurrency::stream::Merge;
19use guestmem::GuestMemory;
20use hvdef::Vtl;
21use inspect::Inspect;
22use mesh::rpc::Rpc;
23use mesh::rpc::RpcError;
24use mesh::rpc::RpcSend;
25use parking_lot::Mutex;
26use slab::Slab;
27use std::future::Future;
28use std::pin::Pin;
29use std::pin::pin;
30use std::sync::Arc;
31use std::task::Context;
32use std::task::Poll;
33use std::task::Waker;
34use thiserror::Error;
35use tracing::instrument;
36use virt::InitialRegs;
37use virt::Processor;
38use virt::StopVp;
39use virt::StopVpSource;
40use virt::VpHaltReason;
41use virt::VpIndex;
42use virt::VpStopped;
43use virt::io::CpuIo;
44use virt::vp::AccessVpState;
45use vm_topology::processor::TargetVpInfo;
46use vmcore::save_restore::ProtobufSaveRestore;
47use vmcore::save_restore::RestoreError;
48use vmcore::save_restore::SaveError;
49use vmcore::save_restore::SavedStateBlob;
50#[cfg(feature = "gdb")]
51use vmm_core_defs::debug_rpc::DebuggerVpState;
52
53const NUM_VTLS: usize = 3;
54
55/// Trait for controlling a VP on a bound partition.
56#[async_trait(?Send)]
57trait ControlVp: ProtobufSaveRestore {
58    /// Run the VP until `stop` says to stop.
59    async fn run_vp(
60        &mut self,
61        vtl_guest_memory: &[Option<GuestMemory>; NUM_VTLS],
62        stop: StopVp<'_>,
63    ) -> Result<StopReason, HaltReason>;
64
65    /// Inspect the VP.
66    fn inspect_vp(&mut self, gm: &[Option<GuestMemory>; NUM_VTLS], req: inspect::Request<'_>);
67
68    /// Sets the register state at first boot.
69    fn set_initial_regs(
70        &mut self,
71        vtl: Vtl,
72        state: &InitialRegs,
73        to_set: RegistersToSet,
74    ) -> Result<(), RegisterSetError>;
75
76    #[cfg(feature = "gdb")]
77    fn debug(&mut self) -> &mut dyn DebugVp;
78}
79
80enum StopReason {
81    OnRequest(VpStopped),
82    Cancel,
83}
84
85#[derive(Copy, Clone, Debug, PartialEq, Eq)]
86pub enum RegistersToSet {
87    All,
88    MtrrsOnly,
89}
90
91#[cfg(feature = "gdb")]
92trait DebugVp {
93    fn set_debug_state(
94        &mut self,
95        vtl: Vtl,
96        state: Option<&virt::x86::DebugState>,
97    ) -> anyhow::Result<()>;
98
99    fn set_vp_state(&mut self, vtl: Vtl, state: &DebuggerVpState) -> anyhow::Result<()>;
100
101    fn get_vp_state(&mut self, vtl: Vtl) -> anyhow::Result<Box<DebuggerVpState>>;
102}
103
104struct BoundVp<'a, T, U> {
105    vp: &'a mut T,
106    io: &'a U,
107    vp_index: VpIndex,
108}
109
110impl<T: ProtobufSaveRestore, U> ProtobufSaveRestore for BoundVp<'_, T, U> {
111    fn save(&mut self) -> Result<SavedStateBlob, SaveError> {
112        self.vp.save()
113    }
114
115    fn restore(&mut self, state: SavedStateBlob) -> Result<(), RestoreError> {
116        self.vp.restore(state)
117    }
118}
119
120#[async_trait(?Send)]
121impl<T, U> ControlVp for BoundVp<'_, T, U>
122where
123    T: Processor + ProtobufSaveRestore,
124    U: CpuIo,
125{
126    async fn run_vp(
127        &mut self,
128        vtl_guest_memory: &[Option<GuestMemory>; NUM_VTLS],
129        stop: StopVp<'_>,
130    ) -> Result<StopReason, HaltReason> {
131        let r = self.vp.run_vp(stop, self.io).await;
132        // Convert the inner error type to a generic one.
133        match r.unwrap_err() {
134            VpHaltReason::Stop(stop) => Ok(StopReason::OnRequest(stop)),
135            VpHaltReason::Cancel => Ok(StopReason::Cancel),
136            VpHaltReason::PowerOff => Err(HaltReason::PowerOff),
137            VpHaltReason::Reset => Err(HaltReason::Reset),
138            VpHaltReason::Hibernate => Err(HaltReason::Hibernate),
139            VpHaltReason::TripleFault { vtl } => {
140                let registers = self.vp.access_state(vtl).registers().ok().map(Arc::new);
141
142                tracing::error!(?vtl, vp = self.vp_index.index(), "triple fault");
143                self.trace_fault(
144                    vtl,
145                    vtl_guest_memory[vtl as usize].as_ref(),
146                    registers.as_deref(),
147                );
148                Err(HaltReason::TripleFault {
149                    vp: self.vp_index.index(),
150                    registers,
151                })
152            }
153            VpHaltReason::SingleStep => {
154                tracing::debug!("single step");
155                Err(HaltReason::SingleStep {
156                    vp: self.vp_index.index(),
157                })
158            }
159            VpHaltReason::HwBreak(breakpoint) => {
160                tracing::debug!(?breakpoint, "hardware breakpoint");
161                Err(HaltReason::HwBreakpoint {
162                    vp: self.vp_index.index(),
163                    breakpoint,
164                })
165            }
166        }
167    }
168
169    fn inspect_vp(
170        &mut self,
171        vtl_guest_memory: &[Option<GuestMemory>; NUM_VTLS],
172        req: inspect::Request<'_>,
173    ) {
174        let mut resp = req.respond();
175        resp.merge(&mut *self.vp);
176        for (name, vtl) in [
177            ("vtl0", Vtl::Vtl0),
178            ("vtl1", Vtl::Vtl1),
179            ("vtl2", Vtl::Vtl2),
180        ] {
181            if self.vp.vtl_inspectable(vtl) {
182                resp.field_mut(
183                    name,
184                    &mut inspect::adhoc_mut(|req| {
185                        self.inspect_vtl(vtl_guest_memory[vtl as usize].as_ref(), req, vtl)
186                    }),
187                );
188            }
189        }
190    }
191
192    fn set_initial_regs(
193        &mut self,
194        vtl: Vtl,
195        state: &InitialRegs,
196        to_set: RegistersToSet,
197    ) -> Result<(), RegisterSetError> {
198        let InitialRegs {
199            registers,
200            #[cfg(guest_arch = "x86_64")]
201            mtrrs,
202            #[cfg(guest_arch = "x86_64")]
203            pat,
204            #[cfg(guest_arch = "aarch64")]
205            system_registers,
206        } = state;
207        let mut access = self.vp.access_state(vtl);
208        // Only set the registers on the BSP.
209        if self.vp_index.is_bsp() && to_set == RegistersToSet::All {
210            access
211                .set_registers(registers)
212                .map_err(|err| RegisterSetError("registers", err.into()))?;
213
214            #[cfg(guest_arch = "aarch64")]
215            access
216                .set_system_registers(system_registers)
217                .map_err(|err| RegisterSetError("system_registers", err.into()))?;
218        }
219
220        // Set MTRRs and PAT on all VPs.
221        #[cfg(guest_arch = "x86_64")]
222        access
223            .set_mtrrs(mtrrs)
224            .map_err(|err| RegisterSetError("mtrrs", err.into()))?;
225        #[cfg(guest_arch = "x86_64")]
226        access
227            .set_pat(pat)
228            .map_err(|err| RegisterSetError("pat", err.into()))?;
229
230        Ok(())
231    }
232
233    #[cfg(feature = "gdb")]
234    fn debug(&mut self) -> &mut dyn DebugVp {
235        self
236    }
237}
238
239impl<T, U> BoundVp<'_, T, U>
240where
241    T: Processor + ProtobufSaveRestore,
242    U: CpuIo,
243{
244    fn inspect_vtl(&mut self, gm: Option<&GuestMemory>, req: inspect::Request<'_>, vtl: Vtl) {
245        let mut resp = req.respond();
246        resp.field("enabled", true)
247            .merge(self.vp.access_state(vtl).inspect_all());
248
249        let _ = gm;
250        #[cfg(all(guest_arch = "x86_64", feature = "gdb"))]
251        if let Some(gm) = gm {
252            let registers = self.vp.access_state(vtl).registers();
253            if let Ok(registers) = &registers {
254                resp.field_with("next_instruction", || {
255                    Some(
256                        vp_state::next_instruction(gm, self.debug(), vtl, registers).map_or_else(
257                            |err| format!("{:#}", err),
258                            |(instr, _)| instr.to_string(),
259                        ),
260                    )
261                })
262                .field_with("previous_instruction", || {
263                    Some(
264                        vp_state::previous_instruction(gm, self.debug(), vtl, registers)
265                            .map_or_else(|err| format!("{:#}", err), |instr| instr.to_string()),
266                    )
267                });
268            }
269        }
270    }
271
272    #[cfg(guest_arch = "x86_64")]
273    fn trace_fault(
274        &mut self,
275        vtl: Vtl,
276        guest_memory: Option<&GuestMemory>,
277        registers: Option<&virt::x86::vp::Registers>,
278    ) {
279        use cvm_tracing::CVM_CONFIDENTIAL;
280
281        #[cfg(not(feature = "gdb"))]
282        let _ = (guest_memory, vtl);
283
284        let Some(registers) = registers else {
285            return;
286        };
287
288        let virt::x86::vp::Registers {
289            rax,
290            rcx,
291            rdx,
292            rbx,
293            rsp,
294            rbp,
295            rsi,
296            rdi,
297            r8,
298            r9,
299            r10,
300            r11,
301            r12,
302            r13,
303            r14,
304            r15,
305            rip,
306            rflags,
307            cs,
308            ds,
309            es,
310            fs,
311            gs,
312            ss,
313            tr,
314            ldtr,
315            gdtr,
316            idtr,
317            cr0,
318            cr2,
319            cr3,
320            cr4,
321            cr8,
322            efer,
323        } = *registers;
324        tracing::error!(
325            CVM_CONFIDENTIAL,
326            vp = self.vp_index.index(),
327            ?vtl,
328            rax,
329            rcx,
330            rdx,
331            rbx,
332            rsp,
333            rbp,
334            rsi,
335            rdi,
336            r8,
337            r9,
338            r10,
339            r11,
340            r12,
341            r13,
342            r14,
343            r15,
344            rip,
345            rflags,
346            "triple fault register state",
347        );
348        tracing::error!(
349            CVM_CONFIDENTIAL,
350            ?vtl,
351            vp = self.vp_index.index(),
352            ?cs,
353            ?ds,
354            ?es,
355            ?fs,
356            ?gs,
357            ?ss,
358            ?tr,
359            ?ldtr,
360            ?gdtr,
361            ?idtr,
362            cr0,
363            cr2,
364            cr3,
365            cr4,
366            cr8,
367            efer,
368            "triple fault system register state",
369        );
370
371        #[cfg(feature = "gdb")]
372        if let Some(guest_memory) = guest_memory {
373            if let Ok((instr, bytes)) =
374                vp_state::next_instruction(guest_memory, self, vtl, registers)
375            {
376                tracing::error!(
377                    CVM_CONFIDENTIAL,
378                    instruction = instr.to_string(),
379                    ?bytes,
380                    "faulting instruction"
381                );
382            }
383        }
384    }
385
386    #[cfg(guest_arch = "aarch64")]
387    fn trace_fault(
388        &mut self,
389        _vtl: Vtl,
390        _guest_memory: Option<&GuestMemory>,
391        _registers: Option<&virt::aarch64::vp::Registers>,
392    ) {
393        // TODO
394    }
395}
396
397#[cfg(feature = "gdb")]
398impl<T: Processor, U> DebugVp for BoundVp<'_, T, U> {
399    fn set_debug_state(
400        &mut self,
401        vtl: Vtl,
402        state: Option<&virt::x86::DebugState>,
403    ) -> anyhow::Result<()> {
404        self.vp
405            .set_debug_state(vtl, state)
406            .context("failed to set debug state")
407    }
408
409    #[cfg(guest_arch = "x86_64")]
410    fn set_vp_state(&mut self, vtl: Vtl, state: &DebuggerVpState) -> anyhow::Result<()> {
411        let mut access = self.vp.access_state(vtl);
412        let DebuggerVpState::X86_64(state) = state else {
413            anyhow::bail!("wrong architecture")
414        };
415        let regs = virt::x86::vp::Registers {
416            rax: state.gp[0],
417            rcx: state.gp[1],
418            rdx: state.gp[2],
419            rbx: state.gp[3],
420            rsp: state.gp[4],
421            rbp: state.gp[5],
422            rsi: state.gp[6],
423            rdi: state.gp[7],
424            r8: state.gp[8],
425            r9: state.gp[9],
426            r10: state.gp[10],
427            r11: state.gp[11],
428            r12: state.gp[12],
429            r13: state.gp[13],
430            r14: state.gp[14],
431            r15: state.gp[15],
432            rip: state.rip,
433            rflags: state.rflags,
434            cs: state.cs,
435            ds: state.ds,
436            es: state.es,
437            fs: state.fs,
438            gs: state.gs,
439            ss: state.ss,
440            cr0: state.cr0,
441            cr2: state.cr2,
442            cr3: state.cr3,
443            cr4: state.cr4,
444            cr8: state.cr8,
445            efer: state.efer,
446            ..access.registers()?
447        };
448        let msrs = virt::x86::vp::VirtualMsrs {
449            kernel_gs_base: state.kernel_gs_base,
450            ..access.virtual_msrs()?
451        };
452        access.set_registers(&regs)?;
453        access.set_virtual_msrs(&msrs)?;
454        access.commit()?;
455        Ok(())
456    }
457
458    #[cfg(guest_arch = "x86_64")]
459    fn get_vp_state(&mut self, vtl: Vtl) -> anyhow::Result<Box<DebuggerVpState>> {
460        let mut access = self.vp.access_state(vtl);
461        let regs = access.registers()?;
462        let msrs = access.virtual_msrs()?;
463        Ok(Box::new(DebuggerVpState::X86_64(
464            vmm_core_defs::debug_rpc::X86VpState {
465                gp: [
466                    regs.rax, regs.rcx, regs.rdx, regs.rbx, regs.rsp, regs.rbp, regs.rsi, regs.rdi,
467                    regs.r8, regs.r9, regs.r10, regs.r11, regs.r12, regs.r13, regs.r14, regs.r15,
468                ],
469                rip: regs.rip,
470                rflags: regs.rflags,
471                cr0: regs.cr0,
472                cr2: regs.cr2,
473                cr3: regs.cr3,
474                cr4: regs.cr4,
475                cr8: regs.cr8,
476                efer: regs.efer,
477                kernel_gs_base: msrs.kernel_gs_base,
478                es: regs.es,
479                cs: regs.cs,
480                ss: regs.ss,
481                ds: regs.ds,
482                fs: regs.fs,
483                gs: regs.gs,
484            },
485        )))
486    }
487
488    #[cfg(guest_arch = "aarch64")]
489    fn set_vp_state(&mut self, vtl: Vtl, state: &DebuggerVpState) -> anyhow::Result<()> {
490        let DebuggerVpState::Aarch64(state) = state else {
491            anyhow::bail!("wrong architecture")
492        };
493        let mut access = self.vp.access_state(vtl);
494        let regs = virt::aarch64::vp::Registers {
495            x0: state.x[0],
496            x1: state.x[1],
497            x2: state.x[2],
498            x3: state.x[3],
499            x4: state.x[4],
500            x5: state.x[5],
501            x6: state.x[6],
502            x7: state.x[7],
503            x8: state.x[8],
504            x9: state.x[9],
505            x10: state.x[10],
506            x11: state.x[11],
507            x12: state.x[12],
508            x13: state.x[13],
509            x14: state.x[14],
510            x15: state.x[15],
511            x16: state.x[16],
512            x17: state.x[17],
513            x18: state.x[18],
514            x19: state.x[19],
515            x20: state.x[20],
516            x21: state.x[21],
517            x22: state.x[22],
518            x23: state.x[23],
519            x24: state.x[24],
520            x25: state.x[25],
521            x26: state.x[26],
522            x27: state.x[27],
523            x28: state.x[28],
524            fp: state.x[29],
525            lr: state.x[30],
526            sp_el0: state.sp_el0,
527            sp_el1: state.sp_el1,
528            pc: state.pc,
529            cpsr: state.cpsr,
530        };
531        let sregs = virt::aarch64::vp::SystemRegisters {
532            sctlr_el1: state.sctlr_el1,
533            tcr_el1: state.tcr_el1,
534            ttbr0_el1: state.ttbr0_el1,
535            ttbr1_el1: state.ttbr1_el1,
536            ..access.system_registers()?
537        };
538        access.set_registers(&regs)?;
539        access.set_system_registers(&sregs)?;
540        access.commit()?;
541        Ok(())
542    }
543
544    #[cfg(guest_arch = "aarch64")]
545    fn get_vp_state(&mut self, vtl: Vtl) -> anyhow::Result<Box<DebuggerVpState>> {
546        let mut access = self.vp.access_state(vtl);
547        let regs = access.registers()?;
548        let sregs = access.system_registers()?;
549
550        Ok(Box::new(DebuggerVpState::Aarch64(
551            vmm_core_defs::debug_rpc::Aarch64VpState {
552                x: [
553                    regs.x0, regs.x1, regs.x2, regs.x3, regs.x4, regs.x5, regs.x6, regs.x7,
554                    regs.x8, regs.x9, regs.x10, regs.x11, regs.x12, regs.x13, regs.x14, regs.x15,
555                    regs.x16, regs.x17, regs.x18, regs.x19, regs.x20, regs.x21, regs.x22, regs.x23,
556                    regs.x24, regs.x25, regs.x26, regs.x27, regs.x28, regs.fp, regs.lr,
557                ],
558                sp_el0: regs.sp_el0,
559                sp_el1: regs.sp_el1,
560                pc: regs.pc,
561                cpsr: regs.cpsr,
562                sctlr_el1: sregs.sctlr_el1,
563                tcr_el1: sregs.tcr_el1,
564                ttbr0_el1: sregs.ttbr0_el1,
565                ttbr1_el1: sregs.ttbr1_el1,
566            },
567        )))
568    }
569}
570
571/// Tracks whether the VP should halt due to a guest-initiated condition (triple
572/// fault, etc.).
573#[derive(Inspect)]
574pub struct Halt {
575    #[inspect(flatten)]
576    state: Mutex<HaltState>,
577    #[inspect(skip)]
578    send: mesh::Sender<InternalHaltReason>,
579}
580
581#[derive(Default, Inspect)]
582struct HaltState {
583    halt_count: usize,
584    #[inspect(skip)]
585    wakers: Slab<Option<Waker>>,
586}
587
588impl Halt {
589    /// Returns a new halt object, plus a receiver to asynchronously receive the
590    /// reason for a halt.
591    pub fn new() -> (Self, HaltReasonReceiver) {
592        let (send, recv) = mesh::channel();
593        (
594            Self {
595                state: Default::default(),
596                send,
597            },
598            HaltReasonReceiver(recv),
599        )
600    }
601
602    /// Halts all VPs and sends the halt reason to the receiver returned by
603    /// [`Self::new()`].
604    ///
605    /// After this returns, it's guaranteed that any VPs that try to run again
606    /// will instead halt. So if this is called from a VP thread, it will ensure
607    /// that that VP will not resume.
608    pub fn halt(&self, reason: HaltReason) {
609        self.halt_internal(InternalHaltReason::Halt(reason));
610    }
611
612    /// Halts all VPs temporarily, resets their variable MTRRs to their initial
613    /// state, then resumes the VPs.
614    ///
615    /// This is used by the legacy BIOS, since it stomps over the variable MTRRs
616    /// in undesirable ways and is difficult to fix.
617    pub fn replay_mtrrs(&self) {
618        self.halt_internal(InternalHaltReason::ReplayMtrrs);
619    }
620
621    fn halt_internal(&self, reason: InternalHaltReason) {
622        // Set the VP halt state immediately and wake them up.
623        let mut inner = self.state.lock();
624        inner.halt_count += 1;
625        for waker in inner.wakers.iter_mut().filter_map(|x| x.1.take()) {
626            waker.wake();
627        }
628
629        // Send the halt reason asynchronously.
630        self.send.send(reason);
631    }
632
633    /// Clears a single halt reason. Must be called for each halt reason that
634    /// arrives in order to resume the VM.
635    fn clear_halt(&self) {
636        let mut inner = self.state.lock();
637        inner.halt_count = inner
638            .halt_count
639            .checked_sub(1)
640            .expect("too many halt clears");
641    }
642
643    fn is_halted(&self) -> bool {
644        self.state.lock().halt_count != 0
645    }
646
647    fn halted(&self) -> Halted<'_> {
648        Halted {
649            halt: self,
650            idx: None,
651        }
652    }
653}
654
655struct Halted<'a> {
656    halt: &'a Halt,
657    idx: Option<usize>,
658}
659
660impl Clone for Halted<'_> {
661    fn clone(&self) -> Self {
662        Self {
663            halt: self.halt,
664            idx: None,
665        }
666    }
667}
668
669impl Future for Halted<'_> {
670    type Output = ();
671
672    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
673        let mut halt = self.halt.state.lock();
674        if halt.halt_count != 0 {
675            return Poll::Ready(());
676        }
677
678        if let Some(idx) = self.idx {
679            halt.wakers[idx] = Some(cx.waker().clone());
680        } else {
681            self.idx = Some(halt.wakers.insert(Some(cx.waker().clone())));
682        }
683        Poll::Pending
684    }
685}
686
687impl Drop for Halted<'_> {
688    fn drop(&mut self) {
689        if let Some(idx) = self.idx {
690            self.halt.state.lock().wakers.remove(idx);
691        }
692    }
693}
694
695#[derive(Inspect)]
696struct Inner {
697    #[inspect(flatten)]
698    halt: Arc<Halt>,
699    #[inspect(skip)]
700    vtl_guest_memory: [Option<GuestMemory>; NUM_VTLS],
701}
702
703#[derive(Inspect)]
704pub struct VpSet {
705    #[inspect(flatten)]
706    inner: Arc<Inner>,
707    #[inspect(rename = "vp", iter_by_index)]
708    vps: Vec<Vp>,
709    #[inspect(skip)]
710    started: bool,
711}
712
713#[derive(Inspect)]
714struct Vp {
715    #[inspect(flatten, send = "|req| VpEvent::State(StateEvent::Inspect(req))")]
716    send: mesh::Sender<VpEvent>,
717    #[inspect(skip)]
718    done: mesh::OneshotReceiver<()>,
719    #[inspect(flatten)]
720    vp_info: TargetVpInfo,
721}
722
723impl VpSet {
724    pub fn new(vtl_guest_memory: [Option<GuestMemory>; NUM_VTLS], halt: Arc<Halt>) -> Self {
725        let inner = Inner {
726            vtl_guest_memory,
727            halt,
728        };
729        Self {
730            inner: Arc::new(inner),
731            vps: Vec::new(),
732            started: false,
733        }
734    }
735
736    /// Adds a VP and returns its runner.
737    pub fn add(&mut self, vp: TargetVpInfo) -> VpRunner {
738        assert!(!self.started);
739        let (send, recv) = mesh::channel();
740        let (done_send, done_recv) = mesh::oneshot();
741        self.vps.push(Vp {
742            send,
743            done: done_recv,
744            vp_info: vp,
745        });
746        let (cancel_send, cancel_recv) = mesh::channel();
747        VpRunner {
748            recv,
749            _done: done_send,
750            cancel_recv,
751            cancel_send,
752            inner: RunnerInner {
753                vp: vp.as_ref().vp_index,
754                inner: self.inner.clone(),
755                state: VpState::Stopped,
756            },
757        }
758    }
759
760    /// Starts all VPs.
761    pub fn start(&mut self) {
762        if !self.started {
763            for vp in &self.vps {
764                vp.send.send(VpEvent::Start);
765            }
766            self.started = true;
767        }
768    }
769
770    /// Initiates a halt to the VPs.
771    #[cfg_attr(not(feature = "gdb"), expect(dead_code))]
772    pub fn halt(&mut self, reason: HaltReason) {
773        self.inner.halt.halt(reason);
774    }
775
776    /// Resets the halt state for all VPs.
777    ///
778    /// The VPs must be stopped.
779    pub fn clear_halt(&mut self) {
780        assert!(!self.started);
781        self.inner.halt.clear_halt();
782    }
783
784    /// Stops all VPs.
785    pub async fn stop(&mut self) {
786        if self.started {
787            self.vps
788                .iter()
789                .map(|vp| {
790                    let (send, recv) = mesh::oneshot();
791                    vp.send.send(VpEvent::Stop(send));
792                    // Ignore VPs whose runners have been dropped.
793                    async { recv.await.ok() }
794                })
795                .collect::<JoinAll<_>>()
796                .await;
797            self.started = false;
798        }
799    }
800
801    pub async fn save(&mut self) -> Result<Vec<(VpIndex, SavedStateBlob)>, SaveError> {
802        assert!(!self.started);
803        self.vps
804            .iter()
805            .enumerate()
806            .map(async |(index, vp)| {
807                let data = vp
808                    .send
809                    .call(|x| VpEvent::State(StateEvent::Save(x)), ())
810                    .await
811                    .map_err(|err| SaveError::Other(RunnerGoneError(err).into()))
812                    .and_then(|x| x)
813                    .map_err(|err| SaveError::ChildError(format!("vp{index}"), Box::new(err)))?;
814                Ok((VpIndex::new(index as u32), data))
815            })
816            .collect::<TryJoinAll<_>>()
817            .await
818    }
819
820    pub async fn restore(
821        &mut self,
822        states: impl IntoIterator<Item = (VpIndex, SavedStateBlob)>,
823    ) -> Result<(), RestoreError> {
824        assert!(!self.started);
825        states
826            .into_iter()
827            .map(|(vp_index, data)| {
828                let vp = self.vps.get(vp_index.index() as usize);
829                async move {
830                    let vp = vp.ok_or_else(|| {
831                        RestoreError::UnknownEntryId(format!("vp{}", vp_index.index()))
832                    })?;
833                    vp.send
834                        .call(|x| VpEvent::State(StateEvent::Restore(x)), data)
835                        .await
836                        .map_err(|err| RestoreError::Other(RunnerGoneError(err).into()))
837                        .and_then(|x| x)
838                        .map_err(|err| {
839                            RestoreError::ChildError(
840                                format!("vp{}", vp_index.index()),
841                                Box::new(err),
842                            )
843                        })
844                }
845            })
846            .collect::<TryJoinAll<_>>()
847            .await?;
848
849        Ok(())
850    }
851
852    /// Tears down the VPs.
853    pub async fn teardown(self) {
854        self.vps
855            .into_iter()
856            .map(|vp| vp.done.map(drop))
857            .collect::<JoinAll<_>>()
858            .await;
859    }
860
861    pub async fn set_initial_regs(
862        &mut self,
863        vtl: Vtl,
864        initial_regs: Arc<InitialRegs>,
865        to_set: RegistersToSet,
866    ) -> Result<(), RegisterSetError> {
867        self.vps
868            .iter()
869            .map(|vp| {
870                let initial_regs = initial_regs.clone();
871                async move {
872                    vp.send
873                        .call(
874                            |x| VpEvent::State(StateEvent::SetInitialRegs(x)),
875                            (vtl, initial_regs, to_set),
876                        )
877                        .await
878                        .map_err(|err| {
879                            RegisterSetError("initial_regs", RunnerGoneError(err).into())
880                        })?
881                }
882            })
883            .collect::<TryJoinAll<_>>()
884            .await?;
885
886        Ok(())
887    }
888}
889
890/// Error returned when registers could not be set on a VP.
891#[derive(Debug, Error)]
892#[error("failed to set VP register set {0}")]
893pub struct RegisterSetError(&'static str, #[source] anyhow::Error);
894
895#[derive(Debug, Error)]
896#[error("the vp runner was dropped")]
897struct RunnerGoneError(#[source] RpcError);
898
899#[cfg(feature = "gdb")]
900impl VpSet {
901    /// Set the debug state for a single VP.
902    pub async fn set_debug_state(
903        &self,
904        vp: VpIndex,
905        state: virt::x86::DebugState,
906    ) -> anyhow::Result<()> {
907        self.vps[vp.index() as usize]
908            .send
909            .call(
910                |x| VpEvent::State(StateEvent::Debug(DebugEvent::SetDebugState(x))),
911                Some(state),
912            )
913            .await
914            .map_err(RunnerGoneError)?
915    }
916
917    /// Clear the debug state for all VPs.
918    pub async fn clear_debug_state(&self) -> anyhow::Result<()> {
919        for vp in &self.vps {
920            vp.send
921                .call(
922                    |x| VpEvent::State(StateEvent::Debug(DebugEvent::SetDebugState(x))),
923                    None,
924                )
925                .await
926                .map_err(RunnerGoneError)??;
927        }
928        Ok(())
929    }
930
931    pub async fn set_vp_state(
932        &self,
933        vp: VpIndex,
934        state: Box<DebuggerVpState>,
935    ) -> anyhow::Result<()> {
936        self.vps[vp.index() as usize]
937            .send
938            .call(
939                |x| VpEvent::State(StateEvent::Debug(DebugEvent::SetVpState(x))),
940                state,
941            )
942            .await
943            .map_err(RunnerGoneError)?
944    }
945
946    pub async fn get_vp_state(&self, vp: VpIndex) -> anyhow::Result<Box<DebuggerVpState>> {
947        self.vps[vp.index() as usize]
948            .send
949            .call(
950                |x| VpEvent::State(StateEvent::Debug(DebugEvent::GetVpState(x))),
951                (),
952            )
953            .await
954            .map_err(RunnerGoneError)?
955    }
956
957    pub async fn read_virtual_memory(
958        &self,
959        vp: VpIndex,
960        gva: u64,
961        len: usize,
962    ) -> anyhow::Result<Vec<u8>> {
963        self.vps[vp.index() as usize]
964            .send
965            .call(
966                |x| VpEvent::State(StateEvent::Debug(DebugEvent::ReadVirtualMemory(x))),
967                (gva, len),
968            )
969            .await
970            .map_err(RunnerGoneError)?
971    }
972
973    pub async fn write_virtual_memory(
974        &self,
975        vp: VpIndex,
976        gva: u64,
977        data: Vec<u8>,
978    ) -> anyhow::Result<()> {
979        self.vps[vp.index() as usize]
980            .send
981            .call(
982                |x| VpEvent::State(StateEvent::Debug(DebugEvent::WriteVirtualMemory(x))),
983                (gva, data),
984            )
985            .await
986            .map_err(RunnerGoneError)?
987    }
988}
989
990#[derive(Debug)]
991enum VpEvent {
992    Start,
993    Stop(mesh::OneshotSender<()>),
994    State(StateEvent),
995}
996
997#[derive(Debug)]
998enum StateEvent {
999    Inspect(inspect::Deferred),
1000    SetInitialRegs(Rpc<(Vtl, Arc<InitialRegs>, RegistersToSet), Result<(), RegisterSetError>>),
1001    Save(Rpc<(), Result<SavedStateBlob, SaveError>>),
1002    Restore(Rpc<SavedStateBlob, Result<(), RestoreError>>),
1003    #[cfg(feature = "gdb")]
1004    Debug(DebugEvent),
1005}
1006
1007#[cfg(feature = "gdb")]
1008#[derive(Debug)]
1009enum DebugEvent {
1010    SetDebugState(Rpc<Option<virt::x86::DebugState>, anyhow::Result<()>>),
1011    SetVpState(Rpc<Box<DebuggerVpState>, anyhow::Result<()>>),
1012    GetVpState(Rpc<(), anyhow::Result<Box<DebuggerVpState>>>),
1013    ReadVirtualMemory(Rpc<(u64, usize), anyhow::Result<Vec<u8>>>),
1014    WriteVirtualMemory(Rpc<(u64, Vec<u8>), anyhow::Result<()>>),
1015}
1016
1017/// An object used to dispatch a virtual processor.
1018#[must_use]
1019pub struct VpRunner {
1020    recv: mesh::Receiver<VpEvent>,
1021    cancel_send: mesh::Sender<()>,
1022    cancel_recv: mesh::Receiver<()>,
1023    _done: mesh::OneshotSender<()>,
1024    inner: RunnerInner,
1025}
1026
1027/// An object that can cancel a pending call into [`VpRunner::run`].
1028pub struct RunnerCanceller(mesh::Sender<()>);
1029
1030impl RunnerCanceller {
1031    /// Requests that the current or next call to [`VpRunner::run`] return as
1032    /// soon as possible.
1033    pub fn cancel(&mut self) {
1034        self.0.send(());
1035    }
1036}
1037
1038/// Error returned when a VP run is cancelled.
1039#[derive(Debug)]
1040pub struct RunCancelled(bool);
1041
1042impl RunCancelled {
1043    /// Returns `true` if the run was cancelled by the user, or `false` if it was
1044    /// cancelled by the VP itself.
1045    pub fn is_user_cancelled(&self) -> bool {
1046        self.0
1047    }
1048}
1049
1050struct RunnerInner {
1051    vp: VpIndex,
1052    inner: Arc<Inner>,
1053    state: VpState,
1054}
1055
1056#[derive(Copy, Clone, Debug, Inspect, PartialEq, Eq)]
1057enum VpState {
1058    Stopped,
1059    Running,
1060    Halted,
1061}
1062
1063impl VpRunner {
1064    /// Runs the VP dispatch loop for `vp`, using `io` to handle CPU requests.
1065    ///
1066    /// Returns [`RunCancelled`] if [`RunnerCanceller::cancel`] was called, or
1067    /// if the VP returns [`VpHaltReason::Cancel`]. In this case, the call can
1068    /// be reissued, with the same or different `vp` object, to continue running
1069    /// the VP.
1070    ///
1071    /// Do not reissue this call if it returns `Ok`. Do not drop this future
1072    /// without awaiting it to completion.
1073    pub async fn run(
1074        &mut self,
1075        vp: &mut (impl Processor + ProtobufSaveRestore),
1076        io: &impl CpuIo,
1077    ) -> Result<(), RunCancelled> {
1078        let vp_index = self.inner.vp;
1079        self.run_inner(&mut BoundVp { vp, io, vp_index }).await
1080    }
1081
1082    /// Returns an object that can be used to cancel a `run` call.
1083    pub fn canceller(&self) -> RunnerCanceller {
1084        RunnerCanceller(self.cancel_send.clone())
1085    }
1086
1087    #[instrument(level = "debug", name = "run_vp", skip_all, fields(vp_index = self.inner.vp.index()))]
1088    async fn run_inner(&mut self, vp: &mut dyn ControlVp) -> Result<(), RunCancelled> {
1089        loop {
1090            // Wait for start.
1091            while self.inner.state != VpState::Running {
1092                let r = (self.recv.next().map(Ok), self.cancel_recv.next().map(Err))
1093                    .race()
1094                    .await
1095                    .map_err(|_| RunCancelled(true))?;
1096                match r {
1097                    Some(VpEvent::Start) => {
1098                        assert_eq!(self.inner.state, VpState::Stopped);
1099                        self.inner.state = VpState::Running;
1100                    }
1101                    Some(VpEvent::Stop(send)) => {
1102                        assert_eq!(self.inner.state, VpState::Halted);
1103                        self.inner.state = VpState::Stopped;
1104                        send.send(());
1105                    }
1106                    Some(VpEvent::State(event)) => self.inner.state_event(vp, event),
1107                    None => return Ok(()),
1108                }
1109            }
1110
1111            // If the VPs are already halted, wait for the next request without
1112            // running the VP even once.
1113            if self.inner.inner.halt.is_halted() {
1114                self.inner.state = VpState::Halted;
1115                continue;
1116            }
1117
1118            let mut stop_complete = None;
1119            let mut state_requests = Vec::new();
1120            let mut cancelled_by_user = None;
1121            {
1122                enum Event {
1123                    Vp(VpEvent),
1124                    Teardown,
1125                    Halt,
1126                    VpStopped(Result<StopReason, HaltReason>),
1127                    Cancel,
1128                }
1129
1130                let stop = StopVpSource::new();
1131
1132                let run_vp = vp
1133                    .run_vp(&self.inner.inner.vtl_guest_memory, stop.checker())
1134                    .into_stream()
1135                    .map(Event::VpStopped);
1136
1137                let halt = self
1138                    .inner
1139                    .inner
1140                    .halt
1141                    .halted()
1142                    .into_stream()
1143                    .map(|_| Event::Halt);
1144
1145                let recv = (&mut self.recv)
1146                    .map(Event::Vp)
1147                    .chain(async { Event::Teardown }.into_stream());
1148
1149                let cancel = (&mut self.cancel_recv).map(|()| Event::Cancel);
1150
1151                let s = (recv, halt, cancel).merge();
1152
1153                // Since `run_vp` will block the thread until it receives a
1154                // cancellation notification, always poll the other sources to
1155                // exhaustion before polling the future.
1156                let mut s = pin!(select_with_strategy(s, run_vp, |_: &mut ()| {
1157                    futures::stream::PollNext::Left
1158                }));
1159
1160                // Wait for stop or a VP failure.
1161                while let Some(event) = s.next().await {
1162                    match event {
1163                        Event::Vp(VpEvent::Start) => panic!("vp already started"),
1164                        Event::Vp(VpEvent::Stop(send)) => {
1165                            tracing::debug!("stopping VP");
1166                            stop.stop();
1167                            stop_complete = Some(send);
1168                        }
1169                        Event::Vp(VpEvent::State(event)) => {
1170                            // Stop the VP so that we can drop the run_vp future
1171                            // before manipulating state.
1172                            //
1173                            // FUTURE: This causes inspection delays during slow
1174                            // MMIO/PIO exit handling. Fix the backends to support
1175                            // calling inspect while run_vp is still alive (but
1176                            // suspended).
1177                            stop.stop();
1178                            state_requests.push(event);
1179                        }
1180                        Event::Halt => {
1181                            tracing::debug!("stopping VP due to halt");
1182                            stop.stop();
1183                        }
1184                        Event::Cancel => {
1185                            tracing::debug!("run cancelled externally");
1186                            stop.stop();
1187                            cancelled_by_user = Some(true);
1188                        }
1189                        Event::Teardown => {
1190                            tracing::debug!("tearing down");
1191                            stop.stop();
1192                        }
1193                        Event::VpStopped(r) => {
1194                            match r {
1195                                Ok(StopReason::OnRequest(VpStopped { .. })) => {
1196                                    assert!(stop.is_stopping(), "vp stopped without a reason");
1197                                    tracing::debug!("VP stopped on request");
1198                                }
1199                                Ok(StopReason::Cancel) => {
1200                                    tracing::debug!("run cancelled internally");
1201                                    cancelled_by_user = Some(false);
1202                                }
1203                                Err(halt_reason) => {
1204                                    tracing::debug!("VP halted");
1205                                    self.inner.inner.halt.halt(halt_reason);
1206                                }
1207                            }
1208                            break;
1209                        }
1210                    }
1211                }
1212            }
1213            for event in state_requests {
1214                self.inner.state_event(vp, event);
1215            }
1216
1217            if let Some(send) = stop_complete {
1218                self.inner.state = VpState::Stopped;
1219                send.send(());
1220            }
1221
1222            if let Some(by_user) = cancelled_by_user {
1223                return Err(RunCancelled(by_user));
1224            }
1225        }
1226    }
1227}
1228
1229impl RunnerInner {
1230    fn state_event(&mut self, vp: &mut dyn ControlVp, event: StateEvent) {
1231        match event {
1232            StateEvent::Inspect(deferred) => {
1233                deferred.respond(|resp| {
1234                    resp.field("state", self.state)
1235                        .merge(inspect::adhoc_mut(|req| {
1236                            vp.inspect_vp(&self.inner.vtl_guest_memory, req)
1237                        }));
1238                });
1239            }
1240            StateEvent::SetInitialRegs(rpc) => {
1241                rpc.handle_sync(|(vtl, state, to_set)| vp.set_initial_regs(vtl, &state, to_set))
1242            }
1243            StateEvent::Save(rpc) => rpc.handle_sync(|()| vp.save()),
1244            StateEvent::Restore(rpc) => rpc.handle_sync(|data| vp.restore(data)),
1245            #[cfg(feature = "gdb")]
1246            StateEvent::Debug(event) => match event {
1247                DebugEvent::SetDebugState(rpc) => {
1248                    rpc.handle_sync(|state| vp.debug().set_debug_state(Vtl::Vtl0, state.as_ref()))
1249                }
1250                DebugEvent::SetVpState(rpc) => {
1251                    rpc.handle_sync(|state| vp.debug().set_vp_state(Vtl::Vtl0, &state))
1252                }
1253                DebugEvent::GetVpState(rpc) => {
1254                    rpc.handle_sync(|()| vp.debug().get_vp_state(Vtl::Vtl0))
1255                }
1256                DebugEvent::ReadVirtualMemory(rpc) => rpc.handle_sync(|(gva, len)| {
1257                    let mut buf = vec![0; len];
1258                    vp_state::read_virtual_memory(
1259                        self.inner.vtl_guest_memory[0]
1260                            .as_ref()
1261                            .context("no guest memory for vtl0")?,
1262                        vp.debug(),
1263                        Vtl::Vtl0,
1264                        gva,
1265                        &mut buf,
1266                    )?;
1267                    Ok(buf)
1268                }),
1269                DebugEvent::WriteVirtualMemory(rpc) => rpc.handle_sync(|(gva, buf)| {
1270                    vp_state::write_virtual_memory(
1271                        self.inner.vtl_guest_memory[0]
1272                            .as_ref()
1273                            .context("no guest memory for vtl0")?,
1274                        vp.debug(),
1275                        Vtl::Vtl0,
1276                        gva,
1277                        &buf,
1278                    )?;
1279                    Ok(())
1280                }),
1281            },
1282        }
1283    }
1284}
1285
1286#[cfg(feature = "gdb")]
1287mod vp_state {
1288    use super::DebugVp;
1289    use anyhow::Context;
1290    use guestmem::GuestMemory;
1291    use hvdef::Vtl;
1292    use vmm_core_defs::debug_rpc::DebuggerVpState;
1293
1294    fn translate_gva(
1295        guest_memory: &GuestMemory,
1296        debug: &mut dyn DebugVp,
1297        vtl: Vtl,
1298        gva: u64,
1299    ) -> anyhow::Result<u64> {
1300        let state = debug.get_vp_state(vtl).context("failed to get vp state")?;
1301
1302        match &*state {
1303            DebuggerVpState::X86_64(state) => {
1304                let registers = virt_support_x86emu::translate::TranslationRegisters {
1305                    cr0: state.cr0,
1306                    cr4: state.cr4,
1307                    efer: state.efer,
1308                    cr3: state.cr3,
1309                    rflags: state.rflags,
1310                    ss: state.ss.into(),
1311                    // For debug translation, don't worry about accidentally reading
1312                    // page tables from shared memory.
1313                    encryption_mode: virt_support_x86emu::translate::EncryptionMode::None,
1314                };
1315                let flags = virt_support_x86emu::translate::TranslateFlags {
1316                    validate_execute: false,
1317                    validate_read: false,
1318                    validate_write: false,
1319                    override_smap: false,
1320                    enforce_smap: false,
1321                    privilege_check: virt_support_x86emu::translate::TranslatePrivilegeCheck::None,
1322                    set_page_table_bits: false,
1323                };
1324                Ok(virt_support_x86emu::translate::translate_gva_to_gpa(
1325                    guest_memory,
1326                    gva,
1327                    &registers,
1328                    flags,
1329                )?
1330                .gpa)
1331            }
1332            DebuggerVpState::Aarch64(state) => {
1333                let registers = virt_support_aarch64emu::translate::TranslationRegisters {
1334                    cpsr: state.cpsr.into(),
1335                    sctlr: state.sctlr_el1.into(),
1336                    tcr: state.tcr_el1.into(),
1337                    ttbr0: state.ttbr0_el1,
1338                    ttbr1: state.ttbr1_el1,
1339                    syndrome: 0,
1340                    // For debug translation, don't worry about accidentally reading
1341                    // page tables from shared memory.
1342                    encryption_mode: virt_support_aarch64emu::translate::EncryptionMode::None,
1343                };
1344                let flags = virt_support_aarch64emu::translate::TranslateFlags {
1345                    validate_execute: false,
1346                    validate_read: false,
1347                    validate_write: false,
1348                    privilege_check:
1349                        virt_support_aarch64emu::translate::TranslatePrivilegeCheck::None,
1350                    set_page_table_bits: false,
1351                };
1352                Ok(virt_support_aarch64emu::translate::translate_gva_to_gpa(
1353                    guest_memory,
1354                    gva,
1355                    &registers,
1356                    flags,
1357                )?)
1358            }
1359        }
1360    }
1361
1362    pub(super) fn read_virtual_memory(
1363        guest_memory: &GuestMemory,
1364        debug: &mut dyn DebugVp,
1365        vtl: Vtl,
1366        gva: u64,
1367        buf: &mut [u8],
1368    ) -> anyhow::Result<()> {
1369        let mut offset = 0;
1370        while offset < buf.len() {
1371            let gpa = translate_gva(guest_memory, debug, vtl, gva + offset as u64)
1372                .context("failed to translate gva")?;
1373            let this_len = (buf.len() - offset).min(4096 - (gpa & 4095) as usize);
1374            guest_memory.read_at(gpa, &mut buf[offset..offset + this_len])?;
1375            offset += this_len;
1376        }
1377        Ok(())
1378    }
1379
1380    pub(super) fn write_virtual_memory(
1381        guest_memory: &GuestMemory,
1382        debug: &mut dyn DebugVp,
1383        vtl: Vtl,
1384        gva: u64,
1385        buf: &[u8],
1386    ) -> anyhow::Result<()> {
1387        let mut offset = 0;
1388        while offset < buf.len() {
1389            let gpa = translate_gva(guest_memory, debug, vtl, gva + offset as u64)
1390                .context("failed to translate gva")?;
1391            let this_len = (buf.len() - offset).min(4096 - (gpa & 4095) as usize);
1392            guest_memory.write_at(gpa, &buf[offset..offset + this_len])?;
1393            offset += this_len;
1394        }
1395        Ok(())
1396    }
1397
1398    #[cfg(guest_arch = "x86_64")]
1399    fn bits(regs: &virt::x86::vp::Registers) -> u32 {
1400        if regs.cr0 & x86defs::X64_CR0_PE != 0 {
1401            if regs.efer & x86defs::X64_EFER_LMA != 0 {
1402                64
1403            } else {
1404                32
1405            }
1406        } else {
1407            16
1408        }
1409    }
1410
1411    #[cfg(guest_arch = "x86_64")]
1412    fn linear_ip(regs: &virt::x86::vp::Registers, rip: u64) -> u64 {
1413        if bits(regs) == 64 {
1414            rip
1415        } else {
1416            // 32 or 16 bits
1417            regs.cs.base.wrapping_add(rip)
1418        }
1419    }
1420
1421    /// Get the previous instruction for debugging purposes.
1422    #[cfg(guest_arch = "x86_64")]
1423    pub(super) fn previous_instruction(
1424        guest_memory: &GuestMemory,
1425        debug: &mut dyn DebugVp,
1426        vtl: Vtl,
1427        regs: &virt::x86::vp::Registers,
1428    ) -> anyhow::Result<iced_x86::Instruction> {
1429        let mut bytes = [0u8; 16];
1430        // Read 16 bytes before RIP.
1431        let rip = regs.rip.wrapping_sub(16);
1432        read_virtual_memory(guest_memory, debug, vtl, linear_ip(regs, rip), &mut bytes)
1433            .context("failed to read memory")?;
1434        let mut decoder = iced_x86::Decoder::new(bits(regs), &bytes, 0);
1435
1436        // Try decoding at each byte until we find the instruction right before the current one.
1437        for offset in 0..16 {
1438            decoder.set_ip(rip.wrapping_add(offset));
1439            decoder.try_set_position(offset as usize).unwrap();
1440            let instr = decoder.decode();
1441            if !instr.is_invalid() && instr.next_ip() == regs.rip {
1442                return Ok(instr);
1443            }
1444        }
1445        Err(anyhow::anyhow!("could not find previous instruction"))
1446    }
1447
1448    /// Get the next instruction for debugging purposes.
1449    #[cfg(guest_arch = "x86_64")]
1450    pub(super) fn next_instruction(
1451        guest_memory: &GuestMemory,
1452        debug: &mut dyn DebugVp,
1453        vtl: Vtl,
1454        regs: &virt::x86::vp::Registers,
1455    ) -> anyhow::Result<(iced_x86::Instruction, [u8; 16])> {
1456        let mut bytes = [0u8; 16];
1457        read_virtual_memory(
1458            guest_memory,
1459            debug,
1460            vtl,
1461            linear_ip(regs, regs.rip),
1462            &mut bytes,
1463        )
1464        .context("failed to read memory")?;
1465        let mut decoder = iced_x86::Decoder::new(bits(regs), &bytes, 0);
1466        decoder.set_ip(regs.rip);
1467        Ok((decoder.decode(), bytes))
1468    }
1469}
1470
1471struct VpWaker {
1472    partition: Arc<dyn RequestYield>,
1473    vp: VpIndex,
1474    inner: Waker,
1475}
1476
1477impl VpWaker {
1478    fn new(partition: Arc<dyn RequestYield>, vp: VpIndex, waker: Waker) -> Self {
1479        Self {
1480            partition,
1481            vp,
1482            inner: waker,
1483        }
1484    }
1485}
1486
1487impl std::task::Wake for VpWaker {
1488    fn wake_by_ref(self: &Arc<Self>) {
1489        self.partition.request_yield(self.vp);
1490        self.inner.wake_by_ref();
1491    }
1492
1493    fn wake(self: Arc<Self>) {
1494        self.wake_by_ref()
1495    }
1496}
1497
1498/// Trait for requesting that a VP yield in its [`virt::Processor::run_vp`]
1499/// call.
1500pub trait RequestYield: Send + Sync {
1501    /// Forces the run_vp call to yield to the scheduler (i.e. return
1502    /// Poll::Pending).
1503    fn request_yield(&self, vp_index: VpIndex);
1504}
1505
1506impl<T: virt::Partition> RequestYield for T {
1507    fn request_yield(&self, vp_index: VpIndex) {
1508        self.request_yield(vp_index)
1509    }
1510}
1511
1512/// Blocks on a future, where the future may run a VP (and so the associated
1513/// waker needs to ask the VP to yield).
1514pub fn block_on_vp<F: Future>(partition: Arc<dyn RequestYield>, vp: VpIndex, fut: F) -> F::Output {
1515    let mut fut = pin!(fut);
1516    pal_async::local::block_on(std::future::poll_fn(|cx| {
1517        let waker = Arc::new(VpWaker::new(partition.clone(), vp, cx.waker().clone())).into();
1518        let mut cx = Context::from_waker(&waker);
1519        fut.poll_unpin(&mut cx)
1520    }))
1521}