pvmfw: Use tinyvec::ArrayVec in MemoryTracker
Instead of a DIY implementation, make use of the crate-provided struct.
Test: atest MicrodroidTestApp
Change-Id: I19418245f990a4be2300890767a1004e21b48ee7
diff --git a/pvmfw/Android.bp b/pvmfw/Android.bp
index 455b214..b78e077 100644
--- a/pvmfw/Android.bp
+++ b/pvmfw/Android.bp
@@ -17,6 +17,7 @@
"liblibfdt",
"liblog_rust_nostd",
"libpvmfw_embedded_key",
+ "libtinyvec_nostd",
"libvmbase",
],
static_libs: [
diff --git a/pvmfw/src/memory.rs b/pvmfw/src/memory.rs
index 0f1892d..ca0b886 100644
--- a/pvmfw/src/memory.rs
+++ b/pvmfw/src/memory.rs
@@ -19,22 +19,22 @@
use core::cmp::max;
use core::cmp::min;
use core::fmt;
-use core::mem;
-use core::mem::MaybeUninit;
use core::num::NonZeroUsize;
use core::ops::Range;
use core::result;
use log::error;
+use tinyvec::ArrayVec;
type MemoryRange = Range<usize>;
-#[derive(Clone, Copy, Debug)]
+#[derive(Clone, Copy, Debug, Default)]
enum MemoryType {
+ #[default]
ReadOnly,
ReadWrite,
}
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Default)]
struct MemoryRegion {
range: MemoryRange,
mem_type: MemoryType,
@@ -62,9 +62,7 @@
/// Tracks non-overlapping slices of main memory.
pub struct MemoryTracker {
- // TODO: Use tinyvec::ArrayVec
- count: usize,
- regions: [MaybeUninit<MemoryRegion>; MemoryTracker::CAPACITY],
+ regions: ArrayVec<[MemoryRegion; MemoryTracker::CAPACITY]>,
total: MemoryRange,
page_table: mmu::PageTable,
}
@@ -113,13 +111,7 @@
/// Create a new instance from an active page table, covering the maximum RAM size.
pub fn new(page_table: mmu::PageTable) -> Self {
- Self {
- total: Self::BASE..Self::MAX_ADDR,
- count: 0,
- page_table,
- // SAFETY - MaybeUninit items (of regions) do not require initialization.
- regions: unsafe { MaybeUninit::uninit().assume_init() },
- }
+ Self { total: Self::BASE..Self::MAX_ADDR, page_table, regions: ArrayVec::new() }
}
/// Resize the total RAM size.
@@ -132,7 +124,7 @@
if self.total.end < range.end {
return Err(MemoryTrackerError::SizeTooLarge);
}
- if !self.regions().iter().all(|r| r.is_within(range)) {
+ if !self.regions.iter().all(|r| r.is_within(range)) {
return Err(MemoryTrackerError::SizeTooSmall);
}
@@ -168,31 +160,24 @@
self.alloc_range_mut(&(base..(base + size.get())))
}
- fn regions(&self) -> &[MemoryRegion] {
- // SAFETY - The first self.count regions have been properly initialized.
- unsafe { mem::transmute::<_, &[MemoryRegion]>(&self.regions[..self.count]) }
- }
-
fn add(&mut self, region: MemoryRegion) -> Result<MemoryRange> {
if !region.is_within(&self.total) {
return Err(MemoryTrackerError::OutOfRange);
}
- if self.regions().iter().any(|r| r.overlaps(region.as_ref())) {
+ if self.regions.iter().any(|r| r.overlaps(region.as_ref())) {
return Err(MemoryTrackerError::Overlaps);
}
- if self.regions.len() == self.count {
+ if self.regions.try_push(region).is_some() {
return Err(MemoryTrackerError::Full);
}
- let region = self.regions[self.count].write(region);
- self.count += 1;
- Ok(region.as_ref().clone())
+ Ok(self.regions.last().unwrap().as_ref().clone())
}
}
impl Drop for MemoryTracker {
fn drop(&mut self) {
- for region in self.regions().iter() {
+ for region in self.regions.iter() {
match region.mem_type {
MemoryType::ReadWrite => {
// TODO: Use page table's dirty bit to only flush pages that were touched.