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