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