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