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