Skip to main content

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