Skip to content

Commit 77d446e

Browse files
committed
aml: support PCI config space field reads
1 parent b6b78ca commit 77d446e

File tree

4 files changed

+97
-35
lines changed

4 files changed

+97
-35
lines changed

aml/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ license = "MIT/Apache-2.0"
1313
spinning_top = "0.3.0"
1414
bit_field = "0.10.2"
1515
byteorder = { version = "1.5.0", default-features = false }
16+
log = "0.4"
17+
pci_types = "0.10.0"

aml/src/lib.rs

Lines changed: 80 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ pub mod op_region;
99
pub mod pci_routing;
1010
pub mod resource;
1111

12+
pub use pci_types::PciAddress;
13+
1214
use alloc::{
1315
boxed::Box,
1416
collections::btree_map::BTreeMap,
@@ -82,6 +84,24 @@ where
8284
}
8385
}
8486

87+
pub fn invoke_method_if_present(
88+
&self,
89+
path: AmlName,
90+
args: Vec<Arc<Object>>,
91+
) -> Result<Option<Arc<Object>>, AmlError> {
92+
match self.invoke_method(path.clone(), args) {
93+
Ok(result) => Ok(Some(result)),
94+
Err(AmlError::ObjectDoesNotExist(not_present)) => {
95+
if path == not_present {
96+
Ok(None)
97+
} else {
98+
Err(AmlError::ObjectDoesNotExist(not_present))
99+
}
100+
}
101+
Err(other) => Err(other),
102+
}
103+
}
104+
85105
pub fn install_region_handler<RH>(&self, space: RegionSpace, handler: RH)
86106
where
87107
RH: RegionHandler + 'static,
@@ -200,14 +220,13 @@ where
200220
else {
201221
panic!()
202222
};
203-
let region_offset = region_offset.as_integer()?;
204-
let region_length = region_length.as_integer()?;
205-
let region_space = RegionSpace::from(*region_space);
206223

207224
let region = Object::OpRegion(OpRegion {
208-
space: region_space,
209-
base: region_offset,
210-
length: region_length,
225+
space: RegionSpace::from(*region_space),
226+
base: region_offset.as_integer()?,
227+
length: region_length.as_integer()?,
228+
parent_device_path: context.current_scope.clone(),
229+
});
211230
});
212231
self.namespace.lock().insert(name.resolve(&context.current_scope)?, Arc::new(region))?;
213232
}
@@ -1493,7 +1512,45 @@ where
14931512
_ => panic!(),
14941513
}
14951514
}),
1496-
RegionSpace::PciConfig => todo!(),
1515+
RegionSpace::PciConfig => {
1516+
/*
1517+
* TODO: it's not ideal to do these reads for every native access. See if we can
1518+
* cache them somewhere?
1519+
*/
1520+
let seg = match self.invoke_method_if_present(
1521+
AmlName::from_str("_SEG").unwrap().resolve(&region.parent_device_path)?,
1522+
vec![],
1523+
)? {
1524+
Some(value) => value.as_integer()?,
1525+
None => 0,
1526+
};
1527+
let bus = match self.invoke_method_if_present(
1528+
AmlName::from_str("_BBR").unwrap().resolve(&region.parent_device_path)?,
1529+
vec![],
1530+
)? {
1531+
Some(value) => value.as_integer()?,
1532+
None => 0,
1533+
};
1534+
let (device, function) = {
1535+
let adr = self.invoke_method_if_present(
1536+
AmlName::from_str("_ADR").unwrap().resolve(&region.parent_device_path)?,
1537+
vec![],
1538+
)?;
1539+
let adr = match adr {
1540+
Some(adr) => adr.as_integer()?,
1541+
None => 0,
1542+
};
1543+
(adr.get_bits(16..32), adr.get_bits(0..16))
1544+
};
1545+
1546+
let address = PciAddress::new(seg as u16, bus as u8, device as u8, function as u8);
1547+
match length {
1548+
1 => Ok(self.handler.read_pci_u8(address, offset as u16) as u64),
1549+
2 => Ok(self.handler.read_pci_u16(address, offset as u16) as u64),
1550+
4 => Ok(self.handler.read_pci_u32(address, offset as u16) as u64),
1551+
_ => panic!(),
1552+
}
1553+
}
14971554

