From 309c8873557d46aaddf1d153df6a03e9a018d4ce Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Mon, 14 Jul 2025 10:22:14 +0800 Subject: [PATCH 01/18] sw64: fix sw64_rrk_store() wrap handling Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- Make sure we are clearing the rrk area instead of a random area when handling rrk wrap. Fixes: 4f54079bec6e ("sw64: improve sw64_rrk") Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/dup_print.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sw_64/kernel/dup_print.c b/arch/sw_64/kernel/dup_print.c index fa604abef38c..2d77ccae30d2 100644 --- a/arch/sw_64/kernel/dup_print.c +++ b/arch/sw_64/kernel/dup_print.c @@ -54,7 +54,7 @@ void sw64_rrk_store(const char *text, u16 text_len, u64 ts_nsec, int level, max_offset_allowed = PRINTK_SIZE - text_len - header_len - (newline_first ? 1 : 0); if (unlikely(sw64_printk_offset >= max_offset_allowed)) { sw64_printk_offset = 0; - memset(sw64_printk_buf, 0, PRINTK_SIZE); + memset((void *)KERNEL_PRINTK_BUFF_BASE, 0, PRINTK_SIZE); wrap = true; } sw64_printk_buf = (char *)(KERNEL_PRINTK_BUFF_BASE + sw64_printk_offset); -- Gitee From bfca7d4f21c19de27733a968b29afe3681e1657d Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Thu, 4 Jul 2024 11:31:16 +0800 Subject: [PATCH 02/18] sw64: use wait/complete for smp boot Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- Use wait and complete functions instead of udelay for smp boot synchronization. Signed-off-by: Mao Minkai Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/smp.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/arch/sw_64/kernel/smp.c b/arch/sw_64/kernel/smp.c index 93122a011f66..53aeb4c9792f 100644 --- a/arch/sw_64/kernel/smp.c +++ b/arch/sw_64/kernel/smp.c @@ -21,6 +21,8 @@ #include "proto.h" +static DECLARE_COMPLETION(cpu_running); + struct smp_rcb_struct *smp_rcb; EXPORT_SYMBOL(smp_rcb); @@ -135,15 +137,13 @@ void smp_callin(void) save_ktp(); upshift_freq(); cpuid = smp_processor_id(); - local_irq_disable(); + WARN_ON_ONCE(!irqs_disabled()); if (cpu_online(cpuid)) { pr_err("??, cpu 0x%x already present??\n", cpuid); BUG(); } - set_cpu_online(cpuid, true); - /* Set trap vectors. */ trap_init(); @@ -182,6 +182,10 @@ void smp_callin(void) store_cpu_topology(cpuid); numa_add_cpu(cpuid); + set_cpu_online(cpuid, true); + + complete(&cpu_running); + /* Must have completely accurate bogos. */ local_irq_enable(); @@ -205,7 +209,6 @@ static inline void set_secondary_ready(int cpuid) */ static int secondary_cpu_start(int cpuid, struct task_struct *idle) { - unsigned long timeout; /* * Precalculate the target ksp. */ @@ -222,17 +225,12 @@ static int secondary_cpu_start(int cpuid, struct task_struct *idle) #endif /* Wait 10 seconds for secondary cpu. */ - timeout = jiffies + 10*HZ; - while (time_before(jiffies, timeout)) { - if (cpu_online(cpuid)) - goto started; - udelay(10); - barrier(); + if (!wait_for_completion_timeout(&cpu_running, + msecs_to_jiffies(10000))) { + pr_err("SMP: Processor %d failed to start.\n", cpuid); + return -1; } - pr_err("SMP: Processor %d failed to start.\n", cpuid); - return -1; -started: return 0; } -- Gitee From 0719e3236f0a0ee5d40c060d490c3fc98d047b15 Mon Sep 17 00:00:00 2001 From: Gu Yuchen Date: Tue, 15 Jul 2025 10:06:46 +0800 Subject: [PATCH 03/18] sw64: ftrace: add HAVE_DYNAMIC_FTRACE_WITH_ARGS support Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- Allow for arguments to be passed in to ftrace_regs by default. If this is set, then arguments and stack can be found from the pt_regs. Signed-off-by: Gu Yuchen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 1 + arch/sw_64/include/asm/ftrace.h | 66 +++++++++++++++ arch/sw_64/kernel/entry-ftrace.S | 140 +++++++++++++++---------------- arch/sw_64/kernel/ftrace.c | 12 +++ 4 files changed, 146 insertions(+), 73 deletions(-) diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index ca5f37673985..be41bac8cbe9 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -94,6 +94,7 @@ config SW64 select HAVE_C_RECORDMCOUNT select HAVE_DEBUG_BUGVERBOSE select HAVE_DYNAMIC_FTRACE + select HAVE_DYNAMIC_FTRACE_WITH_ARGS select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS select HAVE_DYNAMIC_FTRACE_WITH_REGS select HAVE_EBPF_JIT diff --git a/arch/sw_64/include/asm/ftrace.h b/arch/sw_64/include/asm/ftrace.h index 33122cd7f91b..eb1b05186705 100644 --- a/arch/sw_64/include/asm/ftrace.h +++ b/arch/sw_64/include/asm/ftrace.h @@ -46,6 +46,70 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr) return addr; } +#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS +struct ftrace_ops; + +struct ftrace_regs { + struct pt_regs regs; +}; + +static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs) +{ + return &fregs->regs; +} + +static __always_inline unsigned long +ftrace_regs_get_instruction_pointer(const struct ftrace_regs *fregs) +{ + return fregs->regs.regs[28]; +} + + static __always_inline void +ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs, unsigned long ip) +{ + fregs->regs.regs[27] = ip; + fregs->regs.regs[28] = ip; +} + +static __always_inline unsigned long +ftrace_regs_get_stack_pointer(const struct ftrace_regs *fregs) +{ + return fregs->regs.regs[30]; +} + +static __always_inline unsigned long +ftrace_regs_get_argument(struct ftrace_regs *fregs, unsigned int n) +{ + if (n < 6) + return fregs->regs.regs[16+n]; + return 0; +} + +static __always_inline unsigned long +ftrace_regs_get_return_value(const struct ftrace_regs *fregs) +{ + return fregs->regs.regs[0]; +} + +static __always_inline void +ftrace_regs_set_return_value(struct ftrace_regs *fregs, unsigned long ret) +{ + fregs->regs.regs[0] = ret; +} + +static __always_inline void +ftrace_override_function_with_return(struct ftrace_regs *fregs) +{ + fregs->regs.regs[27] = fregs->regs.regs[26]; + fregs->regs.regs[28] = fregs->regs.regs[26]; +} + +int ftrace_regs_query_register_offset(const char *name); + +#define ftrace_graph_func ftrace_graph_func +void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, + struct ftrace_ops *op, struct ftrace_regs *fregs); + #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS static inline void __arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr) @@ -57,6 +121,8 @@ __arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr) __arch_ftrace_set_direct_caller(&(fregs)->regs, addr) #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ +#endif + #endif /* ifndef __ASSEMBLY__ */ #ifndef __ASSEMBLY__ diff --git a/arch/sw_64/kernel/entry-ftrace.S b/arch/sw_64/kernel/entry-ftrace.S index 9274ca8d9769..ec3677d40477 100644 --- a/arch/sw_64/kernel/entry-ftrace.S +++ b/arch/sw_64/kernel/entry-ftrace.S @@ -75,7 +75,7 @@ #endif .endm - .macro SAVE_PT_REGS + .macro SAVE_PT_REGS allregs=0 /* save $26 & fp of the function before caller */ subl $sp, 0x10, $sp stl $26, 0($sp) @@ -88,15 +88,11 @@ stl $15, 0x8($sp) ldi $15, 0($sp) - /* save pt_regs */ ldi $sp, -PT_REGS_SIZE($sp) stl $0, PT_REGS_R0($sp) +#ifdef CONFIG_FUNCTION_GRAPH_TRACER stl $9, PT_REGS_R9($sp) - stl $10, PT_REGS_R10($sp) - stl $11, PT_REGS_R11($sp) - stl $12, PT_REGS_R12($sp) - stl $13, PT_REGS_R13($sp) - stl $14, PT_REGS_R14($sp) +#endif stl $15, PT_REGS_R15($sp) stl $16, PT_REGS_R16($sp) stl $17, PT_REGS_R17($sp) @@ -112,6 +108,15 @@ stl $27, PT_REGS_R27($sp) stl $28, PT_REGS_R28($sp) stl $29, PT_REGS_GP($sp) + subl $28, MCOUNT_INSN_SIZE, $0 + stl $0, PT_REGS_PC($sp) + .if \allregs + stl $10, PT_REGS_R10($sp) + stl $11, PT_REGS_R11($sp) + stl $12, PT_REGS_R12($sp) + stl $13, PT_REGS_R13($sp) + stl $14, PT_REGS_R14($sp) + .endif ldi $0, PT_REGS_SIZE($sp) stl $0, PT_REGS_R30($sp) @@ -120,15 +125,12 @@ stl $2, PT_REGS_R2($sp) .endm - .macro RESTORE_PT_REGS + .macro RESTORE_PT_REGS allregs=0 /* restore pt_regs */ ldl $0, PT_REGS_R0($sp) +#ifdef CONFIG_FUNCTION_GRAPH_TRACER ldl $9, PT_REGS_R9($sp) - ldl $10, PT_REGS_R10($sp) - ldl $11, PT_REGS_R11($sp) - ldl $12, PT_REGS_R12($sp) - ldl $13, PT_REGS_R13($sp) - ldl $14, PT_REGS_R14($sp) +#endif ldl $15, PT_REGS_R15($sp) ldl $16, PT_REGS_R16($sp) ldl $17, PT_REGS_R17($sp) @@ -144,11 +146,23 @@ ldl $27, PT_REGS_R27($sp) ldl $28, PT_REGS_R28($sp) ldl $29, PT_REGS_GP($sp) + .if \allregs + ldl $10, PT_REGS_R10($sp) + ldl $11, PT_REGS_R11($sp) + ldl $12, PT_REGS_R12($sp) + ldl $13, PT_REGS_R13($sp) + ldl $14, PT_REGS_R14($sp) + .endif ldi $sp, PT_REGS_SIZE($sp) /* only restore $fp */ ldl $15, 0x18($sp) addl $sp, 0x20, $sp + + bne $2, .Ldirect\@ + ret $31, ($28), 1 +.Ldirect\@: + ret $31, ($2), 1 /* direct call */ .endm .macro RESTORE_GRAPH_REG_ARGS @@ -173,6 +187,40 @@ addl $sp, 16, $sp .endm + .macro ftrace_common allregs=0 + br $27, 1f +1: ldgp $29, 0($27) + + subl $28, MCOUNT_INSN_SIZE, $16 + bis $26, $31, $17 + ldi $4, function_trace_op + ldl $18, 0($4) + mov $sp, $19 + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + bis $31, $16, $9 +#endif + ldi $4, current_tracer + ldl $27, 0($4) + +.if \allregs == 0 + .global ftrace_call +ftrace_call: + nop +.endif + +.if \allregs + .global ftrace_regs_call +ftrace_regs_call: + nop +.endif + +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + RESTORE_GRAPH_REG_ARGS + call ftrace_graph_caller +#endif + ldl $2, PT_REGS_R2($sp) // load direct call addr + .endm #ifdef CONFIG_FUNCTION_GRAPH_TRACER /* @@ -243,35 +291,9 @@ _mcount: .global ftrace_caller .ent ftrace_caller ftrace_caller: - mcount_enter - br $27, 1f -1: ldgp $29, 0($27) - - subl $28, MCOUNT_INSN_SIZE, $16 - bis $26, $31, $17 - ldl $18, function_trace_op - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER - /* - * the graph tracer (specifically, prepare_ftrace_return) needs these - * arguments but for now the function tracer occupies the regs, so we - * save them in callee-saved regs to recover later. - */ - bis $31, $16, $9 -#endif - ldi $4, current_tracer - ldl $27, 0($4) - - .global ftrace_call -ftrace_call: /* tracer(pc, ra); */ - nop - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER - RESTORE_GRAPH_ARGS - call ftrace_graph_caller -#endif - mcount_end - ret $31, ($28), 1 + SAVE_PT_REGS allregs=0 + ftrace_common allregs=0 + RESTORE_PT_REGS allregs=0 .end ftrace_caller #else /* !CONFIG_DYNAMIC_FTRACE */ @@ -316,37 +338,9 @@ skip_ftrace: .global ftrace_regs_caller .ent ftrace_regs_caller ftrace_regs_caller: - SAVE_PT_REGS - br $27, 1f -1: ldgp $29, 0($27) - - subl $28, MCOUNT_INSN_SIZE, $16 - stl $16, PT_REGS_PC($sp) - bis $26, $31, $17 - ldi $4, function_trace_op - ldl $18, 0($4) - mov $sp, $19 - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER - bis $31, $16, $9 -#endif - ldi $4, current_tracer - ldl $27, 0($4) - - .global ftrace_regs_call -ftrace_regs_call: - nop - -#ifdef CONFIG_FUNCTION_GRAPH_TRACER - RESTORE_GRAPH_REG_ARGS - call ftrace_graph_caller -#endif - ldl $2, PT_REGS_R2($sp) // load direct call addr - RESTORE_PT_REGS - bne $2, .Ldirect - ret $31, ($28), 1 -.Ldirect: - ret $31, ($2), 1 + SAVE_PT_REGS allregs=1 + ftrace_common allregs=1 + RESTORE_PT_REGS allregs=1 .end ftrace_regs_caller #endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */ diff --git a/arch/sw_64/kernel/ftrace.c b/arch/sw_64/kernel/ftrace.c index 511760ac18c2..84ba10d93c9f 100644 --- a/arch/sw_64/kernel/ftrace.c +++ b/arch/sw_64/kernel/ftrace.c @@ -175,6 +175,17 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, * Turn on/off the call to ftrace_graph_caller() in ftrace_caller() * depending on @enable. */ +#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS +void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, + struct ftrace_ops *op, struct ftrace_regs *fregs) +{ + struct pt_regs *regs = arch_ftrace_get_regs(fregs); + unsigned long *parent = (unsigned long *)®s->regs[26]; + unsigned long frame_pointer = regs->regs[15]; + + prepare_ftrace_return(parent, ip, frame_pointer); +} +#else static int ftrace_modify_graph_caller(bool enable) { unsigned long pc = (unsigned long)&ftrace_graph_call; @@ -194,5 +205,6 @@ int ftrace_disable_ftrace_graph_caller(void) { return ftrace_modify_graph_caller(false); } +#endif /* CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS */ #endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ -- Gitee From 84c7c0947e29dffa085d52c756fa531064dcc0f9 Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Thu, 17 Jul 2025 10:55:50 +0800 Subject: [PATCH 04/18] sw64: fix guest kdump function Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- Using the kdump function to reset cpu in the guest will cause errors, so the temporary solution is to change the non-zero cpu to enter cpu_relax. Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/machine_kexec.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/sw_64/kernel/machine_kexec.c b/arch/sw_64/kernel/machine_kexec.c index 5d54e7cf6823..9547f12a5299 100644 --- a/arch/sw_64/kernel/machine_kexec.c +++ b/arch/sw_64/kernel/machine_kexec.c @@ -155,8 +155,10 @@ static void machine_crash_nonpanic_core(void *unused) atomic_dec(&waiting_for_crash_ipi); while (READ_ONCE(smp_rcb->ready) != 0) mdelay(1); - if (cpu != 0) - reset_cpu(cpu); + if (cpu != 0) { + while (1) + cpu_relax(); + } else machine_kexec(kexec_crash_image); } @@ -209,8 +211,10 @@ void machine_crash_shutdown(struct pt_regs *regs) pr_info("Loading crashdump kernel...\n"); #ifdef CONFIG_SMP WRITE_ONCE(smp_rcb->ready, 0); - if (cpu != 0) - reset_cpu(cpu); + if (cpu != 0) { + while (1) + cpu_relax(); + } #endif } -- Gitee From da5f6460871125a057e76a14ea54fc9d5dcaa611 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 8 Jul 2025 16:31:40 +0800 Subject: [PATCH 05/18] sw64: kvm: enable dirty log gradually in small chunks for core4 Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- When enabling dirty log for the first time, initialize all the bits of the dirty bitmap to 1, and do not write protect the pages. Instead, set write protection in small chunks during subsequent dirty log clearing, thereby reducing the time taken of kvm->mmu_lock. Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/kvm_host.h | 4 ++++ arch/sw_64/kvm/mmu.c | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/arch/sw_64/include/asm/kvm_host.h b/arch/sw_64/include/asm/kvm_host.h index cf0009f2d365..1d475442b795 100644 --- a/arch/sw_64/include/asm/kvm_host.h +++ b/arch/sw_64/include/asm/kvm_host.h @@ -51,6 +51,10 @@ #define KVM_HALT_POLL_NS_DEFAULT 0 #define KVM_IRQCHIP_NUM_PINS 256 + +#define KVM_DIRTY_LOG_MANUAL_CAPS (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \ + KVM_DIRTY_LOG_INITIALLY_SET) + /* KVM Hugepage definitions for sw64 */ #define KVM_NR_PAGE_SIZES 3 #define KVM_HPAGE_GFN_SHIFT(x) (((x) - 1) * 9) diff --git a/arch/sw_64/kvm/mmu.c b/arch/sw_64/kvm/mmu.c index 24f6bc3545b4..f853069de47b 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -546,6 +546,14 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, if (change == KVM_MR_FLAGS_ONLY && (!(old->flags & KVM_MEM_LOG_DIRTY_PAGES) && new->flags & KVM_MEM_LOG_DIRTY_PAGES)) { kvm_mark_migration(kvm, 1); + + /* + * Initially-all-set does not require write protecting any page, + * because they're all assumed to be dirty. + */ + if (kvm_dirty_log_manual_protect_and_init_set(kvm)) + return; + kvm_mmu_wp_memory_region(kvm, new->id); } -- Gitee From 2766832596fb84e582fca11da6b349077067f5eb Mon Sep 17 00:00:00 2001 From: Yu Jiayi Date: Wed, 16 Jul 2025 16:49:12 +0800 Subject: [PATCH 06/18] sw64: kvm: fix undefined error with ftrace disabled Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- The previous commit b486f4c2d424 ("sw64: kvm: fix perf kvm support") introduces calls to some macros and functions when CONFIG_GUEST_PERF_EVENTS=y. However, the head file that defines them is not included when closed ftrace build option. So, we add the introduction of the head file. Signed-off-by: Yu Jiayi Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/kvm_host.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/sw_64/include/asm/kvm_host.h b/arch/sw_64/include/asm/kvm_host.h index 1d475442b795..35c8bf9fd515 100644 --- a/arch/sw_64/include/asm/kvm_host.h +++ b/arch/sw_64/include/asm/kvm_host.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include -- Gitee From b320d72ae0c5e174c7addcefcf0b1e98f2a8d257 Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Tue, 17 Jun 2025 14:16:56 +0800 Subject: [PATCH 07/18] =?UTF-8?q?sw64:=20kvm:=20save=20the=20virtual=C2=A0?= =?UTF-8?q?address=20of=20irqs=5Fpending=20in=20vcpucb?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- The format of virtual address may change in the future. Add an irqs_addr member in vcb to save the virtual address of irqs_pending, so hmcode can get the correct virtual address by accessing the physical address. To distinguish this feature, change the value of feat_vint to 2. Signed-off-by: Lei Yilong Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/vcpu.h | 8 ++++---- arch/sw_64/kvm/kvm_core4.c | 2 ++ arch/sw_64/kvm/sw64.c | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/arch/sw_64/include/asm/vcpu.h b/arch/sw_64/include/asm/vcpu.h index b069031add39..38066427afdb 100644 --- a/arch/sw_64/include/asm/vcpu.h +++ b/arch/sw_64/include/asm/vcpu.h @@ -110,10 +110,10 @@ struct vcpucb { unsigned long csr_earg2; unsigned long csr_scratch; unsigned long atc; - unsigned long reserved1[10]; - /* Pending virtual interrupts */ - DECLARE_BITMAP(irqs_pending, CORE4VM_IRQS); - unsigned long reserved2[31]; + unsigned long reserved1[10]; /* USE IN HMCODE */ + DECLARE_BITMAP(irqs_pending, CORE4VM_IRQS); /* Pending virtual interrupts */ + unsigned long irqs_addr; + unsigned long reserved2[30]; }; #endif diff --git a/arch/sw_64/kvm/kvm_core4.c b/arch/sw_64/kvm/kvm_core4.c index 98fdbfe88fed..cea377ac265b 100644 --- a/arch/sw_64/kvm/kvm_core4.c +++ b/arch/sw_64/kvm/kvm_core4.c @@ -97,6 +97,8 @@ long kvm_sw64_set_vcb(struct file *filp, unsigned long arg) set_timer(vcpu, 200000000); vcpu->arch.vcb.migration_mark = 0; } + + vcpu->arch.vcb.irqs_addr = (unsigned long)&vcpu->arch.vcb.irqs_pending; return 0; } diff --git a/arch/sw_64/kvm/sw64.c b/arch/sw_64/kvm/sw64.c index 19c0449b59dc..73c547fb674c 100644 --- a/arch/sw_64/kvm/sw64.c +++ b/arch/sw_64/kvm/sw64.c @@ -191,7 +191,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) return -EINVAL; feature_vint = (cpuid(GET_FEATURES, 0) & CPU_FEAT_VINT); - smp_rcb->feat_vint = 1; + smp_rcb->feat_vint = 2; return kvm_sw64_init_vm(kvm); } -- Gitee From c3846fba9e2e43dc0089fe679eaea7ca736c4a7e Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 26 Jun 2025 14:19:29 +0800 Subject: [PATCH 08/18] sw64: cpufreq: using PLL0 to provide clock for idle cores Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- To reduce the power consumption of the Sunway platform when idle, PLL0 is used to provide clock for idle cores, and PLL0 always maintains the lowest frequency. Use PLL2 to provide clock for running cores, while PLL1 remains stable at all times. Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/cpufreq/sunway-cpufreq.c | 118 +++++++++++++++++++------------ 1 file changed, 72 insertions(+), 46 deletions(-) diff --git a/drivers/cpufreq/sunway-cpufreq.c b/drivers/cpufreq/sunway-cpufreq.c index ba12dad3b28b..a68ff16efa66 100644 --- a/drivers/cpufreq/sunway-cpufreq.c +++ b/drivers/cpufreq/sunway-cpufreq.c @@ -19,6 +19,8 @@ #define CLK_LV1_SEL_MUXB (0x1UL << 3) #define OFFSET_CLU_LV1_SEL 0x3a80UL +#define OFFSET_CLU_LV2_SEL_H 0x3a00UL +#define OFFSET_CLU_LV2_SEL_L 0x3b00UL #define OFFSET_CLK_CTL 0x3b80UL /* @@ -31,16 +33,20 @@ .driver_data = (mv) \ } +enum sunway_cpu_pll { + SUNWAY_CPU_PLL0 = 0, + SUNWAY_CPU_PLL1 = 1, + SUNWAY_CPU_PLL2 = 2 +}; + #ifdef CONFIG_PLATFORM_JUNZHANG -#define CLK0_PROTECT (0x1UL << 0) -#define CLK2_PROTECT (0x1UL << 32) -#define CORE_CLK2_VALID (0x1UL << 33) -#define CORE_CLK2_RESET (0x1UL << 34) -#define CORE_CLK2_LOCK (0x1UL << 35) -#define CORE_PLL0_CFG_SHIFT 4 -#define CORE_PLL1_CFG_SHIFT 20 -#define CORE_PLL2_CFG_SHIFT 36 -#define CORE_PLL2_CFG_MASK 0x1f + +#define CLK_PROTECT(pll) (0x1UL << (16 * (pll))) +#define CLK_VALID(pll) (0x1UL << (1 + 16 * (pll))) +#define CLK_RESET(pll) (0x1UL << (2 + 16 * (pll))) +#define CLK_LOCK(pll) (0x1UL << (3 + 16 * (pll))) +#define PLL_CFG_SHIFT(pll) (4 + 16 * (pll)) +#define CORE_PLL_CFG_MASK 0x1f struct cpufreq_frequency_table freq_table[] = { {0, 0, CPUFREQ_ENTRY_INVALID}, /* 200Mhz is ignored */ @@ -77,19 +83,17 @@ struct cpufreq_frequency_table freq_table[] = { FV(2850, 0), {0, 0, CPUFREQ_TABLE_END}, }; + #endif #ifdef CONFIG_PLATFORM_XUELANG -#define CLK_PROTECT (0x1UL << 0) -#define CLK0_PROTECT CLK_PROTECT -#define CLK2_PROTECT CLK_PROTECT -#define CORE_CLK2_VALID (0x1UL << 15) -#define CORE_CLK2_RESET (0x1UL << 16) -#define CORE_CLK2_LOCK (0x1UL << 17) -#define CORE_PLL0_CFG_SHIFT 4 -#define CORE_PLL1_CFG_SHIFT 11 -#define CORE_PLL2_CFG_SHIFT 18 -#define CORE_PLL2_CFG_MASK 0xf + +#define CLK_PROTECT(pll) (0x1UL << 0) +#define CLK_VALID(pll) (0x1UL << (1 + 7 * (pll))) +#define CLK_RESET(pll) (0x1UL << (2 + 7 * (pll))) +#define CLK_LOCK(pll) (0x1UL << (3 + 7 * (pll))) +#define PLL_CFG_SHIFT(pll) (4 + 7 * (pll)) +#define CORE_PLL_CFG_MASK 0xf struct cpufreq_frequency_table freq_table[] = { {0, 0, CPUFREQ_ENTRY_INVALID}, /* 200Mhz is ignored */ @@ -128,6 +132,7 @@ static void __init fill_freq_table(struct cpufreq_frequency_table *ft) for (i = 3; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) freq_table[i].frequency = freq_off * 38 + ((i - 3) * freq_off); } + #endif static unsigned int sunway_get_rate(struct cpufreq_policy *policy) @@ -141,8 +146,8 @@ static unsigned int sunway_get_rate(struct cpufreq_policy *policy) spbu_base = misc_platform_get_spbu_base(node); /* PLL2 provides working frequency for core */ - val = readq(spbu_base + OFFSET_CLK_CTL) >> CORE_PLL2_CFG_SHIFT; - val &= CORE_PLL2_CFG_MASK; + val = readq(spbu_base + OFFSET_CLK_CTL) >> PLL_CFG_SHIFT(SUNWAY_CPU_PLL2); + val &= CORE_PLL_CFG_MASK; for (i = 0; ft[i].frequency != CPUFREQ_TABLE_END; i++) { if (val == i) { @@ -155,41 +160,57 @@ static unsigned int sunway_get_rate(struct cpufreq_policy *policy) return 0; } -static int sunway_set_rate(struct cpufreq_policy *policy, unsigned int index) +static int sunway_update_pll_cfg(struct cpufreq_policy *policy, + enum sunway_cpu_pll pll, unsigned long pll_cfg) { - int retry, node; + int retry = 0, node; void __iomem *spbu_base; node = per_cpu(hard_node_id, policy->cpu); spbu_base = misc_platform_get_spbu_base(node); - /* select PLL0/PLL1 */ - writeq(CLK_LV1_SEL_PROTECT, spbu_base + OFFSET_CLU_LV1_SEL); - /* reset PLL2 */ - writeq(CLK2_PROTECT | CORE_CLK2_RESET | CORE_CLK2_VALID, spbu_base + OFFSET_CLK_CTL); - /* configure PLL2_CFG */ - writeq(CLK2_PROTECT | CORE_CLK2_VALID | (unsigned long)index << CORE_PLL2_CFG_SHIFT, + /* PLL1 should keep stable */ + if (WARN_ON(pll == SUNWAY_CPU_PLL1)) + return -EINVAL; + + if (pll == SUNWAY_CPU_PLL0) { + /* LV1 MUXA select PLL2, LV1 MUXB select PLL2 */ + writeq(CLK_LV1_SEL_MUXA | CLK_LV1_SEL_MUXB | CLK_LV1_SEL_PROTECT, + spbu_base + OFFSET_CLU_LV1_SEL); + } else if (pll == SUNWAY_CPU_PLL2) { + /* LV1 MUXA keep PLL0 selected, LV1 MUXB select PLL1 */ + writeq(CLK_LV1_SEL_PROTECT, spbu_base + OFFSET_CLU_LV1_SEL); + } + + /* Reset PLL */ + writeq(CLK_PROTECT(pll) | CLK_RESET(pll) | CLK_VALID(pll), spbu_base + OFFSET_CLK_CTL); - udelay(1); - /* reset over */ - writeq(CORE_CLK2_VALID, spbu_base + OFFSET_CLK_CTL); - retry = 0; + /* Configure PLL */ + writeq(CLK_PROTECT(pll) | CLK_VALID(pll) | pll_cfg << PLL_CFG_SHIFT(pll), + spbu_base + OFFSET_CLK_CTL); + + udelay(2); + + /* Reset over */ + writeq(CLK_VALID(pll), spbu_base + OFFSET_CLK_CTL); + + /* Wait until PLL stable */ while (retry < MAX_RETRY) { - if (readq(spbu_base + OFFSET_CLK_CTL) & CORE_CLK2_LOCK) + if (readq(spbu_base + OFFSET_CLK_CTL) & CLK_LOCK(pll)) break; retry++; udelay(100); } - if (retry == MAX_RETRY) + if (pll_cfg && (retry == MAX_RETRY)) return -ETIME; - /* configure over */ + /* Configure over */ writeq(0, spbu_base + OFFSET_CLK_CTL); - /* select PLL2/PLL2 */ - writeq(CLK_LV1_SEL_MUXA | CLK_LV1_SEL_MUXB | CLK_LV1_SEL_PROTECT, - spbu_base + OFFSET_CLU_LV1_SEL); + + /* LV1 MUXA select PLL0, LV1 MUXB select PLL2 */ + writeq(CLK_LV1_SEL_MUXB | CLK_LV1_SEL_PROTECT, spbu_base + OFFSET_CLU_LV1_SEL); return 0; } @@ -210,23 +231,18 @@ static unsigned int sunway_cpufreq_get(unsigned int cpu) static int sunway_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { - int ret; unsigned int cpu = policy->cpu; if (!cpu_online(cpu)) return -ENODEV; - /* setting the cpu frequency */ - ret = sunway_set_rate(policy, index); - if (ret) - return ret; - - return 0; + return sunway_update_pll_cfg(policy, SUNWAY_CPU_PLL2, index); } static int sunway_cpufreq_init(struct cpufreq_policy *policy) { int cpu, node; + void __iomem *spbu_base; node = per_cpu(hard_node_id, policy->cpu); @@ -237,6 +253,16 @@ static int sunway_cpufreq_init(struct cpufreq_policy *policy) policy->freq_table = freq_table; + spbu_base = misc_platform_get_spbu_base(node); + + /* LV2 MUX select the clock output by LV1 MUXB as working freq */ + writeq(~0ULL, spbu_base + OFFSET_CLU_LV2_SEL_L); + if (is_junzhang_v1() || is_junzhang_v2()) + writeq(~0ULL, spbu_base + OFFSET_CLU_LV2_SEL_H); + + /* Set PLL0 to the lowest freq */ + sunway_update_pll_cfg(policy, SUNWAY_CPU_PLL0, 0); + return 0; } -- Gitee From 8e91ee62306d930512470a5daade0b673ed83e1e Mon Sep 17 00:00:00 2001 From: Gu Yuchen Date: Wed, 23 Jul 2025 09:58:13 +0800 Subject: [PATCH 09/18] sw64: fix incorrect macro definitions for sw64 in bpf_tracing.h Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- Fix incorrect macro definitions for sw64 in bpf_tracing.h. Signed-off-by: Gu Yuchen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- tools/lib/bpf/bpf_tracing.h | 46 ++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/tools/lib/bpf/bpf_tracing.h b/tools/lib/bpf/bpf_tracing.h index 8d34cb534ca6..48d3464204a0 100644 --- a/tools/lib/bpf/bpf_tracing.h +++ b/tools/lib/bpf/bpf_tracing.h @@ -450,30 +450,28 @@ struct pt_regs___arm64 { #elif defined(bpf_target_sw64) /* sw64 provides struct user_pt_regs instead of struct pt_regs to userspace */ -struct pt_regs; -#define PT_REGS_SW64 const volatile struct user_pt_regs -#define PT_REGS_PARM1(x) (((PT_REGS_SW64 *)(x))->regs[16]) -#define PT_REGS_PARM2(x) (((PT_REGS_SW64 *)(x))->regs[17]) -#define PT_REGS_PARM3(x) (((PT_REGS_SW64 *)(x))->regs[18]) -#define PT_REGS_PARM4(x) (((PT_REGS_SW64 *)(x))->regs[19]) -#define PT_REGS_PARM5(x) (((PT_REGS_SW64 *)(x))->regs[20]) -#define PT_REGS_RET(x) (((PT_REGS_SW64 *)(x))->regs[26]) -/* Works only with CONFIG_FRAME_POINTER */ -#define PT_REGS_FP(x) (((PT_REGS_SW64 *)(x))->regs[15]) -#define PT_REGS_RC(x) (((PT_REGS_SW64 *)(x))->regs[0]) -#define PT_REGS_SP(x) (((PT_REGS_SW64 *)(x))->regs[30]) -#define PT_REGS_IP(x) (((PT_REGS_SW64 *)(x))->pc) - -#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[16]) -#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[17]) -#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[18]) -#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[19]) -#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[20]) -#define PT_REGS_RET_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[26]) -#define PT_REGS_FP_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[15]) -#define PT_REGS_RC_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[0]) -#define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), regs[30]) -#define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_SW64 *)(x), pc) +#define __PT_REGS_CAST(x) ((const struct user_pt_regs *)(x)) +#define __PT_PARM1_REG regs[16] +#define __PT_PARM2_REG regs[17] +#define __PT_PARM3_REG regs[18] +#define __PT_PARM4_REG regs[19] +#define __PT_PARM5_REG regs[20] +#define __PT_PARM6_REG regs[21] + +/* sw64 does not select ARCH_HAS_SYSCALL_WRAPPER. */ +#define PT_REGS_SYSCALL_REGS(ctx) ctx +#define __PT_PARM1_SYSCALL_REG __PT_PARM1_REG +#define __PT_PARM2_SYSCALL_REG __PT_PARM2_REG +#define __PT_PARM3_SYSCALL_REG __PT_PARM3_REG +#define __PT_PARM4_SYSCALL_REG __PT_PARM4_REG +#define __PT_PARM5_SYSCALL_REG __PT_PARM5_REG +#define __PT_PARM6_SYSCALL_REG __PT_PARM6_REG + +#define __PT_RET_REG regs[26] +#define __PT_FP_REG regs[15] +#define __PT_RC_REG regs[0] +#define __PT_SP_REG regs[30] +#define __PT_IP_REG pc #endif -- Gitee From 3488a3cfbe9912837ba496d51a7364450c06707a Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 23 Jul 2025 10:31:44 +0800 Subject: [PATCH 10/18] sw64: efi: remove meaningless code from asm/efi.h Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/efi.h | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/arch/sw_64/include/asm/efi.h b/arch/sw_64/include/asm/efi.h index ef2eda461f94..f2a470127c47 100644 --- a/arch/sw_64/include/asm/efi.h +++ b/arch/sw_64/include/asm/efi.h @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0 */ + #ifndef _ASM_SW64_EFI_H #define _ASM_SW64_EFI_H -#include #include #ifdef CONFIG_EFI @@ -28,14 +28,4 @@ extern unsigned long sunway_bios_version; /* arch specific definitions used by the stub code */ -/* - * AArch64 requires the DTB to be 8-byte aligned in the first 512MiB from - * start of kernel and may not cross a 2MiB boundary. We set alignment to - * 2MiB so we know it won't cross a 2MiB boundary. - */ -#define EFI_FDT_ALIGN SZ_2M /* used by allocate_new_fdt_and_exit_boot() */ -#define MAX_FDT_OFFSET SZ_512M - -#define efi_call_early(f, ...) sys_table_arg->boottime->f(__VA_ARGS__) - #endif /* _ASM_SW64_EFI_H */ -- Gitee From e7d67a42683264e04bfe5a86387d5895d2438ea6 Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Tue, 29 Jul 2025 07:00:40 +0000 Subject: [PATCH 11/18] sw64: crypto: implement crc32 assembly optimization Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- Optimize crc32 and crc32c algorithms using CRC32[BHWL] and CRC32C[BHWL] instructions in Core4. Signed-off-by: Xu Yiwei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/Kconfig | 1 + arch/sw_64/Makefile | 1 + arch/sw_64/crypto/Kconfig | 15 ++++++++++ arch/sw_64/crypto/Makefile | 1 + arch/sw_64/crypto/crc32.S | 19 +++++++++++++ arch/sw_64/crypto/crc32_template.S | 44 ++++++++++++++++++++++++++++++ arch/sw_64/crypto/crc32c.S | 19 +++++++++++++ crypto/Kconfig | 3 ++ 8 files changed, 103 insertions(+) create mode 100644 arch/sw_64/crypto/Kconfig create mode 100644 arch/sw_64/crypto/Makefile create mode 100644 arch/sw_64/crypto/crc32.S create mode 100644 arch/sw_64/crypto/crc32_template.S create mode 100644 arch/sw_64/crypto/crc32c.S diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index be41bac8cbe9..bcad24f568d0 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -148,6 +148,7 @@ config SW64 select SW64_TIMER select SWIOTLB select THREAD_INFO_IN_TASK + select CRYPTO_CRC32_SW64 if !SUBARCH_C3B config LOCKDEP_SUPPORT def_bool y diff --git a/arch/sw_64/Makefile b/arch/sw_64/Makefile index 41b90403ee3c..c2d3e332f922 100644 --- a/arch/sw_64/Makefile +++ b/arch/sw_64/Makefile @@ -42,6 +42,7 @@ head-y := arch/sw_64/kernel/head.o core-y += arch/sw_64/ drivers-$(CONFIG_PCI) += arch/sw_64/pci/ libs-y += arch/sw_64/lib/ +drivers-y += arch/sw_64/crypto/ # export what is needed by arch/sw_64/boot/Makefile LIBS_Y := $(patsubst %/, %/lib.a, $(libs-y)) diff --git a/arch/sw_64/crypto/Kconfig b/arch/sw_64/crypto/Kconfig new file mode 100644 index 000000000000..00d2e92be324 --- /dev/null +++ b/arch/sw_64/crypto/Kconfig @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 + +menu "Accelerated Cryptographic Algorithms for CPU (SW64)" + +config CRYPTO_CRC32_SW64 + tristate "CRC32c and CRC32" + depends on SW64 && !SUBARCH_C3B + select CRC32 + select CRYPTO_HASH + help + CRC32c and CRC32 CRC algorithms + + Architecture: SW64 with CRC32 instructions + +endmenu diff --git a/arch/sw_64/crypto/Makefile b/arch/sw_64/crypto/Makefile new file mode 100644 index 000000000000..ed00a8978d1a --- /dev/null +++ b/arch/sw_64/crypto/Makefile @@ -0,0 +1 @@ +lib-$(CONFIG_CRYPTO_CRC32_SW64) += crc32.o crc32c.o diff --git a/arch/sw_64/crypto/crc32.S b/arch/sw_64/crypto/crc32.S new file mode 100644 index 000000000000..2daf961208bd --- /dev/null +++ b/arch/sw_64/crypto/crc32.S @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#define CRC32OP_L(x, y, z) crc32l x, y, z +#define CRC32OP_W(x, y, z) crc32w x, y, z +#define CRC32OP_H(x, y, z) crc32h x, y, z +#define CRC32OP_B(x, y, z) crc32b x, y, z + + .text + .global crc32_le + .align 4 + .ent crc32_le +crc32_le: + .prologue 0 +#include "crc32_template.S" + .end crc32_le + +#undef CRC32OP_L +#undef CRC32OP_W +#undef CRC32OP_H +#undef CRC32OP_B diff --git a/arch/sw_64/crypto/crc32_template.S b/arch/sw_64/crypto/crc32_template.S new file mode 100644 index 000000000000..56e56ac42014 --- /dev/null +++ b/arch/sw_64/crypto/crc32_template.S @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * $16: crc + * $17: buf + * $18: len + */ + + beq $18, $return_crc + srl $18, 4, $19 + beq $19, $check_8B + + .align 4 +$loop_16B: + ldl_a $1, 8($17) + ldl_a $2, 8($17) + CRC32OP_L($16, $1, $16) + CRC32OP_L($16, $2, $16) + subl $19, 1, $19 + bne $19, $loop_16B + +$check_8B: + and $18, 8, $3 + beq $3, $check_4B + ldl_a $1, 8($17) + CRC32OP_L($16, $1, $16) +$check_4B: + and $18, 4, $3 + beq $3, $check_2B + ldw_a $1, 4($17) + CRC32OP_W($16, $1, $16) +$check_2B: + and $18, 2, $3 + beq $3, $check_1B + ldhu_a $1, 2($17) + CRC32OP_H($16, $1, $16) +$check_1B: + and $18, 1, $3 + beq $3, $return_crc + ldbu_a $1, 1($17) + CRC32OP_B($16, $1, $16) + +$return_crc: + mov $16, $0 + ret diff --git a/arch/sw_64/crypto/crc32c.S b/arch/sw_64/crypto/crc32c.S new file mode 100644 index 000000000000..1005bc113ebb --- /dev/null +++ b/arch/sw_64/crypto/crc32c.S @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#define CRC32OP_L(x, y, z) crc32cl x, y, z +#define CRC32OP_W(x, y, z) crc32cw x, y, z +#define CRC32OP_H(x, y, z) crc32ch x, y, z +#define CRC32OP_B(x, y, z) crc32cb x, y, z + + .text + .global __crc32c_le + .align 4 + .ent __crc32c_le +__crc32c_le: + .prologue 0 +#include "crc32_template.S" + .end __crc32c_le + +#undef CRC32OP_L +#undef CRC32OP_W +#undef CRC32OP_H +#undef CRC32OP_B diff --git a/crypto/Kconfig b/crypto/Kconfig index fc0f75d8be01..c1815d86bd7b 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1446,6 +1446,9 @@ endif if X86 source "arch/x86/crypto/Kconfig" endif +if SW64 +source "arch/sw_64/crypto/Kconfig" +endif endif source "drivers/crypto/Kconfig" -- Gitee From 4c1742f729361216c306549f8eef9f447580a756 Mon Sep 17 00:00:00 2001 From: Cui Mingrui Date: Wed, 30 Jul 2025 06:13:15 +0000 Subject: [PATCH 12/18] sw64: selftests/net: add sw64 support for io_uring_zerocopy_tx Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- The io_uring_zerocopy_tx test fails on sw64 architecture due to missing arch-specific io_uring syscall numbers. This patch adds sw64 syscall definitions to fix this issue. Signed-off-by: Cui Mingrui Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- tools/testing/selftests/net/io_uring_zerocopy_tx.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tools/testing/selftests/net/io_uring_zerocopy_tx.c b/tools/testing/selftests/net/io_uring_zerocopy_tx.c index 154287740172..dd7c23066ab7 100644 --- a/tools/testing/selftests/net/io_uring_zerocopy_tx.c +++ b/tools/testing/selftests/net/io_uring_zerocopy_tx.c @@ -120,6 +120,16 @@ struct io_uring { # ifndef __NR_io_uring_register # define __NR_io_uring_register 537 # endif +#elif defined(__sw_64__) +# ifndef __NR_io_uring_setup +# define __NR_io_uring_setup 272 +# endif +# ifndef __NR_io_uring_enter +# define __NR_io_uring_enter 273 +# endif +# ifndef __NR_io_uring_register +# define __NR_io_uring_register 274 +# endif #else /* !__alpha__ */ # ifndef __NR_io_uring_setup # define __NR_io_uring_setup 425 -- Gitee From 2c6151b21916f01182af6f63440dd24b67885f53 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 31 Jul 2025 09:08:43 +0800 Subject: [PATCH 13/18] sw64: fix missing characters for sw64_rrk Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- When LOG_CONT is set, sw64_rrk will lose characters when saving logs. Fixes: 4f54079bec6e ("sw64: improve sw64_rrk") Signed-off-by: Jing Li Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- kernel/printk/printk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index de9f3fc6ec2b..3fdf3cb3b743 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2258,7 +2258,7 @@ int vprintk_store(int facility, int level, } #ifdef CONFIG_SW64_RRK - sw64_rrk_store(&r.text_buf[r.info->text_len], text_len, + sw64_rrk_store(&r.text_buf[r.info->text_len - text_len], text_len, r.info->ts_nsec, -1, e.id, !!(flags & LOG_NEWLINE)); #endif -- Gitee From 182718d1631ddc6d01c283e1b3168efdc7bd940c Mon Sep 17 00:00:00 2001 From: Wang Yicheng Date: Wed, 30 Jul 2025 16:33:44 +0800 Subject: [PATCH 14/18] sw64: cpuidle: add dedicated driver Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- Introduce a cpuidle driver for SW64 platform. This driver defines platform-specific idle states and integrates with generic cpuidle framework. Currently, CONFIG_CPU_FREQ must be enabled to ensure that the cpuidle framework works correctly on SW64 platform. Signed-off-by: Wang Yicheng Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/cpuidle/Kconfig | 5 + drivers/cpuidle/Kconfig.sw64 | 6 ++ drivers/cpuidle/Makefile | 4 + drivers/cpuidle/cpuidle-sw64.c | 172 +++++++++++++++++++++++++++++++++ 4 files changed, 187 insertions(+) create mode 100644 drivers/cpuidle/Kconfig.sw64 create mode 100644 drivers/cpuidle/cpuidle-sw64.c diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index c1bebadf22bc..2e8e0970c282 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -70,6 +70,11 @@ depends on RISCV source "drivers/cpuidle/Kconfig.riscv" endmenu +menu "SW64 CPU Idle Drivers" +depends on SW64 +source "drivers/cpuidle/Kconfig.sw64" +endmenu + config HALTPOLL_CPUIDLE tristate "Haltpoll cpuidle driver" depends on ARCH_CPUIDLE_HALTPOLL && ARCH_HAS_OPTIMIZED_POLL diff --git a/drivers/cpuidle/Kconfig.sw64 b/drivers/cpuidle/Kconfig.sw64 new file mode 100644 index 000000000000..0f23175ad36a --- /dev/null +++ b/drivers/cpuidle/Kconfig.sw64 @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# SW64 CPU Idle drivers +# +config SW64_CPUIDLE + bool "Generic SW64 CPU idle Driver" diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index f29dfd1525b0..200b6de3847e 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -39,3 +39,7 @@ obj-$(CONFIG_POWERNV_CPUIDLE) += cpuidle-powernv.o ############################################################################### # RISC-V drivers obj-$(CONFIG_RISCV_SBI_CPUIDLE) += cpuidle-riscv-sbi.o + +############################################################################### +# SW64 drivers +obj-$(CONFIG_SW64_CPUIDLE) += cpuidle-sw64.o diff --git a/drivers/cpuidle/cpuidle-sw64.c b/drivers/cpuidle/cpuidle-sw64.c new file mode 100644 index 000000000000..7af9d75185c1 --- /dev/null +++ b/drivers/cpuidle/cpuidle-sw64.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0 +/* SW64 generic CPU idle driver */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_NODES 4 +#define CORE_ID_BITMASK 0x1F +#define MAX_NR_LOCKS_PER_NODE 64 + +extern void arch_cpu_idle(void); +static void __iomem *spbu_base[MAX_NODES]; +static int cpu_siblings[NR_CPUS]; +static bool cpu_deeper_states[NR_CPUS]; +static spinlock_t per_core_lock[MAX_NODES][MAX_NR_LOCKS_PER_NODE]; + +/* CLU_LV2_SEL offset for LV2 MUX */ +#define OFFSET_CLU_LV2_SELH 0x3a00UL +#define OFFSET_CLU_LV2_SELL 0x3b00UL +#define OFFSET_CLU_LV2(core) ((core) > 31 ? OFFSET_CLU_LV2_SELH : OFFSET_CLU_LV2_SELL) + +static bool can_switch_freq(int cpu_sibling) +{ + return cpu_sibling < 0 || + !cpu_online(cpu_sibling) || + cpu_deeper_states[cpu_sibling]; +} + +/* + * sw64_do_deeper_idle + * + * Handles frequency scaling by writing specific bits to + * CLU_LV2_SEL when CPU core wants a deeper idle state. + */ +static void sw64_do_deeper_idle(int cpu) +{ + int core_id, node_id, cpu_sibling; + unsigned long flags; + u64 freq_scaling; + + core_id = rcid_to_core_id(cpu_to_rcid(cpu)); + node_id = rcid_to_domain_id(cpu_to_rcid(cpu)); + cpu_sibling = cpu_siblings[cpu]; + + /* downshift frequency before idle if possible*/ + spin_lock_irqsave(&per_core_lock[node_id][core_id], flags); + cpu_deeper_states[cpu] = true; + if (can_switch_freq(cpu_sibling)) { + freq_scaling = 0x1UL << (2 * (core_id & CORE_ID_BITMASK)); + writeq(freq_scaling, spbu_base[node_id] + OFFSET_CLU_LV2(core_id)); + } + spin_unlock_irqrestore(&per_core_lock[node_id][core_id], flags); + + arch_cpu_idle(); + + /* upshift frequency after idle */ + spin_lock_irqsave(&per_core_lock[node_id][core_id], flags); + cpu_deeper_states[cpu] = false; + freq_scaling = 0x3UL << (2 * (core_id & CORE_ID_BITMASK)); + writeq(freq_scaling, spbu_base[node_id] + OFFSET_CLU_LV2(core_id)); + spin_unlock_irqrestore(&per_core_lock[node_id][core_id], flags); +} + +/* + * sw64_idle_enter - Programs CPU to enter the specified state + * + * dev: cpuidle device + * drv: cpuidle driver + * index: state index + * + * Called from the cpuidle framework to program the device to the + * specified target state selected by the governor. + */ +static int sw64_idle_enter(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) +{ + + int cpu = smp_processor_id(); + bool deeper_idle = IS_ENABLED(CONFIG_SW64_CPUFREQ); + + if (!is_in_host()) { + arch_cpu_idle(); + return index; + } + + if (cpu == 0) + deeper_idle = false; + + if (index > 0 && deeper_idle) + sw64_do_deeper_idle(cpu); + else + arch_cpu_idle(); + + return index; +} + +static struct cpuidle_driver sw64_idle_driver = { + .name = "sw64_idle", + .owner = THIS_MODULE, + /* + * State at index 0 is halt and considered standard on + * all SW64 platforms. State at index 1 represents an + * idle state where the CPU enters a halt state combined + * with frequency scaling, which means the CPU core run + * at a reduced frequnecy (e.g., 200MHz) to achieve power + * savings. + * + * To enable State 1, CONFIG_SW64_CPUFREQ must be enabled, + * otherwise the required frequency scaling support will + * be unavailable. + */ + .states[0] = { + .name = "idle0", + .desc = "sw64 idle 0", + .exit_latency = 1, + .target_residency = 1, + .enter = sw64_idle_enter, + }, + .states[1] = { + .name = "idle1", + .desc = "sw64 idle 1", + .exit_latency = 100, + .target_residency = 100, + .enter = sw64_idle_enter, + }, + .state_count = 2, + .cpumask = (struct cpumask *) cpu_possible_mask, +}; + +static int get_sibling_cpu(int cpu) +{ + const cpumask_t *mask = topology_sibling_cpumask(cpu); + int sibling; + + for_each_cpu(sibling, mask) { + if (sibling != cpu) + return sibling; + } + + return -1; +} + +static int __init sw64_cpuidle_init(void) +{ + int i, cpu; + int core_id, node_id; + + for_each_online_cpu(cpu) { + cpu_siblings[cpu] = get_sibling_cpu(cpu); + core_id = rcid_to_core_id(cpu_to_rcid(cpu)); + node_id = rcid_to_domain_id(cpu_to_rcid(cpu)); + spin_lock_init(&per_core_lock[node_id][core_id]); + } + + for (i = 0; i < MAX_NODES; ++i) + spbu_base[i] = misc_platform_get_spbu_base(i); + + return cpuidle_register(&sw64_idle_driver, cpu_possible_mask); +} + +static void __exit sw64_cpuidle_exit(void) +{ + cpuidle_unregister(&sw64_idle_driver); +} +device_initcall(sw64_cpuidle_init); -- Gitee From bcd9bbcf48768ff99b02c2f27739b6eed7e6f061 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Fri, 1 Aug 2025 12:01:53 +0800 Subject: [PATCH 15/18] sw64: kvm: remove the duplicated Kconfig selection of KVM Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- Remove the redundantly selected KVM_GENERIC_DIRTYLOG_READ_PROTECT Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/sw_64/kvm/Kconfig b/arch/sw_64/kvm/Kconfig index 124cead28b53..8fef5561516b 100644 --- a/arch/sw_64/kvm/Kconfig +++ b/arch/sw_64/kvm/Kconfig @@ -27,7 +27,6 @@ config KVM select HAVE_KVM_MSI select KVM_VFIO select MMU_NOTIFIER - select KVM_GENERIC_DIRTYLOG_READ_PROTECT select TUN select GENERIC_ALLOCATOR select KVM_GENERIC_DIRTYLOG_READ_PROTECT -- Gitee From a9f5d22b7b9979990ff50f88a69b23c54ba7d58e Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Fri, 1 Aug 2025 09:45:38 +0800 Subject: [PATCH 16/18] sw64: kvm: fix compile error of kvm.ko Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- Export misc_platform_get_intpu_base to ensure the KVM module can resolve the symbol. Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- drivers/platform/sw64/misc-platform.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/sw64/misc-platform.c b/drivers/platform/sw64/misc-platform.c index 4d47ebb90546..af426429ef23 100644 --- a/drivers/platform/sw64/misc-platform.c +++ b/drivers/platform/sw64/misc-platform.c @@ -163,6 +163,7 @@ void __iomem *misc_platform_get_intpu_base(unsigned long node) return intpu_base; } +EXPORT_SYMBOL(misc_platform_get_intpu_base); void __iomem *misc_platform_get_gpio_base(unsigned long node) { -- Gitee From c2b296688d16f29d0b3826db22cf4a6d35e368fb Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Thu, 31 Jul 2025 16:51:49 +0800 Subject: [PATCH 17/18] sw64: kvm: fix missing kvm_unregister_perf_callbacks Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- Commit b486f4c2d424 ("sw64: kvm: fix perf kvm support") missed the kvm_unregister_perf_callbacks() operation, fix it. Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kvm/kvm_core3.c | 2 ++ arch/sw_64/kvm/kvm_core4.c | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/sw_64/kvm/kvm_core3.c b/arch/sw_64/kvm/kvm_core3.c index 378831c21139..910688f915cc 100644 --- a/arch/sw_64/kvm/kvm_core3.c +++ b/arch/sw_64/kvm/kvm_core3.c @@ -383,6 +383,7 @@ static int __init kvm_core3_init(void) if (likely(!ret)) return 0; + kvm_unregister_perf_callbacks(); vmem_exit(); out: bind_vcpu_exit(); @@ -392,6 +393,7 @@ static int __init kvm_core3_init(void) static void __exit kvm_core3_exit(void) { kvm_exit(); + kvm_unregister_perf_callbacks(); vmem_exit(); bind_vcpu_exit(); } diff --git a/arch/sw_64/kvm/kvm_core4.c b/arch/sw_64/kvm/kvm_core4.c index cea377ac265b..a13e9fd57249 100644 --- a/arch/sw_64/kvm/kvm_core4.c +++ b/arch/sw_64/kvm/kvm_core4.c @@ -226,15 +226,18 @@ static int __init kvm_core4_init(void) ret = kvm_init(sizeof(struct kvm_vcpu), 0, THIS_MODULE); - if (ret) - return ret; + if (likely(!ret)) + return 0; - return 0; + kvm_unregister_perf_callbacks(); + + return ret; } static void __exit kvm_core4_exit(void) { kvm_exit(); + kvm_unregister_perf_callbacks(); } module_init(kvm_core4_init); -- Gitee From 6361501a23c3f000596e2ba2bdadd58285926c87 Mon Sep 17 00:00:00 2001 From: Gu Yuchen Date: Mon, 4 Aug 2025 14:00:42 +0800 Subject: [PATCH 18/18] sw64: ptrace: return -EIO in invalid PEEKUSR/POKEUSR requests Sunway inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/ICR460 -------------------------------- When PTRACE_PEEKUSR or PTRACE_POKEUSR operations are called with an out-of-bounds or unaligned address, the system should return -EIO instead of 0. This commit fixes the issue. Signed-off-by: Gu Yuchen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/ptrace.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/sw_64/kernel/ptrace.c b/arch/sw_64/kernel/ptrace.c index 9c5539f58ded..5842fcc5044b 100644 --- a/arch/sw_64/kernel/ptrace.c +++ b/arch/sw_64/kernel/ptrace.c @@ -127,7 +127,9 @@ get_reg_addr(struct task_struct *task, unsigned long regno) unsigned long get_reg(struct task_struct *task, unsigned long regno) { - return *get_reg_addr(task, regno); + unsigned long addr = *get_reg_addr(task, regno); + + return (addr) ? addr : -EIO; } /* @@ -136,8 +138,9 @@ get_reg(struct task_struct *task, unsigned long regno) static int put_reg(struct task_struct *task, unsigned long regno, unsigned long data) { - *get_reg_addr(task, regno) = data; - return 0; + unsigned long addr = *get_reg_addr(task, regno); + + return (addr) ? 0 : -EIO; } static inline int -- Gitee