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)