1use 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#[async_trait(?Send)]
56trait ControlVp: ProtobufSaveRestore {
57 async fn run_vp(
59 &mut self,
60 vtl_guest_memory: &[Option<GuestMemory>; NUM_VTLS],
61 stop: StopVp<'_>,
62 ) -> Result<StopReason, HaltReason>;
63
64 fn inspect_vp(&mut self, gm: &[Option<GuestMemory>; NUM_VTLS], req: inspect::Request<'_>);
66
67 fn set_initial_regs(
69 &mut self,
70 vtl: Vtl,
71 state: &InitialRegs,
72 to_set: RegistersToSet,
73 ) -> Result<(), RegisterSetError>;
74
75 fn reset(&mut self) -> anyhow::Result<()>;
77
78 fn scrub(&mut self, vtl: Vtl) -> anyhow::Result<()>;
80
81 #[cfg(feature = "gdb")]
82 fn debug(&mut self) -> &mut dyn DebugVp;
83
84 #[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 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 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 #[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) = ®isters {
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 }
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(®s)?;
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(®s)?;
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#[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 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 pub fn halt(&self, reason: HaltReason) {
656 self.halt_internal(InternalHaltReason::Halt(reason));
657 }
658
659 pub fn replay_mtrrs(&self) {
665 self.halt_internal(InternalHaltReason::ReplayMtrrs);
666 }
667
668 fn halt_internal(&self, reason: InternalHaltReason) {
669 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 self.send.send(reason);
678 }
679
680 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 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 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 #[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 pub fn clear_halt(&mut self) {
827 assert!(!self.started);
828 self.inner.halt.clear_halt();
829 }
830
831 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 async { recv.await.ok() }
841 })
842 .collect::<JoinAll<_>>()
843 .await;
844 self.started = false;
845 }
846 }
847
848 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 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 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#[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 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 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 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#[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
1130pub struct RunnerCanceller(mesh::Sender<()>);
1132
1133impl RunnerCanceller {
1134 pub fn cancel(&mut self) {
1137 self.0.send(());
1138 }
1139}
1140
1141#[derive(Debug)]
1143pub struct RunCancelled(bool);
1144
1145impl RunCancelled {
1146 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 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 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 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 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 let mut s = pin!(select_with_strategy(s, run_vp, |_: &mut ()| {
1260 futures::stream::PollNext::Left
1261 }));
1262
1263 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.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 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 ®isters,
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 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 ®isters,
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 regs.cs.base.wrapping_add(rip)
1525 }
1526 }
1527
1528 #[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 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 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 #[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
1605pub trait RequestYield: Send + Sync {
1608 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
1619pub 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}