int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
{
- u32 i, j, index, nr_parent_irqs, nr_mmios, nr_handlers = 0;
+ u32 i, j, index, nr_parent_irqs, nr_mmios, nr_guest_files, nr_handlers = 0;
struct imsic_global_config *global;
struct imsic_local_config *local;
void __iomem **mmios_va = NULL;
}
/* Configure handlers for target CPUs */
+ global->nr_guest_files = BIT(global->guest_index_bits) - 1;
for (i = 0; i < nr_parent_irqs; i++) {
rc = imsic_get_parent_hartid(fwnode, i, &hartid);
if (rc) {
local->msi_pa = mmios[index].start + reloff;
local->msi_va = mmios_va[index] + reloff;
+ /*
+ * KVM uses global->nr_guest_files to determine the available guest
+ * interrupt files on each CPU. Take the minimum number of guest
+ * interrupt files across all CPUs to avoid KVM incorrectly allocating
+ * an unexisted or unmapped guest interrupt file on some CPUs.
+ */
+ nr_guest_files = (resource_size(&mmios[index]) - reloff) / IMSIC_MMIO_PAGE_SZ - 1;
+ global->nr_guest_files = min(global->nr_guest_files, nr_guest_files);
+
nr_handlers++;
}