From c31f6641024ec506bf40328462428db943913962 Mon Sep 17 00:00:00 2001 From: liuyun Date: Mon, 13 Mar 2023 11:38:06 +0800 Subject: [PATCH] LoongArch: Fix virtual machine startup error LoongArch inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6MUZX -------------------------------- Signed-off-by: liuyun Signed-off-by: maobibo Change-Id: Icf291821c13d073c3d22fbb044ff32d7c77f677f --- arch/loongarch/include/asm/irq.h | 1 + arch/loongarch/include/asm/loongarch.h | 5 ++++ arch/loongarch/kernel/legacy_boot.c | 11 ++++--- drivers/irqchip/irq-loongson-eiointc.c | 40 +++++++++++++++++--------- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h index f3e3ba1cc843..31be19474288 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 7ead7a1f8aa0..33a8fa446ba9 100644 --- a/arch/loongarch/include/asm/loongarch.h +++ b/arch/loongarch/include/asm/loongarch.h @@ -275,6 +275,11 @@ static __always_inline u64 iocsr_read64(u32 reg) return __iocsrrd_d(reg); } +static __always_inline void iocsr_write8(u8 val, u32 reg) +{ + __iocsrwr_b(val, reg); +} + static __always_inline void iocsr_write32(u32 val, u32 reg) { __iocsrwr_w(val, reg); diff --git a/arch/loongarch/kernel/legacy_boot.c b/arch/loongarch/kernel/legacy_boot.c index 99b69173460d..67f5ef66dcfd 100644 --- a/arch/loongarch/kernel/legacy_boot.c +++ b/arch/loongarch/kernel/legacy_boot.c @@ -278,7 +278,7 @@ int setup_legacy_IRQ(void) printk("Pic domain error!\n"); return -1; } - if (pic_domain) + if (pic_domain && !cpu_has_hypervisor) pch_lpc_acpi_init(pic_domain, acpi_pchlpc); return 0; @@ -530,9 +530,12 @@ unsigned long legacy_boot_init(unsigned long argc, unsigned long cmdptr, unsigne 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("Fatal error, bpi ver BONE!\n"); + else + panic("Fatal error, bpi ver BONE!\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 ca32e73bb924..a4836666e42f 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -58,7 +58,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) @@ -89,6 +91,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; @@ -111,16 +118,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)); @@ -147,13 +160,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++) { @@ -170,7 +184,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; -- GitLab