Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion virtualization/arm_vgic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ axdevice_base = { workspace = true }
axvm-types = { workspace = true }
aarch64-cpu = "11.0"
aarch64_sysreg = { workspace = true }
ax-errno = { workspace = true }
bitmaps = {version = "3.2", default-features = false}
log = "0.4"
ax-memory-addr = { workspace = true }
spin = { workspace = true }
tock-registers = "0.10"
thiserror = { workspace = true }
22 changes: 11 additions & 11 deletions virtualization/arm_vgic/src/devops_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use ax_errno::AxResult;
use axdevice_base::{AccessWidth, BaseDeviceOps, DeviceAddrRange, EmuDeviceType};
use axdevice_base::{AccessWidth, BaseDeviceOps, DeviceAddrRange, DeviceResult, EmuDeviceType};
use axvm_types::GuestPhysAddrRange;

use crate::vgic::Vgic;
Expand Down Expand Up @@ -52,32 +51,33 @@ impl BaseDeviceOps<GuestPhysAddrRange> for Vgic {
/// - `width`: The width of the data to be read, determining the size of the read operation.
///
/// Returns:
/// - `AxResult<usize>`: The result of the read operation, including any errors and the size of the data read.
/// - `DeviceResult<usize>`: The result of the read operation, including any errors and the size of the data read.
fn handle_read(
&self,
addr: <GuestPhysAddrRange as DeviceAddrRange>::Addr,
width: AccessWidth,
) -> AxResult<usize> {
) -> DeviceResult<usize> {
// Perform bitwise operation to ensure the address is aligned to byte boundaries
let addr = addr.as_usize() & 0xfff;

// Match different read operations based on the width parameter
match width {
let value = match width {
AccessWidth::Byte => {
// Handle 1-byte read
self.handle_read8(addr)
self.handle_read8(addr)?
}
AccessWidth::Word => {
// Handle 2-byte read
self.handle_read16(addr)
self.handle_read16(addr)?
}
AccessWidth::Dword => {
// Handle 4-byte read
self.handle_read32(addr)
self.handle_read32(addr)?
}
// Return success for unsupported widths without performing any operation
_ => Ok(0),
}
_ => 0,
};
Ok(value)
}
/// Handles write operations of different widths.
///
Expand All @@ -94,7 +94,7 @@ impl BaseDeviceOps<GuestPhysAddrRange> for Vgic {
addr: <GuestPhysAddrRange as DeviceAddrRange>::Addr,
width: AccessWidth,
val: usize,
) -> AxResult {
) -> DeviceResult {
// Convert the physical address to a `usize` and apply a mask to ensure proper alignment
let addr = addr.as_usize() & 0xfff;

Expand Down
66 changes: 66 additions & 0 deletions virtualization/arm_vgic/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//! Typed errors reported by the virtual Generic Interrupt Controller.

use alloc::string::String;

use axdevice_base::{AccessWidth, DeviceError};

/// Result type returned by VGIC operations.
pub type VgicResult<T = ()> = Result<T, VgicError>;

/// Errors reported by the virtual Generic Interrupt Controller.
#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
pub enum VgicError {
/// An IRQ identifier is outside the supported range.
#[error("VGIC IRQ {irq} is outside the supported range 0..{max}")]
InvalidIrq {
/// The rejected IRQ identifier.
irq: usize,
/// The exclusive upper bound for valid IRQ identifiers.
max: usize,
},
/// A register access has an invalid address or width.
#[error("invalid VGIC {operation} at offset {offset:#x} with width {width:?}")]
InvalidAccess {
/// Whether the access is a read or write.
operation: &'static str,
/// Register offset from the controller base.
offset: usize,
/// Width of the register access.
width: AccessWidth,
},
/// A register or controller operation is unsupported.
#[error("unsupported VGIC operation {operation}: {detail}")]
Unsupported {
/// The unsupported operation.
operation: &'static str,
/// Diagnostic detail describing the limitation.
detail: String,
},
/// A host GIC or MMIO backend operation failed.
#[error("VGIC backend operation {operation} failed: {detail}")]
Backend {
/// The backend operation that failed.
operation: &'static str,
/// Diagnostic detail from the backend.
detail: String,
},
}

impl From<VgicError> for DeviceError {
fn from(error: VgicError) -> Self {
match error {
VgicError::InvalidIrq { .. } | VgicError::InvalidAccess { .. } => Self::InvalidInput {
operation: "access ARM VGIC",
detail: alloc::format!("{error}"),
},
VgicError::Unsupported { .. } => Self::Unsupported {
operation: "access ARM VGIC",
detail: alloc::format!("{error}"),
},
VgicError::Backend { .. } => Self::Backend {
operation: "access ARM VGIC",
detail: alloc::format!("{error}"),
},
}
}
}
3 changes: 3 additions & 0 deletions virtualization/arm_vgic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@
extern crate alloc;

mod devops_impl;
mod error;
pub mod host;

pub use error::{VgicError, VgicResult};

/// Virtual GIC implementation module.
pub mod vgic;
pub use vgic::Vgic;
Expand Down
16 changes: 9 additions & 7 deletions virtualization/arm_vgic/src/v3/gits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use core::ptr;

use ax_kspin::SpinNoIrq;
use ax_memory_addr::PhysAddr;
use axdevice_base::{AccessWidth, BaseDeviceOps};
use axdevice_base::{AccessWidth, BaseDeviceOps, DeviceResult};
use axvm_types::{GuestPhysAddr, GuestPhysAddrRange, HostPhysAddr};
use log::{debug, trace, warn};
use spin::Once;
Expand Down Expand Up @@ -122,7 +122,7 @@ impl BaseDeviceOps<GuestPhysAddrRange> for Gits {
&self,
addr: <GuestPhysAddrRange as axdevice_base::DeviceAddrRange>::Addr,
width: AccessWidth,
) -> ax_errno::AxResult<usize> {
) -> DeviceResult<usize> {
let gits_base = self.host_gits_base;
let reg = addr - self.addr;
// let reg = mmio.address;
Expand All @@ -136,7 +136,7 @@ impl BaseDeviceOps<GuestPhysAddrRange> for Gits {
);

// mmio_perform_access(gits_base, mmio);
match reg {
let result = match reg {
GITS_CTRL => perform_mmio_read(gits_base + reg, width),
GITS_CBASER => Ok(self.with_regs(|r| r.cbaser)),
GITS_DT_BASER => {
Expand All @@ -159,15 +159,16 @@ impl BaseDeviceOps<GuestPhysAddrRange> for Gits {
GITS_CREADR => Ok(self.with_regs(|r| r.creadr)),
GITS_TYPER => perform_mmio_read(gits_base + reg, width),
_ => perform_mmio_read(gits_base + reg, width),
}
};
Ok(result?)
}

fn handle_write(
&self,
addr: <GuestPhysAddrRange as axdevice_base::DeviceAddrRange>::Addr,
width: AccessWidth,
val: usize,
) -> ax_errno::AxResult {
) -> DeviceResult {
let gits_base = self.host_gits_base;
let reg = addr - self.addr;
// let reg = mmio.address;
Expand All @@ -182,7 +183,7 @@ impl BaseDeviceOps<GuestPhysAddrRange> for Gits {
);

// mmio_perform_access(gits_base, mmio);
match reg {
let result = match reg {
GITS_CTRL => perform_mmio_write(gits_base + reg, width, val),
GITS_CBASER => {
if self.is_root_vm {
Expand Down Expand Up @@ -233,7 +234,8 @@ impl BaseDeviceOps<GuestPhysAddrRange> for Gits {
}
GITS_TYPER => perform_mmio_write(gits_base + reg, width, val),
_ => perform_mmio_write(gits_base + reg, width, val),
}
};
Ok(result?)
}
}

Expand Down
7 changes: 3 additions & 4 deletions virtualization/arm_vgic/src/v3/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use ax_errno::AxResult;
use axdevice_base::AccessWidth;
use axvm_types::HostPhysAddr;

use crate::host;
use crate::{VgicResult, host};

pub(crate) fn perform_mmio_read(addr: HostPhysAddr, width: AccessWidth) -> AxResult<usize> {
pub(crate) fn perform_mmio_read(addr: HostPhysAddr, width: AccessWidth) -> VgicResult<usize> {
let addr = host::phys_to_virt(addr).as_ptr();

match width {
Expand All @@ -33,7 +32,7 @@ pub(crate) fn perform_mmio_write(
addr: HostPhysAddr,
width: AccessWidth,
val: usize,
) -> AxResult<()> {
) -> VgicResult<()> {
let addr = host::phys_to_virt(addr).as_mut_ptr();

match width {
Expand Down
Loading
Loading