feat(kvm/aarch64): create and init GIC V3 and ITS

Signed-off-by: Changyuan Lyu <changyuanl@google.com>
This commit is contained in:
Changyuan Lyu 2024-06-24 22:30:17 -07:00 committed by Lencerf
parent b71ee9aac3
commit 9fb57c7655
5 changed files with 177 additions and 9 deletions

View file

@ -233,6 +233,16 @@ pub trait GicV2: Debug + Send + Sync + 'static {
fn set_num_irqs(&self, val: u32) -> Result<()>;
}
#[cfg(target_arch = "aarch64")]
pub trait GicV3: Debug + Send + Sync + 'static {
fn init(&self) -> Result<()>;
}
#[cfg(target_arch = "aarch64")]
pub trait Its: Debug + Send + Sync + 'static {
fn init(&self) -> Result<()>;
}
#[derive(Debug, Clone, Deserialize)]
pub enum Coco {
#[cfg(target_arch = "x86_64")]
@ -289,6 +299,21 @@ pub trait Vm {
type GicV2: GicV2;
#[cfg(target_arch = "aarch64")]
fn create_gic_v2(&self, distributor_base: u64, cpu_interface_base: u64) -> Result<Self::GicV2>;
#[cfg(target_arch = "aarch64")]
type GicV3: GicV3;
#[cfg(target_arch = "aarch64")]
fn create_gic_v3(
&self,
distributor_base: u64,
redistributor_base: u64,
redistributor_count: u32,
) -> Result<Self::GicV3>;
#[cfg(target_arch = "aarch64")]
type Its: Its;
#[cfg(target_arch = "aarch64")]
fn create_its(&self, base: u64) -> Result<Self::Its>;
}
pub trait Hypervisor {

View file

@ -26,8 +26,8 @@ use crate::hv::hvf::bindings::{
use crate::hv::hvf::check_ret;
use crate::hv::hvf::vcpu::HvfVcpu;
use crate::hv::{
error, GicV2, IoeventFd, IoeventFdRegistry, IrqFd, IrqSender, MemMapOption, MsiSender, Result,
Vm, VmMemory,
error, GicV2, GicV3, IoeventFd, IoeventFdRegistry, IrqFd, IrqSender, Its, MemMapOption,
MsiSender, Result, Vm, VmMemory,
};
#[derive(Debug)]
@ -196,6 +196,24 @@ impl GicV2 for HvfGicV2 {
}
}
#[derive(Debug)]
pub struct HvfGicV3;
impl GicV3 for HvfGicV3 {
fn init(&self) -> Result<()> {
unimplemented!()
}
}
#[derive(Debug)]
pub struct HvfIts;
impl Its for HvfIts {
fn init(&self) -> Result<()> {
unimplemented!()
}
}
#[derive(Debug)]
pub struct HvfVm {
pub(super) vcpus: Mutex<HashMap<u32, u64>>,
@ -250,4 +268,17 @@ impl Vm for HvfVm {
fn create_irq_sender(&self, _pin: u8) -> Result<Self::IrqSender> {
unimplemented!()
}
type GicV3 = HvfGicV3;
fn create_gic_v3(
&self,
_distributor_base: u64,
_redistributor_base: u64,
_redistributor_count: u32,
) -> Result<Self::GicV3> {
unimplemented!()
}
type Its = HvfIts;
fn create_its(&self, _base: u64) -> Result<Self::Its> {
unimplemented!()
}
}

View file

@ -14,6 +14,8 @@
use std::fmt::{Debug, Formatter, Result};
#[cfg(target_arch = "aarch64")]
use bitfield::bitfield;
use bitflags::bitflags;
use crate::c_enum;
@ -530,6 +532,8 @@ c_enum! {
pub struct KvmDevType(u32);
{
ARM_VGIC_V2 = 5;
ARM_VGIC_V3 = 7;
ARM_ITS = 8;
}
}
@ -542,15 +546,21 @@ c_enum! {
CPU_REGS = 2;
NR_IRQS = 3;
CTL = 4;
REDIS_REG = 5;
CPU_SYSREGS = 6;
}
}
#[cfg(target_arch = "aarch64")]
c_enum! {
pub struct KvmVgicV2AddrType(u64);
pub struct KvmVgicAddrType(u64);
{
DIST = 0;
CPU = 1;
DIST_V2 = 0;
CPU_V2 = 1;
DIST_V3 = 2;
REDIST_V3 = 3;
ITS = 4;
REDIST_REGION_V3 = 5;
}
}
@ -559,9 +569,24 @@ c_enum! {
pub struct KvmDevArmVgicCtrl(u64);
{
INIT = 0;
ITS_SAVE_TABLES = 1;
ITS_RESTORE_TABLES = 2;
VGIC_SAVE_PENDING_TABLES = 3;
ITS_RESET = 4;
}
}
#[cfg(target_arch = "aarch64")]
bitfield! {
#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct KvmVgicV3RedistRegion(u64);
impl Debug;
pub count, set_count: 63, 52;
pub base, set_base: 51, 16;
pub index, set_index: 11, 0;
}
#[cfg(target_arch = "aarch64")]
#[repr(C)]
#[derive(Debug, Copy, Clone, Default)]

View file

@ -13,12 +13,12 @@
// limitations under the License.
use crate::hv::kvm::bindings::{
KvmDevArmVgicCtrl, KvmDevArmVgicGrp, KvmDevType, KvmVgicV2AddrType,
KvmDevArmVgicCtrl, KvmDevArmVgicGrp, KvmDevType, KvmVgicAddrType, KvmVgicV3RedistRegion,
};
use crate::hv::kvm::device::KvmDevice;
use crate::hv::kvm::vm::KvmVm;
use crate::hv::kvm::Result;
use crate::hv::GicV2;
use crate::hv::{GicV2, GicV3, Its};
#[derive(Debug)]
pub struct KvmGicV2 {
@ -83,14 +83,82 @@ impl KvmVm {
let gic = KvmGicV2 { dev };
gic.dev.set_attr(
KvmDevArmVgicGrp::ADDR.raw(),
KvmVgicV2AddrType::DIST.raw(),
KvmVgicAddrType::DIST_V2.raw(),
&distributor_base,
)?;
gic.dev.set_attr(
KvmDevArmVgicGrp::ADDR.raw(),
KvmVgicV2AddrType::CPU.raw(),
KvmVgicAddrType::CPU_V2.raw(),
&cpu_interface_base,
)?;
Ok(gic)
}
}
#[derive(Debug)]
pub struct KvmGicV3 {
dev: KvmDevice,
}
impl GicV3 for KvmGicV3 {
fn init(&self) -> Result<()> {
self.dev.set_attr(
KvmDevArmVgicGrp::CTL.raw(),
KvmDevArmVgicCtrl::INIT.raw(),
&(),
)?;
Ok(())
}
}
impl KvmVm {
pub fn kvm_create_gic_v3(
&self,
distributor_base: u64,
redistributor_base: u64,
redistributor_count: u32,
) -> Result<KvmGicV3> {
let dev = KvmDevice::new(&self.vm, KvmDevType::ARM_VGIC_V3)?;
dev.set_attr(
KvmDevArmVgicGrp::ADDR.raw(),
KvmVgicAddrType::DIST_V3.raw(),
&distributor_base,
)?;
let mut redist_region = KvmVgicV3RedistRegion(redistributor_base);
redist_region.set_count(redistributor_count as u64);
dev.set_attr(
KvmDevArmVgicGrp::ADDR.raw(),
KvmVgicAddrType::REDIST_REGION_V3.raw(),
&redist_region,
)?;
Ok(KvmGicV3 { dev })
}
}
#[derive(Debug)]
pub struct KvmIts {
dev: KvmDevice,
}
impl Its for KvmIts {
fn init(&self) -> Result<()> {
self.dev.set_attr(
KvmDevArmVgicGrp::CTL.raw(),
KvmDevArmVgicCtrl::INIT.raw(),
&(),
)?;
Ok(())
}
}
impl KvmVm {
pub fn kvm_create_its(&self, base: u64) -> Result<KvmIts> {
let dev = KvmDevice::new(&self.vm, KvmDevType::ARM_ITS)?;
dev.set_attr(
KvmDevArmVgicGrp::ADDR.raw(),
KvmVgicAddrType::ITS.raw(),
&base,
)?;
Ok(KvmIts { dev })
}
}

View file

@ -663,6 +663,25 @@ impl Vm for KvmVm {
fn create_gic_v2(&self, distributor_base: u64, cpu_interface_base: u64) -> Result<Self::GicV2> {
self.kvm_create_gic_v2(distributor_base, cpu_interface_base)
}
#[cfg(target_arch = "aarch64")]
type GicV3 = aarch64::KvmGicV3;
#[cfg(target_arch = "aarch64")]
fn create_gic_v3(
&self,
distributor_base: u64,
redistributor_base: u64,
redistributor_count: u32,
) -> Result<Self::GicV3> {
self.kvm_create_gic_v3(distributor_base, redistributor_base, redistributor_count)
}
#[cfg(target_arch = "aarch64")]
type Its = aarch64::KvmIts;
#[cfg(target_arch = "aarch64")]
fn create_its(&self, base: u64) -> Result<Self::Its> {
self.kvm_create_its(base)
}
}
#[cfg(test)]