From acde62868f99502801cc2d58ff2c9888847566d0 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Mon, 14 Jul 2025 10:22:14 +0800 Subject: [PATCH 01/21] anolis: sw64: fix sw64_rrk_store() wrap handling ANBZ: #4688 Make sure we are clearing the rrk area instead of a random area when handling rrk wrap. Fixes: 6f8f839c92d8 ("anolis: 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 560a814a116ca3c48ecd2dab1651da5510c8dd79 Mon Sep 17 00:00:00 2001 From: Mao Minkai Date: Thu, 4 Jul 2024 11:31:16 +0800 Subject: [PATCH 02/21] anolis: sw64: use wait/complete for smp boot ANBZ: #4688 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 d150d81a9129..f31a7c589fb7 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); @@ -136,15 +138,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(); @@ -183,6 +183,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(); @@ -206,7 +210,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. */ @@ -223,17 +226,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 6ad567c1a4a2a75eb296f481f7d5482fe78e3ce6 Mon Sep 17 00:00:00 2001 From: Gu Yuchen Date: Tue, 15 Jul 2025 10:06:46 +0800 Subject: [PATCH 03/21] anolis: sw64: ftrace: add HAVE_DYNAMIC_FTRACE_WITH_ARGS support ANBZ: #4688 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 8bd45cc963a4..6c19a83f6a53 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 ed905e7bdd19dc540a81be3cfd7f5f238c4b89c6 Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Thu, 17 Jul 2025 10:55:50 +0800 Subject: [PATCH 04/21] anolis: sw64: fix guest kdump function ANBZ: #4688 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 ce1ab7d4d996f010bdcf93dfbec240f603b33481 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Tue, 8 Jul 2025 16:31:40 +0800 Subject: [PATCH 05/21] anolis: sw64: kvm: enable dirty log gradually in small chunks for core4 ANBZ: #4688 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 54d361bf193f7fc73aacaa8dd43ffb23094735c3 Mon Sep 17 00:00:00 2001 From: Yu Jiayi Date: Wed, 16 Jul 2025 16:49:12 +0800 Subject: [PATCH 06/21] anolis: sw64: kvm: fix undefined error with ftrace disabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ANBZ: #4688 The previous commit 847888a23ae2 ("anolis: 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 cc49afa6e3206d5df6f526101996c8dbdb6883dc Mon Sep 17 00:00:00 2001 From: Lei Yilong Date: Tue, 17 Jun 2025 14:16:56 +0800 Subject: [PATCH 07/21] =?UTF-8?q?anolis:=20sw64:=20kvm:=20save=20the=20vir?= =?UTF-8?q?tual=C2=A0address=20of=20irqs=5Fpending=20in=20vcpucb?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ANBZ: #4688 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 053115c8284c..1cec96017ef9 100644 --- a/arch/sw_64/kvm/sw64.c +++ b/arch/sw_64/kvm/sw64.c @@ -245,7 +245,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 168cd223248f1063349fa8886a630ca8ea8fa20b Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 26 Jun 2025 14:19:29 +0800 Subject: [PATCH 08/21] anolis: sw64: cpufreq: using PLL0 to provide clock for idle cores ANBZ: #4688 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 21ccbd62f7f85e38fcee676e2974e7bef9d270ba Mon Sep 17 00:00:00 2001 From: Gu Yuchen Date: Wed, 23 Jul 2025 09:58:13 +0800 Subject: [PATCH 09/21] anolis: sw64: fix incorrect macro definitions for sw64 in bpf_tracing.h ANBZ: #4688 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 a747c5f29859ef6b85d9ccdbb6c0a3e35d02ce9b Mon Sep 17 00:00:00 2001 From: Jing Li Date: Wed, 23 Jul 2025 10:31:44 +0800 Subject: [PATCH 10/21] anolis: sw64: efi: remove meaningless code from asm/efi.h ANBZ: #4688 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 98db7f0000cd3f91af1f320ca45296720fb423d9 Mon Sep 17 00:00:00 2001 From: Xu Yiwei Date: Tue, 29 Jul 2025 07:00:40 +0000 Subject: [PATCH 11/21] anolis: sw64: crypto: implement crc32 assembly optimization ANBZ: #4688 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 6c19a83f6a53..314fcdb5cb18 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -154,6 +154,7 @@ config SW64 select HAVE_CONTEXT_TRACKING select HAVE_NMI select HAVE_DMA_CONTIGUOUS + 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 f3c3b6b10daa..d6f1cd2a3338 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 e71fa38be0fa9ed1b8cc2facf7c0ecb31dc83486 Mon Sep 17 00:00:00 2001 From: Cui Mingrui Date: Wed, 30 Jul 2025 06:13:15 +0000 Subject: [PATCH 12/21] anolis: sw64: selftests/net: add sw64 support for io_uring_zerocopy_tx ANBZ: #4688 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 8bc7a9ebf63036b7e2b80935c3e233e00db61d40 Mon Sep 17 00:00:00 2001 From: Jing Li Date: Thu, 31 Jul 2025 09:08:43 +0800 Subject: [PATCH 13/21] anolis: sw64: fix missing characters for sw64_rrk ANBZ: #4688 When LOG_CONT is set, sw64_rrk will lose characters when saving logs. Fixes: 6f8f839c92d8 ("anolis: 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 3e05a5acf979aa168edf4d22bb3c614d51ceb483 Mon Sep 17 00:00:00 2001 From: Wang Yicheng Date: Wed, 30 Jul 2025 16:33:44 +0800 Subject: [PATCH 14/21] anolis: sw64: cpuidle: add dedicated driver ANBZ: #4688 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..ba832dbc8e7b --- /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 enbale 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 b043390d4fa5962c6f6583be64e916b7bae4ce54 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Fri, 1 Aug 2025 12:01:53 +0800 Subject: [PATCH 15/21] anolis: sw64: kvm: remove the duplicated Kconfig selection of KVM ANBZ: #4688 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 7a21ef17b58a862dff825127385e908e408f2682 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Fri, 1 Aug 2025 09:45:38 +0800 Subject: [PATCH 16/21] anolis: sw64: kvm: fix compile error of kvm.ko ANBZ: #4688 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 836242805ae4..4a14aa21b798 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 7252ca0c23bc60c69f20ce38009565eba9bf01c2 Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Thu, 31 Jul 2025 16:51:49 +0800 Subject: [PATCH 17/21] anolis: sw64: kvm: fix missing kvm_unregister_perf_callbacks ANBZ: #4688 Commit 52d59e833fcd ("anolis: 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 3abb99ab8fad884ce3a69ad9df4daf373fc69a67 Mon Sep 17 00:00:00 2001 From: Gu Yuchen Date: Mon, 4 Aug 2025 14:00:42 +0800 Subject: [PATCH 18/21] anolis: sw64: ptrace: return -EIO in invalid PEEKUSR/POKEUSR requests ANBZ: #4688 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 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/sw_64/kernel/ptrace.c b/arch/sw_64/kernel/ptrace.c index 9c5539f58ded..e3c159eb2af7 100644 --- a/arch/sw_64/kernel/ptrace.c +++ b/arch/sw_64/kernel/ptrace.c @@ -127,7 +127,8 @@ 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 +137,8 @@ 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 From c8d5ad3425e1fa25abc9e78f81e5d246533ac879 Mon Sep 17 00:00:00 2001 From: Gu Yuchen Date: Fri, 8 Aug 2025 10:25:55 +0800 Subject: [PATCH 19/21] anolis: sw64: rethook: fix a bug in rethook_trampoline ANBZ: #4688 The load gp instruction is missing in rethook_trampoline, this commit fixes this bug. Signed-off-by: Gu Yuchen Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/kernel/kprobes/rethook_trampoline.S | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/sw_64/kernel/kprobes/rethook_trampoline.S b/arch/sw_64/kernel/kprobes/rethook_trampoline.S index f194237751c3..a77d870628ee 100644 --- a/arch/sw_64/kernel/kprobes/rethook_trampoline.S +++ b/arch/sw_64/kernel/kprobes/rethook_trampoline.S @@ -98,10 +98,12 @@ ENTRY(arch_rethook_trampoline) save_all_base_regs mov $sp, $16 + br $27, 1f +1: ldgp $29, 0($27) call arch_rethook_trampoline_callback mov $0, $26 restore_all_base_regs - ret + ret $31, ($26), 1 ENDPROC(arch_rethook_trampoline) -- Gitee From cbd7c3f9a913429c7e51a8be97ccfa059b816ede Mon Sep 17 00:00:00 2001 From: Min Fanlei Date: Wed, 23 Jul 2025 09:29:44 +0800 Subject: [PATCH 20/21] anolis: sw64: kvm: use read/write spin lock for KVM MMU ANBZ: #4688 This patch replaces MMU spinlock with rwlock. And to reduce MMU lock contention during dirty logging, the permission relaxation operations would be performed under read lock. Signed-off-by: Min Fanlei Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- arch/sw_64/include/asm/kvm_host.h | 2 + arch/sw_64/kvm/mmu.c | 70 ++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 19 deletions(-) diff --git a/arch/sw_64/include/asm/kvm_host.h b/arch/sw_64/include/asm/kvm_host.h index 35c8bf9fd515..7dd763a7d4c2 100644 --- a/arch/sw_64/include/asm/kvm_host.h +++ b/arch/sw_64/include/asm/kvm_host.h @@ -56,6 +56,8 @@ #define KVM_DIRTY_LOG_MANUAL_CAPS (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \ KVM_DIRTY_LOG_INITIALLY_SET) +#define KVM_HAVE_MMU_RWLOCK + /* 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 f853069de47b..28e77cfcaadb 100644 --- a/arch/sw_64/kvm/mmu.c +++ b/arch/sw_64/kvm/mmu.c @@ -237,7 +237,7 @@ static void unmap_apt_range(struct kvm *kvm, phys_addr_t start, u64 size) phys_addr_t addr = start, end = start + size; phys_addr_t next; - assert_spin_locked(&kvm->mmu_lock); + lockdep_assert_held_write(&kvm->mmu_lock); WARN_ON(size & ~PAGE_MASK); pgd = kvm->arch.pgd + pgd_index(addr); @@ -258,7 +258,7 @@ static void unmap_apt_range(struct kvm *kvm, phys_addr_t start, u64 size) * to prevent starvation and lockup detector warnings. */ if (next != end) - cond_resched_lock(&kvm->mmu_lock); + cond_resched_rwlock_write(&kvm->mmu_lock); } while (p4d++, addr = next, addr != end); } @@ -319,12 +319,12 @@ void apt_unmap_vm(struct kvm *kvm) idx = srcu_read_lock(&kvm->srcu); down_read(¤t->mm->mmap_lock); - spin_lock(&kvm->mmu_lock); + write_lock(&kvm->mmu_lock); slots = kvm_memslots(kvm); kvm_for_each_memslot(memslot, bkt, slots) apt_unmap_memslot(kvm, memslot); - spin_unlock(&kvm->mmu_lock); + write_unlock(&kvm->mmu_lock); up_read(¤t->mm->mmap_lock); srcu_read_unlock(&kvm->srcu, idx); } @@ -489,7 +489,7 @@ static void apt_wp_range(struct kvm *kvm, phys_addr_t addr, phys_addr_t end) * that the page tables are not freed while we released * the lock. */ - cond_resched_lock(&kvm->mmu_lock); + cond_resched_rwlock_write(&kvm->mmu_lock); if (!READ_ONCE(kvm->arch.pgd)) break; next = p4d_addr_end(addr, end); @@ -518,9 +518,9 @@ void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot) phys_addr_t start = memslot->base_gfn << PAGE_SHIFT; phys_addr_t end = (memslot->base_gfn + memslot->npages) << PAGE_SHIFT; - spin_lock(&kvm->mmu_lock); + write_lock(&kvm->mmu_lock); apt_wp_range(kvm, start, end); - spin_unlock(&kvm->mmu_lock); + write_unlock(&kvm->mmu_lock); kvm_flush_remote_tlbs(kvm); // 需要通知其他vcpu进行tlb刷新,利用request机制 } @@ -572,10 +572,10 @@ void kvm_arch_flush_shadow_memslot(struct kvm *kvm, gpa_t gpa = slot->base_gfn << PAGE_SHIFT; phys_addr_t size = slot->npages << PAGE_SHIFT; - spin_lock(&kvm->mmu_lock); + write_lock(&kvm->mmu_lock); // flush_apt_tlbs(kvm); unmap_apt_range(kvm, gpa, size); - spin_unlock(&kvm->mmu_lock); + write_unlock(&kvm->mmu_lock); } /** @@ -618,13 +618,13 @@ void kvm_free_apt_pgd(struct kvm *kvm) { void *pgd = NULL; - spin_lock(&kvm->mmu_lock); + write_lock(&kvm->mmu_lock); if (kvm->arch.pgd) { unmap_apt_range(kvm, 0, KVM_PHYS_SIZE); pgd = READ_ONCE(kvm->arch.pgd); kvm->arch.pgd = NULL; } - spin_unlock(&kvm->mmu_lock); + write_unlock(&kvm->mmu_lock); /* Free the HW pgd, one page at a time */ if (pgd) @@ -778,6 +778,19 @@ static bool apt_is_exec(struct kvm *kvm, phys_addr_t addr) return kvm_pte_exec(ptep); } +static bool apt_is_pte(struct kvm *kvm, phys_addr_t addr) +{ + pud_t *pudp; + pmd_t *pmdp; + pte_t *ptep; + + apt_get_leaf_entry(kvm, addr, &pudp, &pmdp, &ptep); + if (ptep) + return true; + + return false; +} + static int apt_set_pte_fast(struct kvm_vcpu *vcpu, struct kvm_mmu_memory_cache *cache, const pte_t *new_pte, unsigned long flags) @@ -785,7 +798,7 @@ static int apt_set_pte_fast(struct kvm_vcpu *vcpu, pud_t *pud; pmd_t *pmd; pte_t *pte, old_pte; - unsigned long as_info, inv_hpa; + unsigned long as_info, inv_hpa, cur_pte; int inv_level; struct kvm *kvm = vcpu->kvm; bool logging_active = flags & KVM_APT_FLAG_LOGGING_ACTIVE; @@ -882,15 +895,18 @@ static int apt_set_pte_fast(struct kvm_vcpu *vcpu, if (pte_val(old_pte) == pte_val(*new_pte)) return 0; - /* Do we need WRITE_ONCE(pte, 0)? */ - set_pte(pte, __pte(0)); + cur_pte = cmpxchg(&pte->pte, pte_val(old_pte), pte_val(*new_pte)); + if (cur_pte != pte_val(old_pte)) + return 0; + kvm_flush_remote_tlbs(kvm); } else { get_page(virt_to_page(pte)); + + /* Do we need WRITE_ONCE(pte, new_pte)? */ + set_pte(pte, *new_pte); } - /* Do we need WRITE_ONCE(pte, new_pte)? */ - set_pte(pte, *new_pte); return 0; } @@ -1210,9 +1226,10 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, unsigned long as_info, access_type; unsigned long mmu_seq, vma_pagesize, flags = 0; struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache; - bool logging_active, write_fault, exec_fault, writable, force_pte; + bool logging_active, write_fault, exec_fault, writable, force_pte, use_read_lock; force_pte = false; + use_read_lock = false; logging_active = memslot_is_logging(kvm, memslot); fault_gpa = vcpu->arch.vcb.fault_gpa; gfn = fault_gpa >> PAGE_SHIFT; @@ -1293,9 +1310,20 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, */ if (!write_fault) writable = false; + + /* Only acquire the read lock if the guest faults on a write to + * a PAGE_SIZE granule when dirty logging is enabled. + */ + if (apt_is_pte(kvm, fault_gpa)) { + use_read_lock = (fault_status == AF_STATUS_FOW && write_fault); + } } - spin_lock(&kvm->mmu_lock); + if (use_read_lock) + read_lock(&kvm->mmu_lock); + else + write_lock(&kvm->mmu_lock); + if (mmu_invalidate_retry(kvm, mmu_seq)) goto out_unlock; @@ -1389,7 +1417,11 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, } out_unlock: - spin_unlock(&kvm->mmu_lock); + if (use_read_lock) + read_unlock(&kvm->mmu_lock); + else + write_unlock(&kvm->mmu_lock); + kvm_release_pfn_clean(pfn); return ret; } -- Gitee From 005cfbd9d59fce90cd113cf96ed68d156740788b Mon Sep 17 00:00:00 2001 From: He Chuyue Date: Tue, 5 Aug 2025 16:41:31 +0800 Subject: [PATCH 21/21] anolis: sw64: perf tools: Add support for get_cpuid_str function ANBZ: #4688 The get_cpuid_str function returns the string that contains values of VENDOR_ID, CPU FAMILY and MODEL in hex format separated by coma. The values themselves are taken from first cpu entry in "/proc/cpuinfo" that contains "vendor_id", "cpu family" and "model". Signed-off-by: He Chuyue Reviewed-by: He Sheng Signed-off-by: Gu Zitao --- tools/perf/arch/sw_64/util/Build | 2 + tools/perf/arch/sw_64/util/header.c | 111 ++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 tools/perf/arch/sw_64/util/header.c diff --git a/tools/perf/arch/sw_64/util/Build b/tools/perf/arch/sw_64/util/Build index 39f459b636a0..5d42a8f74970 100644 --- a/tools/perf/arch/sw_64/util/Build +++ b/tools/perf/arch/sw_64/util/Build @@ -1,4 +1,6 @@ +perf-y += header.o perf-y += perf_regs.o + perf-$(CONFIG_DWARF) += dwarf-regs.o perf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o perf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o diff --git a/tools/perf/arch/sw_64/util/header.c b/tools/perf/arch/sw_64/util/header.c new file mode 100644 index 000000000000..da2f0f567126 --- /dev/null +++ b/tools/perf/arch/sw_64/util/header.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Implementation of get_cpuid(). + * + * Author: Nikita Shubin + * Bibo Mao + * Huacai Chen + * Chuyue He + */ + +#include +#include +#include +#include +#include "util/debug.h" +#include "util/header.h" + +/* + * Output example from /proc/cpuinfo + * vendor_id : sunway + * cpu family : 8 + * model : 65 + */ +#define CPUINFO_VENDOR "vendor_id" +#define CPUINFO_FAMILY "cpu family" +#define CPUINFO_MODEL "model" +#define CPUINFO "/proc/cpuinfo" + +static char *_get_field(const char *line) +{ + char *line2, *nl; + + line2 = strrchr(line, ' '); + if (!line2) + return NULL; + + line2++; + nl = strrchr(line, '\n'); + if (!nl) + return NULL; + + return strndup(line2, nl - line2); +} + +static char *_get_cpuid(void) +{ + unsigned long line_sz; + char *line, *vendorid, *family, *model, *cpuid; + FILE *file; + + file = fopen(CPUINFO, "r"); + if (file == NULL) + return NULL; + + line = vendorid = family = model = cpuid = NULL; + while (getline(&line, &line_sz, file) != -1) { + if (!strncmp(line, CPUINFO_VENDOR, strlen(CPUINFO_VENDOR))) { + vendorid = _get_field(line); + if (!vendorid) + goto out_free; + } else if (!strncmp(line, CPUINFO_FAMILY, strlen(CPUINFO_FAMILY))) { + family = _get_field(line); + if (!family) + goto out_free; + } else if (!strncmp(line, CPUINFO_MODEL, strlen(CPUINFO_MODEL))) { + model = _get_field(line); + if (!model) + goto out_free; + break; + } + } + + if (!vendorid || !family || !model) + goto out_free; + + if (asprintf(&cpuid, "%s-%s-%s", vendorid, family, model) < 0) + cpuid = NULL; + +out_free: + fclose(file); + free(vendorid); + free(family); + free(model); + + return cpuid; +} + +int get_cpuid(char *buffer, size_t sz) +{ + int ret = 0; + char *cpuid = _get_cpuid(); + + if (!cpuid) + return -EINVAL; + + if (sz < strlen(cpuid)) { + ret = ENOBUFS; + goto out_free; + } + + scnprintf(buffer, sz, "%s", cpuid); + +out_free: + free(cpuid); + return ret; +} + +char *get_cpuid_str(struct perf_pmu *pmu __maybe_unused) +{ + return _get_cpuid(); +} -- Gitee