Merge branch 'rw_van_230406' into 'master'

Add AmlHandler read/write of physaddr

See merge request redox-os/drivers!92
This commit is contained in:
Jeremy Soller
2023-04-14 14:19:19 +00:00
3 changed files with 442 additions and 245 deletions
+24 -245
View File
@@ -2,7 +2,7 @@ use rustc_hash::FxHashMap;
use std::convert::{TryFrom, TryInto};
use std::fmt::Write;
use std::ops::Deref;
use std::sync::Arc;
use std::sync::{Arc, Mutex};
use std::{fmt, mem};
use syscall::flag::PhysmapFlags;
@@ -19,6 +19,7 @@ use amlserde::{AmlHandleLookup, AmlSerde};
pub mod dmar;
use self::dmar::Dmar;
use crate::aml_physmem::{AmlPageCache, AmlPhysMemHandler};
#[cfg(target_arch = "aarch64")]
pub const PAGE_SIZE: usize = 4096;
@@ -244,15 +245,21 @@ pub struct Ssdt(Sdt);
pub struct AmlSymbols {
aml_context: AmlContext,
// k = name, v = description
cache: FxHashMap<String, String>,
symbol_cache: FxHashMap<String, String>,
page_cache: Arc<Mutex<AmlPageCache>>,
list: String,
}
impl AmlSymbols {
pub fn new() -> Self {
let page_cache = Arc::new(Mutex::new(AmlPageCache::default()));
Self {
aml_context: AmlContext::new(Box::new(AmlPhysMemHandler), aml::DebugVerbosity::None),
cache: FxHashMap::default(),
aml_context: AmlContext::new(
Box::new(AmlPhysMemHandler::new(Arc::clone(&page_cache))),
aml::DebugVerbosity::None,
),
symbol_cache: FxHashMap::default(),
page_cache,
list: "".to_string(),
}
}
@@ -266,7 +273,7 @@ impl AmlSymbols {
}
pub fn symbols_cache(&self) -> &FxHashMap<String, String> {
&self.cache
&self.symbol_cache
}
pub fn parse_table(&mut self, aml: &[u8]) -> Result<(), AmlError> {
@@ -274,7 +281,7 @@ impl AmlSymbols {
}
pub fn lookup(&self, symbol: &str) -> Option<String> {
if let Some(description) = self.cache.get(symbol) {
if let Some(description) = self.symbol_cache.get(symbol) {
log::trace!("Found symbol in cache, {}, {}", symbol, description);
return Some(description.to_owned());
}
@@ -343,7 +350,7 @@ impl AmlSymbols {
log::trace!("Updating symbols list");
self.list = symbols_str;
self.cache = symbol_cache;
self.symbol_cache = symbol_cache;
}
}
@@ -423,6 +430,15 @@ impl AcpiContext {
}
}
}
if let Ok(mut page_cache) = aml_symbols.page_cache.lock() {
page_cache.clear();
} else {
log::error!("failed to lock AmlPageCache");
}
// force drop of page_cache from the previous if let
{}
}
pub fn dsdt(&self) -> Option<&Dsdt> {
@@ -518,7 +534,7 @@ impl AcpiContext {
/// Discard any cached symbols list. To be called if the AML namespace changes.
pub fn aml_symbols_reset(&self) {
let mut aml_symbols = self.aml_symbols.write();
aml_symbols.cache = FxHashMap::default();
aml_symbols.symbol_cache = FxHashMap::default();
aml_symbols.list = "".to_string();
}
@@ -825,240 +841,3 @@ impl AmlContainingTable for Ssdt {
&*self.0
}
}
struct AmlPhysMemHandler;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
impl aml::Handler for AmlPhysMemHandler {
fn read_u8(&self, _address: usize) -> u8 {
log::error!("read u8 {:X}", _address);
0
}
fn read_u16(&self, _address: usize) -> u16 {
log::error!("read u16 {:X}", _address);
0
}
fn read_u32(&self, _address: usize) -> u32 {
log::error!("read u32 {:X}", _address);
0
}
fn read_u64(&self, _address: usize) -> u64 {
log::error!("read u64 {:X}", _address);
0
}
fn write_u8(&mut self, _address: usize, _value: u8) {
log::error!("write u8 {:X} = {:X}", _address, _value);
}
fn write_u16(&mut self, _address: usize, _value: u16) {
log::error!("write u16 {:X} = {:X}", _address, _value);
}
fn write_u32(&mut self, _address: usize, _value: u32) {
log::error!("write u32 {:X} = {:X}", _address, _value);
}
fn write_u64(&mut self, _address: usize, _value: u64) {
log::error!("write u64 {:X} = {:X}", _address, _value);
}
fn read_io_u8(&self, port: u16) -> u8 {
Pio::<u8>::new(port).read()
}
fn read_io_u16(&self, port: u16) -> u16 {
Pio::<u16>::new(port).read()
}
fn read_io_u32(&self, port: u16) -> u32 {
Pio::<u32>::new(port).read()
}
fn write_io_u8(&self, port: u16, value: u8) {
Pio::<u8>::new(port).write(value)
}
fn write_io_u16(&self, port: u16, value: u16) {
Pio::<u16>::new(port).write(value)
}
fn write_io_u32(&self, port: u16, value: u32) {
Pio::<u32>::new(port).write(value)
}
fn read_pci_u8(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16) -> u8 {
log::error!("read pci u8 {:X}", _device);
0
}
fn read_pci_u16(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
) -> u16 {
log::error!("read pci u8 {:X}", _device);
0
}
fn read_pci_u32(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
) -> u32 {
log::error!("read pci u8 {:X}", _device);
0
}
fn write_pci_u8(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
_value: u8,
) {
log::error!("write pci u8 {:X}", _device);
}
fn write_pci_u16(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
_value: u16,
) {
log::error!("write pci u8 {:X}", _device);
}
fn write_pci_u32(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
_value: u32,
) {
log::error!("write pci u8 {:X}", _device);
}
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
impl aml::Handler for AmlPhysMemHandler {
fn read_u8(&self, _address: usize) -> u8 {
log::error!("read u8 {:X}", _address);
0
}
fn read_u16(&self, _address: usize) -> u16 {
log::error!("read u16 {:X}", _address);
0
}
fn read_u32(&self, _address: usize) -> u32 {
log::error!("read u32 {:X}", _address);
0
}
fn read_u64(&self, _address: usize) -> u64 {
log::error!("read u64 {:X}", _address);
0
}
fn write_u8(&mut self, _address: usize, _value: u8) {
log::error!("write u8 {:X} = {:X}", _address, _value);
}
fn write_u16(&mut self, _address: usize, _value: u16) {
log::error!("write u16 {:X} = {:X}", _address, _value);
}
fn write_u32(&mut self, _address: usize, _value: u32) {
log::error!("write u32 {:X} = {:X}", _address, _value);
}
fn write_u64(&mut self, _address: usize, _value: u64) {
log::error!("write u64 {:X} = {:X}", _address, _value);
}
fn read_io_u8(&self, port: u16) -> u8 {
log::error!("read io u8 {:X}", port);
0
}
fn read_io_u16(&self, port: u16) -> u16 {
log::error!("read io u16 {:X}", port);
0
}
fn read_io_u32(&self, port: u16) -> u32 {
log::error!("read io u32 {:X}", port);
0
}
fn write_io_u8(&self, port: u16, value: u8) {
log::error!("write io u8 {:X} = {:X}", port, value);
}
fn write_io_u16(&self, port: u16, value: u16) {
log::error!("write io u16 {:X} = {:X}", port, value);
}
fn write_io_u32(&self, port: u16, value: u32) {
log::error!("write io u32 {:X} = {:X}", port, value);
}
fn read_pci_u8(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16) -> u8 {
log::error!("read pci u8 {:X}", _device);
0
}
fn read_pci_u16(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
) -> u16 {
log::error!("read pci u8 {:X}", _device);
0
}
fn read_pci_u32(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
) -> u32 {
log::error!("read pci u8 {:X}", _device);
0
}
fn write_pci_u8(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
_value: u8,
) {
log::error!("write pci u8 {:X}", _device);
}
fn write_pci_u16(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
_value: u16,
) {
log::error!("write pci u8 {:X}", _device);
}
fn write_pci_u32(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
_value: u32,
) {
log::error!("write pci u8 {:X}", _device);
}
}
+417
View File
@@ -0,0 +1,417 @@
use num_traits::PrimInt;
use rustc_hash::FxHashMap;
use std::fmt::LowerHex;
use std::mem::size_of;
use std::sync::{Arc, Mutex};
use syscall::{Io, PhysmapFlags, Pio, PAGE_SIZE};
const PAGE_MASK: usize = !(PAGE_SIZE - 1);
const OFFSET_MASK: usize = PAGE_SIZE - 1;
struct MappedPage {
phys_page: usize,
virt_page: usize,
}
impl MappedPage {
fn new(phys_page: usize) -> std::io::Result<Self> {
let virt_page = unsafe {
syscall::physmap(phys_page, PAGE_SIZE, PhysmapFlags::empty())
.map_err(|error| std::io::Error::from_raw_os_error(error.errno))?
};
Ok(Self {
phys_page,
virt_page,
})
}
}
impl Drop for MappedPage {
fn drop(&mut self) {
log::trace!("Drop page {:#x}", self.phys_page);
if let Err(e) = unsafe { syscall::physunmap(self.virt_page) } {
log::error!("physunmap: {:?}", e);
}
}
}
#[derive(Default)]
pub struct AmlPageCache {
page_cache: FxHashMap<usize, MappedPage>,
}
impl AmlPageCache {
/// get a virtual address for the given physical page
fn get_page(&mut self, phys_target: usize) -> std::io::Result<&MappedPage> {
let phys_page = phys_target & PAGE_MASK;
if self.page_cache.contains_key(&phys_page) {
log::trace!("re-using cached page {:#x}", phys_page);
Ok(self
.page_cache
.get(&phys_page)
.expect("could not get page after contains=true"))
} else {
let mapped_page = MappedPage::new(phys_page)?;
log::trace!("adding page {:#x} to cache", mapped_page.phys_page);
self.page_cache.insert(phys_page, mapped_page);
Ok(self
.page_cache
.get(&phys_page)
.expect("can't find page that was just inserted"))
}
}
/// The offset into the virtual slice of T that matches the physical target
fn sized_index<T>(phys_target: usize) -> usize {
assert_eq!(
phys_target & !(size_of::<T>() - 1),
phys_target,
"address {} is not aligned",
phys_target
);
(phys_target & OFFSET_MASK) / size_of::<T>()
}
/// Read from the given physical address
fn read_from_phys<T: PrimInt + LowerHex>(&mut self, phys_target: usize) -> std::io::Result<T> {
let mapped_page = self.get_page(phys_target)?;
let page_as_slice = unsafe {
std::slice::from_raw_parts(
mapped_page.virt_page as *const T,
PAGE_SIZE / size_of::<T>(),
)
};
// for debugging only
let _virt_ptr = page_as_slice[Self::sized_index::<T>(phys_target)..].as_ptr() as usize;
let val = page_as_slice[Self::sized_index::<T>(phys_target)];
log::trace!(
"read {:#x}, virt {:#x}, val {:#x}",
phys_target,
_virt_ptr,
val
);
Ok(val)
}
/// Write to the given physical address
fn write_to_phys<T: PrimInt + LowerHex>(
&mut self,
phys_target: usize,
val: T,
) -> std::io::Result<()> {
let mapped_page = self.get_page(phys_target)?;
let page_as_slice = unsafe {
std::slice::from_raw_parts_mut(
mapped_page.virt_page as *mut T,
PAGE_SIZE / size_of::<T>(),
)
};
// for debugging only
let _virt_ptr = page_as_slice[Self::sized_index::<T>(phys_target)..].as_ptr() as usize;
page_as_slice[Self::sized_index::<T>(phys_target)] = val;
log::trace!(
"write {:#x}, virt {:#x}, val {:#x}",
phys_target,
_virt_ptr,
val
);
Ok(())
}
pub fn clear(&mut self) {
log::trace!("Clear page cache");
self.page_cache.clear();
}
}
pub struct AmlPhysMemHandler {
page_cache: Arc<Mutex<AmlPageCache>>,
}
/// Read from a physical address.
/// Generic parameter must be u8, u16, u32 or u64.
impl AmlPhysMemHandler {
pub fn new(page_cache: Arc<Mutex<AmlPageCache>>) -> Self {
Self { page_cache }
}
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
impl aml::Handler for AmlPhysMemHandler {
fn read_u8(&self, address: usize) -> u8 {
log::trace!("read u8 {:X}", address);
if let Ok(mut page_cache) = self.page_cache.lock() {
if let Ok(value) = page_cache.read_from_phys::<u8>(address) {
return value;
}
}
0
}
fn read_u16(&self, address: usize) -> u16 {
log::trace!("read u16 {:X}", address);
if let Ok(mut page_cache) = self.page_cache.lock() {
if let Ok(value) = page_cache.read_from_phys::<u16>(address) {
return value;
}
}
0
}
fn read_u32(&self, address: usize) -> u32 {
log::trace!("read u32 {:X}", address);
if let Ok(mut page_cache) = self.page_cache.lock() {
if let Ok(value) = page_cache.read_from_phys::<u32>(address) {
return value;
}
}
0
}
fn read_u64(&self, address: usize) -> u64 {
log::trace!("read u64 {:X}", address);
if let Ok(mut page_cache) = self.page_cache.lock() {
if let Ok(value) = page_cache.read_from_phys::<u64>(address) {
return value;
}
}
0
}
fn write_u8(&mut self, address: usize, value: u8) {
log::error!("write u8 {:X} = {:X}", address, value);
if let Ok(mut page_cache) = self.page_cache.lock() {
if page_cache.write_to_phys::<u8>(address, value).is_err() {
log::error!("failed to get page {:#x}", address);
}
}
}
fn write_u16(&mut self, address: usize, value: u16) {
log::error!("write u16 {:X} = {:X}", address, value);
if let Ok(mut page_cache) = self.page_cache.lock() {
if page_cache.write_to_phys::<u16>(address, value).is_err() {
log::error!("failed to get page {:#x}", address);
}
}
}
fn write_u32(&mut self, address: usize, value: u32) {
log::error!("write u32 {:X} = {:X}", address, value);
if let Ok(mut page_cache) = self.page_cache.lock() {
if page_cache.write_to_phys::<u32>(address, value).is_err() {
log::error!("failed to get page {:#x}", address);
}
}
}
fn write_u64(&mut self, address: usize, value: u64) {
log::error!("write u64 {:X} = {:X}", address, value);
if let Ok(mut page_cache) = self.page_cache.lock() {
if page_cache.write_to_phys::<u64>(address, value).is_err() {
log::error!("failed to get page {:#x}", address);
}
}
}
// Pio must be enabled via syscall::iopl(3)
fn read_io_u8(&self, port: u16) -> u8 {
Pio::<u8>::new(port).read()
}
fn read_io_u16(&self, port: u16) -> u16 {
Pio::<u16>::new(port).read()
}
fn read_io_u32(&self, port: u16) -> u32 {
Pio::<u32>::new(port).read()
}
fn write_io_u8(&self, port: u16, value: u8) {
Pio::<u8>::new(port).write(value)
}
fn write_io_u16(&self, port: u16, value: u16) {
Pio::<u16>::new(port).write(value)
}
fn write_io_u32(&self, port: u16, value: u32) {
Pio::<u32>::new(port).write(value)
}
fn read_pci_u8(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16) -> u8 {
log::error!("read pci u8 {:X}", _device);
0
}
fn read_pci_u16(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
) -> u16 {
log::error!("read pci u16 {:X}", _device);
0
}
fn read_pci_u32(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
) -> u32 {
log::error!("read pci u32 {:X}", _device);
0
}
fn write_pci_u8(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
_value: u8,
) {
log::error!("write pci u8 {:X}", _device);
}
fn write_pci_u16(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
_value: u16,
) {
log::error!("write pci u16 {:X}", _device);
}
fn write_pci_u32(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
_value: u32,
) {
log::error!("write pci u32 {:X}", _device);
}
}
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
impl aml::Handler for AmlPhysMemHandler {
fn read_u8(&self, _address: usize) -> u8 {
log::error!("read u8 {:X}", _address);
0
}
fn read_u16(&self, _address: usize) -> u16 {
log::error!("read u16 {:X}", _address);
0
}
fn read_u32(&self, _address: usize) -> u32 {
log::error!("read u32 {:X}", _address);
0
}
fn read_u64(&self, _address: usize) -> u64 {
log::error!("read u64 {:X}", _address);
0
}
fn write_u8(&mut self, _address: usize, _value: u8) {
log::error!("write u8 {:X} = {:X}", _address, _value);
}
fn write_u16(&mut self, _address: usize, _value: u16) {
log::error!("write u16 {:X} = {:X}", _address, _value);
}
fn write_u32(&mut self, _address: usize, _value: u32) {
log::error!("write u32 {:X} = {:X}", _address, _value);
}
fn write_u64(&mut self, _address: usize, _value: u64) {
log::error!("write u64 {:X} = {:X}", _address, _value);
}
fn read_io_u8(&self, port: u16) -> u8 {
log::error!("read io u8 {:X}", port);
0
}
fn read_io_u16(&self, port: u16) -> u16 {
log::error!("read io u16 {:X}", port);
0
}
fn read_io_u32(&self, port: u16) -> u32 {
log::error!("read io u32 {:X}", port);
0
}
fn write_io_u8(&self, port: u16, value: u8) {
log::error!("write io u8 {:X} = {:X}", port, value);
}
fn write_io_u16(&self, port: u16, value: u16) {
log::error!("write io u16 {:X} = {:X}", port, value);
}
fn write_io_u32(&self, port: u16, value: u32) {
log::error!("write io u32 {:X} = {:X}", port, value);
}
fn read_pci_u8(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16) -> u8 {
log::error!("read pci u8 {:X}", _device);
0
}
fn read_pci_u16(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
) -> u16 {
log::error!("read pci u8 {:X}", _device);
0
}
fn read_pci_u32(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
) -> u32 {
log::error!("read pci u8 {:X}", _device);
0
}
fn write_pci_u8(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
_value: u8,
) {
log::error!("write pci u8 {:X}", _device);
}
fn write_pci_u16(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
_value: u16,
) {
log::error!("write pci u8 {:X}", _device);
}
fn write_pci_u32(
&self,
_segment: u16,
_bus: u8,
_device: u8,
_function: u8,
_offset: u16,
_value: u32,
) {
log::error!("write pci u8 {:X}", _device);
}
}
+1
View File
@@ -16,6 +16,7 @@ use syscall::flag::{EventFlags, O_NONBLOCK};
mod acpi;
mod scheme;
mod aml_physmem;
fn monotonic() -> (u64, u64) {
use syscall::call::clock_gettime;