[pvmfw] Move assembly wrappers to vmbase for reuse
In both pvmfw and rialo.
Test: atest libpvmfw.bootargs.test
Test: m pvmfw_img
Bug: 282928116
Change-Id: If93cfca26cddcc27aca15baae85a0f7609160c42
diff --git a/pvmfw/src/bootargs.rs b/pvmfw/src/bootargs.rs
index f9c8278..e4b1b65 100644
--- a/pvmfw/src/bootargs.rs
+++ b/pvmfw/src/bootargs.rs
@@ -106,14 +106,14 @@
}
#[cfg(test)]
-#[allow(dead_code)]
-mod helpers;
-
-#[cfg(test)]
mod tests {
-
use super::*;
- use crate::cstr;
+
+ macro_rules! cstr {
+ ($str:literal) => {{
+ core::ffi::CStr::from_bytes_with_nul(concat!($str, "\0").as_bytes()).unwrap()
+ }};
+ }
fn check(raw: &CStr, expected: Result<&[(&str, Option<&str>)], ()>) {
let actual = BootArgsIterator::new(raw);
diff --git a/pvmfw/src/exceptions.rs b/pvmfw/src/exceptions.rs
index e819729..4b24d14 100644
--- a/pvmfw/src/exceptions.rs
+++ b/pvmfw/src/exceptions.rs
@@ -14,11 +14,12 @@
//! Exception handlers.
+use crate::helpers::page_4kb_of;
use crate::memory::{MemoryTrackerError, MEMORY};
-use crate::{helpers::page_4kb_of, read_sysreg};
use core::fmt;
use vmbase::console;
use vmbase::logger;
+use vmbase::read_sysreg;
use vmbase::{eprintln, power::reboot};
const UART_PAGE: usize = page_4kb_of(console::BASE_ADDRESS);
diff --git a/pvmfw/src/helpers.rs b/pvmfw/src/helpers.rs
index 9c4cb1b..1d39e1f 100644
--- a/pvmfw/src/helpers.rs
+++ b/pvmfw/src/helpers.rs
@@ -16,6 +16,7 @@
use core::arch::asm;
use core::ops::Range;
+use vmbase::read_sysreg;
use zeroize::Zeroize;
pub const SIZE_4KB: usize = 4 << 10;
@@ -25,41 +26,6 @@
pub const GUEST_PAGE_SIZE: usize = SIZE_4KB;
pub const PVMFW_PAGE_SIZE: usize = SIZE_4KB;
-/// Read a value from a system register.
-#[macro_export]
-macro_rules! read_sysreg {
- ($sysreg:literal) => {{
- let mut r: usize;
- // Safe because it reads a system register and does not affect Rust.
- #[allow(unused_unsafe)] // In case the macro is used within an unsafe block.
- unsafe {
- core::arch::asm!(
- concat!("mrs {}, ", $sysreg),
- out(reg) r,
- options(nomem, nostack, preserves_flags),
- )
- }
- r
- }};
-}
-
-/// Write a value to a system register.
-///
-/// # Safety
-///
-/// Callers must ensure that side effects of updating the system register are properly handled.
-#[macro_export]
-macro_rules! write_sysreg {
- ($sysreg:literal, $val:expr) => {{
- let value: usize = $val;
- core::arch::asm!(
- concat!("msr ", $sysreg, ", {}"),
- in(reg) value,
- options(nomem, nostack, preserves_flags),
- )
- }};
-}
-
/// Computes the largest multiple of the provided alignment smaller or equal to the address.
///
/// Note: the result is undefined if alignment isn't a power of two.
@@ -196,46 +162,3 @@
const DBM_AVAILABLE: usize = 1 << 1;
read_sysreg!("id_aa64mmfr1_el1") & DBM_AVAILABLE != 0
}
-
-/// Executes a data synchronization barrier.
-#[macro_export]
-macro_rules! dsb {
- ($option:literal) => {{
- // Safe because this is just a memory barrier and does not affect Rust.
- #[allow(unused_unsafe)] // In case the macro is used within an unsafe block.
- unsafe {
- core::arch::asm!(concat!("dsb ", $option), options(nomem, nostack, preserves_flags));
- }
- }};
-}
-
-/// Executes an instruction synchronization barrier.
-#[macro_export]
-macro_rules! isb {
- () => {{
- // Safe because this is just a memory barrier and does not affect Rust.
- #[allow(unused_unsafe)] // In case the macro is used within an unsafe block.
- unsafe {
- core::arch::asm!("isb", options(nomem, nostack, preserves_flags));
- }
- }};
-}
-
-/// Invalidates cached leaf PTE entries by virtual address.
-#[macro_export]
-macro_rules! tlbi {
- ($option:literal, $asid:expr, $addr:expr) => {{
- let asid: usize = $asid;
- let addr: usize = $addr;
- // Safe because it invalidates TLB and doesn't affect Rust. When the address matches a
- // block entry larger than the page size, all translations for the block are invalidated.
- #[allow(unused_unsafe)] // In case the macro is used within an unsafe block.
- unsafe {
- core::arch::asm!(
- concat!("tlbi ", $option, ", {x}"),
- x = in(reg) (asid << 48) | (addr >> 12),
- options(nomem, nostack, preserves_flags)
- );
- }
- }};
-}
diff --git a/pvmfw/src/memory.rs b/pvmfw/src/memory.rs
index 2f6e7a4..c316dd2 100644
--- a/pvmfw/src/memory.rs
+++ b/pvmfw/src/memory.rs
@@ -18,7 +18,6 @@
use crate::helpers::{self, dbm_available, page_4kb_of, RangeExt, PVMFW_PAGE_SIZE, SIZE_4MB};
use crate::mmu;
-use crate::{dsb, isb, read_sysreg, tlbi, write_sysreg};
use aarch64_paging::paging::{Attributes, Descriptor, MemoryRegion as VaRange};
use alloc::alloc::alloc_zeroed;
use alloc::alloc::dealloc;
@@ -41,6 +40,7 @@
use once_cell::race::OnceBox;
use spin::mutex::SpinMutex;
use tinyvec::ArrayVec;
+use vmbase::{dsb, isb, read_sysreg, tlbi, write_sysreg};
/// Base of the system's contiguous "main" memory.
pub const BASE_ADDR: usize = 0x8000_0000;
diff --git a/vmbase/src/arch.rs b/vmbase/src/arch.rs
new file mode 100644
index 0000000..d7b63b3
--- /dev/null
+++ b/vmbase/src/arch.rs
@@ -0,0 +1,93 @@
+// Copyright 2023, 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.
+
+//! Wrappers of assembly calls.
+
+/// Reads a value from a system register.
+#[macro_export]
+macro_rules! read_sysreg {
+ ($sysreg:literal) => {{
+ let mut r: usize;
+ // Safe because it reads a system register and does not affect Rust.
+ #[allow(unused_unsafe)] // In case the macro is used within an unsafe block.
+ unsafe {
+ core::arch::asm!(
+ concat!("mrs {}, ", $sysreg),
+ out(reg) r,
+ options(nomem, nostack, preserves_flags),
+ )
+ }
+ r
+ }};
+}
+
+/// Writes a value to a system register.
+///
+/// # Safety
+///
+/// Callers must ensure that side effects of updating the system register are properly handled.
+#[macro_export]
+macro_rules! write_sysreg {
+ ($sysreg:literal, $val:expr) => {{
+ let value: usize = $val;
+ core::arch::asm!(
+ concat!("msr ", $sysreg, ", {}"),
+ in(reg) value,
+ options(nomem, nostack, preserves_flags),
+ )
+ }};
+}
+
+/// Executes an instruction synchronization barrier.
+#[macro_export]
+macro_rules! isb {
+ () => {{
+ // Safe because this is just a memory barrier and does not affect Rust.
+ #[allow(unused_unsafe)] // In case the macro is used within an unsafe block.
+ unsafe {
+ core::arch::asm!("isb", options(nomem, nostack, preserves_flags));
+ }
+ }};
+}
+
+/// Executes a data synchronization barrier.
+#[macro_export]
+macro_rules! dsb {
+ ($option:literal) => {{
+ // Safe because this is just a memory barrier and does not affect Rust.
+ #[allow(unused_unsafe)] // In case the macro is used within an unsafe block.
+ unsafe {
+ core::arch::asm!(concat!("dsb ", $option), options(nomem, nostack, preserves_flags));
+ }
+ }};
+}
+
+/// Invalidates cached leaf PTE entries by virtual address.
+#[macro_export]
+macro_rules! tlbi {
+ ($option:literal, $asid:expr, $addr:expr) => {{
+ let asid: usize = $asid;
+ let addr: usize = $addr;
+ // Safe because it invalidates TLB and doesn't affect Rust. When the address matches a
+ // block entry larger than the page size, all translations for the block are invalidated.
+ #[allow(unused_unsafe)] // In case the macro is used within an unsafe block.
+ unsafe {
+ core::arch::asm!(
+ concat!("tlbi ", $option, ", {x}"),
+ x = in(reg) (asid << 48) | (addr >> 12),
+ options(nomem, nostack, preserves_flags)
+ );
+ }
+ }};
+}
diff --git a/vmbase/src/lib.rs b/vmbase/src/lib.rs
index d577802..0eca1e4 100644
--- a/vmbase/src/lib.rs
+++ b/vmbase/src/lib.rs
@@ -16,6 +16,7 @@
#![no_std]
+pub mod arch;
mod bionic;
pub mod console;
mod entry;