From bca773678bbc38c1aad00955296349ca2bf883f1 Mon Sep 17 00:00:00 2001 From: Yanteng Si Date: Thu, 25 Jul 2024 16:29:05 +0800 Subject: [PATCH 1/6] Revert "irqchip/loongson-eiointc: fix gsi register error" This reverts commit 16b46d963210d7dbd0bfc9d3a46c99681756414a. --- arch/loongarch/include/asm/numa.h | 1 - drivers/irqchip/irq-loongson-eiointc.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/loongarch/include/asm/numa.h b/arch/loongarch/include/asm/numa.h index ad288cbbff83d..b5f9de9f102e4 100644 --- a/arch/loongarch/include/asm/numa.h +++ b/arch/loongarch/include/asm/numa.h @@ -12,7 +12,6 @@ #include #define NODE_ADDRSPACE_SHIFT 44 -#define NODES_PER_FLATMODE_NODE 4 #define pa_to_nid(addr) (((addr) & 0xf00000000000) >> NODE_ADDRSPACE_SHIFT) #define nid_to_addrbase(nid) (_ULCAST_(nid) << NODE_ADDRSPACE_SHIFT) diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index 488951a740cde..c5c26b8e8d0c5 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -375,7 +375,7 @@ int __init pch_msi_parse_madt(union acpi_subtable_headers *header, int node; if (cpu_has_flatmode) - node = eiointc_priv[nr_pics - 1]->node / NODES_PER_FLATMODE_NODE; + node = cpu_to_node(eiointc_priv[nr_pics - 1]->node * CORES_PER_EIO_NODE); else node = eiointc_priv[nr_pics - 1]->node; @@ -478,7 +478,7 @@ int __init eiointc_acpi_init(struct irq_domain *parent, goto out_free_handle; if (cpu_has_flatmode) - node = acpi_eiointc->node / NODES_PER_FLATMODE_NODE; + node = cpu_to_node(acpi_eiointc->node * CORES_PER_EIO_NODE); else node = acpi_eiointc->node; acpi_set_vec_parent(node, priv->eiointc_domain, pch_group); From cea76560208b9e760cff7612b07c8aaeb6a3bc6c Mon Sep 17 00:00:00 2001 From: Yanteng Si Date: Thu, 25 Jul 2024 11:41:13 +0800 Subject: [PATCH 2/6] irqchip/loongson-eiointc: Use early_cpu_to_node() instead of cpu_to_node() Multi-bridge machines required that all eiointc controllers in the system are initialized, otherwise the system does not boot. The initialization happens on the boot CPU during early boot and relies on cpu_to_node() for identifying the individual nodes. That works when the number of possible CPUs is large enough, but with a command line limit, e.g. "nr_cpus=$N" for kdump, but fails when the CPUs of the secondary nodes are not covered. During early ACPI enumeration all CPU to node mappings are recorded up to CONFIG_NR_CPUS. These are accessible via early_cpu_to_node() even in the case that "nr_cpus=N" truncates the number of possible CPUs and only provides the possible CPUs via cpu_to_node() translation. Change the node lookup in the driver to use early_cpu_to_node() so that even with a limitation on the number of possible CPUs all eointc instances are initialized. This can't obviously cure the case where CONFIG_NR_CPUS is too small. [ tglx: Massaged changelog ] Fixes: 64cc451e45e1 ("irqchip/loongson-eiointc: Fix incorrect use of acpi_get_vec_parent") Signed-off-by: Huacai Chen Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20240623034113.1808727-1-chenhuacai@loongson.cn Signed-off-by: Yanteng Si --- drivers/irqchip/irq-loongson-eiointc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/irqchip/irq-loongson-eiointc.c b/drivers/irqchip/irq-loongson-eiointc.c index c5c26b8e8d0c5..5c5462681c03c 100644 --- a/drivers/irqchip/irq-loongson-eiointc.c +++ b/drivers/irqchip/irq-loongson-eiointc.c @@ -15,6 +15,7 @@ #include #include #include +#include #define EIOINTC_REG_NODEMAP 0x14a0 #define EIOINTC_REG_IPMAP 0x14c0 @@ -375,7 +376,7 @@ int __init pch_msi_parse_madt(union acpi_subtable_headers *header, int node; if (cpu_has_flatmode) - node = cpu_to_node(eiointc_priv[nr_pics - 1]->node * CORES_PER_EIO_NODE); + node = early_cpu_to_node(eiointc_priv[nr_pics - 1]->node * CORES_PER_EIO_NODE); else node = eiointc_priv[nr_pics - 1]->node; @@ -478,7 +479,7 @@ int __init eiointc_acpi_init(struct irq_domain *parent, goto out_free_handle; if (cpu_has_flatmode) - node = cpu_to_node(acpi_eiointc->node * CORES_PER_EIO_NODE); + node = early_cpu_to_node(acpi_eiointc->node * CORES_PER_EIO_NODE); else node = acpi_eiointc->node; acpi_set_vec_parent(node, priv->eiointc_domain, pch_group); From c443214b4c347e7134b7a925fee56e97164b8a40 Mon Sep 17 00:00:00 2001 From: Yanteng Si Date: Thu, 25 Jul 2024 22:40:58 +0800 Subject: [PATCH 3/6] LoongArch: Always enumerate MADT and setup logical-physical CPU mapping Some drivers want to use cpu_logical_map(), early_cpu_to_node() and some other CPU mapping APIs, even if we use "nr_cpus=1" to hard limit the CPU number. This is strongly required for the multi-bridges machines. Currently, we stop parsing the MADT if the nr_cpus limit is reached, but to achieve the above goal we should always enumerate the MADT table and setup logical-physical CPU mapping whether there is a nr_cpus limit. Rework the MADT enumeration: 1. Define a flag "cpu_enumerated" to distinguish the first enumeration (cpu_enumerated=0) and the physical hotplug case (cpu_enumerated=1) for set_processor_mask(). 2. If cpu_enumerated=0, stop parsing only when NR_CPUS limit is reached, so we can setup logical-physical CPU mapping; if cpu_enumerated=1, stop parsing when nr_cpu_ids limit is reached, so we can avoid some runtime bugs. Once logical-physical CPU mapping is setup, we will let cpu_enumerated=1. 3. Use find_first_zero_bit() instead of cpumask_next_zero() to find the next zero bit (free logical CPU id) in the cpu_present_mask, because cpumask_next_zero() will stop at nr_cpu_ids. 4. Only touch cpu_possible_mask if cpu_enumerated=0, this is in order to avoid some potential crashes, because cpu_possible_mask is marked as __ro_after_init. 5. In prefill_possible_map(), clear cpu_present_mask bits greater than nr_cpu_ids, in order to avoid a CPU be "present" but not "possible". Signed-off-by: Huacai Chen Signed-off-by: Yanteng Si --- arch/loongarch/kernel/acpi.c | 22 ++++++++++++++++------ arch/loongarch/kernel/setup.c | 4 +++- arch/loongarch/kernel/smp.c | 7 +++---- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/arch/loongarch/kernel/acpi.c b/arch/loongarch/kernel/acpi.c index 58819b017ba83..a8fdb8dafa3ba 100644 --- a/arch/loongarch/kernel/acpi.c +++ b/arch/loongarch/kernel/acpi.c @@ -58,15 +58,22 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) return ioremap_cache(phys, size); } +static int cpu_enumerated = 0; + #ifdef CONFIG_SMP int set_processor_mask(u32 id, u32 flags) { - + int nr_cpus; int cpu, cpuid = id; - if (num_processors >= nr_cpu_ids) { - pr_warn(PREFIX "nr_cpus/possible_cpus limit of %i reached." - " processor 0x%x ignored.\n", nr_cpu_ids, cpuid); + if (!cpu_enumerated) + nr_cpus = NR_CPUS; + else + nr_cpus = nr_cpu_ids; + + if (num_processors >= nr_cpus) { + pr_warn(PREFIX "nr_cpus limit of %i reached." + " processor 0x%x ignored.\n", nr_cpus, cpuid); return -ENODEV; @@ -74,11 +81,13 @@ int set_processor_mask(u32 id, u32 flags) if (cpuid == loongson_sysconf.boot_cpu_id) cpu = 0; else - cpu = cpumask_next_zero(-1, cpu_present_mask); + cpu = find_first_zero_bit(cpumask_bits(cpu_present_mask), NR_CPUS); + + if (!cpu_enumerated) + set_cpu_possible(cpu, true); if (flags & ACPI_MADT_ENABLED) { num_processors++; - set_cpu_possible(cpu, true); set_cpu_present(cpu, true); __cpu_number_map[cpuid] = cpu; __cpu_logical_map[cpu] = cpuid; @@ -143,6 +152,7 @@ static void __init acpi_process_madt(void) acpi_table_parse_madt(ACPI_MADT_TYPE_EIO_PIC, acpi_parse_eio_master, MAX_IO_PICS); + cpu_enumerated = 1; loongson_sysconf.nr_cpus = num_processors; } diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index adee6b984b68c..4f74200a99223 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -613,8 +613,10 @@ static void __init prefill_possible_map(void) for (i = 0; i < possible; i++) set_cpu_possible(i, true); - for (; i < NR_CPUS; i++) + for (; i < NR_CPUS; i++) { + set_cpu_present(i, false); set_cpu_possible(i, false); + } set_nr_cpu_ids(possible); } diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index 881f6ec02b2f2..e3a75b51f4b3b 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -282,11 +282,10 @@ static void __init fdt_smp_setup(void) if (cpuid >= nr_cpu_ids) continue; - if (cpuid == loongson_sysconf.boot_cpu_id) { + if (cpuid == loongson_sysconf.boot_cpu_id) cpu = 0; - } else { - cpu = cpumask_next_zero(-1, cpu_present_mask); - } + else + cpu = find_first_zero_bit(cpumask_bits(cpu_present_mask), NR_CPUS); num_processors++; set_cpu_possible(cpu, true); From cfd73317785c9d53647614178a8540cdc9011da1 Mon Sep 17 00:00:00 2001 From: Yanteng Si Date: Thu, 25 Jul 2024 22:41:06 +0800 Subject: [PATCH 4/6] LoongArch: Automatically disable KASLR for hibernation Hibernation assumes the memory layout after resume be the same as that before sleep, so it expects the kernel is loaded at the same position. To achieve this goal we automatically disable KASLR if user explicitly requests hibernation via the "resume=" command line. Since "nohibernate" and "noresume" have higher priorities than "resume=", we only disable KASLR if there is no "nohibernate" and "noresume". Signed-off-by: Huacai Chen Signed-off-by: Yanteng Si --- arch/loongarch/kernel/relocate.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/arch/loongarch/kernel/relocate.c b/arch/loongarch/kernel/relocate.c index aaa27823ea29d..1e6220e7916e0 100644 --- a/arch/loongarch/kernel/relocate.c +++ b/arch/loongarch/kernel/relocate.c @@ -124,6 +124,32 @@ static inline __init bool kaslr_disabled(void) if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) return true; +#ifdef CONFIG_HIBERNATION + str = strstr(builtin_cmdline, "nohibernate"); + if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) + return false; + + str = strstr(boot_command_line, "nohibernate"); + if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) + return false; + + str = strstr(builtin_cmdline, "noresume"); + if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) + return false; + + str = strstr(boot_command_line, "noresume"); + if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) + return false; + + str = strstr(builtin_cmdline, "resume="); + if (str == builtin_cmdline || (str > builtin_cmdline && *(str - 1) == ' ')) + return true; + + str = strstr(boot_command_line, "resume="); + if (str == boot_command_line || (str > boot_command_line && *(str - 1) == ' ')) + return true; +#endif + return false; } From ed88c1ea8036729960c49be8603e9009727c04d6 Mon Sep 17 00:00:00 2001 From: Yanteng Si Date: Thu, 25 Jul 2024 14:59:54 +0800 Subject: [PATCH 5/6] loongarch: configs: Configure degbuginfo Configure degbuginfo so that crash can be resolved Signed-off-by: duanchenghao Signed-off-by: Yanteng Si --- arch/loongarch/configs/loongson3_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/loongarch/configs/loongson3_defconfig b/arch/loongarch/configs/loongson3_defconfig index 98475952cb905..9169eba0517f1 100644 --- a/arch/loongarch/configs/loongson3_defconfig +++ b/arch/loongarch/configs/loongson3_defconfig @@ -2187,7 +2187,7 @@ CONFIG_PRINTK_TIME=y CONFIG_PRINTK_CALLER=y CONFIG_BOOT_PRINTK_DELAY=y CONFIG_DYNAMIC_DEBUG=y -CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y +CONFIG_DEBUG_INFO_DWARF4=y CONFIG_DEBUG_INFO_BTF=y CONFIG_FRAME_WARN=4096 CONFIG_STRIP_ASM_SYMS=y From 4f52e0b1c840717aee03ad2e00997c1f3c275e0d Mon Sep 17 00:00:00 2001 From: Yanteng Si Date: Thu, 25 Jul 2024 09:26:18 +0800 Subject: [PATCH 6/6] LoongArch: fix HT RX INT TRANS register not initialized When we boot Loongson-TC542F0 3C5000 4-Node dual bridge machine, boot failed with no root partition found. The reason is HT RX INT TRANS register not initialized, So we initialize it. Fixes: db5bb24abc8d ("LoongArch: Old BPI compatibility") Reported-by: Qianwen Li Signed-off-by: Hongchen Zhang Signed-off-by: Yanteng Si --- arch/loongarch/kernel/irq.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/loongarch/kernel/irq.c b/arch/loongarch/kernel/irq.c index 06dca97fbe934..c8754a44fd9f1 100644 --- a/arch/loongarch/kernel/irq.c +++ b/arch/loongarch/kernel/irq.c @@ -91,6 +91,13 @@ void __init init_IRQ(void) int i, ret; unsigned int order = get_order(IRQ_STACK_SIZE); struct page *page; + unsigned long node; + + if (!acpi_gbl_reduced_hardware) { + for_each_node(node) + writel(0x40000000 | (node << 12), + (volatile void __iomem *)(0x80000efdfb000274UL + (node<<44))); + } clear_csr_ecfg(ECFG0_IM); clear_csr_estat(ESTATF_IP);