From ae1e2bef350c0ad56104259985bcce46cdfbdf20 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 9 Sep 2025 16:40:49 +0800 Subject: [PATCH 01/19] sw64: kvm: add the C4 kvm_regs structure to uapi kvm.h Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- This patch adds the definition of struct kvm_regs to uapi kvm.h to expose it to userspace. Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/uapi/asm/kvm.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/sw_64/include/uapi/asm/kvm.h b/arch/sw_64/include/uapi/asm/kvm.h index e43f382156f65..855858e5beca9 100644 --- a/arch/sw_64/include/uapi/asm/kvm.h +++ b/arch/sw_64/include/uapi/asm/kvm.h @@ -2,6 +2,8 @@ #ifndef _UAPI_ASM_SW64_KVM_H #define _UAPI_ASM_SW64_KVM_H +#include + /* * KVM SW specific structures and definitions. */ @@ -22,6 +24,20 @@ enum SW64_KVM_IRQ { #define KVM_NR_IRQCHIPS 1 +#ifndef __KERNEL__ +struct kvm_regs { + union { + struct user_pt_regs regs; + struct { + unsigned long r[31]; + unsigned long pc; + unsigned long ps; + }; + }; + struct user_fpsimd_state fpstate; +}; +#endif + /* * for KVM_GET_FPU and KVM_SET_FPU */ -- Gitee From 6708ca11912457afd8b47f0f6d65d05f50b49dc8 Mon Sep 17 00:00:00 2001 From: Gu Yuchen Date: Mon, 8 Sep 2025 12:33:59 +0800 Subject: [PATCH 02/19] sw64: fix unresolved reference error when close pci Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- The pcie_save and pcie_restore functions depend on CONFIG_PCI option, the subfunctions they call are only compiled when CONFIG_PCI option is enabled. This commit fixes the issue. Signed-off-by: Gu Yuchen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/chip_setup.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/sw_64/kernel/chip_setup.c b/arch/sw_64/kernel/chip_setup.c index df98e141b14f4..d4e5b1736bc14 100644 --- a/arch/sw_64/kernel/chip_setup.c +++ b/arch/sw_64/kernel/chip_setup.c @@ -90,6 +90,7 @@ static void i2c_srst(void) writeq(0x1, spbu_base + OFFSET_I2C2_SRST_L); } +#ifdef CONFIG_PCI static void pcie_save(void) { struct pci_controller *hose; @@ -130,6 +131,17 @@ static void pcie_restore(void) } } +#else +static void pcie_save(void) +{ + +} + +static void pcie_restore(void) +{ + +} +#endif static unsigned long saved_dvc_int, saved_long_time; -- Gitee From 36804969a7c37cba4277aac2cdeaa8ae2434b5fb Mon Sep 17 00:00:00 2001 From: Gao Chen Date: Wed, 24 Sep 2025 15:24:30 +0800 Subject: [PATCH 03/19] sw64: revert ioremap() to __va() in ioport_map() Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- Revert ioremap() to __va() in ioport_map() since devices like UHCI call it during interrupts where ioremap() is forbidden. Signed-off-by: Gao Chen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/lib/iomap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/sw_64/lib/iomap.c b/arch/sw_64/lib/iomap.c index 8377313e1a719..ee8607fa95ecd 100644 --- a/arch/sw_64/lib/iomap.c +++ b/arch/sw_64/lib/iomap.c @@ -427,8 +427,8 @@ EXPORT_SYMBOL(_memset_c_io); void __iomem *ioport_map(unsigned long port, unsigned int size) { if (port >= 0x100000) - return ioremap(port, size); + return __va(port); - return ioremap((port << legacy_io_shift) | legacy_io_base, size); + return __va((port << legacy_io_shift) | legacy_io_base); } EXPORT_SYMBOL(ioport_map); -- Gitee From ecc31d41f3aabdeb2f5be286b3d157eb590050c6 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Mon, 14 Apr 2025 17:06:03 +0800 Subject: [PATCH 04/19] sw64: use orig_r0 as syscall nr Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- Use orig_r0 as syscall number to make sure we can get the correct number after syscall_set_return_value() which modifies the value of regs[0]. For backward compatibility, any modifications made to $0 and $19 at syscall entry are also reflected on orig_r0 and orig_r19. If users want to skip syscall and set return value directly at syscall entry, they can use PTRACE_POKEUSR to set $0 and orig_r0 first, then use PTRACE_SETREGSET to set orig_r0 only (note type NT_SW64_SYSTEM_CALL). Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/syscall.h | 2 +- arch/sw_64/kernel/ptrace.c | 22 ++++++++++++++++++---- arch/sw_64/kernel/sys_sw64.c | 4 +--- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/arch/sw_64/include/asm/syscall.h b/arch/sw_64/include/asm/syscall.h index a821bf68be164..33b4101a81e46 100644 --- a/arch/sw_64/include/asm/syscall.h +++ b/arch/sw_64/include/asm/syscall.h @@ -13,7 +13,7 @@ extern syscall_fn_t sys_call_table[]; static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) { - return regs->regs[0]; + return regs->orig_r0; } static inline long diff --git a/arch/sw_64/kernel/ptrace.c b/arch/sw_64/kernel/ptrace.c index 15d05e2a95073..cad0713d3d3c4 100644 --- a/arch/sw_64/kernel/ptrace.c +++ b/arch/sw_64/kernel/ptrace.c @@ -148,6 +148,20 @@ put_reg(struct task_struct *task, unsigned long regno, unsigned long data) return PTR_ERR(addr); else { *addr = data; + + /* + * Any modifications made to $0 and $19 at syscall entry + * should also be reflected on orig_r0 and orig_r19. + * + * See syscall_set() for how to modify orig_r0 only. + */ + if (task->ptrace_message == PTRACE_EVENTMSG_SYSCALL_ENTRY) { + if (regno == PT_REG_BASE) + task_pt_regs(task)->orig_r0 = data; + if (regno == (PT_REG_BASE + 19)) + task_pt_regs(task)->orig_r19 = data; + } + return 0; } } @@ -425,7 +439,6 @@ long arch_ptrace(struct task_struct *child, long request, asmlinkage unsigned long syscall_trace_enter(void) { - unsigned long ret = 0; struct pt_regs *regs = current_pt_regs(); if (test_thread_flag(TIF_SYSCALL_TRACE) && @@ -439,9 +452,10 @@ asmlinkage unsigned long syscall_trace_enter(void) #endif if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) - trace_sys_enter(regs, regs->regs[0]); - audit_syscall_entry(regs->regs[0], regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]); - return ret ?: regs->regs[0]; + trace_sys_enter(regs, regs->orig_r0); + audit_syscall_entry(regs->orig_r0, regs->regs[16], + regs->regs[17], regs->regs[18], regs->regs[19]); + return regs->orig_r0; } asmlinkage void diff --git a/arch/sw_64/kernel/sys_sw64.c b/arch/sw_64/kernel/sys_sw64.c index 1397d86ac7a20..09289be850fcf 100644 --- a/arch/sw_64/kernel/sys_sw64.c +++ b/arch/sw_64/kernel/sys_sw64.c @@ -346,7 +346,7 @@ asmlinkage void noinstr do_entSys(struct pt_regs *regs) regs->orig_r0 = regs->regs[0]; regs->orig_r19 = regs->regs[19]; - nr = regs->regs[0]; + nr = regs->orig_r0; if (ti_flags & _TIF_SYSCALL_WORK) { nr = syscall_trace_enter(); @@ -369,8 +369,6 @@ asmlinkage void noinstr do_entSys(struct pt_regs *regs) syscall_set_return_value(current, regs, -ENOSYS, 0); if (nr == NO_SYSCALL) goto syscall_out; - regs->orig_r0 = regs->regs[0]; - regs->orig_r19 = regs->regs[19]; } if (nr < __NR_syscalls) { -- Gitee From 3e3bc454edecde96261aeddf61e7069f6d9fdc1b Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Mon, 29 Sep 2025 07:08:24 +0000 Subject: [PATCH 05/19] sw64: msi: fix affinity change of managed irq Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- If a managed irq's affinity does not intersect with cpu_online_mask, it should be disabled instead of migrating into one of the online cpus. This patch add a check to stop affinity mask of a managed irq from changing into cpu_online_mask. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/irqchip/irq-sunway-msi-v2.c | 3 +++ drivers/irqchip/irq-sunway-msi.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/irqchip/irq-sunway-msi-v2.c b/drivers/irqchip/irq-sunway-msi-v2.c index 119859b5551a1..b32c277c781f8 100644 --- a/drivers/irqchip/irq-sunway-msi-v2.c +++ b/drivers/irqchip/irq-sunway-msi-v2.c @@ -234,6 +234,9 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs, if (irqd_affinity_is_managed(irq_data)) { mask = irq_data_get_affinity_mask(irq_data); cpumask_and(&searchmask, mask, cpu_online_mask); + + if (cpumask_empty(&searchmask)) + return -EINVAL; } else { node = irq_data_get_node(irq_data); cpumask_copy(&searchmask, cpumask_of_node(node)); diff --git a/drivers/irqchip/irq-sunway-msi.c b/drivers/irqchip/irq-sunway-msi.c index 8c678c034c5a1..17be578d75b63 100644 --- a/drivers/irqchip/irq-sunway-msi.c +++ b/drivers/irqchip/irq-sunway-msi.c @@ -213,6 +213,9 @@ static int __assign_irq_vector(int virq, unsigned int nr_irqs, if (irqd_affinity_is_managed(irq_data)) { mask = irq_data_get_affinity_mask(irq_data); cpumask_and(&searchmask, mask, cpu_online_mask); + + if (cpumask_empty(&searchmask)) + return -EINVAL; } else { node = irq_data_get_node(irq_data); cpumask_copy(&searchmask, cpumask_of_node(node)); -- Gitee From 972a836d5997352041e74cb19a2af33d58ca8bd8 Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Mon, 22 Sep 2025 06:54:19 +0000 Subject: [PATCH 06/19] sw64: irqchip: update effective affinity for INTx Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- As CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK is selected, it is necessary to update effective affinity when setting affinity for INTx. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/irqchip/irq-sunway-pci-intx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/irqchip/irq-sunway-pci-intx.c b/drivers/irqchip/irq-sunway-pci-intx.c index 47a42776e736d..5b3393c26bde7 100644 --- a/drivers/irqchip/irq-sunway-pci-intx.c +++ b/drivers/irqchip/irq-sunway-pci-intx.c @@ -60,6 +60,7 @@ static int __assign_piu_intx_config(struct intx_chip_data *chip_data, unsigned int cpu; int thread, node, core, rcid; unsigned int i; + struct irq_data *irq_data; if (is_guest_or_emul()) return 0; @@ -89,6 +90,9 @@ static int __assign_piu_intx_config(struct intx_chip_data *chip_data, (i << PCI_INTXCONFIG_OFFSET)); chip_data->intxconfig[i] = intxconfig; } + irq_data = irq_get_irq_data(hose->int_irq); + irq_data_update_effective_affinity(irq_data, cpumask_of(cpu)); + return 0; } -- Gitee From dae8c0d687086df417590e4d8c0301360900ed5d Mon Sep 17 00:00:00 2001 From: Jing Li Date: Fri, 22 Aug 2025 09:07:31 +0800 Subject: [PATCH 07/19] sw64: powercap: avoid checking meaningless target freq Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- The target freq field is only meaningful when powercap is enabled and frequency limitation is required. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/platform/sw64/powercap.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/platform/sw64/powercap.c b/drivers/platform/sw64/powercap.c index 3f380ace56017..0bb62065065e5 100644 --- a/drivers/platform/sw64/powercap.c +++ b/drivers/platform/sw64/powercap.c @@ -243,6 +243,16 @@ static inline bool is_powercap_cpu_match(const struct sunway_powercap_cpu *data, return true; } +static inline bool is_powercap_enabled(const struct sunway_powercap_freq *freq) +{ + return !!(freq->flags & FREQ_FLAG_ENABLE); +} + +static inline bool is_powercap_no_limit(const struct sunway_powercap_freq *freq) +{ + return !!(freq->flags & FREQ_FLAG_FREE); +} + static int sunway_powercap_validate_freq(const struct sunway_powercap_freq *freq, struct sunway_powercap_ack *ack) { @@ -268,6 +278,10 @@ static int sunway_powercap_validate_freq(const struct sunway_powercap_freq *freq ack->flags |= ACK_FLAG_VALID_NODE; ack->flags |= ACK_FLAG_VALID_CORE; + /* Make sure that the target freq field is meaningful */ + if (!is_powercap_enabled(freq) || is_powercap_no_limit(freq)) + return 0; + if (cpufreq_frequency_table_get_index(policy, target_freq) < 0) { pr_err("invalid target freq %u\n", target_freq); return -EINVAL; @@ -284,16 +298,6 @@ static int sunway_powercap_validate_freq(const struct sunway_powercap_freq *freq return -EINVAL; } -static inline bool is_powercap_enabled(const struct sunway_powercap_freq *freq) -{ - return !!(freq->flags & FREQ_FLAG_ENABLE); -} - -static inline bool is_powercap_no_limit(const struct sunway_powercap_freq *freq) -{ - return !!(freq->flags & FREQ_FLAG_FREE); -} - static inline bool is_powercap_freq_data_terminate(const struct sunway_powercap_freq *freq) { -- Gitee From 81d73ef3b3ba62de0548074973645950349bc44d Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 18 Sep 2025 16:51:48 +0800 Subject: [PATCH 08/19] sw64: powercap: fix Kconfig dependency for SW64_POWERCAP Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- The function of Sunway powercap driver is built on the basis of Sunway cpufreq driver, so SW64_POWERCAP depends on SW64_CPUFREQ rather than the generic CPUFREQ. Furthermore, Sunway powercap driver will fail to link when CONFIG_IPMI_HANDLER=m, so directly select IPMI_HANDLER. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index cc1958c87ff3c..bcf17da4ee7c6 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -691,8 +691,9 @@ config ARCH_HIBERNATION_POSSIBLE config SW64_POWERCAP bool "Sunway powercap driver" + select IPMI_HANDLER select IPMI_SI - depends on SW64 && CPU_FREQ && ACPI && IPMI_HANDLER + depends on SW64_CPUFREQ && ACPI help This enables support for the sunway powercap driver based on BMC and IPMI system interface. -- Gitee From 3fef9e5795196b92ab06ed8abb2edc85c0e7a496 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 18 Sep 2025 17:08:38 +0800 Subject: [PATCH 09/19] sw64: powercap: increase the interval of polling mode Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- The polling interval is too small, resulting in excessive occupation of IPMI bandwidth, thus increasing the polling interval. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/platform/sw64/powercap.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/platform/sw64/powercap.c b/drivers/platform/sw64/powercap.c index 0bb62065065e5..61eef40952039 100644 --- a/drivers/platform/sw64/powercap.c +++ b/drivers/platform/sw64/powercap.c @@ -18,6 +18,8 @@ #define SUNWAY_POWERCAP_ACPI_NOTIFY_VALUE 0x84 +#define POLL_INTERVAL_UNIT_10MS 10 + enum sunway_powercap_version { SUNWAY_POWERCAP_V1 = 1, SUNWAY_POWERCAP_VERSION_MAX, @@ -531,7 +533,7 @@ static int sunway_powercap_setup_cfg(const struct sunway_powercap_cfg *cfg) driver_data.version = cfg->version; driver_data.mode = cfg->mode; - driver_data.poll_interval = cfg->poll_interval; + driver_data.poll_interval = cfg->poll_interval * POLL_INTERVAL_UNIT_10MS; if (is_poll_mode) { timer_setup(&driver_data.timer, sunway_powercap_poll_func, 0); -- Gitee From 90c40464d1b0385e1c4b03859b040721cf914692 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 18 Sep 2025 17:20:09 +0800 Subject: [PATCH 10/19] sw64: powercap: fix misuse of an uninitialized temporary variable Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- Due to typo, the temporary variable related_cpu is misused. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/platform/sw64/powercap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/platform/sw64/powercap.c b/drivers/platform/sw64/powercap.c index 61eef40952039..b1856ca24ddc2 100644 --- a/drivers/platform/sw64/powercap.c +++ b/drivers/platform/sw64/powercap.c @@ -704,10 +704,10 @@ static int sunway_powercap_probe(struct platform_device *pdev) struct freq_qos_request *req; /* Initial state */ - powercap_cpu_data[related_cpu].state = SUNWAY_POWERCAP_STATE_FREE; + powercap_cpu_data[cpu].state = SUNWAY_POWERCAP_STATE_FREE; - powercap_cpu_data[related_cpu].core = rcid_to_core_id(rcid); - powercap_cpu_data[related_cpu].node = rcid_to_domain_id(rcid); + powercap_cpu_data[cpu].core = rcid_to_core_id(rcid); + powercap_cpu_data[cpu].node = rcid_to_domain_id(rcid); if (powercap_cpu_data[cpu].policy) continue; -- Gitee From a7cd25a4dbf2e87bfcf6fa1e25bd28a67c6d752a Mon Sep 17 00:00:00 2001 From: Jing Li Date: Fri, 17 Oct 2025 17:34:43 +0800 Subject: [PATCH 11/19] sw64: efi: fix compile error when CONFIG_EFI=n Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/cpu.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/sw_64/kernel/cpu.c b/arch/sw_64/kernel/cpu.c index 84b4a66a06e9a..89961119fa03c 100644 --- a/arch/sw_64/kernel/cpu.c +++ b/arch/sw_64/kernel/cpu.c @@ -70,7 +70,7 @@ static int cpuinfo_cpu_online(unsigned int cpu) return 0; } -static const char * __init dmi_get_string(const struct dmi_header *dm, u8 s) +static __maybe_unused const char * __init dmi_get_string(const struct dmi_header *dm, u8 s) { const u8 *bp = ((u8 *) dm) + dm->length; const u8 *nsp; @@ -90,7 +90,7 @@ static const char * __init dmi_get_string(const struct dmi_header *dm, u8 s) return ""; } -static void __init find_dmi_processor_version(const struct dmi_header *dm, +static __maybe_unused void __init find_dmi_processor_version(const struct dmi_header *dm, void *private) { char *dmi_data = (char *)dm; @@ -113,10 +113,12 @@ static void __init get_model_id(void) int i; unsigned long val; +#ifdef CONFIG_EFI /* Prefer model id from SMBIOS */ if (!IS_ENABLED(CONFIG_SUBARCH_C3B) && BIOS_SUPPORT_RESET_CLALLBACK((void *)bios_version)) dmi_walk(find_dmi_processor_version, NULL); +#endif if (strlen(model_id) > 0) return; @@ -128,7 +130,7 @@ static void __init get_model_id(void) } } -static void __init find_dmi_processor_manufacturer(const struct dmi_header *dm, +static __maybe_unused void __init find_dmi_processor_manufacturer(const struct dmi_header *dm, void *private) { char *dmi_data = (char *)dm; @@ -151,10 +153,12 @@ static void __init get_vendor_id(void) int i; unsigned long val; +#ifdef CONFIG_EFI /* Prefer vendor id from SMBIOS */ if (!IS_ENABLED(CONFIG_SUBARCH_C3B) && BIOS_SUPPORT_RESET_CLALLBACK((void *)bios_version)) dmi_walk(find_dmi_processor_manufacturer, NULL); +#endif if (strlen(vendor_id) > 0) return; @@ -166,7 +170,7 @@ static void __init get_vendor_id(void) } } -static void __init find_dmi_processor_family(const struct dmi_header *dm, +static __maybe_unused void __init find_dmi_processor_family(const struct dmi_header *dm, void *private) { char *dmi_data = (char *)dm; @@ -182,10 +186,12 @@ static void __init find_dmi_processor_family(const struct dmi_header *dm, static void __init get_family(void) { +#ifdef CONFIG_EFI /* Prefer processor family from SMBIOS */ if (!IS_ENABLED(CONFIG_SUBARCH_C3B) && BIOS_SUPPORT_RESET_CLALLBACK((void *)bios_version)) dmi_walk(find_dmi_processor_family, NULL); +#endif if (family) return; -- Gitee From e0ffe45ff625810636e0daa10b226852665f46d9 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Wed, 30 Apr 2025 15:02:59 +0800 Subject: [PATCH 12/19] sw64: enable -relax when CONFIG_FUNCTION_TRACER=y Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- Enable linker relaxation when CONFIG_FUNCTION_TRACER=y. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/Makefile b/arch/sw_64/Makefile index 0e849e05d985d..61d986658a1fd 100644 --- a/arch/sw_64/Makefile +++ b/arch/sw_64/Makefile @@ -17,13 +17,17 @@ archheaders: NM := $(NM) -B CCVERSION := $(shell $(CC) -dumpversion) -LDFLAGS_vmlinux := -static -N #-relax +LDFLAGS_vmlinux := -static -N CHECKFLAGS += -D__sw__ ifeq ($(CONFIG_RELOCATABLE),y) LDFLAGS_vmlinux += --emit-relocs endif +ifeq ($(CONFIG_FUNCTION_TRACER),y) + LDFLAGS_vmlinux += -relax +endif + CHECKFLAGS += -D__sw__ cflags-y := -pipe -ffixed-8 -mno-fp-regs #-msmall-data ifneq ($(CONFIG_SUBARCH_C3B),y) -- Gitee From 6a0369312879097d78f1bb1677b2d7936d78aaf2 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 27 May 2025 11:34:05 +0800 Subject: [PATCH 13/19] sw64: update cflags for new compiler Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- Enable gcc memcpy and memset auto inline. Enable gcc leaf function frame pointer optimization. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/sw_64/Makefile b/arch/sw_64/Makefile index 61d986658a1fd..73afc380b3d1b 100644 --- a/arch/sw_64/Makefile +++ b/arch/sw_64/Makefile @@ -33,6 +33,9 @@ cflags-y := -pipe -ffixed-8 -mno-fp-regs #-msmall-data ifneq ($(CONFIG_SUBARCH_C3B),y) cflags-y += -fsw-rev -fsw-unalign-byte endif +cflags-y += $(call cc-option, -fsw-memcpy) +cflags-y += $(call cc-option, -fsw-memclr) +cflags-y += $(call cc-option, -fsw-leaf-optimize-fp) cflags-y += $(call cc-option, -fno-jump-tables) cflags-y += $(cpuflags-y) -- Gitee From bfbcd3acaa69c5d5af9746d4251c85ab5fcfcefb Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 27 May 2025 11:28:06 +0800 Subject: [PATCH 14/19] sw64: optimize asid clearation Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- Clear the asid array using memset. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/mmu.h | 5 +++++ arch/sw_64/include/asm/mmu_context.h | 5 +---- arch/sw_64/kernel/smp.c | 19 ++++++++----------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/arch/sw_64/include/asm/mmu.h b/arch/sw_64/include/asm/mmu.h index f24219fac654b..3f4a394915fb6 100644 --- a/arch/sw_64/include/asm/mmu.h +++ b/arch/sw_64/include/asm/mmu.h @@ -7,4 +7,9 @@ typedef struct { unsigned long asid[NR_CPUS]; void *vdso; } mm_context_t; + +static inline void clear_asid(mm_context_t *mm_context) +{ + memset(mm_context->asid, 0, sizeof(mm_context->asid[0]) * nr_cpu_ids); +} #endif /* _ASM_SW64_MMU_H */ diff --git a/arch/sw_64/include/asm/mmu_context.h b/arch/sw_64/include/asm/mmu_context.h index bfc3dbc5f12fd..a62041aaa4e0e 100644 --- a/arch/sw_64/include/asm/mmu_context.h +++ b/arch/sw_64/include/asm/mmu_context.h @@ -93,10 +93,7 @@ switch_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm, static inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm) { - int i; - - for_each_possible_cpu(i) - mm->context.asid[i] = 0; + clear_asid(&mm->context); return 0; } diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index f0ad2cf3c3e77..6c6a98a07ac6e 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -723,7 +723,6 @@ static void ipi_flush_tlb_mm(void *x) void flush_tlb_mm(struct mm_struct *mm) { - /* happens as a result of exit_mmap() * Shall we clear mm->context.asid[] here? */ @@ -735,12 +734,11 @@ void flush_tlb_mm(struct mm_struct *mm) if (atomic_read(&mm->mm_users) != 1 || mm != current->mm) { on_each_cpu_mask(mm_cpumask(mm), ipi_flush_tlb_mm, mm, 1); } else { - int cpu, this_cpu = smp_processor_id(); + int cpu = smp_processor_id(); + unsigned long asid = mm->context.asid[cpu]; - for_each_online_cpu(cpu) { - if (cpu != this_cpu && mm->context.asid[cpu]) - mm->context.asid[cpu] = 0; - } + clear_asid(&mm->context); + mm->context.asid[cpu] = asid; local_flush_tlb_mm(mm); } @@ -775,12 +773,11 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) }; on_each_cpu_mask(mm_cpumask(mm), ipi_flush_tlb_page, &info, 1); } else { - int cpu, this_cpu = smp_processor_id(); + int cpu = smp_processor_id(); + unsigned long asid = mm->context.asid[cpu]; - for_each_online_cpu(cpu) { - if (cpu != this_cpu && mm->context.asid[cpu]) - mm->context.asid[cpu] = 0; - } + clear_asid(&mm->context); + mm->context.asid[cpu] = asid; local_flush_tlb_page(vma, addr); } -- Gitee From 47c93ce485380a4509935cf771a5a1cd2f5ce449 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Wed, 11 Jun 2025 16:45:19 +0800 Subject: [PATCH 15/19] sw64: Add inline find_next_set/and/clear_bit() Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- Add inline version of find_next_xxx_bit to eliminate function call overhead. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/bitops.h | 89 +++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/arch/sw_64/include/asm/bitops.h b/arch/sw_64/include/asm/bitops.h index 634785f4cb530..41618d339859e 100644 --- a/arch/sw_64/include/asm/bitops.h +++ b/arch/sw_64/include/asm/bitops.h @@ -542,6 +542,95 @@ static inline unsigned int __arch_hweight8(unsigned int w) return __arch_hweight64(w & 0xff); } +#define find_next_bit_le find_next_bit_le +#define find_next_bit __find_next_set_bit +static inline unsigned long __find_next_set_bit(const unsigned long *addr, + unsigned long size, + unsigned long offset) +{ + unsigned long word; + + if (unlikely(offset >= size)) + return size; + + word = addr[offset / BITS_PER_LONG]; + + /* Handle 1st word. */ + word = word >> (offset % BITS_PER_LONG) << (offset % BITS_PER_LONG); + + offset &= ~(BITS_PER_LONG - 1); + + while (!word) { + offset += BITS_PER_LONG; + if (offset >= size) + return size; + + word = addr[offset / BITS_PER_LONG]; + } + + return (offset + __ffs(word)) < size ? (offset + __ffs(word)) : size; +} + +#define find_next_and_bit __find_next_and_bit +static inline unsigned long __find_next_and_bit(const unsigned long *addr1, + const unsigned long *addr2, unsigned long size, + unsigned long offset) +{ + unsigned long word; + + if (unlikely(offset >= size)) + return size; + + word = addr1[offset / BITS_PER_LONG]; + word &= addr2[offset / BITS_PER_LONG]; + + /* Handle 1st word. */ + word = word >> (offset % BITS_PER_LONG) << (offset % BITS_PER_LONG); + + offset &= ~(BITS_PER_LONG - 1); + + while (!word) { + offset += BITS_PER_LONG; + if (offset >= size) + return size; + + word = addr1[offset / BITS_PER_LONG]; + word &= addr2[offset / BITS_PER_LONG]; + } + + return (offset + __ffs(word)) < size ? (offset + __ffs(word)) : size; +} + +#define find_next_zero_bit_le find_next_zero_bit_le +#define find_next_zero_bit __find_next_zero_bit +static inline unsigned long __find_next_zero_bit(const unsigned long *addr, unsigned + long size, unsigned long offset) +{ + unsigned long word; + + if (unlikely(offset >= size)) + return size; + + word = addr[offset / BITS_PER_LONG]; + word ^= ~(0UL); + + /* Handle 1st word. */ + word = word >> (offset % BITS_PER_LONG) << (offset % BITS_PER_LONG); + + offset &= ~(BITS_PER_LONG - 1); + + while (!word) { + offset += BITS_PER_LONG; + if (offset >= size) + return size; + + word = addr[offset / BITS_PER_LONG]; + word ^= ~(0UL); + } + + return (offset + __ffs(word)) < size ? (offset + __ffs(word)) : size; +} + #include #endif /* __KERNEL__ */ -- Gitee From c3df4d3d7bb2ac81d3082a7af04d7ea47bd0c89d Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 20 May 2025 15:19:47 +0800 Subject: [PATCH 16/19] sw64: optimize ipi handling Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- Avoid using xchg() which has lock instructions to get ipi pending. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/smp.c | 69 ++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 6c6a98a07ac6e..497c8fc406ff5 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -37,18 +37,20 @@ void *idle_task_pointer[NR_CPUS]; /* State of each CPU */ DEFINE_PER_CPU(int, cpu_state) = { 0 }; -/* A collection of single bit ipi messages. */ -static struct { - unsigned long bits ____cacheline_aligned; -} ipi_data[NR_CPUS] __cacheline_aligned; - enum ipi_message_type { IPI_RESCHEDULE, IPI_CALL_FUNC, IPI_CPU_STOP, IPI_IRQ_WORK, + IPI_MAX, }; +#define IPI_PENDING_TYPE u64 +/* A collection of single bit ipi messages. */ +static struct { + IPI_PENDING_TYPE pending[IPI_MAX] ____cacheline_aligned; +} ipi_data[CONFIG_NR_CPUS] __cacheline_aligned; + int smp_num_cpus = 1; /* Number that came online. */ EXPORT_SYMBOL(smp_num_cpus); @@ -64,6 +66,22 @@ enum core_version { CORE_VERSION_RESERVED = 3 /* 3 and greater are reserved */ }; +static inline void get_ipi_pending(int cpu, IPI_PENDING_TYPE *dst) +{ + int i; + + /* make sure we can see pending for this ipi */ + smp_mb(); + for (i = 0; i < IPI_MAX; i++) { + if (READ_ONCE(ipi_data[cpu].pending[i])) { + WRITE_ONCE(dst[i], 1); + WRITE_ONCE(ipi_data[cpu].pending[i], 0); + } + } + /* make sure we won't miss any pending set after ipi */ + smp_mb(); +} + #ifdef CONFIG_SUBARCH_C4 #define OFFSET_CLU_LV2_SELH 0x3a00UL #define OFFSET_CLU_LV2_SELL 0x3b00UL @@ -593,13 +611,15 @@ static void send_ipi_message(const struct cpumask *to_whom, enum ipi_message_typ { int i; - mb(); - for_each_cpu(i, to_whom) - set_bit(operation, &ipi_data[i].bits); - - mb(); - for_each_cpu(i, to_whom) - send_ipi(i, II_II0); + /* make sure ipi data are written before setting pending */ + smp_mb(); + for_each_cpu(i, to_whom) { + WRITE_ONCE(ipi_data[i].pending[operation], 1); + /* make sure pending is set before sending ipi */ + smp_mb(); + if (READ_ONCE(ipi_data[i].pending[operation])) + send_ipi(i, II_II0); + } } static void ipi_cpu_stop(int cpu) @@ -620,20 +640,13 @@ void arch_irq_work_raise(void) void handle_ipi(struct pt_regs *regs) { int cpu = smp_processor_id(); - unsigned long *pending_ipis = &ipi_data[cpu].bits; - unsigned long ops; - - mb(); /* Order interrupt and bit testing. */ - while ((ops = xchg(pending_ipis, 0)) != 0) { - mb(); /* Order bit clearing and data access. */ - do { - unsigned long which; - - which = ops & -ops; - ops &= ~which; - which = __ffs(which); + IPI_PENDING_TYPE pending[IPI_MAX] = { 0 }; + int i; - switch (which) { + get_ipi_pending(cpu, pending); + for (i = 0; i < IPI_MAX; i++) { + if (pending[i]) { + switch (i) { case IPI_RESCHEDULE: scheduler_ipi(); break; @@ -651,12 +664,10 @@ void handle_ipi(struct pt_regs *regs) break; default: - pr_crit("Unknown IPI on CPU %d: %lu\n", cpu, which); + pr_crit("Unknown IPI on CPU %d\n", cpu); break; } - } while (ops); - - mb(); /* Order data access and bit testing. */ + } } cpu_data[cpu].ipi_count++; -- Gitee From 0573ae60e6562a2cc76c05d0fb3388902cd6f37b Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Tue, 3 Jun 2025 14:40:58 +0800 Subject: [PATCH 17/19] sw64: add missing memory clobbers Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- Fixes: f86c0df67642 ("sw64: reimplement cmpxchg and xchg") Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/xchg.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/sw_64/include/asm/xchg.h b/arch/sw_64/include/asm/xchg.h index d69dfe893ec4f..0c44f871e2a7b 100644 --- a/arch/sw_64/include/asm/xchg.h +++ b/arch/sw_64/include/asm/xchg.h @@ -310,6 +310,7 @@ ____xchg(_u32, volatile int *m, unsigned long val) ".previous" : [old_v]"=&r"(val), [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2) : [new_v]"r"(val), [m]"r"(m) + : "memory" ); return val; @@ -332,6 +333,7 @@ ____xchg(_u64, volatile long *m, unsigned long val) ".previous" : [old_v]"=&r"(val), [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2) : [new_v]"r"(val), [m]"r"(m) + : "memory" ); return val; -- Gitee From 98d960a57f7a1c57f27b40c4ea66b8580d2cfdad Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Wed, 22 Oct 2025 11:13:38 +0800 Subject: [PATCH 18/19] sw64: add trap related macros Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- Add ENT_IDX and TRAP_CAUSE macros for all traps. Fixes ENT_IDX_SUSPEND which should be 6 for C3B and 7 for C4. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/traps.h | 28 ++++++++++++++++++++++++++++ arch/sw_64/kernel/irq.c | 5 +++-- arch/sw_64/kernel/smp.c | 5 +++-- arch/sw_64/kernel/traps.c | 13 +++++++------ drivers/irqchip/irq-sunway-cpu.c | 5 +++-- 5 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 arch/sw_64/include/asm/traps.h diff --git a/arch/sw_64/include/asm/traps.h b/arch/sw_64/include/asm/traps.h new file mode 100644 index 0000000000000..17064049632f1 --- /dev/null +++ b/arch/sw_64/include/asm/traps.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_SW64_TRAPS_H +#define _ASM_SW64_TRAPS_H + +#define ENT_IDX_INT 0 +#define ENT_IDX_ARITH 1 +#define ENT_IDX_MM 2 +#define ENT_IDX_IF 3 +#define ENT_IDX_UNA 4 +#define ENT_IDX_SYS 5 + +#if defined(CONFIG_SUBARCH_C3B) +/* C3B does not support NMI, so invalid idx */ +# define ENT_IDX_NMI (-1) +# define ENT_IDX_SUSPEND 6 +#elif defined(CONFIG_SUBARCH_C4) +# define ENT_IDX_NMI 6 +# define ENT_IDX_SUSPEND 7 +#endif + +#define TRAP_CAUSE_NMI (-2) +#define TRAP_CAUSE_INT (-1) +#define TRAP_CAUSE_ARITH 1 +#define TRAP_CAUSE_MM 2 +#define TRAP_CAUSE_IF 3 +#define TRAP_CAUSE_UNA 4 + +#endif /* _ASM_SW64_TRAPS_H */ diff --git a/arch/sw_64/kernel/irq.c b/arch/sw_64/kernel/irq.c index 78cac3ce2056c..e147637585439 100644 --- a/arch/sw_64/kernel/irq.c +++ b/arch/sw_64/kernel/irq.c @@ -20,6 +20,7 @@ #include #include +#include volatile unsigned long irq_err_count; DEFINE_PER_CPU(unsigned long, irq_pmi_count); @@ -173,10 +174,10 @@ void __init init_IRQ(void) unsigned long nmi_stack __maybe_unused = nmi_stack_page ? (unsigned long)page_address(nmi_stack_page) : 0; - wrent(entInt, 0); + wrent(entInt, ENT_IDX_INT); if (IS_ENABLED(CONFIG_SUBARCH_C4) && is_in_host()) { sw64_write_csr_imb(nmi_stack + THREAD_SIZE, CSR_NMI_STACK); - wrent(entNMI, 6); + wrent(entNMI, ENT_IDX_NMI); set_nmi(INT_PC); } diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 497c8fc406ff5..2c8fd8b6efc1f 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "proto.h" @@ -170,7 +171,7 @@ void smp_callin(void) trap_init(); /* Set interrupt vector. */ - wrent(entInt, 0); + wrent(entInt, ENT_IDX_INT); /* Get our local ticker going. */ sw64_setup_timer(); @@ -192,7 +193,7 @@ void smp_callin(void) nmi_stack = nmi_stack_page ? (unsigned long)page_address(nmi_stack_page) : 0; sw64_write_csr_imb(nmi_stack + THREAD_SIZE, CSR_NMI_STACK); - wrent(entNMI, 6); + wrent(entNMI, ENT_IDX_NMI); set_nmi(INT_PC); } diff --git a/arch/sw_64/kernel/traps.c b/arch/sw_64/kernel/traps.c index 2fd63a95d6cbc..a0403130835af 100644 --- a/arch/sw_64/kernel/traps.c +++ b/arch/sw_64/kernel/traps.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "proto.h" @@ -410,13 +411,13 @@ trap_init(void) register unsigned long gptr __asm__("$29"); wrkgp(gptr); - wrent(entArith, 1); - wrent(entMM, 2); - wrent(entIF, 3); - wrent(entUna, 4); - wrent(entSys, 5); + wrent(entArith, ENT_IDX_ARITH); + wrent(entMM, ENT_IDX_MM); + wrent(entIF, ENT_IDX_IF); + wrent(entUna, ENT_IDX_UNA); + wrent(entSys, ENT_IDX_SYS); #ifdef CONFIG_EFI if (smp_processor_id() == 0) - wrent((void *)entSuspend, 6); + wrent((void *)entSuspend, ENT_IDX_SUSPEND); #endif } diff --git a/drivers/irqchip/irq-sunway-cpu.c b/drivers/irqchip/irq-sunway-cpu.c index c0c83833ab9d1..0ba130d979c6b 100644 --- a/drivers/irqchip/irq-sunway-cpu.c +++ b/drivers/irqchip/irq-sunway-cpu.c @@ -11,6 +11,7 @@ #include #include #include +#include /** * The topology of interrupt controllers of SW64 is as follows: @@ -87,7 +88,7 @@ asmlinkage void noinstr do_entInt(struct pt_regs *regs) /* restart idle routine if it is interrupted */ if (regs->pc > (u64)__idle_start && regs->pc < (u64)__idle_end) regs->pc = (u64)__idle_start; - if (unlikely(regs->cause == -2 && IS_ENABLED(CONFIG_SUBARCH_C4))) + if (unlikely(regs->cause == TRAP_CAUSE_NMI && IS_ENABLED(CONFIG_SUBARCH_C4))) nmi_enter(); else irq_enter(); @@ -176,7 +177,7 @@ asmlinkage void noinstr do_entInt(struct pt_regs *regs) out: set_irq_regs(old_regs); - if (unlikely(regs->cause == -2 && IS_ENABLED(CONFIG_SUBARCH_C4))) + if (unlikely(regs->cause == TRAP_CAUSE_NMI && IS_ENABLED(CONFIG_SUBARCH_C4))) nmi_exit(); else irq_exit(); -- Gitee From ce333dffd36e2ef73a85c73f49aa3db7246312b9 Mon Sep 17 00:00:00 2001 From: Gao Chen Date: Wed, 22 Oct 2025 16:13:45 +0800 Subject: [PATCH 19/19] sw64: fix the condition for enabling hw_una_enabled Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ID3AYT -------------------------------- The hw_una_enabled should be enabled by checking hmcode feature. Signed-off-by: Gao Chen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index 6ddccb4a5822b..b75dbf73ba0af 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -590,7 +590,7 @@ static void __init setup_firmware_fdt(void) static void __init setup_cpu_caps(void) { - if (!IS_ENABLED(CONFIG_SUBARCH_C3B) && !is_junzhang_v1()) + if (cpuid(GET_FEATURES, 0) & CPU_FEAT_UNA) static_branch_enable(&hw_una_enabled); } -- Gitee