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