1#![cfg(target_os = "linux")]
7
8use crate::run::RunContext;
9use crate::run::RunnerBuilder;
10use crate::run::TestResult;
11use guestmem::GuestMemory;
12use std::sync::Arc;
13use virt::Partition;
14use virt_mshv_vtl::UhLateParams;
15use virt_mshv_vtl::UhPartitionNewParams;
16use virt_mshv_vtl::UhProcessorBox;
17
18impl RunContext<'_> {
19 pub async fn run_paravisor_vmm(
20 &mut self,
21 isolation: virt::IsolationType,
22 test: &crate::load::TestInfo,
23 ) -> anyhow::Result<TestResult> {
24 let params = UhPartitionNewParams {
25 isolation,
26 hide_isolation: false,
27 lower_vtl_memory_layout: &self.state.memory_layout,
28 topology: &self.state.processor_topology,
29 cvm_cpuid_info: None,
30 snp_secrets: None,
31 vtom: None,
32 handle_synic: true,
33 no_sidecar_hotplug: false,
34 use_mmio_hypercalls: false,
35 intercept_debug_exceptions: false,
36 disable_proxy_redirect: false,
37 disable_lower_vtl_timer_virt: true,
39 };
40 let p = virt_mshv_vtl::UhProtoPartition::new(¶ms, |_| self.state.driver.clone())?;
41
42 let m = underhill_mem::init(&underhill_mem::Init {
43 processor_topology: &self.state.processor_topology,
44 isolation,
45 vtl0_alias_map_bit: None,
46 vtom: p.get_vtom(),
47 mem_layout: &self.state.memory_layout,
48 complete_memory_layout: &self.state.memory_layout,
49 boot_init: None,
50 shared_pool: &[],
51 maximum_vtl: hvdef::Vtl::Vtl0,
52 })
53 .await?;
54
55 let cvm_params = if isolation == virt::IsolationType::Cca {
56 let cvm_memory = m.cvm_memory().unwrap();
57 Some(virt_mshv_vtl::CvmLateParams {
58 shared_gm: cvm_memory.shared_gm.clone(),
59 isolated_memory_protector: cvm_memory.protector.clone(),
60 shared_dma_client: Arc::new(user_driver::lockmem::LockedMemorySpawner),
61 private_dma_client: self.state.cca_private_dma_client(),
62 })
63 } else {
64 None
65 };
66
67 let (partition, vps) = p
68 .build(UhLateParams {
69 gm: [
70 m.vtl0().clone(),
71 m.vtl1().cloned().unwrap_or(GuestMemory::empty()),
72 ]
73 .into(),
74 vtl0_kernel_exec_gm: m.vtl0().clone(),
75 vtl0_user_exec_gm: m.vtl0().clone(),
76 #[cfg(guest_arch = "x86_64")]
77 cpuid: Vec::new(),
78 crash_notification_send: mesh::channel().0,
79 vmtime: self.vmtime_source,
80 cvm_params,
81 vmbus_relay: false,
82 })
83 .await?;
84
85 let partition = Arc::new(partition);
86
87 let mut threads = Vec::new();
88 let r = self
89 .run(m.vtl0(), partition.caps(), test, async |_this, runner| {
90 let [vp] = vps.try_into().ok().unwrap();
91 threads.push(start_vp(vp, runner, isolation).await?);
92 Ok(())
93 })
94 .await?;
95
96 for thread in threads {
97 thread.join().unwrap();
98 }
99
100 Arc::into_inner(partition).expect("partition is no longer referenced");
102
103 Ok(r)
104 }
105}
106
107async fn start_vp(
108 mut vp: UhProcessorBox,
109 mut runner: RunnerBuilder,
110 isolation: virt::IsolationType,
111) -> anyhow::Result<std::thread::JoinHandle<()>> {
112 let vp_thread = std::thread::spawn(move || {
113 let pool = pal_uring::IoUringPool::new("vp", 256).unwrap();
114 let driver = pool.client().initiator().clone();
115 match isolation {
116 #[cfg(guest_arch = "aarch64")]
117 virt::IsolationType::Cca => pool.client().set_idle_task(async move |mut control| {
118 let vp = vp
119 .bind_processor::<virt_mshv_vtl::CcaBacked>(&driver, Some(&mut control))
120 .unwrap();
121 runner.build(vp).unwrap().run_vp().await;
122 }),
123 _ => pool.client().set_idle_task(async move |mut control| {
124 let vp = vp
125 .bind_processor::<virt_mshv_vtl::HypervisorBacked>(&driver, Some(&mut control))
126 .unwrap();
127 runner.build(vp).unwrap().run_vp().await;
128 }),
129 }
130 pool.run()
131 });
132 Ok(vp_thread)
133}