mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-01 02:55:45 +00:00
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:
parent
0856ebbd42
commit
c5e966c972
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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]
|
||||||
|
@ -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(
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user