Add --enable-earlycon option to vm tool

This should make it easier to debug issues that occur before
virtio_console is available.

The code is guarded by the new RELEASE_AVF_IMPROVE_DEBUGGABLE_VMS
trunk-stable flag. This patch also guards the corresponding change in
pvmfw with the same flag just for the sake of consistency.

This is effectively a relanding of
ec68eaf6e8ba07cf400cdc33501cdd1a85dfe665 with a minor fix to avoid build
breakage.

Test: vm run-microdroid --protected --enable-earlycon --debug full
Test: vm run-microdroid --protected --enable-earlycon --debug none
Test: atest MicrodroidTests
Change-Id: Ic01b35a633456d2fc202374c10da1e22a83ee23d
diff --git a/android/vm/src/main.rs b/android/vm/src/main.rs
index 3c0887c..6eee201 100644
--- a/android/vm/src/main.rs
+++ b/android/vm/src/main.rs
@@ -109,6 +109,23 @@
     /// Note: this is only supported on Android kernels android14-5.15 and higher.
     #[arg(long)]
     gdb: Option<NonZeroU16>,
+
+    /// Whether to enable earlycon. Only supported for debuggable Linux-based VMs.
+    #[cfg(debuggable_vms_improvements)]
+    #[arg(long)]
+    enable_earlycon: bool,
+}
+
+impl DebugConfig {
+    #[cfg(debuggable_vms_improvements)]
+    fn enable_earlycon(&self) -> bool {
+        self.enable_earlycon
+    }
+
+    #[cfg(not(debuggable_vms_improvements))]
+    fn enable_earlycon(&self) -> bool {
+        false
+    }
 }
 
 #[derive(Args, Default)]
diff --git a/android/vm/src/run.rs b/android/vm/src/run.rs
index b3743ae..823546f 100644
--- a/android/vm/src/run.rs
+++ b/android/vm/src/run.rs
@@ -148,7 +148,7 @@
 
     let payload_config_str = format!("{:?}!{:?}", config.apk, payload);
 
-    let custom_config = CustomConfig {
+    let mut custom_config = CustomConfig {
         gdbPort: config.debug.gdb.map(u16::from).unwrap_or(0) as i32, // 0 means no gdb
         vendorImage: vendor,
         devices: config
@@ -163,6 +163,21 @@
         ..Default::default()
     };
 
+    if config.debug.enable_earlycon() {
+        if config.debug.debug != DebugLevel::FULL {
+            bail!("earlycon is only supported for debuggable VMs")
+        }
+        if cfg!(target_arch = "aarch64") {
+            custom_config
+                .extraKernelCmdlineParams
+                .push(String::from("earlycon=uart8250,mmio,0x3f8"));
+        } else if cfg!(target_arch = "x86_64") {
+            custom_config.extraKernelCmdlineParams.push(String::from("earlycon=uart8250,io,0x3f8"));
+        } else {
+            bail!("unexpected architecture!");
+        }
+    }
+
     let vm_config = VirtualMachineConfig::AppConfig(VirtualMachineAppConfig {
         name: config.common.name.unwrap_or_else(|| String::from("VmRunApp")),
         apk: apk_fd.into(),