pvmfw: Issue MMIO_GUARD_MAP for UART

Share the MMIO page containing the UART with the VMM.

When handling a synchronous exception, don't print to the UART if it
would cause re-entering the handler.

Bug: 237371962
Test: m pvmfw_img && flash pvmfw.img && access UART
Change-Id: Ia384f2e3a15b40b5e67cfafd50e571848fd5a126
diff --git a/pvmfw/src/main.rs b/pvmfw/src/main.rs
index 5f918fb..eb97961 100644
--- a/pvmfw/src/main.rs
+++ b/pvmfw/src/main.rs
@@ -18,25 +18,36 @@
 #![no_std]
 
 mod exceptions;
+mod helpers;
+mod smccc;
 
 use core::fmt;
+use helpers::checked_page_of;
 
-use vmbase::{main, power::reboot, println};
+use vmbase::{console, main, power::reboot, println};
 
 #[derive(Debug, Clone)]
-enum Error {}
+enum Error {
+    /// Failed to configure the UART; no logs available.
+    FailedUartSetup,
+}
 
 impl fmt::Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        #[allow(clippy::match_single_binding)]
         let msg = match self {
-            _ => "",
+            Self::FailedUartSetup => "Failed to configure the UART",
         };
         write!(f, "{}", msg)
     }
 }
 
 fn main(fdt_address: u64, payload_start: u64, payload_size: u64, arg3: u64) -> Result<(), Error> {
+    // We need to inform the hypervisor that the MMIO page containing the UART may be shared back.
+    let uart = console::BASE_ADDRESS as u64;
+    let mmio_granule = smccc::mmio_guard_info().map_err(|_| Error::FailedUartSetup)?;
+    let uart_page = checked_page_of(uart, mmio_granule).ok_or(Error::FailedUartSetup)?;
+    smccc::mmio_guard_map(uart_page).map_err(|_| Error::FailedUartSetup)?;
+
     println!("pVM firmware");
     println!(
         "fdt_address={:#018x}, payload_start={:#018x}, payload_size={:#018x}, x3={:#018x}",