From bcd20c588742b33063b96970f63111bd0a66af63 Mon Sep 17 00:00:00 2001 From: Xianglai Li Date: Sat, 8 Mar 2025 17:17:51 +0800 Subject: [PATCH 1/4] anolis: LoongArch: KVM: Reload guest CSR registers after S4 ANBZ: #19753 On host HW guest CSR registers are lost after suspend and resume operation. Since last_vcpu of boot CPU still records latest vCPU pointer so that guest CSR register skips to reload when boot CPU resumes and vCPU is scheduled. Here last_vcpu is cleared so that guest CSR registers will reload from scheduled vCPU context after suspend and resume. Signed-off-by: Bibo Mao Signed-off-by: Xianglai Li Link: https://gitee.com/anolis/cloud-kernel/pulls/4927 --- arch/loongarch/kvm/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/loongarch/kvm/main.c b/arch/loongarch/kvm/main.c index 5f0ddf239352..ef2bad612c00 100644 --- a/arch/loongarch/kvm/main.c +++ b/arch/loongarch/kvm/main.c @@ -314,6 +314,12 @@ int kvm_arch_hardware_enable(void) kvm_debug("GCFG:%lx GSTAT:%lx GINTC:%lx GTLBC:%lx", read_csr_gcfg(), read_csr_gstat(), read_csr_gintc(), read_csr_gtlbc()); + /* + * HW Guest CSR registers are lost after CPU suspend and resume. + * Clear last_vcpu so that Guest CSR registers forced to reload + * from vCPU SW state + */ + this_cpu_ptr(vmcs)->last_vcpu = NULL; return 0; } -- Gitee From b44a5f80cd93656df1fdd6d4b105a686bdf6ee9c Mon Sep 17 00:00:00 2001 From: Xianglai Li Date: Sat, 8 Mar 2025 17:23:07 +0800 Subject: [PATCH 2/4] anolis: LoongArch: KVM: Add interrupt checking with Loongson AVEC ANBZ: #19753 There is newly added macro INT_AVEC with CSR ESTAT register, which is bit 14 used for Loongson AVEC support. AVEC interrupt status bit 14 is supported with macro CSR_ESTAT_IS, here replace hardcoded value 0x1fff with macro CSR_ESTAT_IS so that AVEC interrupt status is supported by KVM also. Signed-off-by: Bibo Mao Signed-off-by: Xianglai Li Link: https://gitee.com/anolis/cloud-kernel/pulls/4927 --- arch/loongarch/kvm/vcpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c index 8d386a6c707b..ad0fc6b2279c 100644 --- a/arch/loongarch/kvm/vcpu.c +++ b/arch/loongarch/kvm/vcpu.c @@ -309,7 +309,7 @@ static int kvm_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu) { int ret = RESUME_GUEST; unsigned long estat = vcpu->arch.host_estat; - u32 intr = estat & 0x1fff; /* Ignore NMI */ + u32 intr = estat & CSR_ESTAT_IS; u32 ecode = (estat & CSR_ESTAT_EXC) >> CSR_ESTAT_EXC_SHIFT; vcpu->mode = OUTSIDE_GUEST_MODE; -- Gitee From 6301f42e05ba9598763136cf42cd5dc0da92397a Mon Sep 17 00:00:00 2001 From: Xianglai Li Date: Fri, 21 Mar 2025 11:05:05 +0800 Subject: [PATCH 3/4] anolis: LoongArch: Revert "LoongArch: Fix cpu hotplug issue" ANBZ: #19753 Upstream kernel community has to solve this problem. This patch also causes other problems. When cpus on node0 are started on the physical machine but cpus on node1 are not started on the physical machine, devices on node1 fail to alloc memory space. In this case, roll back this patch, Then apply the upstream scheme. Signed-off-by: Xianglai Li Link: https://gitee.com/anolis/cloud-kernel/pulls/4927 --- arch/loongarch/include/asm/smp.h | 3 -- arch/loongarch/kernel/acpi.c | 24 ++++++---------- arch/loongarch/kernel/setup.c | 47 -------------------------------- arch/loongarch/kernel/smp.c | 9 +++--- 4 files changed, 13 insertions(+), 70 deletions(-) diff --git a/arch/loongarch/include/asm/smp.h b/arch/loongarch/include/asm/smp.h index cc232901e4dd..630e5ebec21c 100644 --- a/arch/loongarch/include/asm/smp.h +++ b/arch/loongarch/include/asm/smp.h @@ -102,7 +102,4 @@ static inline void __cpu_die(unsigned int cpu) } #endif -int topo_add_cpu(int physid); -int topo_get_cpu(int physid); - #endif /* __ASM_SMP_H */ diff --git a/arch/loongarch/kernel/acpi.c b/arch/loongarch/kernel/acpi.c index 17dc28821a9d..58819b017ba8 100644 --- a/arch/loongarch/kernel/acpi.c +++ b/arch/loongarch/kernel/acpi.c @@ -71,10 +71,10 @@ int set_processor_mask(u32 id, u32 flags) return -ENODEV; } - - cpu = topo_add_cpu(cpuid); - if (cpu < 0) - return -EEXIST; + if (cpuid == loongson_sysconf.boot_cpu_id) + cpu = 0; + else + cpu = cpumask_next_zero(-1, cpu_present_mask); if (flags & ACPI_MADT_ENABLED) { num_processors++; @@ -197,6 +197,8 @@ void __init acpi_boot_table_init(void) goto fdt_earlycon; } + loongson_sysconf.boot_cpu_id = read_csr_cpuid(); + /* * Process the Multiple APIC Description Table (MADT), if present */ @@ -246,7 +248,7 @@ void __init numa_set_distance(int from, int to, int distance) void __init acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) { - int pxm, node, cpu; + int pxm, node; if (srat_disabled()) return; @@ -275,11 +277,6 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa) return; } - cpu = topo_get_cpu(pa->apic_id); - /* Check whether apic_id exists in MADT table */ - if (cpu < 0) - return; - early_numa_add_cpu(pa->apic_id, node); set_cpuid_to_node(pa->apic_id, node); @@ -318,17 +315,12 @@ int acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, u32 acpi_id, int *pcpu { int cpu; - cpu = topo_get_cpu(physid); - /* Check whether apic_id exists in MADT table */ + cpu = set_processor_mask(physid, ACPI_MADT_ENABLED); if (cpu < 0) { pr_info(PREFIX "Unable to map lapic to logical cpu number\n"); return cpu; } - num_processors++; - set_cpu_present(cpu, true); - __cpu_number_map[physid] = cpu; - __cpu_logical_map[cpu] = physid; acpi_map_cpu2node(handle, cpu, physid); *pcpu = cpu; diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index 352d362c901b..f53889dd6182 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -72,8 +72,6 @@ EXPORT_SYMBOL(cpu_data); struct loongson_board_info b_info; static const char dmi_empty_string[] = " "; -static int possible_cpus; -static bool bsp_added; /* * Setup information @@ -378,50 +376,6 @@ static void __init bootcmdline_init(char **cmdline_p) *cmdline_p = boot_command_line; } -int topo_get_cpu(int physid) -{ - int i; - - for (i = 0; i < possible_cpus; i++) - if (cpu_logical_map(i) == physid) - break; - - if (i == possible_cpus) - return -ENOENT; - - return i; -} - -int topo_add_cpu(int physid) -{ - int cpu; - - if (!bsp_added && (physid == loongson_sysconf.boot_cpu_id)) { - bsp_added = true; - return 0; - } - - cpu = topo_get_cpu(physid); - if (cpu >= 0) { - pr_warn("Adding duplicated physical cpuid 0x%x\n", physid); - return -EEXIST; - } - - if (possible_cpus >= nr_cpu_ids) - return -ERANGE; - - __cpu_logical_map[possible_cpus] = physid; - cpu = possible_cpus++; - return cpu; -} - -static void __init topo_init(void) -{ - loongson_sysconf.boot_cpu_id = read_csr_cpuid(); - __cpu_logical_map[0] = loongson_sysconf.boot_cpu_id; - possible_cpus++; -} - static void __init writecombine_detect(void) { u64 cpuname; @@ -446,7 +400,6 @@ void __init platform_init(void) { arch_reserve_vmcore(); arch_parse_crashkernel(); - topo_init(); #ifdef CONFIG_ACPI_TABLE_UPGRADE acpi_table_upgrade(); diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index 5d02bf5126b7..7f693a24687d 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -291,9 +291,10 @@ static void __init fdt_smp_setup(void) if (cpuid >= nr_cpu_ids) continue; - cpu = topo_add_cpu(cpuid); - if (cpu < 0) - continue; + if (cpuid == loongson_sysconf.boot_cpu_id) + cpu = 0; + else + cpu = cpumask_next_zero(-1, cpu_present_mask); num_processors++; set_cpu_possible(cpu, true); @@ -301,7 +302,7 @@ static void __init fdt_smp_setup(void) __cpu_number_map[cpuid] = cpu; __cpu_logical_map[cpu] = cpuid; - early_numa_add_cpu(cpuid, 0); + early_numa_add_cpu(cpu, 0); set_cpuid_to_node(cpuid, 0); } -- Gitee From f7bcce59976f9dad0eee1ca1f19579e782646160 Mon Sep 17 00:00:00 2001 From: Xianglai Li Date: Tue, 25 Mar 2025 09:02:02 +0800 Subject: [PATCH 4/4] anolis: LoongArch: KVM: Repair the restart pressure test virtual machine hang dead problem ANBZ: #19753 After the virtual restart, exintc does not correctly clear the estat register and qemu does not clear the estat register. Estat data sent from qemu is merged instead of overwritten on kvm. In order to solve this problem, the following changes were made to this patch: 1.exintc correctly clears zeros when the VM restarts 2. estat on the qemu side clears ESTAT correctly when the VM restarts 3. When the estat register data on the qemu side is sent to the kvm, the data needs to be overwritten instead of merged Signed-off-by: Xianglai Li Link: https://gitee.com/anolis/cloud-kernel/pulls/4927 --- arch/loongarch/kvm/intc/extioi.c | 2 +- arch/loongarch/kvm/intc/ipi.c | 2 +- arch/loongarch/kvm/intc/pch_pic.c | 2 +- arch/loongarch/kvm/vcpu.c | 7 +++++++ 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/loongarch/kvm/intc/extioi.c b/arch/loongarch/kvm/intc/extioi.c index 6dd90145a511..801ac861c876 100644 --- a/arch/loongarch/kvm/intc/extioi.c +++ b/arch/loongarch/kvm/intc/extioi.c @@ -938,7 +938,7 @@ int kvm_loongarch_reset_extioi(struct kvm *kvm) { struct loongarch_extioi *extioi = kvm->arch.extioi; unsigned long flags; - u8 offset, size; + unsigned long offset, size; u8 *pstart; if (!extioi) diff --git a/arch/loongarch/kvm/intc/ipi.c b/arch/loongarch/kvm/intc/ipi.c index 2638f58bcf81..4459ec42eb40 100644 --- a/arch/loongarch/kvm/intc/ipi.c +++ b/arch/loongarch/kvm/intc/ipi.c @@ -540,7 +540,7 @@ int kvm_loongarch_register_ipi_device(void) int kvm_loongarch_reset_ipi(struct kvm_vcpu *vcpu) { struct ipi_state *s = &vcpu->arch.ipi_state; - u8 offset, size; + unsigned long offset, size; u8 *pstart; if (!s) diff --git a/arch/loongarch/kvm/intc/pch_pic.c b/arch/loongarch/kvm/intc/pch_pic.c index 6726f718e16b..9f287b419910 100644 --- a/arch/loongarch/kvm/intc/pch_pic.c +++ b/arch/loongarch/kvm/intc/pch_pic.c @@ -542,7 +542,7 @@ int kvm_loongarch_register_pch_pic_device(void) int kvm_loongarch_reset_pch(struct kvm *kvm) { struct loongarch_pch_pic *s = kvm->arch.pch_pic; - u8 offset, size; + unsigned long offset, size; u8 *pstart; if (!s) diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c index ad0fc6b2279c..532138bd049f 100644 --- a/arch/loongarch/kvm/vcpu.c +++ b/arch/loongarch/kvm/vcpu.c @@ -874,7 +874,14 @@ static int kvm_set_one_reg(struct kvm_vcpu *vcpu, kvm_loongarch_reset_extioi(vcpu->kvm); kvm_loongarch_reset_pch(vcpu->kvm); } + kvm_loongarch_reset_ipi(vcpu); + /* + * When the vcpu resets, clear the ESTAT and GINTC registers, + * and clear other CSR registers through the _kvm_set_csr register. + */ + kvm_write_sw_gcsr(vcpu->arch.csr, LOONGARCH_CSR_GINTC, 0); + kvm_write_sw_gcsr(vcpu->arch.csr, LOONGARCH_CSR_ESTAT, 0); memset(&vcpu->arch.irq_pending, 0, sizeof(vcpu->arch.irq_pending)); memset(&vcpu->arch.irq_clear, 0, sizeof(vcpu->arch.irq_clear)); break; -- Gitee