From 237fb6c134ac68d288b3ce9a2cc86083f5f6234e Mon Sep 17 00:00:00 2001 From: dallas Date: Tue, 10 Mar 2026 16:33:15 +0800 Subject: [PATCH 1/8] add zone_id for VirtualConfigSpace --- src/pci/pci_config.rs | 4 +- src/pci/pci_struct.rs | 98 +++++++++++++++++++++++++++++-------------- 2 files changed, 69 insertions(+), 33 deletions(-) diff --git a/src/pci/pci_config.rs b/src/pci/pci_config.rs index 34f881fc..a0289b5d 100644 --- a/src/pci/pci_config.rs +++ b/src/pci/pci_config.rs @@ -276,12 +276,12 @@ impl Zone { config_value.get_class().0 == 0x6 }) { - let mut vdev = dev.read().clone(); + let mut vdev = dev.read().config_space.clone(); vdev.set_vbdf(vbdf); self.vpci_bus.insert(vbdf, vdev); } else { let vdev = guard.remove(&bdf).unwrap(); - let mut vdev_inner = vdev.read().clone(); + let mut vdev_inner = vdev.read().config_space.clone(); vdev_inner.set_vbdf(vbdf); self.vpci_bus.insert(vbdf, vdev_inner); } diff --git a/src/pci/pci_struct.rs b/src/pci/pci_struct.rs index 13140269..83bf9f28 100644 --- a/src/pci/pci_struct.rs +++ b/src/pci/pci_struct.rs @@ -368,68 +368,102 @@ pub struct VirtualPciConfigSpace { } #[derive(Clone)] -pub struct ArcRwLockVirtualPciConfigSpace(Arc>); +pub struct VirtualPciConfigSpaceWithZone { + pub zone_id: Option, + pub config_space: VirtualPciConfigSpace, +} + +impl core::ops::Deref for VirtualPciConfigSpaceWithZone { + type Target = VirtualPciConfigSpace; + + fn deref(&self) -> &Self::Target { + &self.config_space + } +} + +impl core::ops::DerefMut for VirtualPciConfigSpaceWithZone { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.config_space + } +} + +impl Debug for VirtualPciConfigSpaceWithZone { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "zone_id: {:?}, ", self.zone_id)?; + self.config_space.fmt(f) + } +} + +#[derive(Clone)] +pub struct ArcRwLockVirtualPciConfigSpace(Arc>); impl ArcRwLockVirtualPciConfigSpace { pub fn new(dev: VirtualPciConfigSpace) -> Self { - Self(Arc::new(RwLock::new(dev))) + Self(Arc::new(RwLock::new(VirtualPciConfigSpaceWithZone { + zone_id: None, + config_space: dev, + }))) } - pub fn inner(&self) -> &Arc> { - &self.0 + pub fn get_zone_id(&self) -> Option { + self.0.read().zone_id + } + + pub fn set_zone_id(&self, zone_id: Option) { + self.0.write().zone_id = zone_id; } pub fn access(&self, offset: PciConfigAddress, size: usize) -> bool { - self.0.read().access(offset, size) + self.read().access(offset, size) } pub fn get_bdf(&self) -> Bdf { - self.0.read().get_bdf() + self.read().get_bdf() } pub fn get_vbdf(&self) -> Bdf { - self.0.read().get_vbdf() + self.read().get_vbdf() } pub fn get_dev_type(&self) -> VpciDevType { - self.0.read().get_dev_type() + self.read().get_dev_type() } pub fn get_config_type(&self) -> HeaderType { - self.0.read().get_config_type() + self.read().get_config_type() } pub fn get_bararr(&self) -> Bar { - self.0.read().get_bararr() + self.read().get_bararr() } pub fn get_rom(&self) -> PciMem { - self.0.read().get_rom() + self.read().get_rom() } pub fn read_emu(&self, field: EndpointField) -> HvResult { - self.0.write().read_emu(field) + self.write().read_emu(field) } pub fn read_emu64(&self, field: EndpointField) -> HvResult { - self.0.write().read_emu64(field) + self.write().read_emu64(field) } pub fn write_emu(&self, field: EndpointField, value: usize) -> HvResult { - self.0.write().write_emu(field, value) + self.write().write_emu(field, value) } // Legacy method for backward compatibility // pub fn write_emu_legacy(&self, offset: PciConfigAddress, size: usize, value: usize) -> HvResult { - // self.0.write().write_emu_legacy(offset, size, value) + // self.write().write_emu_legacy(offset, size, value) // } pub fn read_hw(&self, offset: PciConfigAddress, size: usize) -> HvResult { - self.0.write().read_hw(offset, size) + self.write().read_hw(offset, size) } pub fn write_hw(&self, offset: PciConfigAddress, size: usize, value: usize) -> HvResult { - self.0.write().write_hw(offset, size, value) + self.write().write_hw(offset, size, value) } /// Execute a closure with a reference to the bar at the given slot @@ -437,7 +471,7 @@ impl ArcRwLockVirtualPciConfigSpace { where F: FnOnce(&PciMem) -> R, { - let guard = self.0.read(); + let guard = self.read(); let bar = guard.get_bar_ref(slot); f(bar) } @@ -447,8 +481,8 @@ impl ArcRwLockVirtualPciConfigSpace { where F: FnOnce(&mut PciMem) -> R, { - let mut guard = self.0.write(); - let bar = guard.get_bar_ref_mut(slot); + let mut inner = self.write(); + let bar = inner.get_bar_ref_mut(slot); f(bar) } @@ -457,8 +491,8 @@ impl ArcRwLockVirtualPciConfigSpace { where F: FnOnce(&ConfigValue) -> R, { - let guard = self.0.read(); - f(&guard.config_value) + let guard = self.read(); + f(guard.get_config_value()) } /// Execute a closure with a mutable reference to the config_value @@ -466,8 +500,8 @@ impl ArcRwLockVirtualPciConfigSpace { where F: FnOnce(&mut ConfigValue) -> R, { - let mut guard = self.0.write(); - f(&mut guard.config_value) + let mut inner = self.write(); + inner.with_config_value_mut(f) } /// Execute a closure with a reference to the rom @@ -475,7 +509,7 @@ impl ArcRwLockVirtualPciConfigSpace { where F: FnOnce(&PciMem) -> R, { - let guard = self.0.read(); + let guard = self.read(); let rom = &guard.rom; f(rom) } @@ -485,8 +519,8 @@ impl ArcRwLockVirtualPciConfigSpace { where F: FnOnce(&mut PciMem) -> R, { - let mut guard = self.0.write(); - let rom = &mut guard.rom; + let mut inner = self.write(); + let rom = &mut inner.rom; f(rom) } @@ -495,22 +529,24 @@ impl ArcRwLockVirtualPciConfigSpace { where F: FnOnce(&PciCapabilityList) -> R, { - let guard = self.0.read(); + let guard = self.read(); f(&guard.capabilities) } - pub fn read(&self) -> spin::RwLockReadGuard<'_, VirtualPciConfigSpace> { + pub fn read(&self) -> spin::RwLockReadGuard<'_, VirtualPciConfigSpaceWithZone> { self.0.read() } - pub fn write(&self) -> spin::RwLockWriteGuard<'_, VirtualPciConfigSpace> { + pub fn write(&self) -> spin::RwLockWriteGuard<'_, VirtualPciConfigSpaceWithZone> { self.0.write() } } impl Debug for ArcRwLockVirtualPciConfigSpace { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - self.0.read().fmt(f) + let guard = self.0.read(); + write!(f, "zone_id: {:?}, ", guard.zone_id)?; + guard.config_space.fmt(f) } } From 2d21f8fc8bf46276167f8b7181e8c3299b4eeda2 Mon Sep 17 00:00:00 2001 From: dallas Date: Tue, 10 Mar 2026 17:28:31 +0800 Subject: [PATCH 2/8] update zone_id when allocate dev to zone --- src/pci/pci_config.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/pci/pci_config.rs b/src/pci/pci_config.rs index a0289b5d..c981651e 100644 --- a/src/pci/pci_config.rs +++ b/src/pci/pci_config.rs @@ -280,10 +280,15 @@ impl Zone { vdev.set_vbdf(vbdf); self.vpci_bus.insert(vbdf, vdev); } else { - let vdev = guard.remove(&bdf).unwrap(); - let mut vdev_inner = vdev.read().config_space.clone(); - vdev_inner.set_vbdf(vbdf); - self.vpci_bus.insert(vbdf, vdev_inner); + // Check if device is already allocated to another zone + if dev.get_zone_id().is_none() { + dev.set_zone_id(Some(_zone_id as u32)); + let mut vdev_inner = dev.read().config_space.clone(); + vdev_inner.set_vbdf(vbdf); + self.vpci_bus.insert(vbdf, vdev_inner); + } else { + warn!("Device {:#?} is already allocated to zone {:?}", bdf, dev.get_zone_id()); + } } } else { // warn!("can not find dev {:#?}", bdf); From 6fa73ddede072d8c26b026667a09aea12b5ddd4a Mon Sep 17 00:00:00 2001 From: dallas Date: Tue, 10 Mar 2026 17:39:25 +0800 Subject: [PATCH 3/8] reset zone_id when shutdown --- src/hypercall/mod.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/hypercall/mod.rs b/src/hypercall/mod.rs index ec3e3810..c1a54eaf 100644 --- a/src/hypercall/mod.rs +++ b/src/hypercall/mod.rs @@ -22,6 +22,7 @@ use crate::consts::{INVALID_ADDRESS, MAX_CPU_NUM, MAX_WAIT_TIMES, PAGE_SIZE}; use crate::device::virtio_trampoline::{MAX_DEVS, VIRTIO_BRIDGE, VIRTIO_IRQS}; use crate::error::HvResult; use crate::percpu::{get_cpu_data, PerCpu}; +use crate::pci::pci_config::GLOBAL_PCIE_LIST; use crate::zone::{ add_zone, all_zones_info, find_zone, is_this_root_zone, remove_zone, zone_create, ZoneInfo, }; @@ -272,6 +273,16 @@ impl<'a> HyperCall<'a> { drop(zone_w); drop(zone); + + // Reset zone_id for all devices allocated to this zone + let mut pci_list = GLOBAL_PCIE_LIST.lock(); + for (_bdf, dev) in pci_list.iter() { + if dev.get_zone_id() == Some(zone_id as u32) { + dev.set_zone_id(None); + } + } + drop(pci_list); + remove_zone(zone_id as _); info!("zone {} has been shutdown", zone_id); HyperCallResult::Ok(0) From b4ef4f14fd87521e4b9ab9379dd71a398f1cd7b6 Mon Sep 17 00:00:00 2001 From: dallas Date: Tue, 10 Mar 2026 19:09:44 +0800 Subject: [PATCH 4/8] add accessor for virtual rootcomplex --- src/pci/pci_config.rs | 48 ++++++++++++++++++++++++++++++++++++++++++- src/pci/pci_struct.rs | 22 +++++++++++++++++++- 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/pci/pci_config.rs b/src/pci/pci_config.rs index c981651e..bf91abc3 100644 --- a/src/pci/pci_config.rs +++ b/src/pci/pci_config.rs @@ -49,13 +49,19 @@ use crate::pci::pci_handler::mmio_vpci_handler; use crate::{ memory::mmio_generic_handler, pci::{ - config_accessors::{dwc::DwcConfigRegionBackend, dwc_atu::AtuConfig, PciRegionMmio}, + config_accessors::{dwc::DwcConfigAccessor, dwc::DwcConfigRegionBackend, dwc_atu::AtuConfig, PciConfigAccessor, PciRegionMmio}, pci_handler::{mmio_dwc_cfg_handler, mmio_dwc_io_handler, mmio_vpci_handler_dbi}, PciConfigAddress, }, platform, }; +#[cfg(feature = "ecam_pcie")] +use crate::pci::config_accessors::{ecam::EcamConfigAccessor, PciConfigAccessor}; + +#[cfg(feature = "loongarch64_pcie")] +use crate::pci::config_accessors::{loongarch64::LoongArchConfigAccessor, PciConfigAccessor}; + #[cfg(feature = "loongarch64_pcie")] use crate::pci::pci_handler::mmio_vpci_direct_handler; @@ -184,6 +190,46 @@ impl Zone { let target_domain = target_pci_config.domain; let bus_range_begin = target_pci_config.bus_range_begin as u8; + // Create accessor for VirtualRootComplex, similar to RootComplex + #[cfg(feature = "dwc_pcie")] + { + use alloc::sync::Arc; + let atu_config = platform::ROOT_DWC_ATU_CONFIG + .iter() + .find(|atu_cfg| atu_cfg.ecam_base == ecam_base); + + match atu_config { + Some(cfg) => { + let root_bus = bus_range_begin; + let accessor = Arc::new(DwcConfigAccessor::new(cfg, root_bus)); + self.vpci_bus.set_accessor(accessor); + } + None => { + warn!("No ATU config found for ecam_base 0x{:x}", ecam_base); + continue; + } + } + } + + #[cfg(feature = "loongarch64_pcie")] + { + use alloc::sync::Arc; + let root_bus = bus_range_begin; + let accessor = Arc::new(LoongArchConfigAccessor::new( + ecam_base, + target_pci_config.ecam_size, + root_bus, + )); + self.vpci_bus.set_accessor(accessor); + } + + #[cfg(feature = "ecam_pcie")] + { + use alloc::sync::Arc; + let accessor = Arc::new(EcamConfigAccessor::new(ecam_base)); + self.vpci_bus.set_accessor(accessor); + } + let mut filtered_devices: alloc::vec::Vec = alloc::vec::Vec::new(); for i in 0..num_pci_devs { let dev_config = alloc_pci_devs[i as usize]; diff --git a/src/pci/pci_struct.rs b/src/pci/pci_struct.rs index 83bf9f28..7eb725b9 100644 --- a/src/pci/pci_struct.rs +++ b/src/pci/pci_struct.rs @@ -1470,6 +1470,7 @@ impl RootComplex { pub struct VirtualRootComplex { devs: BTreeMap, base_to_bdf: BTreeMap, + accessor: Option>, } impl VirtualRootComplex { @@ -1477,15 +1478,34 @@ impl VirtualRootComplex { Self { devs: BTreeMap::new(), base_to_bdf: BTreeMap::new(), + accessor: None, } } + pub fn set_accessor(&mut self, accessor: Arc) { + self.accessor = Some(accessor); + } + pub fn insert( &mut self, bdf: Bdf, dev: VirtualPciConfigSpace, ) -> Option { - let base = dev.get_base(); + // Calculate base from vbdf (bdf parameter) using accessor, similar to address() method + let parent_bus = dev.parent_bdf.bus(); + let offset = 0; + let base = if let Some(accessor) = &self.accessor { + match accessor.get_physical_address(bdf, offset, parent_bus) { + Ok(addr) => addr, + Err(_) => { + warn!("can not get physical address for device {:#?}(vbdf), reset device base same to hardware", bdf); + dev.get_base() + }, + } + } else { + warn!("can not found accessor for vpci bus, reset device base same to hardware"); + dev.get_base() + }; info!("pci insert base {:#x} to bdf {:#?}", base, bdf); self.base_to_bdf.insert(base, bdf); self.devs From a030a53b26a6e9679b731c44adae296a20148265 Mon Sep 17 00:00:00 2001 From: dallas Date: Tue, 10 Mar 2026 19:10:15 +0800 Subject: [PATCH 5/8] update vdevice when realloc vbdf --- src/pci/pci_config.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/pci/pci_config.rs b/src/pci/pci_config.rs index bf91abc3..afa3964c 100644 --- a/src/pci/pci_config.rs +++ b/src/pci/pci_config.rs @@ -253,6 +253,7 @@ impl Zone { let mut vbus_pre = bus_range_begin; let mut bus_pre = bus_range_begin; let mut device_pre = 0u8; + let mut vdevice_pre = 0u8; /* * To allow Linux to successfully recognize the devices we add, hvisor needs @@ -292,7 +293,21 @@ impl Zone { vbus_pre }; - let vbdf = Bdf::new(bdf.domain(), vbus, device, vfunction); + // Remap device number to be contiguous, starting from 0 + let vdevice = if bus != bus_pre || device != device_pre { + // New bus or new device, increment device counter + if bus != bus_pre { + vdevice_pre = 0; + } else { + vdevice_pre += 1; + } + vdevice_pre + } else { + // Same bus and device, keep the same virtual device number + vdevice_pre + }; + + let vbdf = Bdf::new(bdf.domain(), vbus, vdevice, vfunction); device_pre = device; bus_pre = bus; From 4eb0dce25b912b7d732730ad7d7eba3d4ba2ef79 Mon Sep 17 00:00:00 2001 From: dallas Date: Tue, 10 Mar 2026 19:14:30 +0800 Subject: [PATCH 6/8] fmt --- src/hypercall/mod.rs | 4 ++-- src/pci/pci_config.rs | 11 +++++++++-- src/pci/pci_struct.rs | 3 +-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/hypercall/mod.rs b/src/hypercall/mod.rs index dc4f75af..f51dcba5 100644 --- a/src/hypercall/mod.rs +++ b/src/hypercall/mod.rs @@ -273,7 +273,7 @@ impl<'a> HyperCall<'a> { drop(zone_w); drop(zone); - + // Reset zone_id for all devices allocated to this zone let mut pci_list = GLOBAL_PCIE_LIST.lock(); for (_bdf, dev) in pci_list.iter() { @@ -282,7 +282,7 @@ impl<'a> HyperCall<'a> { } } drop(pci_list); - + remove_zone(zone_id as _); info!("zone {} has been shutdown", zone_id); HyperCallResult::Ok(0) diff --git a/src/pci/pci_config.rs b/src/pci/pci_config.rs index afa3964c..cac1a3b6 100644 --- a/src/pci/pci_config.rs +++ b/src/pci/pci_config.rs @@ -49,7 +49,10 @@ use crate::pci::pci_handler::mmio_vpci_handler; use crate::{ memory::mmio_generic_handler, pci::{ - config_accessors::{dwc::DwcConfigAccessor, dwc::DwcConfigRegionBackend, dwc_atu::AtuConfig, PciConfigAccessor, PciRegionMmio}, + config_accessors::{ + dwc::DwcConfigAccessor, dwc::DwcConfigRegionBackend, dwc_atu::AtuConfig, + PciConfigAccessor, PciRegionMmio, + }, pci_handler::{mmio_dwc_cfg_handler, mmio_dwc_io_handler, mmio_vpci_handler_dbi}, PciConfigAddress, }, @@ -348,7 +351,11 @@ impl Zone { vdev_inner.set_vbdf(vbdf); self.vpci_bus.insert(vbdf, vdev_inner); } else { - warn!("Device {:#?} is already allocated to zone {:?}", bdf, dev.get_zone_id()); + warn!( + "Device {:#?} is already allocated to zone {:?}", + bdf, + dev.get_zone_id() + ); } } } else { diff --git a/src/pci/pci_struct.rs b/src/pci/pci_struct.rs index 7eb725b9..c654edf6 100644 --- a/src/pci/pci_struct.rs +++ b/src/pci/pci_struct.rs @@ -1491,7 +1491,6 @@ impl VirtualRootComplex { bdf: Bdf, dev: VirtualPciConfigSpace, ) -> Option { - // Calculate base from vbdf (bdf parameter) using accessor, similar to address() method let parent_bus = dev.parent_bdf.bus(); let offset = 0; let base = if let Some(accessor) = &self.accessor { @@ -1500,7 +1499,7 @@ impl VirtualRootComplex { Err(_) => { warn!("can not get physical address for device {:#?}(vbdf), reset device base same to hardware", bdf); dev.get_base() - }, + } } } else { warn!("can not found accessor for vpci bus, reset device base same to hardware"); From 4c268dd9b45a74cdb86a65c4e28f61f041ad7a6c Mon Sep 17 00:00:00 2001 From: dallas Date: Wed, 11 Mar 2026 14:39:05 +0800 Subject: [PATCH 7/8] warning fixed --- src/hypercall/mod.rs | 2 +- src/pci/pci_config.rs | 18 +++++++----------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/hypercall/mod.rs b/src/hypercall/mod.rs index f51dcba5..82489b11 100644 --- a/src/hypercall/mod.rs +++ b/src/hypercall/mod.rs @@ -275,7 +275,7 @@ impl<'a> HyperCall<'a> { drop(zone); // Reset zone_id for all devices allocated to this zone - let mut pci_list = GLOBAL_PCIE_LIST.lock(); + let pci_list = GLOBAL_PCIE_LIST.lock(); for (_bdf, dev) in pci_list.iter() { if dev.get_zone_id() == Some(zone_id as u32) { dev.set_zone_id(None); diff --git a/src/pci/pci_config.rs b/src/pci/pci_config.rs index cac1a3b6..777f6f06 100644 --- a/src/pci/pci_config.rs +++ b/src/pci/pci_config.rs @@ -44,14 +44,14 @@ use crate::pci::{ use crate::pci::{mem_alloc::BaseAllocator, pci_struct::RootComplex}; #[cfg(feature = "ecam_pcie")] -use crate::pci::pci_handler::mmio_vpci_handler; +use crate::pci::{config_accessors::ecam::EcamConfigAccessor, pci_handler::mmio_vpci_handler}; + #[cfg(feature = "dwc_pcie")] use crate::{ memory::mmio_generic_handler, pci::{ config_accessors::{ - dwc::DwcConfigAccessor, dwc::DwcConfigRegionBackend, dwc_atu::AtuConfig, - PciConfigAccessor, PciRegionMmio, + dwc::DwcConfigAccessor, dwc::DwcConfigRegionBackend, dwc_atu::AtuConfig, PciRegionMmio, }, pci_handler::{mmio_dwc_cfg_handler, mmio_dwc_io_handler, mmio_vpci_handler_dbi}, PciConfigAddress, @@ -59,14 +59,10 @@ use crate::{ platform, }; -#[cfg(feature = "ecam_pcie")] -use crate::pci::config_accessors::{ecam::EcamConfigAccessor, PciConfigAccessor}; - #[cfg(feature = "loongarch64_pcie")] -use crate::pci::config_accessors::{loongarch64::LoongArchConfigAccessor, PciConfigAccessor}; - -#[cfg(feature = "loongarch64_pcie")] -use crate::pci::pci_handler::mmio_vpci_direct_handler; +use crate::pci::{ + config_accessors::loongarch64::LoongArchConfigAccessor, pci_handler::mmio_vpci_direct_handler, +}; pub static GLOBAL_PCIE_LIST: Lazy>> = Lazy::new(|| { @@ -181,7 +177,7 @@ impl Zone { pci_config: &[HvPciConfig], _num_pci_config: usize, ) -> HvResult { - let mut guard = GLOBAL_PCIE_LIST.lock(); + let guard = GLOBAL_PCIE_LIST.lock(); for target_pci_config in pci_config { // Skip empty config if target_pci_config.ecam_base == 0 { From c5e0041c23b0d53955609075d3d254a6a76c5747 Mon Sep 17 00:00:00 2001 From: dallas Date: Wed, 11 Mar 2026 16:48:45 +0800 Subject: [PATCH 8/8] support vbdf for gits --- src/device/irqchip/gicv3/gits.rs | 137 +++++++++++++++++++++---------- 1 file changed, 93 insertions(+), 44 deletions(-) diff --git a/src/device/irqchip/gicv3/gits.rs b/src/device/irqchip/gicv3/gits.rs index 9a44abe8..5b57551f 100644 --- a/src/device/irqchip/gicv3/gits.rs +++ b/src/device/irqchip/gicv3/gits.rs @@ -20,7 +20,7 @@ use spin::{mutex::Mutex, Once, RwLock}; use crate::{ consts::MAX_ZONE_NUM, cpu_data::this_zone, device::irqchip::gicv3::gicr::enable_one_lpi, - memory::Frame, + memory::Frame, pci::pci_struct::Bdf, }; use super::host_gits_base; @@ -45,6 +45,18 @@ pub const CMDQ_PAGES_NUM: usize = 16; // 16 pages, 64KB pub const PER_CMD_BYTES: usize = 0x20; pub const PER_CMD_QWORD: usize = PER_CMD_BYTES >> 3; +pub const ITS_CMD_MOVI: usize = 0x01; +pub const ITS_CMD_INT: usize = 0x03; +pub const ITS_CMD_CLEAR: usize = 0x04; +pub const ITS_CMD_SYNC: usize = 0x05; +pub const ITS_CMD_MAPD: usize = 0x08; +pub const ITS_CMD_MAPC: usize = 0x09; +pub const ITS_CMD_MAPTI: usize = 0x0a; +pub const ITS_CMD_MAPI: usize = 0x0b; +pub const ITS_CMD_INV: usize = 0x0c; +pub const ITS_CMD_INVALL: usize = 0x0d; +pub const ITS_CMD_DISCARD: usize = 0x0f; + fn ring_ptr_update(val: usize, page_num: usize) -> usize { let total_size = CMDQ_PAGE_SIZE * page_num; if val >= total_size { @@ -237,32 +249,65 @@ impl Cmdq { let binding = this_zone(); let zone = binding.read(); let cpuset_bitmap = zone.cpu_set.bitmap; + + let vicid_to_icid_checked = |vicid: u64| -> u64 { + vicid_to_icid(vicid, cpuset_bitmap) + .expect("vicid to icid failed, maybe logical_id out of range") + }; + let set_cmd2_icid = |cmd2: &mut u64, icid: u64| { + *cmd2 &= !0xffffu64; + *cmd2 |= icid & 0xffff; + }; + + // vbdf -> bdf + let id_32 = (value[0] >> 32) as u32; + let domain = (id_32 >> 16) as u8; + let vbus = ((id_32 >> 8) & 0xFF) as u8; + let vdevice = ((id_32 >> 3) & 0x1F) as u8; + let vfunction = (id_32 & 0x07) as u8; + + let vbdf = Bdf::new(domain, vbus, vdevice, vfunction); + let bdf = match zone.vpci_bus.get(&vbdf) { + Some(vdev) => vdev.read().get_bdf(), + None => Bdf { + domain, + bus: 0, + device: 0, + function: 0, + }, + }; + + let phys_id_32 = ((bdf.domain as u32) << 16) + | ((bdf.bus as u32) << 8) + | ((bdf.device as u32) << 3) + | (bdf.function as u32); + + // new_cmd[0] = cmd0_tmp + // CLEAR DISCARD INT INV MAPD MAPI MAPTI MOVI + let cmd0_tmp = (value[0] & 0xffffffff) | ((phys_id_32 as u64) << 32); + match code { - 0x0b => { - let id = value[0] & 0xffffffff00000000; + ITS_CMD_MAPI => { + new_cmd[0] = cmd0_tmp; + let event = value[1] & 0xffffffff; let vicid = value[2] & 0xffff; - let icid = vicid_to_icid(vicid, cpuset_bitmap) - .expect("vicid to icid failed, maybe logical_id out of range"); - new_cmd[2] &= !0xffffu64; - new_cmd[2] |= icid & 0xffff; + let icid = vicid_to_icid_checked(vicid); + set_cmd2_icid(&mut new_cmd[2], icid); enable_one_lpi((event - 8192) as _); debug!( - "MAPI cmd, for device {:#x}, event = intid = {:#x} -> vicid {:#x} (icid {:#x})", - id >> 32, + "MAPI cmd, for vbdf {:#x}:{:#x}:{:#x}:{:#x} -> {:#x}:{:#x}:{:#x}:{:#x}, event = intid = {:#x} -> vicid {:#x} (icid {:#x})", + domain, vbus, vdevice, vfunction, + bdf.domain, bdf.bus, bdf.device, bdf.function, event, vicid, icid ); } - 0x08 => { - let id = value[0] & 0xffffffff00000000; + ITS_CMD_MAPD => { + new_cmd[0] = cmd0_tmp; + let itt_base = value[2] & 0x000fffffffffff00; // the lowest 8 bits are zeros - debug!( - "MAPD cmd, for device {:#x}, itt base {:#x}", - id >> 32, - itt_base - ); let phys_itt_base = unsafe { this_zone() .read() @@ -274,69 +319,73 @@ impl Cmdq { new_cmd[2] &= !0x000fffffffffff00u64; new_cmd[2] |= phys_itt_base as u64; debug!( - "MAPD cmd, set ITT: {:#x} to device {:#x}", + "MAPD cmd, set ITT: {:#x} to vbdf {:#x}:{:#x}:{:#x}:{:#x} -> {:#x}:{:#x}:{:#x}:{:#x}", phys_itt_base, - id >> 32 + domain, vbus, vdevice, vfunction, + bdf.domain, bdf.bus, bdf.device, bdf.function ); } - 0x0a => { - let id = value[0] & 0xffffffff00000000; + ITS_CMD_MAPTI => { + new_cmd[0] = cmd0_tmp; + let event = value[1] & 0xffffffff; let intid = value[1] >> 32; let vicid = value[2] & 0xffff; - let icid = vicid_to_icid(vicid, cpuset_bitmap) - .expect("vicid to icid failed, maybe logical_id out of range"); - new_cmd[2] &= !0xffffu64; - new_cmd[2] |= icid & 0xffff; + let icid = vicid_to_icid_checked(vicid); + set_cmd2_icid(&mut new_cmd[2], icid); enable_one_lpi((intid - 8192) as _); debug!( - "MAPTI cmd, for device {:#x}, event {:#x} -> vicid {:#x} (icid {:#x}) + intid {:#x}", - id >> 32, + "MAPTI cmd, for vbdf {:#x}:{:#x}:{:#x}:{:#x} -> {:#x}:{:#x}:{:#x}:{:#x}, event {:#x} -> vicid {:#x} (icid {:#x}) + intid {:#x}", + domain, vbus, vdevice, vfunction, + bdf.domain, bdf.bus, bdf.device, bdf.function, event, vicid, icid, intid ); } - 0x09 => { + ITS_CMD_MAPC => { let vicid = value[2] & 0xffff; - let icid = vicid_to_icid(vicid, cpuset_bitmap) - .expect("vicid to icid failed, maybe logical_id out of range"); - new_cmd[2] &= !0xffffu64; - new_cmd[2] |= icid & 0xffff; + let icid = vicid_to_icid_checked(vicid); + set_cmd2_icid(&mut new_cmd[2], icid); let rd_base = (value[2] >> 16) & 0x7ffffffff; debug!( "MAPC cmd, vicid {:#x} (icid {:#x}) -> redist {:#x}", vicid, icid, rd_base ); } - 0x05 => { + ITS_CMD_SYNC => { debug!("SYNC cmd"); } - 0x04 => { + ITS_CMD_CLEAR => { + new_cmd[0] = cmd0_tmp; debug!("CLEAR cmd"); } - 0x0f => { + ITS_CMD_DISCARD => { + new_cmd[0] = cmd0_tmp; debug!("DISCARD cmd"); } - 0x03 => { + ITS_CMD_INT => { + new_cmd[0] = cmd0_tmp; debug!("INT cmd"); } - 0x0c => { + ITS_CMD_INV => { + new_cmd[0] = cmd0_tmp; debug!("INV cmd"); } - 0x0d => { + ITS_CMD_INVALL => { debug!("INVALL cmd"); } - 0x01 => { + ITS_CMD_MOVI => { + new_cmd[0] = cmd0_tmp; + let vicid = value[2] & 0xffff; - let icid = vicid_to_icid(vicid, cpuset_bitmap) - .expect("vicid to icid failed, maybe logical_id out of range"); - new_cmd[2] &= !0xffffu64; - new_cmd[2] |= icid & 0xffff; + let icid = vicid_to_icid_checked(vicid); + set_cmd2_icid(&mut new_cmd[2], icid); debug!( - "MOVI, for Device {:#x}, new vicid({}) -> icid({})", - value[0] >> 32, + "MOVI, for vbdf {:#x}:{:#x}:{:#x}:{:#x} -> {:#x}:{:#x}:{:#x}:{:#x}, new vicid({}) -> icid({})", + domain, vbus, vdevice, vfunction, + bdf.domain, bdf.bus, bdf.device, bdf.function, vicid, icid );