Move common VM functionality into a library.
Bug: 223166344
Test: Ran unprotected VM under crosvm.
Change-Id: I3b027c3a5de037c2adc75cf816518d8db5e10587
diff --git a/pvmfw/Android.bp b/pvmfw/Android.bp
index 3d77b2c..7385288 100644
--- a/pvmfw/Android.bp
+++ b/pvmfw/Android.bp
@@ -13,8 +13,7 @@
"libcore.rust_sysroot",
],
rustlibs: [
- "libpsci",
- "libspin_nostd",
+ "libvmbase",
],
enabled: false,
target: {
diff --git a/pvmfw/src/console.rs b/pvmfw/src/console.rs
deleted file mode 100644
index b52d924..0000000
--- a/pvmfw/src/console.rs
+++ /dev/null
@@ -1,112 +0,0 @@
-// 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.
-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);
-}
-
-/// Reinitialises the UART driver and writes a formatted 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_args(format_args: Arguments) {
- let mut uart = create();
- let _ = write(&mut uart, format_args);
-}
-
-/// Prints the given string to the console.
-///
-/// Panics if the console has not yet been initialised. May hang if used in an exception context;
-/// use `eprint!` instead.
-#[macro_export]
-macro_rules! print {
- ($($arg:tt)*) => ($crate::console::write_args(format_args!($($arg)*)));
-}
-
-/// Prints the given formatted string to the console, followed by a newline.
-///
-/// Panics if the console has not yet been initialised. May hang if used in an exception context;
-/// use `eprintln!` instead.
-#[macro_export]
-macro_rules! println {
- () => ($crate::console::write_str("\n"));
- ($($arg:tt)*) => ({
- $crate::console::write_args(format_args!($($arg)*))};
- $crate::console::write_str("\n");
- );
-}
-
-/// Prints the given string to the console in an emergency, such as an exception handler.
-///
-/// Never panics.
-#[macro_export]
-macro_rules! eprint {
- ($($arg:tt)*) => ($crate::console::emergency_write_args(format_args!($($arg)*)));
-}
-
-/// Prints the given string followed by a newline to the console in an emergency, such as an
-/// exception handler.
-///
-/// Never panics.
-#[macro_export]
-macro_rules! eprintln {
- () => ($crate::console::emergency_write_str("\n"));
- ($($arg:tt)*) => ({
- $crate::console::emergency_write_args(format_args!($($arg)*))};
- $crate::console::emergency_write_str("\n");
- );
-}
diff --git a/pvmfw/src/exceptions.rs b/pvmfw/src/exceptions.rs
index f67a524..61f7846 100644
--- a/pvmfw/src/exceptions.rs
+++ b/pvmfw/src/exceptions.rs
@@ -14,61 +14,59 @@
//! Exception handlers.
-use crate::console::emergency_write_str;
-use crate::eprintln;
use core::arch::asm;
-use psci::system_reset;
+use vmbase::{console::emergency_write_str, eprintln, power::reboot};
#[no_mangle]
extern "C" fn sync_exception_current() {
emergency_write_str("sync_exception_current\n");
print_esr();
- system_reset().unwrap();
+ reboot();
}
#[no_mangle]
extern "C" fn irq_current() {
emergency_write_str("irq_current\n");
- system_reset().unwrap();
+ reboot();
}
#[no_mangle]
extern "C" fn fiq_current() {
emergency_write_str("fiq_current\n");
- system_reset().unwrap();
+ reboot();
}
#[no_mangle]
extern "C" fn serr_current() {
emergency_write_str("serr_current\n");
print_esr();
- system_reset().unwrap();
+ reboot();
}
#[no_mangle]
extern "C" fn sync_lower() {
emergency_write_str("sync_lower\n");
print_esr();
- system_reset().unwrap();
+ reboot();
}
#[no_mangle]
extern "C" fn irq_lower() {
emergency_write_str("irq_lower\n");
- system_reset().unwrap();
+ reboot();
}
#[no_mangle]
extern "C" fn fiq_lower() {
emergency_write_str("fiq_lower\n");
- system_reset().unwrap();
+ reboot();
}
#[no_mangle]
extern "C" fn serr_lower() {
emergency_write_str("serr_lower\n");
print_esr();
- system_reset().unwrap();
+ reboot();
}
#[inline]
diff --git a/pvmfw/src/main.rs b/pvmfw/src/main.rs
index 395c252..3fe3435 100644
--- a/pvmfw/src/main.rs
+++ b/pvmfw/src/main.rs
@@ -17,12 +17,9 @@
#![no_main]
#![no_std]
-mod console;
mod exceptions;
-mod uart;
-use core::panic::PanicInfo;
-use psci::{system_off, system_reset};
+use vmbase::{console, power::shutdown, println};
/// Entry point for pVM firmware.
#[no_mangle]
@@ -30,14 +27,5 @@
console::init();
println!("Hello world");
- system_off().unwrap();
- #[allow(clippy::empty_loop)]
- loop {}
-}
-
-#[panic_handler]
-fn panic(info: &PanicInfo) -> ! {
- eprintln!("{}", info);
- system_reset().unwrap();
- loop {}
+ shutdown();
}
diff --git a/pvmfw/src/uart.rs b/pvmfw/src/uart.rs
deleted file mode 100644
index 0fc2494..0000000
--- a/pvmfw/src/uart.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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 {}