hypervisor: aarch64: use KVM DeviceFd in GIC code

The code is obviously KVM only. We don't need to use dyn Device there.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
This commit is contained in:
Wei Liu 2022-07-20 16:25:04 +00:00 committed by Liu Wei
parent 0856ebbd42
commit c5e966c972
5 changed files with 104 additions and 112 deletions

View File

@ -2,11 +2,11 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::arch::aarch64::gic::{Error, Result}; use crate::arch::aarch64::gic::{Error, Result};
use crate::device::HypervisorDeviceError;
use crate::kvm::kvm_bindings::{ use crate::kvm::kvm_bindings::{
kvm_device_attr, KVM_DEV_ARM_VGIC_GRP_DIST_REGS, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, kvm_device_attr, KVM_DEV_ARM_VGIC_GRP_DIST_REGS, KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
}; };
use crate::Device; use kvm_ioctls::DeviceFd;
use std::sync::Arc;
/* /*
Distributor registers as detailed at page 456 from Distributor registers as detailed at page 456 from
@ -77,7 +77,7 @@ static VGIC_DIST_REGS: &[DistReg] = &[
VGIC_DIST_REG!(GICD_IPRIORITYR, 8, 0), VGIC_DIST_REG!(GICD_IPRIORITYR, 8, 0),
]; ];
fn dist_attr_access(gic: &Arc<dyn Device>, offset: u32, val: &u32, set: bool) -> Result<()> { fn dist_attr_access(gic: &DeviceFd, offset: u32, val: &u32, set: bool) -> Result<()> {
let mut gic_dist_attr = kvm_device_attr { let mut gic_dist_attr = kvm_device_attr {
group: KVM_DEV_ARM_VGIC_GRP_DIST_REGS, group: KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
attr: offset as u64, attr: offset as u64,
@ -85,28 +85,30 @@ fn dist_attr_access(gic: &Arc<dyn Device>, offset: u32, val: &u32, set: bool) ->
flags: 0, flags: 0,
}; };
if set { if set {
gic.set_device_attr(&gic_dist_attr) gic.set_device_attr(&gic_dist_attr).map_err(|e| {
.map_err(Error::SetDeviceAttribute)?; Error::SetDeviceAttribute(HypervisorDeviceError::SetDeviceAttribute(e.into()))
})?;
} else { } else {
gic.get_device_attr(&mut gic_dist_attr) gic.get_device_attr(&mut gic_dist_attr).map_err(|e| {
.map_err(Error::GetDeviceAttribute)?; Error::GetDeviceAttribute(HypervisorDeviceError::GetDeviceAttribute(e.into()))
})?;
} }
Ok(()) Ok(())
} }
/// Get the distributor control register. /// Get the distributor control register.
pub fn read_ctlr(gic: &Arc<dyn Device>) -> Result<u32> { pub fn read_ctlr(gic: &DeviceFd) -> Result<u32> {
let val: u32 = 0; let val: u32 = 0;
dist_attr_access(gic, GICD_CTLR, &val, false)?; dist_attr_access(gic, GICD_CTLR, &val, false)?;
Ok(val) Ok(val)
} }
/// Set the distributor control register. /// Set the distributor control register.
pub fn write_ctlr(gic: &Arc<dyn Device>, val: u32) -> Result<()> { pub fn write_ctlr(gic: &DeviceFd, val: u32) -> Result<()> {
dist_attr_access(gic, GICD_CTLR, &val, true) dist_attr_access(gic, GICD_CTLR, &val, true)
} }
fn get_interrupts_num(gic: &Arc<dyn Device>) -> Result<u32> { fn get_interrupts_num(gic: &DeviceFd) -> Result<u32> {
let num_irq = 0; let num_irq = 0;
let mut nr_irqs_attr = kvm_device_attr { let mut nr_irqs_attr = kvm_device_attr {
@ -115,12 +117,13 @@ fn get_interrupts_num(gic: &Arc<dyn Device>) -> Result<u32> {
addr: &num_irq as *const u32 as u64, addr: &num_irq as *const u32 as u64,
flags: 0, flags: 0,
}; };
gic.get_device_attr(&mut nr_irqs_attr) gic.get_device_attr(&mut nr_irqs_attr).map_err(|e| {
.map_err(Error::GetDeviceAttribute)?; Error::GetDeviceAttribute(HypervisorDeviceError::GetDeviceAttribute(e.into()))
})?;
Ok(num_irq) Ok(num_irq)
} }
fn compute_reg_len(gic: &Arc<dyn Device>, reg: &DistReg, base: u32) -> Result<u32> { fn compute_reg_len(gic: &DeviceFd, reg: &DistReg, base: u32) -> Result<u32> {
// FIXME: // FIXME:
// Redefine some GIC constants to avoid the dependency on `layout` crate. // Redefine some GIC constants to avoid the dependency on `layout` crate.
// This is temporary solution, will be fixed in future refactoring. // This is temporary solution, will be fixed in future refactoring.
@ -147,7 +150,7 @@ fn compute_reg_len(gic: &Arc<dyn Device>, reg: &DistReg, base: u32) -> Result<u3
} }
/// Set distributor registers of the GIC. /// Set distributor registers of the GIC.
pub fn set_dist_regs(gic: &Arc<dyn Device>, state: &[u32]) -> Result<()> { pub fn set_dist_regs(gic: &DeviceFd, state: &[u32]) -> Result<()> {
let mut idx = 0; let mut idx = 0;
for dreg in VGIC_DIST_REGS { for dreg in VGIC_DIST_REGS {
@ -164,7 +167,7 @@ pub fn set_dist_regs(gic: &Arc<dyn Device>, state: &[u32]) -> Result<()> {
Ok(()) Ok(())
} }
/// Get distributor registers of the GIC. /// Get distributor registers of the GIC.
pub fn get_dist_regs(gic: &Arc<dyn Device>) -> Result<Vec<u32>> { pub fn get_dist_regs(gic: &DeviceFd) -> Result<Vec<u32>> {
let mut state = Vec::new(); let mut state = Vec::new();
for dreg in VGIC_DIST_REGS { for dreg in VGIC_DIST_REGS {

View File

@ -3,14 +3,14 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::arch::aarch64::gic::{Error, Result}; use crate::arch::aarch64::gic::{Error, Result};
use crate::device::HypervisorDeviceError;
use crate::kvm::kvm_bindings::{ use crate::kvm::kvm_bindings::{
kvm_device_attr, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, KVM_REG_ARM64_SYSREG_CRM_MASK, kvm_device_attr, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, KVM_REG_ARM64_SYSREG_CRM_MASK,
KVM_REG_ARM64_SYSREG_CRM_SHIFT, KVM_REG_ARM64_SYSREG_CRN_MASK, KVM_REG_ARM64_SYSREG_CRN_SHIFT, KVM_REG_ARM64_SYSREG_CRM_SHIFT, KVM_REG_ARM64_SYSREG_CRN_MASK, KVM_REG_ARM64_SYSREG_CRN_SHIFT,
KVM_REG_ARM64_SYSREG_OP0_MASK, KVM_REG_ARM64_SYSREG_OP0_SHIFT, KVM_REG_ARM64_SYSREG_OP1_MASK, KVM_REG_ARM64_SYSREG_OP0_MASK, KVM_REG_ARM64_SYSREG_OP0_SHIFT, KVM_REG_ARM64_SYSREG_OP1_MASK,
KVM_REG_ARM64_SYSREG_OP1_SHIFT, KVM_REG_ARM64_SYSREG_OP2_MASK, KVM_REG_ARM64_SYSREG_OP2_SHIFT, KVM_REG_ARM64_SYSREG_OP1_SHIFT, KVM_REG_ARM64_SYSREG_OP2_MASK, KVM_REG_ARM64_SYSREG_OP2_SHIFT,
}; };
use crate::Device; use kvm_ioctls::DeviceFd;
use std::sync::Arc;
const KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT: u32 = 32; const KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT: u32 = 32;
const KVM_DEV_ARM_VGIC_V3_MPIDR_MASK: u64 = 0xffffffff << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT as u64; const KVM_DEV_ARM_VGIC_V3_MPIDR_MASK: u64 = 0xffffffff << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT as u64;
@ -79,13 +79,7 @@ static VGIC_ICC_REGS: &[u64] = &[
SYS_ICC_AP1R3_EL1, SYS_ICC_AP1R3_EL1,
]; ];
fn icc_attr_access( fn icc_attr_access(gic: &DeviceFd, offset: u64, typer: u64, val: &u32, set: bool) -> Result<()> {
gic: &Arc<dyn Device>,
offset: u64,
typer: u64,
val: &u32,
set: bool,
) -> Result<()> {
let mut gic_icc_attr = kvm_device_attr { let mut gic_icc_attr = kvm_device_attr {
group: KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, group: KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
attr: ((typer & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) | offset), // this needs the mpidr attr: ((typer & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) | offset), // this needs the mpidr
@ -93,17 +87,19 @@ fn icc_attr_access(
flags: 0, flags: 0,
}; };
if set { if set {
gic.set_device_attr(&gic_icc_attr) gic.set_device_attr(&gic_icc_attr).map_err(|e| {
.map_err(Error::SetDeviceAttribute)?; Error::SetDeviceAttribute(HypervisorDeviceError::SetDeviceAttribute(e.into()))
})?;
} else { } else {
gic.get_device_attr(&mut gic_icc_attr) gic.get_device_attr(&mut gic_icc_attr).map_err(|e| {
.map_err(Error::GetDeviceAttribute)?; Error::GetDeviceAttribute(HypervisorDeviceError::GetDeviceAttribute(e.into()))
})?;
} }
Ok(()) Ok(())
} }
/// Get ICC registers. /// Get ICC registers.
pub fn get_icc_regs(gic: &Arc<dyn Device>, gicr_typer: &[u64]) -> Result<Vec<u32>> { pub fn get_icc_regs(gic: &DeviceFd, gicr_typer: &[u64]) -> Result<Vec<u32>> {
let mut state: Vec<u32> = Vec::new(); let mut state: Vec<u32> = Vec::new();
// We need this for the ICC_AP<m>R<n>_EL1 registers. // We need this for the ICC_AP<m>R<n>_EL1 registers.
let mut num_priority_bits = 0; let mut num_priority_bits = 0;
@ -156,7 +152,7 @@ pub fn get_icc_regs(gic: &Arc<dyn Device>, gicr_typer: &[u64]) -> Result<Vec<u32
} }
/// Set ICC registers. /// Set ICC registers.
pub fn set_icc_regs(gic: &Arc<dyn Device>, gicr_typer: &[u64], state: &[u32]) -> Result<()> { pub fn set_icc_regs(gic: &DeviceFd, gicr_typer: &[u64], state: &[u32]) -> Result<()> {
let mut num_priority_bits = 0; let mut num_priority_bits = 0;
let mut idx = 0; let mut idx = 0;
for ix in gicr_typer { for ix in gicr_typer {

View File

@ -5,15 +5,16 @@ mod icc_regs;
mod redist_regs; mod redist_regs;
use crate::arch::aarch64::gic::{Error, Result, Vgic}; use crate::arch::aarch64::gic::{Error, Result, Vgic};
use crate::device::HypervisorDeviceError;
use crate::kvm::{kvm_bindings, KvmVm}; use crate::kvm::{kvm_bindings, KvmVm};
use crate::{CpuState, Device, Vm}; use crate::{CpuState, Vm};
use dist_regs::{get_dist_regs, read_ctlr, set_dist_regs, write_ctlr}; use dist_regs::{get_dist_regs, read_ctlr, set_dist_regs, write_ctlr};
use icc_regs::{get_icc_regs, set_icc_regs}; use icc_regs::{get_icc_regs, set_icc_regs};
use kvm_ioctls::DeviceFd;
use redist_regs::{construct_gicr_typers, get_redist_regs, set_redist_regs}; use redist_regs::{construct_gicr_typers, get_redist_regs, set_redist_regs};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::any::Any; use std::any::Any;
use std::convert::TryInto; use std::convert::TryInto;
use std::sync::Arc;
const GITS_CTLR: u32 = 0x0000; const GITS_CTLR: u32 = 0x0000;
const GITS_IIDR: u32 = 0x0004; const GITS_IIDR: u32 = 0x0004;
@ -27,7 +28,7 @@ const GITS_BASER: u32 = 0x0100;
/// This is a helper function to get/set the ITS device attribute depending /// This is a helper function to get/set the ITS device attribute depending
/// the bool parameter `set` provided. /// the bool parameter `set` provided.
pub fn gicv3_its_attr_access( pub fn gicv3_its_attr_access(
its_device: &Arc<dyn Device>, its_device: &DeviceFd,
group: u32, group: u32,
attr: u32, attr: u32,
val: &u64, val: &u64,
@ -40,20 +41,22 @@ pub fn gicv3_its_attr_access(
flags: 0, flags: 0,
}; };
if set { if set {
its_device its_device.set_device_attr(&gicv3_its_attr).map_err(|e| {
.set_device_attr(&gicv3_its_attr) Error::SetDeviceAttribute(HypervisorDeviceError::SetDeviceAttribute(e.into()))
.map_err(Error::SetDeviceAttribute) })
} else { } else {
its_device its_device
.get_device_attr(&mut gicv3_its_attr) .get_device_attr(&mut gicv3_its_attr)
.map_err(Error::GetDeviceAttribute) .map_err(|e| {
Error::GetDeviceAttribute(HypervisorDeviceError::GetDeviceAttribute(e.into()))
})
} }
} }
/// Function that saves/restores ITS tables into guest RAM. /// Function that saves/restores ITS tables into guest RAM.
/// ///
/// The tables get flushed to guest RAM whenever the VM gets stopped. /// The tables get flushed to guest RAM whenever the VM gets stopped.
pub fn gicv3_its_tables_access(its_device: &Arc<dyn Device>, save: bool) -> Result<()> { pub fn gicv3_its_tables_access(its_device: &DeviceFd, save: bool) -> Result<()> {
let attr = if save { let attr = if save {
u64::from(kvm_bindings::KVM_DEV_ARM_ITS_SAVE_TABLES) u64::from(kvm_bindings::KVM_DEV_ARM_ITS_SAVE_TABLES)
} else { } else {
@ -68,15 +71,15 @@ pub fn gicv3_its_tables_access(its_device: &Arc<dyn Device>, save: bool) -> Resu
}; };
its_device its_device
.set_device_attr(&init_gic_attr) .set_device_attr(&init_gic_attr)
.map_err(Error::SetDeviceAttribute) .map_err(|e| Error::SetDeviceAttribute(HypervisorDeviceError::SetDeviceAttribute(e.into())))
} }
pub struct KvmGicV3Its { pub struct KvmGicV3Its {
/// The hypervisor agnostic device for the GicV3 /// The KVM device for the GicV3
device: Arc<dyn Device>, device: DeviceFd,
/// The hypervisor agnostic device for the Its device /// The KVM device for the Its device
its_device: Option<Arc<dyn Device>>, its_device: Option<DeviceFd>,
/// Vector holding values of GICR_TYPER for each vCPU /// Vector holding values of GICR_TYPER for each vCPU
gicr_typers: Vec<u64>, gicr_typers: Vec<u64>,
@ -127,14 +130,6 @@ impl KvmGicV3Its {
kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3 kvm_bindings::kvm_device_type_KVM_DEV_TYPE_ARM_VGIC_V3
} }
fn device(&self) -> &Arc<dyn Device> {
&self.device
}
fn its_device(&self) -> Option<&Arc<dyn Device>> {
self.its_device.as_ref()
}
/// Setup the device-specific attributes /// Setup the device-specific attributes
fn init_device_attributes(&mut self, vm: &KvmVm, nr_irqs: u32) -> Result<()> { fn init_device_attributes(&mut self, vm: &KvmVm, nr_irqs: u32) -> Result<()> {
// GicV3 part attributes // GicV3 part attributes
@ -142,7 +137,7 @@ impl KvmGicV3Its {
We are placing the GIC below 1GB so we need to substract the size of the distributor. We are placing the GIC below 1GB so we need to substract the size of the distributor.
*/ */
Self::set_device_attribute( Self::set_device_attribute(
self.device(), &self.device,
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_DIST), u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_DIST),
&self.dist_addr as *const u64 as u64, &self.dist_addr as *const u64 as u64,
@ -153,7 +148,7 @@ impl KvmGicV3Its {
We are calculating here the start of the redistributors address. We have one per CPU. We are calculating here the start of the redistributors address. We have one per CPU.
*/ */
Self::set_device_attribute( Self::set_device_attribute(
self.device(), &self.device,
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ADDR,
u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_REDIST), u64::from(kvm_bindings::KVM_VGIC_V3_ADDR_TYPE_REDIST),
&self.redists_addr as *const u64 as u64, &self.redists_addr as *const u64 as u64,
@ -194,7 +189,7 @@ impl KvmGicV3Its {
*/ */
let nr_irqs_ptr = &nr_irqs as *const u32; let nr_irqs_ptr = &nr_irqs as *const u32;
Self::set_device_attribute( Self::set_device_attribute(
self.device(), &self.device,
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_NR_IRQS, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
0, 0,
nr_irqs_ptr as u64, nr_irqs_ptr as u64,
@ -205,7 +200,7 @@ impl KvmGicV3Its {
* See https://code.woboq.org/linux/linux/virt/kvm/arm/vgic/vgic-kvm-device.c.html#211. * See https://code.woboq.org/linux/linux/virt/kvm/arm/vgic/vgic-kvm-device.c.html#211.
*/ */
Self::set_device_attribute( Self::set_device_attribute(
self.device(), &self.device,
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_CTRL, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_CTRL,
u64::from(kvm_bindings::KVM_DEV_ARM_VGIC_CTRL_INIT), u64::from(kvm_bindings::KVM_DEV_ARM_VGIC_CTRL_INIT),
0, 0,
@ -214,7 +209,7 @@ impl KvmGicV3Its {
} }
/// Create a KVM Vgic device /// Create a KVM Vgic device
fn create_device(vm: &KvmVm) -> Result<Arc<dyn Device>> { fn create_device(vm: &KvmVm) -> Result<DeviceFd> {
let mut gic_device = kvm_bindings::kvm_create_device { let mut gic_device = kvm_bindings::kvm_create_device {
type_: Self::version(), type_: Self::version(),
fd: 0, fd: 0,
@ -226,7 +221,7 @@ impl KvmGicV3Its {
/// Set a GIC device attribute /// Set a GIC device attribute
fn set_device_attribute( fn set_device_attribute(
device: &Arc<dyn Device>, device: &DeviceFd,
group: u32, group: u32,
attr: u64, attr: u64,
addr: u64, addr: u64,
@ -238,9 +233,9 @@ impl KvmGicV3Its {
attr, attr,
addr, addr,
}; };
device device.set_device_attr(&attr).map_err(|e| {
.set_device_attr(&attr) Error::SetDeviceAttribute(HypervisorDeviceError::SetDeviceAttribute(e.into()))
.map_err(Error::SetDeviceAttribute) })
} }
/// Method to initialize the GIC device /// Method to initialize the GIC device
@ -328,18 +323,18 @@ impl Vgic for KvmGicV3Its {
fn state(&self) -> Result<Gicv3ItsState> { fn state(&self) -> Result<Gicv3ItsState> {
let gicr_typers = self.gicr_typers.clone(); let gicr_typers = self.gicr_typers.clone();
let gicd_ctlr = read_ctlr(self.device())?; let gicd_ctlr = read_ctlr(&self.device)?;
let dist_state = get_dist_regs(self.device())?; let dist_state = get_dist_regs(&self.device)?;
let rdist_state = get_redist_regs(self.device(), &gicr_typers)?; let rdist_state = get_redist_regs(&self.device, &gicr_typers)?;
let icc_state = get_icc_regs(self.device(), &gicr_typers)?; let icc_state = get_icc_regs(&self.device, &gicr_typers)?;
let its_baser_state: [u64; 8] = [0; 8]; let its_baser_state: [u64; 8] = [0; 8];
for i in 0..8 { for i in 0..8 {
gicv3_its_attr_access( gicv3_its_attr_access(
self.its_device().unwrap(), self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_BASER + i * 8, GITS_BASER + i * 8,
&its_baser_state[i as usize], &its_baser_state[i as usize],
@ -349,7 +344,7 @@ impl Vgic for KvmGicV3Its {
let its_ctlr_state: u64 = 0; let its_ctlr_state: u64 = 0;
gicv3_its_attr_access( gicv3_its_attr_access(
self.its_device().unwrap(), self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CTLR, GITS_CTLR,
&its_ctlr_state, &its_ctlr_state,
@ -358,7 +353,7 @@ impl Vgic for KvmGicV3Its {
let its_cbaser_state: u64 = 0; let its_cbaser_state: u64 = 0;
gicv3_its_attr_access( gicv3_its_attr_access(
self.its_device().unwrap(), self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CBASER, GITS_CBASER,
&its_cbaser_state, &its_cbaser_state,
@ -367,7 +362,7 @@ impl Vgic for KvmGicV3Its {
let its_creadr_state: u64 = 0; let its_creadr_state: u64 = 0;
gicv3_its_attr_access( gicv3_its_attr_access(
self.its_device().unwrap(), self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CREADR, GITS_CREADR,
&its_creadr_state, &its_creadr_state,
@ -376,7 +371,7 @@ impl Vgic for KvmGicV3Its {
let its_cwriter_state: u64 = 0; let its_cwriter_state: u64 = 0;
gicv3_its_attr_access( gicv3_its_attr_access(
self.its_device().unwrap(), self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CWRITER, GITS_CWRITER,
&its_cwriter_state, &its_cwriter_state,
@ -385,7 +380,7 @@ impl Vgic for KvmGicV3Its {
let its_iidr_state: u64 = 0; let its_iidr_state: u64 = 0;
gicv3_its_attr_access( gicv3_its_attr_access(
self.its_device().unwrap(), self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_IIDR, GITS_IIDR,
&its_iidr_state, &its_iidr_state,
@ -410,17 +405,17 @@ impl Vgic for KvmGicV3Its {
fn set_state(&mut self, state: &Gicv3ItsState) -> Result<()> { fn set_state(&mut self, state: &Gicv3ItsState) -> Result<()> {
let gicr_typers = self.gicr_typers.clone(); let gicr_typers = self.gicr_typers.clone();
write_ctlr(self.device(), state.gicd_ctlr)?; write_ctlr(&self.device, state.gicd_ctlr)?;
set_dist_regs(self.device(), &state.dist)?; set_dist_regs(&self.device, &state.dist)?;
set_redist_regs(self.device(), &gicr_typers, &state.rdist)?; set_redist_regs(&self.device, &gicr_typers, &state.rdist)?;
set_icc_regs(self.device(), &gicr_typers, &state.icc)?; set_icc_regs(&self.device, &gicr_typers, &state.icc)?;
//Restore GICv3ITS registers //Restore GICv3ITS registers
gicv3_its_attr_access( gicv3_its_attr_access(
self.its_device().unwrap(), self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_IIDR, GITS_IIDR,
&state.its_iidr, &state.its_iidr,
@ -428,7 +423,7 @@ impl Vgic for KvmGicV3Its {
)?; )?;
gicv3_its_attr_access( gicv3_its_attr_access(
self.its_device().unwrap(), self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CBASER, GITS_CBASER,
&state.its_cbaser, &state.its_cbaser,
@ -436,7 +431,7 @@ impl Vgic for KvmGicV3Its {
)?; )?;
gicv3_its_attr_access( gicv3_its_attr_access(
self.its_device().unwrap(), self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CREADR, GITS_CREADR,
&state.its_creadr, &state.its_creadr,
@ -444,7 +439,7 @@ impl Vgic for KvmGicV3Its {
)?; )?;
gicv3_its_attr_access( gicv3_its_attr_access(
self.its_device().unwrap(), self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CWRITER, GITS_CWRITER,
&state.its_cwriter, &state.its_cwriter,
@ -453,7 +448,7 @@ impl Vgic for KvmGicV3Its {
for i in 0..8 { for i in 0..8 {
gicv3_its_attr_access( gicv3_its_attr_access(
self.its_device().unwrap(), self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_BASER + i * 8, GITS_BASER + i * 8,
&state.its_baser[i as usize], &state.its_baser[i as usize],
@ -462,10 +457,10 @@ impl Vgic for KvmGicV3Its {
} }
// Restore ITS tables // Restore ITS tables
gicv3_its_tables_access(self.its_device().unwrap(), false)?; gicv3_its_tables_access(self.its_device.as_ref().unwrap(), false)?;
gicv3_its_attr_access( gicv3_its_attr_access(
self.its_device().unwrap(), self.its_device.as_ref().unwrap(),
kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS, kvm_bindings::KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
GITS_CTLR, GITS_CTLR,
&state.its_ctlr, &state.its_ctlr,
@ -484,11 +479,11 @@ impl Vgic for KvmGicV3Its {
addr: 0, addr: 0,
flags: 0, flags: 0,
}; };
self.device() self.device.set_device_attr(&init_gic_attr).map_err(|e| {
.set_device_attr(&init_gic_attr) Error::SetDeviceAttribute(HypervisorDeviceError::SetDeviceAttribute(e.into()))
.map_err(Error::SetDeviceAttribute)?; })?;
// Flush ITS tables to guest RAM. // Flush ITS tables to guest RAM.
gicv3_its_tables_access(self.its_device().unwrap(), true) gicv3_its_tables_access(self.its_device.as_ref().unwrap(), true)
} }
} }
@ -532,12 +527,12 @@ mod tests {
) )
.expect("Cannot create gic"); .expect("Cannot create gic");
let res = get_dist_regs(gic.device()); let res = get_dist_regs(&gic.device);
assert!(res.is_ok()); assert!(res.is_ok());
let state = res.unwrap(); let state = res.unwrap();
assert_eq!(state.len(), 568); assert_eq!(state.len(), 568);
let res = set_dist_regs(gic.device(), &state); let res = set_dist_regs(&gic.device, &state);
assert!(res.is_ok()); assert!(res.is_ok());
} }
@ -558,13 +553,13 @@ mod tests {
.expect("Cannot create gic"); .expect("Cannot create gic");
let gicr_typer = vec![123]; let gicr_typer = vec![123];
let res = get_redist_regs(gic.device(), &gicr_typer); let res = get_redist_regs(&gic.device, &gicr_typer);
assert!(res.is_ok()); assert!(res.is_ok());
let state = res.unwrap(); let state = res.unwrap();
println!("{}", state.len()); println!("{}", state.len());
assert!(state.len() == 24); assert!(state.len() == 24);
assert!(set_redist_regs(gic.device(), &gicr_typer, &state).is_ok()); assert!(set_redist_regs(&gic.device, &gicr_typer, &state).is_ok());
} }
#[test] #[test]
@ -584,13 +579,13 @@ mod tests {
.expect("Cannot create gic"); .expect("Cannot create gic");
let gicr_typer = vec![123]; let gicr_typer = vec![123];
let res = get_icc_regs(gic.device(), &gicr_typer); let res = get_icc_regs(&gic.device, &gicr_typer);
assert!(res.is_ok()); assert!(res.is_ok());
let state = res.unwrap(); let state = res.unwrap();
println!("{}", state.len()); println!("{}", state.len());
assert!(state.len() == 9); assert!(state.len() == 9);
assert!(set_icc_regs(gic.device(), &gicr_typer, &state).is_ok()); assert!(set_icc_regs(&gic.device, &gicr_typer, &state).is_ok());
} }
#[test] #[test]

View File

@ -3,10 +3,11 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
use crate::arch::aarch64::gic::{Error, Result}; use crate::arch::aarch64::gic::{Error, Result};
use crate::device::HypervisorDeviceError;
use crate::kvm::kvm_bindings::{kvm_device_attr, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS}; use crate::kvm::kvm_bindings::{kvm_device_attr, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS};
use crate::kvm::VcpuKvmState; use crate::kvm::VcpuKvmState;
use crate::{CpuState, Device}; use crate::CpuState;
use std::sync::Arc; use kvm_ioctls::DeviceFd;
// Relevant redistributor registers that we want to save/restore. // Relevant redistributor registers that we want to save/restore.
const GICR_CTLR: u32 = 0x0000; const GICR_CTLR: u32 = 0x0000;
@ -84,31 +85,27 @@ static VGIC_SGI_REGS: &[RdistReg] = &[
VGIC_RDIST_REG!(GICR_IPRIORITYR0, 32), VGIC_RDIST_REG!(GICR_IPRIORITYR0, 32),
]; ];
fn redist_attr_access( fn redist_attr_access(gic: &DeviceFd, offset: u32, typer: u64, val: &u32, set: bool) -> Result<()> {
gic: &Arc<dyn Device>, let mut gic_redist_attr = kvm_device_attr {
offset: u32,
typer: u64,
val: &u32,
set: bool,
) -> Result<()> {
let mut gic_dist_attr = kvm_device_attr {
group: KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, group: KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
attr: (typer & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) | (offset as u64), // this needs the mpidr attr: (typer & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) | (offset as u64), // this needs the mpidr
addr: val as *const u32 as u64, addr: val as *const u32 as u64,
flags: 0, flags: 0,
}; };
if set { if set {
gic.set_device_attr(&gic_dist_attr) gic.set_device_attr(&gic_redist_attr).map_err(|e| {
.map_err(Error::SetDeviceAttribute)?; Error::SetDeviceAttribute(HypervisorDeviceError::SetDeviceAttribute(e.into()))
})?;
} else { } else {
gic.get_device_attr(&mut gic_dist_attr) gic.get_device_attr(&mut gic_redist_attr).map_err(|e| {
.map_err(Error::GetDeviceAttribute)?; Error::GetDeviceAttribute(HypervisorDeviceError::GetDeviceAttribute(e.into()))
})?;
} }
Ok(()) Ok(())
} }
fn access_redists_aux( fn access_redists_aux(
gic: &Arc<dyn Device>, gic: &DeviceFd,
gicr_typer: &[u64], gicr_typer: &[u64],
state: &mut Vec<u32>, state: &mut Vec<u32>,
reg_list: &[RdistReg], reg_list: &[RdistReg],
@ -138,7 +135,7 @@ fn access_redists_aux(
} }
/// Get redistributor registers. /// Get redistributor registers.
pub fn get_redist_regs(gic: &Arc<dyn Device>, gicr_typer: &[u64]) -> Result<Vec<u32>> { pub fn get_redist_regs(gic: &DeviceFd, gicr_typer: &[u64]) -> Result<Vec<u32>> {
let mut state = Vec::new(); let mut state = Vec::new();
let mut idx: usize = 0; let mut idx: usize = 0;
access_redists_aux( access_redists_aux(
@ -155,7 +152,7 @@ pub fn get_redist_regs(gic: &Arc<dyn Device>, gicr_typer: &[u64]) -> Result<Vec<
} }
/// Set redistributor registers. /// Set redistributor registers.
pub fn set_redist_regs(gic: &Arc<dyn Device>, gicr_typer: &[u64], state: &[u32]) -> Result<()> { pub fn set_redist_regs(gic: &DeviceFd, gicr_typer: &[u64], state: &[u32]) -> Result<()> {
let mut idx: usize = 0; let mut idx: usize = 0;
let mut mut_state = state.to_owned(); let mut mut_state = state.to_owned();
access_redists_aux( access_redists_aux(

View File

@ -319,12 +319,12 @@ impl KvmVm {
/// Creates an emulated device in the kernel. /// Creates an emulated device in the kernel.
/// ///
/// See the documentation for `KVM_CREATE_DEVICE`. /// See the documentation for `KVM_CREATE_DEVICE`.
fn create_device(&self, device: &mut CreateDevice) -> vm::Result<Arc<dyn device::Device>> { fn create_device(&self, device: &mut CreateDevice) -> vm::Result<DeviceFd> {
let device_fd = self let device_fd = self
.fd .fd
.create_device(device) .create_device(device)
.map_err(|e| vm::HypervisorVmError::CreateDevice(e.into()))?; .map_err(|e| vm::HypervisorVmError::CreateDevice(e.into()))?;
Ok(Arc::new(device_fd)) Ok(device_fd)
} }
} }
@ -694,8 +694,9 @@ impl vm::Vm for KvmVm {
flags: 0, flags: 0,
}; };
self.create_device(&mut vfio_dev) Ok(Arc::new(self.create_device(&mut vfio_dev).map_err(
.map_err(|e| vm::HypervisorVmError::CreatePassthroughDevice(e.into())) |e| vm::HypervisorVmError::CreatePassthroughDevice(e.into()),
)?))
} }
/// ///
/// Start logging dirty pages /// Start logging dirty pages