summaryrefslogtreecommitdiff
path: root/drivers/irqchip/irq-riscv-imsic-state.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/irqchip/irq-riscv-imsic-state.c')
-rw-r--r--drivers/irqchip/irq-riscv-imsic-state.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
index b6cebfee9461..7566c8aa2d48 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.c
+++ b/drivers/irqchip/irq-riscv-imsic-state.c
@@ -784,7 +784,7 @@ static int __init imsic_parse_fwnode(struct fwnode_handle *fwnode,
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;
@@ -878,6 +878,7 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
}
/* 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) {
@@ -918,6 +919,15 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
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++;
}