Skip to content

Commit b8e382d

Browse files
committed
aml: initial implementation of mutexes, DefAcquire, DefRelease
1 parent bb3107a commit b8e382d

File tree

4 files changed

+79
-19
lines changed

4 files changed

+79
-19
lines changed

aml/src/lib.rs

Lines changed: 63 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@ use alloc::{
2020
vec::Vec,
2121
};
2222
use bit_field::BitField;
23-
use core::mem;
24-
use log::{info, trace};
23+
use core::{
24+
mem,
25+
str::FromStr,
26+
};
27+
use log::{info, trace, warn};
2528
use namespace::{AmlName, Namespace, NamespaceLevelKind};
2629
use object::{FieldFlags, FieldUnit, FieldUnitKind, MethodFlags, Object, ObjectType, ReferenceKind};
2730
use op_region::{OpRegion, RegionHandler, RegionSpace};
@@ -397,6 +400,24 @@ where
397400
let [Argument::Object(usec)] = &op.arguments[..] else { panic!() };
398401
self.handler.stall(usec.as_integer()?);
399402
}
403+
Opcode::Acquire => {
404+
let [Argument::Object(mutex)] = &op.arguments[..] else { panic!() };
405+
let Object::Mutex { mutex, sync_level } = **mutex else {
406+
Err(AmlError::InvalidOperationOnObject { op: Operation::Acquire, typ: mutex.typ() })?
407+
};
408+
let timeout = context.next_u16()?;
409+
410+
// TODO: should we do something with the sync level??
411+
self.handler.acquire(mutex, timeout)?;
412+
}
413+
Opcode::Release => {
414+
let [Argument::Object(mutex)] = &op.arguments[..] else { panic!() };
415+
let Object::Mutex { mutex, sync_level } = **mutex else {
416+
Err(AmlError::InvalidOperationOnObject { op: Operation::Release, typ: mutex.typ() })?
417+
};
418+
// TODO: should we do something with the sync level??
419+
self.handler.release(mutex);
420+
}
400421
Opcode::InternalMethodCall => {
401422
let [Argument::Object(method), Argument::Namestring(method_scope)] = &op.arguments[0..2]
402423
else {
@@ -711,7 +732,8 @@ where
711732
let sync_level = context.next()?;
712733

713734
let name = name.resolve(&context.current_scope)?;
714-
self.namespace.lock().insert(name, Arc::new(Object::Mutex { sync_level }))?;
735+
let mutex = self.handler.create_mutex();
736+
self.namespace.lock().insert(name, Arc::new(Object::Mutex { mutex, sync_level }))?;
715737
}
716738
Opcode::Event => {
717739
let name = context.namestring()?;
@@ -723,11 +745,11 @@ where
723745
Opcode::Load => todo!(),
724746
Opcode::Stall => context.start_in_flight_op(OpInFlight::new(Opcode::Stall, 1)),
725747
Opcode::Sleep => context.start_in_flight_op(OpInFlight::new(Opcode::Sleep, 1)),
726-
Opcode::Acquire => todo!(),
748+
Opcode::Acquire => context.start_in_flight_op(OpInFlight::new(opcode, 1)),
749+
Opcode::Release => context.start_in_flight_op(OpInFlight::new(opcode, 1)),
727750
Opcode::Signal => todo!(),
728751
Opcode::Wait => todo!(),
729752
Opcode::Reset => todo!(),
730-
Opcode::Release => todo!(),
731753
Opcode::FromBCD | Opcode::ToBCD => context.start_in_flight_op(OpInFlight::new(opcode, 2)),
732754
Opcode::Revision => {
733755
context.contribute_arg(Argument::Object(Arc::new(Object::Integer(INTERPRETER_REVISION))));
@@ -2219,13 +2241,25 @@ pub enum AmlError {
22192241
InvalidResourceDescriptor,
22202242
UnexpectedResourceType,
22212243

2244+
MutexAquireTimeout,
2245+
22222246
PrtInvalidAddress,
22232247
PrtInvalidPin,
22242248
PrtInvalidGsi,
22252249
PrtInvalidSource,
22262250
PrtNoEntry,
22272251
}
22282252

2253+
/// A `Handle` is an opaque reference to an object that is managed by the user of this library.
2254+
/// They should be returned by the `create_*` methods on `Handler`, and are then used by methods to
2255+
/// refer to a specific object.
2256+
///
2257+
/// The library will treat the value of a handle as entirely opaque. You may manage handles
2258+
/// however you wish, and the same value can be used to refer to objects of different types, if
2259+
/// desired.
2260+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
2261+
pub struct Handle(pub u32);
2262+
22292263
/// This trait represents the interface from the `Interpreter` to the hosting kernel, and allows
22302264
/// AML to interact with the underlying hardware.
22312265
///
@@ -2238,10 +2272,10 @@ pub trait Handler: Send + Sync {
22382272
fn read_u32(&self, address: usize) -> u32;
22392273
fn read_u64(&self, address: usize) -> u64;
22402274

2241-
fn write_u8(&mut self, address: usize, value: u8);
2242-
fn write_u16(&mut self, address: usize, value: u16);
2243-
fn write_u32(&mut self, address: usize, value: u32);
2244-
fn write_u64(&mut self, address: usize, value: u64);
2275+
fn write_u8(&self, address: usize, value: u8);
2276+
fn write_u16(&self, address: usize, value: u16);
2277+
fn write_u32(&self, address: usize, value: u32);
2278+
fn write_u64(&self, address: usize, value: u64);
22452279

22462280
fn read_io_u8(&self, port: u16) -> u8;
22472281
fn read_io_u16(&self, port: u16) -> u16;
@@ -2271,6 +2305,19 @@ pub trait Handler: Send + Sync {
22712305
/// time supported, and should relinquish the processor.
22722306
fn sleep(&self, milliseconds: u64);
22732307

2308+
fn create_mutex(&self) -> Handle;
2309+
2310+
/// Acquire the mutex referred to by the given handle. `timeout` is a millisecond timeout value
2311+
/// with the following meaning:
2312+
/// - `0` - try to acquire the mutex once, in a non-blocking manner. If the mutex cannot be
2313+
/// acquired immediately, return `Err(AmlError::MutexAquireTimeout)`
2314+
/// - `1-0xfffe` - try to acquire the mutex for at least `timeout` milliseconds.
2315+
/// - `0xffff` - try to acquire the mutex indefinitely. Should not return `MutexAquireTimeout`.
2316+
///
2317+
/// AML mutexes are **reentrant** - that is, a thread may acquire the same mutex more than once
2318+
/// without causing a deadlock.
2319+
fn acquire(&self, mutex: Handle, timeout: u16) -> Result<(), AmlError>;
2320+
fn release(&self, mutex: Handle);
22742321
fn breakpoint(&self) {}
22752322

22762323
fn handle_debug(&self, _object: &Object) {}
@@ -2295,10 +2342,10 @@ mod tests {
22952342
fn read_u16(&self, _address: usize) -> u16 {0}
22962343
fn read_u32(&self, _address: usize) -> u32 {0}
22972344
fn read_u64(&self, _address: usize) -> u64 {0}
2298-
fn write_u8(&mut self, _address: usize, _value: u8) {}
2299-
fn write_u16(&mut self, _address: usize, _value: u16) {}
2300-
fn write_u32(&mut self, _address: usize, _value: u32) {}
2301-
fn write_u64(&mut self, _address: usize, _value: u64) {}
2345+
fn write_u8(&self, _address: usize, _value: u8) {}
2346+
fn write_u16(&self, _address: usize, _value: u16) {}
2347+
fn write_u32(&self, _address: usize, _value: u32) {}
2348+
fn write_u64(&self, _address: usize, _value: u64) {}
23022349
fn read_io_u8(&self, _port: u16) -> u8 {0}
23032350
fn read_io_u16(&self, _port: u16) -> u16 {0}
23042351
fn read_io_u32(&self, _port: u16) -> u32 {0}
@@ -2314,6 +2361,9 @@ mod tests {
23142361
fn nanos_since_boot(&self) -> u64 {0}
23152362
fn stall(&self, _microseconds: u64) {}
23162363
fn sleep(&self, _milliseconds: u64) {}
2364+
fn create_mutex(&self) -> Handle { Handle(0) }
2365+
fn acquire(&self, _mutex: Handle, _timeout: u16) -> Result<(), AmlError> { Ok(()) }
2366+
fn release(&self, _mutex: Handle) {}
23172367
}
23182368

23192369
#[test]

aml/src/object.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub enum Object {
1212
FieldUnit(FieldUnit),
1313
Integer(u64),
1414
Method { code: Vec<u8>, flags: MethodFlags },
15-
Mutex { sync_level: u8 },
15+
Mutex { mutex: Handle, sync_level: u8 },
1616
Reference { kind: ReferenceKind, inner: Arc<Object> },
1717
OpRegion(OpRegion),
1818
Package(Vec<Arc<Object>>),

tools/aml_tester/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ aml = { path = "../../aml" }
99
clap = "4"
1010
termion = "1"
1111
log = "0.4"
12+
pci_types = "0.10"

tools/aml_tester/src/main.rs

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

12-
use aml::{namespace::AmlName, AmlError, Interpreter, PciAddress};
12+
use aml::{namespace::AmlName, AmlError, Handle, Interpreter};
1313
use clap::{Arg, ArgAction, ArgGroup};
14+
use pci_types::PciAddress;
1415
use std::{
1516
collections::HashSet,
1617
ffi::OsStr,
@@ -341,16 +342,16 @@ impl aml::Handler for Handler {
341342
0
342343
}
343344

344-
fn write_u8(&mut self, address: usize, value: u8) {
345+
fn write_u8(&self, address: usize, value: u8) {
345346
println!("write_u8 {address:#x}<-{value:#x}");
346347
}
347-
fn write_u16(&mut self, address: usize, value: u16) {
348+
fn write_u16(&self, address: usize, value: u16) {
348349
println!("write_u16 {address:#x}<-{value:#x}");
349350
}
350-
fn write_u32(&mut self, address: usize, value: u32) {
351+
fn write_u32(&self, address: usize, value: u32) {
351352
println!("write_u32 {address:#x}<-{value:#x}");
352353
}
353-
fn write_u64(&mut self, address: usize, value: u64) {
354+
fn write_u64(&self, address: usize, value: u64) {
354355
println!("write_u64 {address:#x}<-{value:#x}");
355356
}
356357

@@ -410,4 +411,12 @@ impl aml::Handler for Handler {
410411
fn sleep(&self, milliseconds: u64) {
411412
println!("Sleeping for {}ms", milliseconds);
412413
}
414+
415+
fn create_mutex(&self) -> Handle {
416+
Handle(0)
417+
}
418+
fn acquire(&self, _mutex: Handle, _timeout: u16) -> Result<(), AmlError> {
419+
Ok(())
420+
}
421+
fn release(&self, _mutex: Handle) {}
413422
}

0 commit comments

Comments
 (0)