crosvm: unix: Run Gunyah Virtual Machines

Run Gunyah virtual machines.

BUG=b:232360323

Change-Id: Ice80f9dafa25ef914bb8b73474b12c59555861a7
Signed-off-by: Elliot Berman <quic_eberman@quicinc.com>
diff --git a/src/crosvm/config.rs b/src/crosvm/config.rs
index be6aeaf..284493f 100644
--- a/src/crosvm/config.rs
+++ b/src/crosvm/config.rs
@@ -84,6 +84,8 @@
         #[cfg(any(target_arch = "aarch64"))]
         #[cfg(all(unix, feature = "geniezone"))]
         static GENIEZONE_PATH: &str = "/dev/gzvm";
+        #[cfg(all(any(target_arch = "arm", target_arch = "aarch64"), feature = "gunyah"))]
+        static GUNYAH_PATH: &str = "/dev/gunyah";
         static VHOST_NET_PATH: &str = "/dev/vhost-net";
     } else if #[cfg(windows)] {
         use base::{Event, Tube};
@@ -1063,6 +1065,12 @@
     pub gpu_server_cgroup_path: Option<PathBuf>,
     #[cfg(all(windows, feature = "gpu"))]
     pub gpu_vmm_config: Option<GpuVmmConfig>,
+    #[cfg(all(
+        unix,
+        any(target_arch = "arm", target_arch = "aarch64"),
+        feature = "gunyah"
+    ))]
+    pub gunyah_device_path: PathBuf,
     pub host_cpu_topology: bool,
     #[cfg(windows)]
     pub host_guid: Option<String>,
@@ -1286,6 +1294,12 @@
             #[cfg(any(target_arch = "aarch64"))]
             #[cfg(all(unix, feature = "geniezone"))]
             geniezone_device_path: PathBuf::from(GENIEZONE_PATH),
+            #[cfg(all(
+                unix,
+                any(target_arch = "arm", target_arch = "aarch64"),
+                feature = "gunyah"
+            ))]
+            gunyah_device_path: PathBuf::from(GUNYAH_PATH),
             host_cpu_topology: false,
             #[cfg(windows)]
             host_guid: None,
diff --git a/src/crosvm/sys/unix.rs b/src/crosvm/sys/unix.rs
index b9debc2..03f40f6 100644
--- a/src/crosvm/sys/unix.rs
+++ b/src/crosvm/sys/unix.rs
@@ -1479,6 +1479,50 @@
     )
 }
 
+#[cfg(all(any(target_arch = "arm", target_arch = "aarch64"), feature = "gunyah"))]
+fn run_gunyah(cfg: Config, components: VmComponents) -> Result<ExitState> {
+    use devices::GunyahIrqChip;
+    use hypervisor::gunyah::{Gunyah, GunyahVcpu, GunyahVm};
+
+    let gunyah = Gunyah::new_with_path(&cfg.gunyah_device_path).with_context(|| {
+        format!(
+            "failed to open Gunyah device {}",
+            cfg.gunyah_device_path.display()
+        )
+    })?;
+
+    let guest_mem = create_guest_memory(&cfg, &components, &gunyah)?;
+
+    #[cfg(feature = "swap")]
+    let swap_controller = if let Some(swap_dir) = cfg.swap_dir.as_ref() {
+        Some(
+            SwapController::launch(guest_mem.clone(), swap_dir, &cfg.jail_config)
+                .context("launch vmm-swap monitor process")?,
+        )
+    } else {
+        None
+    };
+
+    let vm = GunyahVm::new(&gunyah, guest_mem, components.hv_cfg).context("failed to create vm")?;
+
+    // Check that the VM was actually created in protected mode as expected.
+    if cfg.protection_type.isolates_memory() && !vm.check_capability(VmCap::Protected) {
+        bail!("Failed to create protected VM");
+    }
+
+    let vm_clone = vm.try_clone()?;
+
+    run_vm::<GunyahVcpu, GunyahVm>(
+        cfg,
+        components,
+        vm,
+        &mut GunyahIrqChip::new(vm_clone)?,
+        None,
+        #[cfg(feature = "swap")]
+        swap_controller,
+    )
+}
+
 fn get_default_hypervisor(cfg: &Config) -> Result<HypervisorKind> {
     if cfg.kvm_device_path.exists() {
         return Ok(HypervisorKind::Kvm);
@@ -1488,6 +1532,14 @@
     if cfg.geniezone_device_path.exists() {
         return Ok(HypervisorKind::Geniezone);
     }
+    #[cfg(all(
+        unix,
+        any(target_arch = "arm", target_arch = "aarch64"),
+        feature = "gunyah"
+    ))]
+    if cfg.gunyah_device_path.exists() {
+        return Ok(HypervisorKind::Gunyah);
+    }
     bail!("failed to get default hypervisor!");
 }
 
@@ -1511,6 +1563,12 @@
         #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
         #[cfg(feature = "geniezone")]
         HypervisorKind::Geniezone => run_gz(cfg, components),
+        #[cfg(all(
+            unix,
+            any(target_arch = "arm", target_arch = "aarch64"),
+            feature = "gunyah"
+        ))]
+        HypervisorKind::Gunyah => run_gunyah(cfg, components),
     }
 }
 
diff --git a/src/crosvm/sys/unix/config.rs b/src/crosvm/sys/unix/config.rs
index 22414ed..9bd1ab1 100644
--- a/src/crosvm/sys/unix/config.rs
+++ b/src/crosvm/sys/unix/config.rs
@@ -20,6 +20,8 @@
     #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
     #[cfg(feature = "geniezone")]
     Geniezone,
+    #[cfg(all(any(target_arch = "arm", target_arch = "aarch64"), feature = "gunyah"))]
+    Gunyah,
 }
 
 impl FromStr for HypervisorKind {
@@ -31,6 +33,8 @@
             #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
             #[cfg(feature = "geniezone")]
             "geniezone" => Ok(HypervisorKind::Geniezone),
+            #[cfg(all(any(target_arch = "arm", target_arch = "aarch64"), feature = "gunyah"))]
+            "gunyah" => Ok(HypervisorKind::Gunyah),
             _ => Err("invalid hypervisor backend"),
         }
     }