arch, hypervisor: Report KVM IMSIC interrupt IDs

The RISC-V AIA FDT node currently advertises a fixed riscv,num-ids
value. That can diverge from the interrupt identity count configured by
KVM, which matters for guests running with an emulated IMSIC.

Record the NR_IDS value reported by KVM and expose that value through
the generated device tree. Read back the KVM-selected AIA mode without
forcing an emulation mode.

Assisted-by: OpenAI-Codex:GPT-5

Signed-off-by: wangyf0611 <wangyufeng@iscas.ac.cn>
This commit is contained in:
wangyf0611
2026-05-21 15:47:53 +08:00
committed by Rob Bradford
parent 9c2e2a67cc
commit 649ca23345
3 changed files with 18 additions and 9 deletions
+2 -2
View File
@@ -231,8 +231,8 @@ fn create_aia_node(fdt: &mut FdtWriter, aia_device: &Arc<Mutex<dyn Vaia>>) -> Fd
fdt.property_u32("#interrupt-cells", 0u32)?; fdt.property_u32("#interrupt-cells", 0u32)?;
fdt.property_null("interrupt-controller")?; fdt.property_null("interrupt-controller")?;
fdt.property_null("msi-controller")?; fdt.property_null("msi-controller")?;
// TODO complete num-ids let imsic_num_ids = aia_device.lock().unwrap().imsic_num_ids();
fdt.property_u32("riscv,num-ids", 2047u32)?; fdt.property_u32("riscv,num-ids", imsic_num_ids)?;
fdt.property_u32("phandle", AIA_IMSIC_PHANDLE)?; fdt.property_u32("phandle", AIA_IMSIC_PHANDLE)?;
let mut irq_cells = Vec::new(); let mut irq_cells = Vec::new();
+3
View File
@@ -46,6 +46,9 @@ pub trait Vaia: Send + Sync {
/// Returns an array with IMSIC device properties /// Returns an array with IMSIC device properties
fn imsic_properties(&self) -> [u32; 4]; fn imsic_properties(&self) -> [u32; 4];
/// Returns the number of IMSIC interrupt identities exposed to the guest
fn imsic_num_ids(&self) -> u32;
/// Returns the number of vCPUs this AIA handles /// Returns the number of vCPUs this AIA handles
fn vcpu_count(&self) -> u32; fn vcpu_count(&self) -> u32;
+13 -7
View File
@@ -24,6 +24,9 @@ pub struct KvmAiaImsics {
/// Number of CPUs handled by the device /// Number of CPUs handled by the device
vcpu_count: u32, vcpu_count: u32,
/// Number of IMSIC interrupt identities configured by KVM
imsic_num_ids: u32,
} }
#[derive(Clone, Default, Serialize, Deserialize)] #[derive(Clone, Default, Serialize, Deserialize)]
@@ -37,20 +40,17 @@ impl KvmAiaImsics {
/// Setup the device-specific attributes /// Setup the device-specific attributes
fn init_device_attributes(&mut self, nr_irqs: u32) -> Result<()> { fn init_device_attributes(&mut self, nr_irqs: u32) -> Result<()> {
// AIA part attributes // Read the working mode selected by KVM. Possible modes are EMUL,
// Getting the working mode of RISC-V AIA, defaults to EMUL, passible // HW_ACCL and AUTO.
// variants are EMUL, HW_ACCL, AUTO let mut aia_mode_readback: u32 = 0;
let mut aia_mode = kvm_bindings::KVM_DEV_RISCV_AIA_MODE_EMUL;
Self::get_device_attribute( Self::get_device_attribute(
&self.device, &self.device,
kvm_bindings::KVM_DEV_RISCV_AIA_GRP_CONFIG, kvm_bindings::KVM_DEV_RISCV_AIA_GRP_CONFIG,
u64::from(kvm_bindings::KVM_DEV_RISCV_AIA_CONFIG_MODE), u64::from(kvm_bindings::KVM_DEV_RISCV_AIA_CONFIG_MODE),
&raw mut aia_mode as u64, &raw mut aia_mode_readback as u64,
0, 0,
)?; )?;
// Report AIA MODE
// Setting up the number of wired interrupt sources // Setting up the number of wired interrupt sources
Self::set_device_attribute( Self::set_device_attribute(
&self.device, &self.device,
@@ -71,6 +71,7 @@ impl KvmAiaImsics {
)?; )?;
// Report NR_IDS // Report NR_IDS
self.imsic_num_ids = aia_nr_ids;
// Setting up hart_bits // Setting up hart_bits
let max_hart_index = self.vcpu_count as u64 - 1; let max_hart_index = self.vcpu_count as u64 - 1;
@@ -191,6 +192,7 @@ impl KvmAiaImsics {
vcpu_count: config.vcpu_count, vcpu_count: config.vcpu_count,
aplic_addr: config.aplic_addr, aplic_addr: config.aplic_addr,
imsic_addr: config.imsic_addr, imsic_addr: config.imsic_addr,
imsic_num_ids: 0,
}; };
aia_device.init_device_attributes(config.nr_irqs)?; aia_device.init_device_attributes(config.nr_irqs)?;
@@ -226,6 +228,10 @@ impl Vaia for KvmAiaImsics {
] ]
} }
fn imsic_num_ids(&self) -> u32 {
self.imsic_num_ids
}
fn vcpu_count(&self) -> u32 { fn vcpu_count(&self) -> u32 {
self.vcpu_count self.vcpu_count
} }