pvmfw: Leave UART shared for debuggable pVMs

When the payload is debuggable (detected through its VBMeta), pvmfw
allows any cmdline argument to be passed to the guest kernel. For Linux,
this means the host could enable earlycon through the 16550-inspired
UARTs. However, as the Microdroid kernel does not support MMIO_GUARD for
earlycon, this would not work (possibly resulting in a guest kernel
panic due to the unhandled injected exception? TBD).

To support this use-case, make pvmfw leave the UART mapped for the next
stage if it detects that the payload is debuggable (should not be used
in production & reflected in the payload's DICE chain). Note that
debuggable payloads that already support sharing the UART (which, from
the perspective of the hypervisor, would now be sharing it "twice")
should not break as the HVC still succeeds when called on already
guarded MMIO pages.

Test: m pvmfw
Bug: 356622725
Change-Id: I3f8cc3317142ec55d2c864bd658d42fa2c0ae345
diff --git a/guest/pvmfw/src/entry.rs b/guest/pvmfw/src/entry.rs
index 0ff7270..ce04317 100644
--- a/guest/pvmfw/src/entry.rs
+++ b/guest/pvmfw/src/entry.rs
@@ -256,7 +256,7 @@
     )?;
 
     // This wrapper allows main() to be blissfully ignorant of platform details.
-    let next_bcc = crate::main(
+    let (next_bcc, debuggable_payload) = crate::main(
         slices.fdt,
         slices.kernel,
         slices.ramdisk,
@@ -274,11 +274,15 @@
     })?;
     // Call unshare_all_memory here (instead of relying on the dtor) while UART is still mapped.
     MEMORY.lock().as_mut().unwrap().unshare_all_memory();
+
     if let Some(mmio_guard) = get_mmio_guard() {
-        mmio_guard.unmap(UART_PAGE_ADDR).map_err(|e| {
-            error!("Failed to unshare the UART: {e}");
-            RebootReason::InternalError
-        })?;
+        // Keep UART MMIO_GUARD-ed for debuggable payloads, to enable earlycon.
+        if !debuggable_payload {
+            mmio_guard.unmap(UART_PAGE_ADDR).map_err(|e| {
+                error!("Failed to unshare the UART: {e}");
+                RebootReason::InternalError
+            })?;
+        }
     }
 
     // Drop MemoryTracker and deactivate page table.
diff --git a/guest/pvmfw/src/main.rs b/guest/pvmfw/src/main.rs
index 247aa6a..10f8549 100644
--- a/guest/pvmfw/src/main.rs
+++ b/guest/pvmfw/src/main.rs
@@ -67,7 +67,7 @@
     ramdisk: Option<&[u8]>,
     current_bcc_handover: &[u8],
     mut debug_policy: Option<&[u8]>,
-) -> Result<Range<usize>, RebootReason> {
+) -> Result<(Range<usize>, bool), RebootReason> {
     info!("pVM firmware");
     debug!("FDT: {:?}", fdt.as_ptr());
     debug!("Signed kernel: {:?} ({:#x} bytes)", signed_kernel.as_ptr(), signed_kernel.len());
@@ -240,7 +240,7 @@
         (r.start as usize)..(r.end as usize)
     };
 
-    Ok(bcc_range)
+    Ok((bcc_range, debuggable))
 }
 
 fn check_dice_measurements_match_entry(