Device Support
Relevant source files
Purpose and Scope
The device support module provides abstractions for hardware device interaction within the axaddrspace crate. This system defines standardized address types and access patterns for different classes of devices, including memory-mapped devices, I/O ports, and system registers. The module establishes a trait-based architecture that allows uniform handling of diverse device addressing schemes while maintaining type safety.
For information about memory mapping strategies used with devices, see Memory Mapping Backends. For details about the underlying address space management, see Address Space Management.
Device Address Architecture
The device support system is built around two core traits that provide a foundation for device addressing abstractions.
Device Address Trait Hierarchy
flowchart TD DeviceAddr["DeviceAddr traitCopy + Eq + Ord + Debug"] DeviceAddrRange["DeviceAddrRange traitcontains() method"] GuestPhysAddr["GuestPhysAddrPhysical memory addresses"] Port["PortI/O port numbers (u16)"] SysRegAddr["SysRegAddrSystem register addresses (usize)"] AddrRange["AddrRange<GuestPhysAddr>Standard address range"] SysRegAddrRange["SysRegAddrRangeInclusive register range"] PortRange["PortRangeInclusive port range"] DeviceAddr --> GuestPhysAddr DeviceAddr --> Port DeviceAddr --> SysRegAddr DeviceAddrRange --> AddrRange DeviceAddrRange --> PortRange DeviceAddrRange --> SysRegAddrRange GuestPhysAddr --> AddrRange Port --> PortRange SysRegAddr --> SysRegAddrRange
Sources: src/device/device_addr.rs(L9 - L10) src/device/device_addr.rs(L12 - L19) src/device/mod.rs(L66 - L132)
The DeviceAddr trait defines the minimal requirements for types that can represent device addresses. All implementing types must be copyable, comparable, orderable, and debuggable. The DeviceAddrRange trait provides address containment checking for ranges of device addresses.
Device Address Implementations
| Address Type | Underlying Type | Purpose | Range Support |
|---|---|---|---|
| GuestPhysAddr | Guest physical address | Memory-mapped devices | AddrRange |
| Port | u16 | I/O port operations | PortRange |
| SysRegAddr | usize | System register access | SysRegAddrRange |
Sources: src/device/device_addr.rs(L21) src/device/device_addr.rs(L31) src/device/device_addr.rs(L65)
Access Width Specifications
The system defines standardized access widths that correspond to different data transfer sizes during device operations.
AccessWidth Enumeration
flowchart TD
subgraph subGraph0["Conversion Methods"]
TryFromUsize["try_from(usize)"]
IntoUsize["into usize"]
Size["size() -> usize"]
BitsRange["bits_range() -> Range<usize>"]
end
AccessWidth["AccessWidth enum"]
Byte["Byte8-bit (1 byte)"]
Word["Word16-bit (2 bytes)"]
Dword["Dword32-bit (4 bytes)"]
Qword["Qword64-bit (8 bytes)"]
AccessWidth --> BitsRange
AccessWidth --> Byte
AccessWidth --> Dword
AccessWidth --> IntoUsize
AccessWidth --> Qword
AccessWidth --> Size
AccessWidth --> TryFromUsize
AccessWidth --> Word
Sources: src/device/mod.rs(L9 - L64)
The AccessWidth enum provides bidirectional conversion between access sizes and byte counts, along with utility methods for determining bit ranges covered by each access type.
I/O Port Addressing
The Port type encapsulates 16-bit I/O port numbers used in x86-style port-mapped I/O operations.
Port Type Structure
The Port struct wraps a u16 value and provides formatting implementations for debugging and display purposes. Port numbers are used to identify specific I/O devices in architectures that support port-mapped I/O.
flowchart TD
subgraph subGraph2["Range Support"]
PortRange["PortRangestart: Port, end: Port"]
PortRangeNew["new(start: Port, end: Port)"]
PortRangeContains["contains(addr: Port) -> bool"]
end
subgraph Formatting["Formatting"]
LowerHex["LowerHexPort(#x)"]
UpperHex["UpperHexPort(#X)"]
Debug["DebugPort(decimal)"]
end
subgraph Creation["Creation"]
NewMethod["new(port: u16) -> Port"]
NumberMethod["number() -> u16"]
end
Port["Port(u16)"]
Port --> Debug
Port --> LowerHex
Port --> NewMethod
Port --> NumberMethod
Port --> PortRange
Port --> UpperHex
PortRange --> PortRangeContains
PortRange --> PortRangeNew
Sources: src/device/mod.rs(L66 - L98) src/device/device_addr.rs(L67 - L97)
The PortRange struct provides inclusive range checking for port numbers, supporting both formatted output and containment testing.
System Register Addressing
The SysRegAddr type represents addresses used to access architecture-specific system registers.
System Register Type Structure
System register addresses use usize to accommodate different architecture requirements while maintaining generality across platforms. The inclusive range type supports efficient range checking for register banks.
flowchart TD
subgraph subGraph2["Range Support"]
SysRegAddrRange["SysRegAddrRangestart: SysRegAddr, end: SysRegAddr"]
SysRangeNew["new(start: SysRegAddr, end: SysRegAddr)"]
SysRangeContains["contains(addr: SysRegAddr) -> bool"]
SysRangeFormat["LowerHex formatting#x..=#x"]
end
subgraph Formatting["Formatting"]
SysLowerHex["LowerHexSysRegAddr(#x)"]
SysUpperHex["UpperHexSysRegAddr(#X)"]
SysDebug["DebugSysRegAddr(decimal)"]
end
subgraph Creation["Creation"]
NewConst["const new(addr: usize) -> SysRegAddr"]
AddrConst["const addr() -> usize"]
end
SysRegAddr["SysRegAddr(usize)"]
SysRegAddr --> AddrConst
SysRegAddr --> NewConst
SysRegAddr --> SysDebug
SysRegAddr --> SysLowerHex
SysRegAddr --> SysRegAddrRange
SysRegAddr --> SysUpperHex
SysRegAddrRange --> SysRangeContains
SysRegAddrRange --> SysRangeFormat
SysRegAddrRange --> SysRangeNew
Sources: src/device/mod.rs(L100 - L132) src/device/device_addr.rs(L31 - L63)
The SysRegAddrRange struct uses inclusive bounds on both ends, unlike standard Rust ranges, and provides specialized formatting for register address ranges.
Guest Physical Address Device Support
Guest physical addresses serve as device addresses for memory-mapped I/O operations within the guest address space.
GuestPhysAddr Integration
The integration leverages the existing memory_addr::AddrRange type to provide standard range operations while maintaining compatibility with the device address abstraction framework.
Sources: src/device/device_addr.rs(L21 - L29)
The GuestPhysAddr implementation uses the standard AddrRange<GuestPhysAddr> for range operations, providing consistency with other address management components in the system.