BaseDeviceOps Trait
Relevant source files
This document covers the BaseDeviceOps
trait, which defines the core interface that all emulated devices must implement in the ArceOS hypervisor device emulation system. The trait provides a uniform contract for device identification, address mapping, and memory access handling across different types of virtualized hardware.
For information about specific device types that implement this trait, see Device Type System. For details about address space management and memory mapping, see Address Space Management.
Trait Overview
The BaseDeviceOps
trait serves as the fundamental abstraction layer for device emulation in the ArceOS hypervisor. It defines four essential operations that enable the hypervisor to uniformly interact with different types of emulated devices, from simple console devices to complex interrupt controllers.
flowchart TD subgraph Parameters["Parameters"] GPA["GuestPhysAddr"] WIDTH["usize (width)"] VAL["usize (val)"] end subgraph subGraph1["Return Types"] EDT["EmuDeviceType"] AR["AddrRange"] AXR["AxResult"] UNIT["()"] end subgraph subGraph0["BaseDeviceOps Contract"] BDO["BaseDeviceOps trait"] EMU["emu_type()"] ADDR["address_range()"] READ["handle_read()"] WRITE["handle_write()"] end ADDR --> AR BDO --> ADDR BDO --> EMU BDO --> READ BDO --> WRITE EMU --> EDT READ --> AXR READ --> GPA READ --> WIDTH WRITE --> GPA WRITE --> UNIT WRITE --> VAL WRITE --> WIDTH
The trait is designed for no_std
environments and integrates with the ArceOS ecosystem through typed address spaces and standardized error handling.
Sources: axdevice_base/src/lib.rs(L20 - L30)
Method Specifications
Device Type Identification
flowchart TD subgraph subGraph0["Device Categories"] CONSOLE["EmuDeviceTConsole"] VIRTIO["EmuDeviceTVirtioBlk"] GIC["EmuDeviceTGicdV2"] OTHER["Unsupported markdown: list"] end DEV["Device Implementation"] EMU_TYPE["emu_type()"] EDT["EmuDeviceType"] DEV --> EMU_TYPE EDT --> CONSOLE EDT --> GIC EDT --> OTHER EDT --> VIRTIO EMU_TYPE --> EDT
The emu_type()
method returns an EmuDeviceType
enum value that identifies the specific type of device being emulated. This enables the hypervisor to apply device-specific logic and optimizations.
Method | Signature | Purpose |
---|---|---|
emu_type | fn emu_type(&self) -> EmuDeviceType | Device type identification for hypervisor routing |
Sources: axdevice_base/src/lib.rs(L22 - L23)
Address Range Management
flowchart TD subgraph subGraph1["Hypervisor Usage"] LOOKUP["Address lookup"] ROUTING["Device routing"] VALIDATION["Access validation"] end subgraph subGraph0["Address Space Components"] GPA_START["start: GuestPhysAddr"] GPA_END["end: GuestPhysAddr"] SIZE["size calculation"] end ADDR_RANGE["address_range()"] AR["AddrRange"] ADDR_RANGE --> AR AR --> GPA_END AR --> GPA_START AR --> LOOKUP AR --> ROUTING AR --> SIZE AR --> VALIDATION
The address_range()
method defines the guest physical address space region that the device occupies. The hypervisor uses this information to route memory accesses to the appropriate device implementation.
Method | Signature | Purpose |
---|---|---|
address_range | fn address_range(&self) -> AddrRange | Memory-mapped I/O address space definition |
Sources: axdevice_base/src/lib.rs(L24 - L25)
Memory Access Handlers
flowchart TD subgraph subGraph2["Parameters and Results"] GPA_PARAM["GuestPhysAddr addr"] WIDTH_PARAM["usize width"] VAL_PARAM["usize val"] RESULT["AxResult"] VOID_RESULT["()"] end subgraph subGraph1["BaseDeviceOps Methods"] HANDLE_READ["handle_read(addr, width)"] HANDLE_WRITE["handle_write(addr, width, val)"] end subgraph subGraph0["Memory Access Flow"] GUEST["Guest VM Memory Access"] HV_DECODE["Hypervisor Address Decode"] DEVICE_CHECK["Device Range Check"] end DEVICE_CHECK --> HANDLE_READ DEVICE_CHECK --> HANDLE_WRITE GUEST --> HV_DECODE HANDLE_READ --> GPA_PARAM HANDLE_READ --> RESULT HANDLE_READ --> WIDTH_PARAM HANDLE_WRITE --> GPA_PARAM HANDLE_WRITE --> VAL_PARAM HANDLE_WRITE --> VOID_RESULT HANDLE_WRITE --> WIDTH_PARAM HV_DECODE --> DEVICE_CHECK
The memory access handlers implement the core device emulation logic. The handle_read()
method processes guest read operations and returns emulated device state, while handle_write()
processes guest write operations that may modify device behavior.
Method | Signature | Return | Purpose |
---|---|---|---|
handle_read | fn handle_read(&self, addr: GuestPhysAddr, width: usize) -> AxResult | AxResult | Process guest memory read operations |
handle_write | fn handle_write(&self, addr: GuestPhysAddr, width: usize, val: usize) | () | Process guest memory write operations |
Sources: axdevice_base/src/lib.rs(L26 - L29)
Implementation Requirements
Error Handling
Read operations return AxResult<usize>
to handle potential emulation errors such as invalid register addresses or unsupported access widths. Write operations use a void return type, with error conditions typically handled through device-specific state changes or logging.
Access Width Support
The width
parameter specifies the memory access size in bytes (typically 1, 2, 4, or 8). Device implementations must handle the access widths supported by their emulated hardware, potentially returning errors for unsupported widths.
Address Validation
Device implementations should validate that the provided addr
parameter falls within their declared address range and corresponds to a valid device register or memory location.
Integration Patterns
flowchart TD subgraph subGraph2["External Dependencies"] AXADDRSPACE["axaddrspace::GuestPhysAddr"] AXERRNO["axerrno::AxResult"] MEMORY_ADDR["memory_addr::AddrRange"] end subgraph subGraph1["Device Implementation"] DEVICE["Device Struct"] BDO_IMPL["BaseDeviceOps impl"] DEV_STATE["Device State"] end subgraph subGraph0["ArceOS Hypervisor"] HV_CORE["Hypervisor Core"] ADDR_MGR["Address Space Manager"] VM_EXIT["VM Exit Handler"] end ADDR_MGR --> BDO_IMPL BDO_IMPL --> AXADDRSPACE BDO_IMPL --> AXERRNO BDO_IMPL --> DEVICE BDO_IMPL --> MEMORY_ADDR DEVICE --> DEV_STATE HV_CORE --> ADDR_MGR VM_EXIT --> HV_CORE
The trait integrates with the ArceOS hypervisor through standardized address space management and error handling. Device implementations typically maintain internal state and use the trait methods as the primary interface for hypervisor interaction.
Sources: axdevice_base/src/lib.rs(L11 - L18)