Add minimal UART driver for console.

Bug: 223166344
Test: Ran unprotected VM under crosvm.
Change-Id: I4e779ab0c87597db9384247f269b2b28f6e18b30
diff --git a/pvmfw/Android.bp b/pvmfw/Android.bp
index 7123da4..ce096b6 100644
--- a/pvmfw/Android.bp
+++ b/pvmfw/Android.bp
@@ -8,6 +8,9 @@
         "libcompiler_builtins.rust_sysroot",
         "libcore.rust_sysroot",
     ],
+    rustlibs: [
+        "libspin_nostd",
+    ],
     enabled: false,
     target: {
         android_arm64: {
diff --git a/pvmfw/src/console.rs b/pvmfw/src/console.rs
new file mode 100644
index 0000000..d44eb92
--- /dev/null
+++ b/pvmfw/src/console.rs
@@ -0,0 +1,61 @@
+// Copyright 2022, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Console driver for 8250 UART.
+
+use crate::uart::Uart;
+use core::fmt::{write, Arguments, Write};
+use spin::mutex::SpinMutex;
+
+const BASE_ADDRESS: usize = 0x3f8;
+
+static CONSOLE: SpinMutex<Option<Uart>> = SpinMutex::new(None);
+
+/// Initialises a new instance of the UART driver and returns it.
+fn create() -> Uart {
+    // Safe because BASE_ADDRESS is the base of the MMIO region for a UART and is mapped as device
+    // memory.
+    unsafe { Uart::new(BASE_ADDRESS) }
+}
+
+/// Initialises the global instance of the UART driver. This must be called before using
+/// the `print!` and `println!` macros.
+pub fn init() {
+    let uart = create();
+    CONSOLE.lock().replace(uart);
+}
+
+/// Writes a string to the console.
+///
+/// Panics if [`init`] was not called first.
+pub fn write_str(s: &str) {
+    CONSOLE.lock().as_mut().unwrap().write_str(s).unwrap();
+}
+
+/// Writes a formatted string to the console.
+///
+/// Panics if [`init`] was not called first.
+#[allow(unused)]
+pub fn write_args(format_args: Arguments) {
+    write(CONSOLE.lock().as_mut().unwrap(), format_args).unwrap();
+}
+
+/// Reinitialises the UART driver and writes a string to it.
+///
+/// This is intended for use in situations where the UART may be in an unknown state or the global
+/// instance may be locked, such as in an exception handler or panic handler.
+pub fn emergency_write_str(s: &str) {
+    let mut uart = create();
+    let _ = uart.write_str(s);
+}
diff --git a/pvmfw/src/main.rs b/pvmfw/src/main.rs
index 0a359f6..7156213 100644
--- a/pvmfw/src/main.rs
+++ b/pvmfw/src/main.rs
@@ -17,14 +17,20 @@
 #![no_main]
 #![no_std]
 
+mod console;
 mod psci;
+mod uart;
 
+use console::emergency_write_str;
 use core::panic::PanicInfo;
 use psci::{system_off, system_reset};
 
 /// Entry point for pVM firmware.
 #[no_mangle]
 pub extern "C" fn main() -> ! {
+    console::init();
+    console::write_str("Hello world\n");
+
     system_off();
     #[allow(clippy::empty_loop)]
     loop {}
@@ -32,6 +38,7 @@
 
 #[panic_handler]
 fn panic(_info: &PanicInfo) -> ! {
+    emergency_write_str("panic\n");
     system_reset();
     loop {}
 }
diff --git a/pvmfw/src/uart.rs b/pvmfw/src/uart.rs
new file mode 100644
index 0000000..0fc2494
--- /dev/null
+++ b/pvmfw/src/uart.rs
@@ -0,0 +1,59 @@
+// Copyright 2022, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Minimal driver for an 8250 UART. This only implements enough to work with the emulated 8250
+//! provided by crosvm, and won't work with real hardware.
+
+use core::fmt::{self, Write};
+use core::ptr::write_volatile;
+
+/// Minimal driver for an 8250 UART. This only implements enough to work with the emulated 8250
+/// provided by crosvm, and won't work with real hardware.
+pub struct Uart {
+    base_address: *mut u8,
+}
+
+impl Uart {
+    /// Constructs a new instance of the UART driver for a device at the given base address.
+    ///
+    /// # Safety
+    ///
+    /// The given base address must point to the 8 MMIO control registers of an appropriate UART
+    /// device, which must be mapped into the address space of the process as device memory and not
+    /// have any other aliases.
+    pub unsafe fn new(base_address: usize) -> Self {
+        Self { base_address: base_address as *mut u8 }
+    }
+
+    /// Writes a single byte to the UART.
+    pub fn write_byte(&self, byte: u8) {
+        // Safe because we know that the base address points to the control registers of an UART
+        // device which is appropriately mapped.
+        unsafe {
+            write_volatile(self.base_address, byte);
+        }
+    }
+}
+
+impl Write for Uart {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        for c in s.as_bytes() {
+            self.write_byte(*c);
+        }
+        Ok(())
+    }
+}
+
+// Safe because it just contains a pointer to device memory, which can be accessed from any context.
+unsafe impl Send for Uart {}