Merge changes I974e9783,I74c2d43d,I65a4804e

* changes:
  pvmfw: Hack MMIO_GUARD_MAP to expect i32
  pvmfw: Hack MMIO_GUARD_UNMAP to expect NOT_SUPPORTED
  pvmfw: Issue MMIO_GUARD_UNMAP for UART
diff --git a/pvmfw/src/entry.rs b/pvmfw/src/entry.rs
index a606462..99c67fb 100644
--- a/pvmfw/src/entry.rs
+++ b/pvmfw/src/entry.rs
@@ -18,7 +18,7 @@
 use crate::mmio_guard;
 use core::arch::asm;
 use core::slice;
-use log::{debug, LevelFilter};
+use log::{debug, error, LevelFilter};
 use vmbase::{console, logger, main, power::reboot};
 
 #[derive(Debug, Clone)]
@@ -77,6 +77,11 @@
     // This wrapper allows main() to be blissfully ignorant of platform details.
     crate::main(fdt, payload);
 
+    mmio_guard::unmap(console::BASE_ADDRESS).map_err(|e| {
+        error!("Failed to unshare the UART: {e}");
+        RebootReason::InternalError
+    })?;
+
     Ok(())
 }
 
diff --git a/pvmfw/src/mmio_guard.rs b/pvmfw/src/mmio_guard.rs
index 421f2c4..eb6c1fa 100644
--- a/pvmfw/src/mmio_guard.rs
+++ b/pvmfw/src/mmio_guard.rs
@@ -17,6 +17,7 @@
 use crate::helpers;
 use crate::smccc;
 use core::{fmt, result};
+use log::info;
 
 #[derive(Debug, Clone)]
 pub enum Error {
@@ -26,6 +27,8 @@
     InfoFailed(smccc::Error),
     /// Failed to MMIO_GUARD_MAP a page.
     MapFailed(smccc::Error),
+    /// Failed to MMIO_GUARD_UNMAP a page.
+    UnmapFailed(smccc::Error),
     /// The MMIO_GUARD granule used by the hypervisor is not supported.
     UnsupportedGranule(usize),
 }
@@ -38,6 +41,7 @@
             Self::EnrollFailed(e) => write!(f, "Failed to enroll into MMIO_GUARD: {e}"),
             Self::InfoFailed(e) => write!(f, "Failed to get the MMIO_GUARD granule: {e}"),
             Self::MapFailed(e) => write!(f, "Failed to MMIO_GUARD map: {e}"),
+            Self::UnmapFailed(e) => write!(f, "Failed to MMIO_GUARD unmap: {e}"),
             Self::UnsupportedGranule(g) => write!(f, "Unsupported MMIO_GUARD granule: {g}"),
         }
     }
@@ -56,6 +60,10 @@
     mmio_guard_map(helpers::page_4kb_of(addr) as u64).map_err(Error::MapFailed)
 }
 
+pub fn unmap(addr: usize) -> Result<()> {
+    mmio_guard_unmap(helpers::page_4kb_of(addr) as u64).map_err(Error::UnmapFailed)
+}
+
 fn mmio_guard_info() -> smccc::Result<u64> {
     const VENDOR_HYP_KVM_MMIO_GUARD_INFO_FUNC_ID: u32 = 0xc6000005;
     let args = [0u64; 17];
@@ -75,5 +83,31 @@
     let mut args = [0u64; 17];
     args[0] = ipa;
 
-    smccc::checked_hvc64_expect_zero(VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID, args)
+    // TODO(b/253586500): pKVM currently returns a i32 instead of a i64.
+    let is_i32_error_code = |n| u32::try_from(n).ok().filter(|v| (*v as i32) < 0).is_some();
+    match smccc::checked_hvc64_expect_zero(VENDOR_HYP_KVM_MMIO_GUARD_MAP_FUNC_ID, args) {
+        Err(smccc::Error::Unexpected(e)) if is_i32_error_code(e) => {
+            info!("Handled a pKVM bug by interpreting the MMIO_GUARD_MAP return value as i32");
+            match e as u32 as i32 {
+                -1 => Err(smccc::Error::NotSupported),
+                -2 => Err(smccc::Error::NotRequired),
+                -3 => Err(smccc::Error::InvalidParameter),
+                ret => Err(smccc::Error::Unknown(ret as i64)),
+            }
+        }
+        res => res,
+    }
+}
+
+fn mmio_guard_unmap(ipa: u64) -> smccc::Result<()> {
+    const VENDOR_HYP_KVM_MMIO_GUARD_UNMAP_FUNC_ID: u32 = 0xc6000008;
+    let mut args = [0u64; 17];
+    args[0] = ipa;
+
+    // TODO(b/251426790): pKVM currently returns NOT_SUPPORTED for SUCCESS.
+    info!("Expecting a bug making MMIO_GUARD_UNMAP return NOT_SUPPORTED on success");
+    match smccc::checked_hvc64_expect_zero(VENDOR_HYP_KVM_MMIO_GUARD_UNMAP_FUNC_ID, args) {
+        Err(smccc::Error::NotSupported) | Ok(_) => Ok(()),
+        x => x,
+    }
 }