LoongArch inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6MUZX
--------------------------------
Signed-off-by: liuyun liuyun@loongson.cn Signed-off-by: maobibo maobibo@loongson.cn Signed-off-by: yangyinglu yangyinglu@loongson.cn --- arch/loongarch/include/asm/irq.h | 1 + arch/loongarch/include/asm/loongarch.h | 1 + arch/loongarch/kernel/legacy_boot.c | 11 ++++--- drivers/irqchip/irq-loongson-eiointc.c | 40 +++++++++++++++++--------- 4 files changed, 36 insertions(+), 17 deletions(-)
diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h index c7a152d6bf0c..69833188e99f 100644 --- a/arch/loongarch/include/asm/irq.h +++ b/arch/loongarch/include/asm/irq.h @@ -53,6 +53,7 @@ struct acpi_vector_group { extern struct acpi_vector_group pch_group[MAX_IO_PICS]; extern struct acpi_vector_group msi_group[MAX_IO_PICS];
+#define MAX_CORES_PER_EIO_NODE 256 #define CORES_PER_EIO_NODE 4
#define LOONGSON_CPU_UART0_VEC 10 /* CPU UART0 */ diff --git a/arch/loongarch/include/asm/loongarch.h b/arch/loongarch/include/asm/loongarch.h index 10748a20a2ab..9b33b01d8050 100644 --- a/arch/loongarch/include/asm/loongarch.h +++ b/arch/loongarch/include/asm/loongarch.h @@ -214,6 +214,7 @@ __asm__(".macro parse_r var r\n\t" /* IOCSR */ #define iocsr_read32(reg) __iocsrrd_w(reg) #define iocsr_read64(reg) __iocsrrd_d(reg) +#define iocsr_write8(val, reg) __iocsrwr_b(val, reg) #define iocsr_write32(val, reg) __iocsrwr_w(val, reg) #define iocsr_write64(val, reg) __iocsrwr_d(val, reg)
diff --git a/arch/loongarch/kernel/legacy_boot.c b/arch/loongarch/kernel/legacy_boot.c index c7ec165c8875..5e1eb1cbc755 100644 --- a/arch/loongarch/kernel/legacy_boot.c +++ b/arch/loongarch/kernel/legacy_boot.c @@ -211,7 +211,7 @@ int setup_legacy_IRQ(void) }
pic_domain = get_pchpic_irq_domain(); - if (pic_domain) + if (pic_domain && !cpu_has_hypervisor) pch_lpc_acpi_init(pic_domain, acpi_pchlpc);
return 0; @@ -372,9 +372,12 @@ __init unsigned long legacy_boot_init(unsigned long argc, unsigned long cmdptr, efi_bp = (struct boot_params *)bpi; bpi_version = get_bpi_version(&efi_bp->signature); pr_info("BPI%d with boot flags %llx.\n", bpi_version, efi_bp->flags); - if (bpi_version == BPI_VERSION_NONE) - panic("Fatal error, bpi ver BONE!\n"); - else if (bpi_version == BPI_VERSION_V2) + if (bpi_version == BPI_VERSION_NONE) { + if (cpu_has_hypervisor) + pr_err(FW_BUG "Fatal error, bpi ver NONE!\n"); + else + panic(FW_BUG "Fatal error, bpi ver NONE!\n"); + } else if (bpi_version == BPI_VERSION_V2) parse_bpi_flags();
fw_init_cmdline(argc, cmdptr); diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index 4bda50674d0d..3038392f831b 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -55,7 +55,9 @@ static void eiointc_enable(void)
static int cpu_to_eio_node(int cpu) { - return cpu_logical_map(cpu) / CORES_PER_EIO_NODE; + int cores = (cpu_has_hypervisor ? MAX_CORES_PER_EIO_NODE : CORES_PER_EIO_NODE); + + return cpu_logical_map(cpu) / cores; }
static void eiointc_set_irq_route(int pos, unsigned int cpu, unsigned int mnode, nodemask_t *node_map) @@ -86,6 +88,11 @@ static void eiointc_set_irq_route(int pos, unsigned int cpu, unsigned int mnode,
static DEFINE_RAW_SPINLOCK(affinity_lock);
+static void virt_extioi_set_irq_route(int irq, unsigned int cpu) +{ + iocsr_write8(cpu_logical_map(cpu), EIOINTC_REG_ROUTE + irq); +} + static int eiointc_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity, bool force) { unsigned int cpu; @@ -108,16 +115,22 @@ static int eiointc_set_irq_affinity(struct irq_data *d, const struct cpumask *af vector = d->hwirq; regaddr = EIOINTC_REG_ENABLE + ((vector >> 5) << 2);
- /* Mask target vector */ - csr_any_send(regaddr, EIOINTC_ALL_ENABLE & (~BIT(vector & 0x1F)), - 0x0, priv->node * CORES_PER_EIO_NODE); - - /* Set route for target vector */ - eiointc_set_irq_route(vector, cpu, priv->node, &priv->node_map); - - /* Unmask target vector */ - csr_any_send(regaddr, EIOINTC_ALL_ENABLE, - 0x0, priv->node * CORES_PER_EIO_NODE); + if (cpu_has_hypervisor) { + iocsr_write32(EIOINTC_ALL_ENABLE & ~BIT(vector & 0x1F), regaddr); + virt_extioi_set_irq_route(vector, cpu); + iocsr_write32(EIOINTC_ALL_ENABLE, regaddr); + } else { + /* Mask target vector */ + csr_any_send(regaddr, EIOINTC_ALL_ENABLE & (~BIT(vector & 0x1F)), + 0x0, priv->node * CORES_PER_EIO_NODE); + + /* Set route for target vector */ + eiointc_set_irq_route(vector, cpu, priv->node, &priv->node_map); + + /* Unmask target vector */ + csr_any_send(regaddr, EIOINTC_ALL_ENABLE, + 0x0, priv->node * CORES_PER_EIO_NODE); + }
irq_data_update_effective_affinity(d, cpumask_of(cpu));
@@ -144,13 +157,14 @@ static int eiointc_router_init(unsigned int cpu) uint32_t data; uint32_t node = cpu_to_eio_node(cpu); uint32_t index = eiointc_index(node); + int cores = (cpu_has_hypervisor ? MAX_CORES_PER_EIO_NODE : CORES_PER_EIO_NODE);
if (index < 0) { pr_err("Error: invalid nodemap!\n"); return -1; }
- if ((cpu_logical_map(cpu) % CORES_PER_EIO_NODE) == 0) { + if ((cpu_logical_map(cpu) % cores) == 0) { eiointc_enable();
for (i = 0; i < VEC_COUNT / 32; i++) { @@ -167,7 +181,7 @@ static int eiointc_router_init(unsigned int cpu) for (i = 0; i < VEC_COUNT / 4; i++) { /* Route to Node-0 Core-0 */ if (index == 0) - bit = BIT(cpu_logical_map(0)); + bit = (cpu_has_hypervisor ? cpu_logical_map(0) : BIT(cpu_logical_map(0))); else bit = (eiointc_priv[index]->node << 4) | 1;