14981555
RegionSpace::EmbeddedControl
14991556
| RegionSpace::SmBus
@@ -2086,7 +2143,10 @@ pub enum AmlError {
20862143

20872144
/// This trait represents the interface from the `Interpreter` to the hosting kernel, and allows
20882145
/// AML to interact with the underlying hardware.
2089-
// TODO: maybe use `pci_types::PciAddress` to simplify PCI address passing here
2146+
///
2147+
/// ### Implementation notes
2148+
/// Reads and writes to PCI devices must succeed for devices that are not detected during
2149+
/// enumeration of the PCI bus / do not exist.
20902150
pub trait Handler: Send + Sync {
20912151
fn read_u8(&self, address: usize) -> u8;
20922152
fn read_u16(&self, address: usize) -> u16;
@@ -2106,13 +2166,13 @@ pub trait Handler: Send + Sync {
21062166
fn write_io_u16(&self, port: u16, value: u16);
21072167
fn write_io_u32(&self, port: u16, value: u32);
21082168

2109-
fn read_pci_u8(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16) -> u8;
2110-
fn read_pci_u16(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16) -> u16;
2111-
fn read_pci_u32(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16) -> u32;
2169+
fn read_pci_u8(&self, address: PciAddress, offset: u16) -> u8;
2170+
fn read_pci_u16(&self, address: PciAddress, offset: u16) -> u16;
2171+
fn read_pci_u32(&self, address: PciAddress, offset: u16) -> u32;
21122172

2113-
fn write_pci_u8(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16, value: u8);
2114-
fn write_pci_u16(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16, value: u16);
2115-
fn write_pci_u32(&self, segment: u16, bus: u8, device: u8, function: u8, offset: u16, value: u32);
2173+
fn write_pci_u8(&self, address: PciAddress, offset: u16, value: u8);
2174+
fn write_pci_u16(&self, address: PciAddress, offset: u16, value: u16);
2175+
fn write_pci_u32(&self, address: PciAddress, offset: u16, value: u32);
21162176

21172177
/// Returns a monotonically-increasing value of nanoseconds.
21182178
fn nanos_since_boot(&self) -> u64;
@@ -2160,12 +2220,12 @@ mod tests {
21602220
fn write_io_u8(&self, _port: u16, _value: u8) {}
21612221
fn write_io_u16(&self, _port: u16, _value: u16) {}
21622222
fn write_io_u32(&self, _port: u16, _value: u32) {}
2163-
fn read_pci_u8(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16) -> u8 {0}
2164-
fn read_pci_u16(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16) -> u16 {0}
2165-
fn read_pci_u32(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16) -> u32 {0}
2166-
fn write_pci_u8(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16, _value: u8) {}
2167-
fn write_pci_u16(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16, _value: u16) {}
2168-
fn write_pci_u32(&self, _segment: u16, _bus: u8, _device: u8, _function: u8, _offset: u16, _value: u32) {}
2223+
fn read_pci_u8(&self, _address: PciAddress, _offset: u16) -> u8 {0}
2224+
fn read_pci_u16(&self, _address: PciAddress, _offset: u16) -> u16 {0}
2225+
fn read_pci_u32(&self, _address: PciAddress, _offset: u16) -> u32 {0}
2226+
fn write_pci_u8(&self, _address: PciAddress, _offset: u16, _value: u8) {}
2227+
fn write_pci_u16(&self, _address: PciAddress, _offset: u16, _value: u16) {}
2228+
fn write_pci_u32(&self, _address: PciAddress, _offset: u16, _value: u32) {}
21692229
fn nanos_since_boot(&self) -> u64 {0}
21702230
fn stall(&self, _microseconds: u64) {}
21712231
fn sleep(&self, _milliseconds: u64) {}

aml/src/op_region.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use crate::AmlError;
1+
use crate::{AmlError, namespace::AmlName};
22

33
#[derive(Debug)]
44
pub struct OpRegion {
55
pub space: RegionSpace,
66
pub base: u64,
77
pub length: u64,
8-
// parent_device
8+
pub parent_device_path: AmlName,
99
}
1010

1111
pub trait RegionHandler {

tools/aml_tester/src/main.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* - For failing tests, print out a nice summary of the errors for each file
1010
*/
1111

12-
use aml::{namespace::AmlName, AmlError, Interpreter};
12+
use aml::{namespace::AmlName, AmlError, Interpreter, PciAddress};
1313
use clap::{Arg, ArgAction, ArgGroup};
1414
use std::{
1515
collections::HashSet,
@@ -377,27 +377,27 @@ impl aml::Handler for Handler {
377377
println!("write_io_u32 {port:#x}<-{value:#x}");
378378
}
379379

380-
fn read_pci_u8(&self, segment: u16, bus: u8, device: u8, function: u8, _offset: u16) -> u8 {
381-
println!("read_pci_u8 ({segment:#x}, {bus:#x}, {device:#x}, {function:#x})");
380+
fn read_pci_u8(&self, address: PciAddress, _offset: u16) -> u8 {
381+
println!("read_pci_u8 ({address})");
382382
0
383383
}
384-
fn read_pci_u16(&self, segment: u16, bus: u8, device: u8, function: u8, _offset: u16) -> u16 {
385-
println!("read_pci_u16 ({segment:#x}, {bus:#x}, {device:#x}, {function:#x})");
384+
fn read_pci_u16(&self, address: PciAddress, _offset: u16) -> u16 {
385+
println!("read_pci_u16 ({address})");
386386
0
387387
}
388-
fn read_pci_u32(&self, segment: u16, bus: u8, device: u8, function: u8, _offset: u16) -> u32 {
389-
println!("read_pci_32 ({segment:#x}, {bus:#x}, {device:#x}, {function:#x})");
388+
fn read_pci_u32(&self, address: PciAddress, _offset: u16) -> u32 {
389+
println!("read_pci_u32 ({address})");
390390
0
391391
}
392392

393-
fn write_pci_u8(&self, segment: u16, bus: u8, device: u8, function: u8, _offset: u16, value: u8) {
394-
println!("write_pci_u8 ({segment:#x}, {bus:#x}, {device:#x}, {function:#x})<-{value:#x}");
393+
fn write_pci_u8(&self, address: PciAddress, _offset: u16, value: u8) {
394+
println!("write_pci_u8 ({address})<-{value}");
395395
}
396-
fn write_pci_u16(&self, segment: u16, bus: u8, device: u8, function: u8, _offset: u16, value: u16) {
397-
println!("write_pci_u16 ({segment:#x}, {bus:#x}, {device:#x}, {function:#x})<-{value:#x}");
396+
fn write_pci_u16(&self, address: PciAddress, _offset: u16, value: u16) {
397+
println!("write_pci_u16 ({address})<-{value}");
398398
}
399-
fn write_pci_u32(&self, segment: u16, bus: u8, device: u8, function: u8, _offset: u16, value: u32) {
400-
println!("write_pci_u32 ({segment:#x}, {bus:#x}, {device:#x}, {function:#x})<-{value:#x}");
399+
fn write_pci_u32(&self, address: PciAddress, _offset: u16, value: u32) {
400+
println!("write_pci_u32 ({address})<-{value}");
401401
}
402402

403403
fn nanos_since_boot(&self) -> u64 {

0 commit comments

Comments
 (0)