use std::sync::{Arc, Mutex};
pub trait MmioDevice: Send + Sync {
fn read(&self, offset: u64, size: u8) -> u64;
fn write(&self, offset: u64, value: u64, size: u8);
fn len(&self) -> u64;
}
pub struct MmioBus {
entries: Mutex<Vec<(u64, u64, Arc<dyn MmioDevice>)>>,
}
impl MmioBus {
pub fn new() -> Self {
Self {
entries: Mutex::new(Vec::new()),
}
}
pub fn register(&self, base: u64, dev: Arc<dyn MmioDevice>) {
let len = dev.len();
self.entries.lock().unwrap().push((base, len, dev));
}
pub fn lookup(&self, gpa: u64) -> Option<(Arc<dyn MmioDevice>, u64)> {
let g = self.entries.lock().unwrap();
for (base, len, dev) in g.iter() {
if gpa >= *base && gpa < base + len {
return Some((dev.clone(), gpa - base));
}
}
None
}
pub fn read(&self, gpa: u64, size: u8) -> Option<u64> {
let (dev, off) = self.lookup(gpa)?;
Some(dev.read(off, size))
}
pub fn write(&self, gpa: u64, value: u64, size: u8) -> bool {
if let Some((dev, off)) = self.lookup(gpa) {
dev.write(off, value, size);
true
} else {
false
}
}
}