diff --git a/arch/sw_64/Kconfig b/arch/sw_64/Kconfig index 67b08985ff6fdd199a7792f4ee9704b9381e7f9c..30a5dbf40187b5c560bc51dd7994950691d594f1 100644 --- a/arch/sw_64/Kconfig +++ b/arch/sw_64/Kconfig @@ -67,8 +67,9 @@ config SW64 select GENERIC_CLOCKEVENTS select GENERIC_CPU_DEVICES select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO + select GENERIC_IOREMAP if SUBARCH_C4 + select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP select GENERIC_IRQ_LEGACY - select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP select GENERIC_IRQ_MIGRATION if SMP select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW @@ -91,13 +92,18 @@ config SW64 select HAVE_C_RECORDMCOUNT select HAVE_DEBUG_BUGVERBOSE select HAVE_DYNAMIC_FTRACE + select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS select HAVE_DYNAMIC_FTRACE_WITH_REGS select HAVE_EBPF_JIT + select HAVE_EFFICIENT_UNALIGNED_ACCESS if !SUBARCH_C3B select HAVE_FAST_GUP select HAVE_FTRACE_MCOUNT_RECORD + select HAVE_FUNCTION_ERROR_INJECTION + select HAVE_FUNCTION_GRAPH_RETVAL if HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACER select HAVE_GENERIC_VDSO if MMU && 64BIT + select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && HAVE_PERF_EVENTS_NMI select HAVE_IDE select HAVE_KPROBES select HAVE_KPROBES_ON_FTRACE @@ -110,12 +116,14 @@ config SW64 select HAVE_PCSPKR_PLATFORM select HAVE_PERF_EVENTS select HAVE_PERF_EVENTS_NMI if SUBARCH_C4 - select HAVE_HARDLOCKUP_DETECTOR_PERF if PERF_EVENTS && HAVE_PERF_EVENTS_NMI select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_RELIABLE_STACKTRACE if STACKTRACE + select HAVE_RETHOOK select HAVE_RSEQ + select HAVE_SAMPLE_FTRACE_DIRECT + select HAVE_SAMPLE_FTRACE_DIRECT_MULTI select HAVE_SYSCALL_TRACEPOINTS select IRQ_DOMAIN select IRQ_FORCED_THREADING @@ -685,3 +693,5 @@ source "drivers/idle/Kconfig" endmenu source "arch/sw_64/kvm/Kconfig" + +source "arch/sw_64/mm/Kconfig" diff --git a/arch/sw_64/include/asm/elf.h b/arch/sw_64/include/asm/elf.h index f94d69a5b1108d4957c9b5dfa50f6d3fd1174d20..7aec6327901ff01e0c50aabe8067b08a88540af4 100644 --- a/arch/sw_64/include/asm/elf.h +++ b/arch/sw_64/include/asm/elf.h @@ -91,7 +91,11 @@ typedef struct user_fpsimd_state elf_fpregset_t; * that it will "exec", and that there is sufficient room for the brk. */ -#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000) +#ifdef CONFIG_SW64_FORCE_52BIT +#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) +#else +#define ELF_ET_DYN_BASE (2 * DEFAULT_MAP_WINDOW / 3) +#endif /* * $0 is set by ld.so to a pointer to a function which might be diff --git a/arch/sw_64/include/asm/ftrace.h b/arch/sw_64/include/asm/ftrace.h index 871c0b7b0aef29590d626978a2943456f26449fd..33122cd7f91b762f894e53e4a55e97e8de0c2563 100644 --- a/arch/sw_64/include/asm/ftrace.h +++ b/arch/sw_64/include/asm/ftrace.h @@ -46,5 +46,36 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr) return addr; } +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS +static inline void +__arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr) +{ + regs->regs[2] = addr; +} + +#define arch_ftrace_set_direct_caller(fregs, addr) \ + __arch_ftrace_set_direct_caller(&(fregs)->regs, addr) +#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ + #endif /* ifndef __ASSEMBLY__ */ + +#ifndef __ASSEMBLY__ +#ifdef CONFIG_FUNCTION_GRAPH_TRACER +struct fgraph_ret_regs { + unsigned long ax; + unsigned long bp; +}; + +static inline unsigned long fgraph_ret_regs_return_value(struct fgraph_ret_regs *ret_regs) +{ + return ret_regs->ax; +} + +static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs *ret_regs) +{ + return ret_regs->bp; +} +#endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER */ +#endif + #endif /* _ASM_SW64_FTRACE_H */ diff --git a/arch/sw_64/include/asm/hugetlb.h b/arch/sw_64/include/asm/hugetlb.h index f4c8cbe0891a9fd138dfdd1e049a09b82b08ad44..eeeef6530a572312526e4cc4023371fb4de432c2 100644 --- a/arch/sw_64/include/asm/hugetlb.h +++ b/arch/sw_64/include/asm/hugetlb.h @@ -15,7 +15,7 @@ extern void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, #define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR extern pte_t huge_ptep_get_and_clear(struct mm_struct *mm, - unsigned long addr, pte_t *ptep); + unsigned long addr, pte_t *ptep, unsigned long sz); #define __HAVE_ARCH_HUGE_PTEP_CLEAR_FLUSH extern pte_t huge_ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, diff --git a/arch/sw_64/include/asm/io.h b/arch/sw_64/include/asm/io.h index 1695801e6c4bf9f3c0b0c71a478784c0f61fc479..121e909a2cf943e439606555a2f64487f5aee337 100644 --- a/arch/sw_64/include/asm/io.h +++ b/arch/sw_64/include/asm/io.h @@ -30,6 +30,7 @@ extern void outl(u32 b, unsigned long port); #define outw outw #define outl outl +#ifndef CONFIG_GENERIC_IOREMAP static inline void __iomem *__ioremap(phys_addr_t addr, size_t size, pgprot_t prot) { @@ -37,19 +38,21 @@ static inline void __iomem *__ioremap(phys_addr_t addr, size_t size, return (void __iomem *)(tmp); } - #define ioremap(addr, size) __ioremap((addr), (size), PAGE_KERNEL) -#define ioremap_nocache(addr, size) __ioremap((addr), (size), PAGE_KERNEL) -#define ioremap_cache(addr, size) __ioremap((addr), (size), PAGE_KERNEL) + +static inline void __iounmap(volatile void __iomem *addr) +{ +} +#define iounmap __iounmap +#endif + +#define ioremap_nocache(addr, size) ioremap((addr), (size)) +#define ioremap_cache(addr, size) ioremap((addr), (size)) #define ioremap_uc ioremap_nocache #define ioport_map ioport_map extern void __iomem *ioport_map(unsigned long port, unsigned int nr); -static inline void iounmap(volatile void __iomem *addr) -{ -} - /* * String version of IO memory access ops: */ diff --git a/arch/sw_64/include/asm/page.h b/arch/sw_64/include/asm/page.h index 1ba314b342a0a3a15ce7f2387bc554ac322a51e1..89bf4ba56f229a1a7954f35c5ab9c92073c9ff72 100644 --- a/arch/sw_64/include/asm/page.h +++ b/arch/sw_64/include/asm/page.h @@ -67,6 +67,9 @@ extern unsigned long __boot_phys_addr(unsigned long addr); #define VM_DATA_DEFAULT_FLAGS VM_DATA_FLAGS_NON_EXEC #include #include + +#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA + #endif #endif /* _ASM_SW64_PAGE_H */ diff --git a/arch/sw_64/include/asm/pci.h b/arch/sw_64/include/asm/pci.h index 7b0ef64dcf1a75ae0e300198ff55f8c068d361f9..9f71d55be581fe4ef44844fd29848c31e558d2c8 100644 --- a/arch/sw_64/include/asm/pci.h +++ b/arch/sw_64/include/asm/pci.h @@ -48,6 +48,7 @@ enum SUNWAY_PIU_IOR0 { PCACHE_ACCESS = 0xb880UL, PCACHE_ITEM_TAG = 0xb900UL, PCACHE_ITEM_DATA0 = 0xb980UL, + SUNWAY_PIU_IOR0_SIZE = 0xba00UL, }; enum SUNWAY_PIU_IOR1 { @@ -57,6 +58,7 @@ enum SUNWAY_PIU_IOR1 { RCDEBUGINF1 = 0xc80UL, DCACONTROL = 0x1a00UL, DEVICEID0 = 0x1a80UL, + SUNWAY_PIU_IOR1_SIZE = 0x1b00UL, }; enum SUNWAY_RC { @@ -78,6 +80,7 @@ enum SUNWAY_RC { RC_PHY_INT_REG = 0x80000UL, RC_PHY_EXT_GEN1 = 0x82400UL, RC_PHY_EXT_GEN2 = 0x82480UL, + SUNWAY_RC_SIZE = 0x82500UL, }; struct pci_dev; diff --git a/arch/sw_64/include/asm/pgtable.h b/arch/sw_64/include/asm/pgtable.h index 0b9b65685e7443827905e36b7e2f4c47393b7075..0ad6f12c32753ad796e3f06f7ffd1d7fe1cd79c9 100644 --- a/arch/sw_64/include/asm/pgtable.h +++ b/arch/sw_64/include/asm/pgtable.h @@ -188,6 +188,7 @@ static inline void set_p4d(p4d_t *p4dp, p4d_t p4d) #define PAGE_NONE __pgprot(__ACCESS_BITS | _PAGE_FOR | _PAGE_FOW | _PAGE_FOE | _PAGE_LEAF | _PAGE_PROTNONE) #define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_KERN | _PAGE_LEAF) #define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_LEAF | (x)) +#define _PAGE_IOREMAP pgprot_val(PAGE_KERNEL) #define page_valid_kern(x) ((x & (_PAGE_VALID | _PAGE_KERN)) == (_PAGE_VALID | _PAGE_KERN)) #endif @@ -829,7 +830,7 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte) pr_err("%s: %d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e)) extern void paging_init(void); -/* We have our own get_unmapped_area to cope with ADDR_LIMIT_32BIT. */ #define HAVE_ARCH_UNMAPPED_AREA +#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN #endif /* _ASM_SW64_PGTABLE_H */ diff --git a/arch/sw_64/include/asm/processor.h b/arch/sw_64/include/asm/processor.h index f66a77f233c9cc773f039d1b659c27213d59b1b6..4360140e953506fd491c26ae6f23e60ebb86ffac 100644 --- a/arch/sw_64/include/asm/processor.h +++ b/arch/sw_64/include/asm/processor.h @@ -8,7 +8,6 @@ #ifndef _ASM_SW64_PROCESSOR_H #define _ASM_SW64_PROCESSOR_H -#include /* for ADDR_LIMIT_32BIT */ #include #define task_pt_regs(task) \ @@ -27,19 +26,47 @@ /* * We have a 52-bit user address space: 4PB user VM... + * 20230728(mcw): + * To make sure that arch_get_unmapped_area_topdown and old + * software, e.g. golang runtime and v8 jit, works well at + * the same time, just providing 47-bit VAs unless a hint is + * supplied to mmap. */ -#define TASK_SIZE (0x10000000000000UL) -#define UNMAPPED_BASE (TASK_SIZE >> 6) -#define STACK_TOP \ - (current->personality & ADDR_LIMIT_32BIT ? 0x80000000 : 0x00120000000UL) -#define STACK_TOP_MAX 0x00120000000UL +#define VA_BITS (CONFIG_SW64_VA_BITS) +#if VA_BITS > 47 +#define VA_BITS_MIN (47) +#else +#define VA_BITS_MIN (VA_BITS) +#endif -/* This decides where the kernel will search for a free chunk of vm - * space during mmap's. - */ -#define TASK_UNMAPPED_BASE \ - ((current->personality & ADDR_LIMIT_32BIT) ? 0x40000000 : UNMAPPED_BASE) +#define DEFAULT_MAP_WINDOW_64 (1UL << VA_BITS_MIN) +#define TASK_SIZE_64 (1UL << VA_BITS) + +#define TASK_SIZE_MAX TASK_SIZE_64 +#define TASK_SIZE TASK_SIZE_64 +#define DEFAULT_MAP_WINDOW DEFAULT_MAP_WINDOW_64 + +#ifdef CONFIG_SW64_FORCE_52BIT +#define STACK_TOP_MAX TASK_SIZE +#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 4)) +#else +#define STACK_TOP_MAX DEFAULT_MAP_WINDOW +#define TASK_UNMAPPED_BASE (PAGE_ALIGN(DEFAULT_MAP_WINDOW / 4)) +#endif + +#define STACK_TOP STACK_TOP_MAX + +#ifndef CONFIG_SW64_FORCE_52BIT +#define arch_get_mmap_end(addr, len, flags) \ + (((addr) > DEFAULT_MAP_WINDOW) ? TASK_SIZE : DEFAULT_MAP_WINDOW) +#define arch_get_mmap_base(addr, base) ((addr > DEFAULT_MAP_WINDOW) ? \ + base + TASK_SIZE - DEFAULT_MAP_WINDOW : \ + base) +#else +#define arch_get_mmap_end(addr, len, flags) (TASK_SIZE) +#define arch_get_mmap_base(addr, base) (base) +#endif struct thread_struct { struct user_fpsimd_state fpstate; diff --git a/arch/sw_64/include/asm/ptrace.h b/arch/sw_64/include/asm/ptrace.h index 0bbe85297f6288722779e1c234956ec934dce006..3e5730c8b6a23279bbf1df250d2b9b684981d696 100644 --- a/arch/sw_64/include/asm/ptrace.h +++ b/arch/sw_64/include/asm/ptrace.h @@ -87,6 +87,11 @@ static inline long regs_return_value(struct pt_regs *regs) return -regs->regs[0]; } +static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc) +{ + regs->regs[0] = rc; +} + #endif /* !__ASSEMBLY__ */ #endif /* __KERNEL__ */ diff --git a/arch/sw_64/kernel/entry-ftrace.S b/arch/sw_64/kernel/entry-ftrace.S index 426d7561f09706c237172ef0e4c968b136833bdd..5dbae49918757623c90d00138a3ca6fc1f550dd2 100644 --- a/arch/sw_64/kernel/entry-ftrace.S +++ b/arch/sw_64/kernel/entry-ftrace.S @@ -91,14 +91,6 @@ /* save pt_regs */ ldi $sp, -PT_REGS_SIZE($sp) stl $0, PT_REGS_R0($sp) - stl $1, PT_REGS_R1($sp) - stl $2, PT_REGS_R2($sp) - stl $3, PT_REGS_R3($sp) - stl $4, PT_REGS_R4($sp) - stl $5, PT_REGS_R5($sp) - stl $6, PT_REGS_R6($sp) - stl $7, PT_REGS_R7($sp) - stl $8, PT_REGS_R8($sp) stl $9, PT_REGS_R9($sp) stl $10, PT_REGS_R10($sp) stl $11, PT_REGS_R11($sp) @@ -122,19 +114,15 @@ stl $29, PT_REGS_GP($sp) ldi $0, PT_REGS_SIZE($sp) stl $0, PT_REGS_R30($sp) + + /* save direct caller reg */ + ldi $2, 0($31) + stl $2, PT_REGS_R2($sp) .endm .macro RESTORE_PT_REGS /* restore pt_regs */ ldl $0, PT_REGS_R0($sp) - ldl $1, PT_REGS_R1($sp) - ldl $2, PT_REGS_R2($sp) - ldl $3, PT_REGS_R3($sp) - ldl $4, PT_REGS_R4($sp) - ldl $5, PT_REGS_R5($sp) - ldl $6, PT_REGS_R6($sp) - ldl $7, PT_REGS_R7($sp) - ldl $8, PT_REGS_R8($sp) ldl $9, PT_REGS_R9($sp) ldl $10, PT_REGS_R10($sp) ldl $11, PT_REGS_R11($sp) @@ -173,14 +161,16 @@ /* save return value regs*/ .macro save_return_regs - subl $sp, 0x8, $sp - stl $0, 0x0($sp) + subl $sp, 16, $sp + stl $0, 0($sp) + stl $15, 8($sp) .endm /* restore return value regs*/ .macro restore_return_regs - ldl $0, 0x0($sp) - addl $sp, 0x8, $sp + ldl $15, 8($sp) + ldl $0, 0($sp) + addl $sp, 16, $sp .endm @@ -231,7 +221,7 @@ ENTRY(return_to_handler) br $27, 1f 1: ldgp $29, 0($27) save_return_regs - bis $31, $15, $16 /* parent's fp */ + bis $31, $sp, $16 /* ret_regs */ ldi $27, ftrace_return_to_handler call $26, ($27) bis $31, $0, $26 @@ -352,7 +342,10 @@ ftrace_regs_call: call ftrace_graph_caller #endif RESTORE_PT_REGS - ret $31, ($28), 1 + bne $2, .Ldirect + ret $31, ($28), 1 +.Ldirect: + ret $31, ($2), 1 .end ftrace_regs_caller #endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */ diff --git a/arch/sw_64/kernel/kprobes/Makefile b/arch/sw_64/kernel/kprobes/Makefile index 110ba2bf7752361442022553269447ceb802d465..f07b3513c3a63e19c6961d252ecdcdb12bcd3521 100644 --- a/arch/sw_64/kernel/kprobes/Makefile +++ b/arch/sw_64/kernel/kprobes/Makefile @@ -1,3 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_KPROBES) += kprobes.o decode-insn.o obj-$(CONFIG_KPROBES_ON_FTRACE) += kprobes-ftrace.o +obj-$(CONFIG_RETHOOK) += rethook.o rethook_trampoline.o +CFLAGS_REMOVE_rethook.o = $(CC_FLAGS_FTRACE) +CFLAGS_REMOVE_rethook_trampoline.o = $(CC_FLAGS_FTRACE) diff --git a/arch/sw_64/kernel/kprobes/kprobes.c b/arch/sw_64/kernel/kprobes/kprobes.c index 2ee18260f2a3e04066f4747e904811a9601ddb49..662f65fb33817567929f17ad15a48e66b4bbaaa9 100644 --- a/arch/sw_64/kernel/kprobes/kprobes.c +++ b/arch/sw_64/kernel/kprobes/kprobes.c @@ -240,35 +240,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, } return ret; } -/* - * Function return probe trampoline: - * - init_kprobes() establishes a probepoint here - * - When the probed function returns, this probe causes the - * handlers to fire - */ -static void __used kretprobe_trampoline_holder(void) -{ - asm volatile( - /* Keep the assembler from reordering and placing JR here. */ - ".set noreorder\n\t" - "nop\n\t" - ".global __kretprobe_trampoline\n" - "__kretprobe_trampoline:\n\t" - "nop\n\t" - : : : "memory"); -} - -void __kretprobe_trampoline(void); - -void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, - struct pt_regs *regs) -{ - ri->ret_addr = (kprobe_opcode_t *) regs->regs[26]; - ri->fp = NULL; - - /* Replace the return addr with trampoline addr */ - regs->regs[26] = (unsigned long)__kretprobe_trampoline; -} /* * Provide a blacklist of symbols identifying ranges which cannot be kprobed. @@ -283,40 +254,12 @@ int __init arch_populate_kprobe_blacklist(void) return ret; } -/* - * Called when the probe at kretprobe trampoline is hit - */ -static int __kprobes trampoline_probe_handler(struct kprobe *p, - struct pt_regs *regs) -{ - unsigned long orig_ret_address; - - orig_ret_address = __kretprobe_trampoline_handler(regs, NULL); - instruction_pointer(regs) = orig_ret_address; - regs->regs[26] = orig_ret_address; - - /* - * By returning a non-zero value, we are telling - * kprobe_handler() that we don't want the post_handler - * to run (and have re-enabled preemption) - */ - return 1; -} - int __kprobes arch_trampoline_kprobe(struct kprobe *p) { - if (p->addr == (kprobe_opcode_t *)__kretprobe_trampoline) - return 1; - return 0; } -static struct kprobe trampoline_p = { - .addr = (kprobe_opcode_t *)__kretprobe_trampoline, - .pre_handler = trampoline_probe_handler -}; - int __init arch_init_kprobes(void) { - return register_kprobe(&trampoline_p); + return 0; } diff --git a/arch/sw_64/kernel/kprobes/rethook.c b/arch/sw_64/kernel/kprobes/rethook.c new file mode 100644 index 0000000000000000000000000000000000000000..982311b335d376dd1b37fe9cbe5738089c980a77 --- /dev/null +++ b/arch/sw_64/kernel/kprobes/rethook.c @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Generic return hook for sw64. + */ + +#include +#include +#include "rethook.h" + +/* This is called from arch_rethook_trampoline() */ +unsigned long __used arch_rethook_trampoline_callback(struct pt_regs *regs) +{ + return rethook_trampoline_handler(regs, regs->regs[15]); +} + +NOKPROBE_SYMBOL(arch_rethook_trampoline_callback); + +void arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount) +{ + rhn->ret_addr = regs->regs[26]; + rhn->frame = regs->regs[15]; + + /* replace return addr with trampoline */ + regs->regs[26] = (unsigned long)arch_rethook_trampoline; +} + +NOKPROBE_SYMBOL(arch_rethook_prepare); diff --git a/arch/sw_64/kernel/kprobes/rethook.h b/arch/sw_64/kernel/kprobes/rethook.h new file mode 100644 index 0000000000000000000000000000000000000000..b4e2e5fe81c25b70948b2a79bf2c6cf453a35148 --- /dev/null +++ b/arch/sw_64/kernel/kprobes/rethook.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __SW64_RETHOOK_H +#define __SW64_RETHOOK_H + +unsigned long arch_rethook_trampoline_callback(struct pt_regs *regs); +void arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount); + +#endif diff --git a/arch/sw_64/kernel/kprobes/rethook_trampoline.S b/arch/sw_64/kernel/kprobes/rethook_trampoline.S new file mode 100644 index 0000000000000000000000000000000000000000..f194237751c33b51b36379ff7aa5803c6000af64 --- /dev/null +++ b/arch/sw_64/kernel/kprobes/rethook_trampoline.S @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#include +#include +#include + + .text + .set noat + .align 4 + + .macro save_all_base_regs + /* save $26 & fp of the function before caller */ + subl $sp, 0x10, $sp + stl $26, 0($sp) + stl $15, 0x8($sp) + ldi $15, 0($sp) + + /* save $28 & fp of caller */ + subl $sp, 0x10, $sp + stl $28, 0($sp) + stl $15, 0x8($sp) + ldi $15, 0($sp) + + /* save pt_regs */ + ldi $sp, -PT_REGS_SIZE($sp) + stl $0, PT_REGS_R0($sp) + stl $1, PT_REGS_R1($sp) + stl $2, PT_REGS_R2($sp) + stl $3, PT_REGS_R3($sp) + stl $4, PT_REGS_R4($sp) + stl $5, PT_REGS_R5($sp) + stl $6, PT_REGS_R6($sp) + stl $7, PT_REGS_R7($sp) + stl $8, PT_REGS_R8($sp) + 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) + stl $15, PT_REGS_R15($sp) + stl $16, PT_REGS_R16($sp) + stl $17, PT_REGS_R17($sp) + stl $18, PT_REGS_R18($sp) + stl $19, PT_REGS_R19($sp) + stl $20, PT_REGS_R20($sp) + stl $21, PT_REGS_R21($sp) + stl $22, PT_REGS_R22($sp) + stl $23, PT_REGS_R23($sp) + stl $24, PT_REGS_R24($sp) + stl $25, PT_REGS_R25($sp) + stl $26, PT_REGS_R26($sp) + stl $27, PT_REGS_R27($sp) + stl $28, PT_REGS_R28($sp) + stl $29, PT_REGS_GP($sp) + ldi $0, PT_REGS_SIZE($sp) + stl $0, PT_REGS_R30($sp) + .endm + + .macro restore_all_base_regs + /* restore pt_regs */ + ldl $0, PT_REGS_R0($sp) + ldl $1, PT_REGS_R1($sp) + ldl $2, PT_REGS_R2($sp) + ldl $3, PT_REGS_R3($sp) + ldl $4, PT_REGS_R4($sp) + ldl $5, PT_REGS_R5($sp) + ldl $6, PT_REGS_R6($sp) + ldl $7, PT_REGS_R7($sp) + ldl $8, PT_REGS_R8($sp) + 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) + ldl $15, PT_REGS_R15($sp) + ldl $16, PT_REGS_R16($sp) + ldl $17, PT_REGS_R17($sp) + ldl $18, PT_REGS_R18($sp) + ldl $19, PT_REGS_R19($sp) + ldl $20, PT_REGS_R20($sp) + ldl $21, PT_REGS_R21($sp) + ldl $22, PT_REGS_R22($sp) + ldl $23, PT_REGS_R23($sp) + ldl $24, PT_REGS_R24($sp) + ldl $25, PT_REGS_R25($sp) + ldl $27, PT_REGS_R27($sp) + ldl $28, PT_REGS_R28($sp) + ldl $29, PT_REGS_GP($sp) + ldi $sp, PT_REGS_SIZE($sp) + + /* only restore $fp */ + ldl $15, 0x18($sp) + addl $sp, 0x20, $sp + .endm + +ENTRY(arch_rethook_trampoline) + save_all_base_regs + + mov $sp, $16 + call arch_rethook_trampoline_callback + mov $0, $26 + + restore_all_base_regs + + ret +ENDPROC(arch_rethook_trampoline) diff --git a/arch/sw_64/kernel/setup.c b/arch/sw_64/kernel/setup.c index 9cd992ccd581fdb6c32a2435b375392fdb67b112..fc0ebc785a7718debb043369a248fdb3a5159a36 100644 --- a/arch/sw_64/kernel/setup.c +++ b/arch/sw_64/kernel/setup.c @@ -575,6 +575,12 @@ static void __init setup_firmware_fdt(void) } } +static void __init setup_cpu_caps(void) +{ + if (!IS_ENABLED(CONFIG_SUBARCH_C3B) && !is_junzhang_v1()) + static_branch_enable(&hw_una_enabled); +} + static void __init setup_legacy_io(void) { if (is_guest_or_emul()) { @@ -678,6 +684,9 @@ setup_arch(char **cmdline_p) /* Early initialization for device tree */ setup_firmware_fdt(); + /* Now we know who we are, setup caps */ + setup_cpu_caps(); + /* Now we get the final boot_command_line */ *cmdline_p = boot_command_line; diff --git a/arch/sw_64/lib/Makefile b/arch/sw_64/lib/Makefile index aa6d8eee29c20f1da87b9dcc3f8fd1338dd3af46..c2927c1e98dd2d36ac91b42795e5bfea09c1e2b4 100644 --- a/arch/sw_64/lib/Makefile +++ b/arch/sw_64/lib/Makefile @@ -40,6 +40,8 @@ lib-y += $(lib-clear_page-y) $(lib-clear_user-y) $(lib-copy_page-y) $(lib-copy_u obj-y = iomap.o obj-y += iomap_copy.o +obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o + ifeq ($(CONFIG_SUBARCH_C3B),y) # The division routines are built from single source, with different defines. AFLAGS___divlu.o = -DDIV diff --git a/arch/sw_64/lib/error-inject.c b/arch/sw_64/lib/error-inject.c new file mode 100644 index 0000000000000000000000000000000000000000..b1549c4529e58baa3c1d4dbf31dbda677f8ef999 --- /dev/null +++ b/arch/sw_64/lib/error-inject.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include + +void override_function_with_return(struct pt_regs *regs) +{ + instruction_pointer_set(regs, regs->regs[26]); +} +NOKPROBE_SYMBOL(override_function_with_return); diff --git a/arch/sw_64/lib/iomap.c b/arch/sw_64/lib/iomap.c index c73004a87dcd8ac288305870a1526cdc1ceb5fd3..51e7600b0fec03551b9e967c646efb71e5e95805 100644 --- a/arch/sw_64/lib/iomap.c +++ b/arch/sw_64/lib/iomap.c @@ -262,8 +262,8 @@ EXPORT_SYMBOL(_memset_c_io); void __iomem *ioport_map(unsigned long port, unsigned int size) { if (port >= 0x100000) - return __va(port); + return ioremap(port, size); - return __va((port << legacy_io_shift) | legacy_io_base); + return ioremap((port << legacy_io_shift) | legacy_io_base, size); } EXPORT_SYMBOL(ioport_map); diff --git a/arch/sw_64/mm/Kconfig b/arch/sw_64/mm/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..4f5f7f4599d7d73c7977caa4addfcbeb82443ef8 --- /dev/null +++ b/arch/sw_64/mm/Kconfig @@ -0,0 +1,41 @@ +choice + prompt "Virtual address space size" + default SW64_VA_BITS_47 + help + Allows choosing one of multiple possible userspace virtual address space size. + +config SW64_VA_BITS_47 + bool "47-bit" + help + Limit the userspace VAs to 47-bit size. + + It may waste some userspace VA range, but is safe and enough for current + userland to works wells. + +config SW64_VA_BITS_52 + bool "52-bit" + help + Use the full 52-bit size userspace VAs. + + The kernel will attempt to maintain compatibility with older software by + providing 47-bit VAs unless a hint is supplied to mmap. + +endchoice + +config SW64_VA_BITS + int + default 47 if SW64_VA_BITS_47 + default 52 if SW64_VA_BITS_52 + default 47 + help + The size of userspace VA. + +config SW64_FORCE_52BIT + bool "Force 52-bit virtual address for userspace" + depends on SW64_VA_BITS_52 && EXPERT + help + This configuration option disable the 47-bit compatibility logic, and forces + all userspace address to be 52-bit if possible. + + Note, it is not 100% safe for software that unable to handle VA bigger than + 47-bit to works well with this option enabled. Do not enable it for now. diff --git a/arch/sw_64/mm/hugetlbpage.c b/arch/sw_64/mm/hugetlbpage.c index f986422398ef36671e6577613a3d585033a29d5d..d723a506e9b38ef3bbedd08a28377f86a135e010 100644 --- a/arch/sw_64/mm/hugetlbpage.c +++ b/arch/sw_64/mm/hugetlbpage.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -217,25 +218,24 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file, info.flags = 0; info.length = len; - info.low_limit = current->mm->mmap_legacy_base; - info.high_limit = TASK_SIZE; + info.low_limit = current->mm->mmap_base; + info.high_limit = arch_get_mmap_end(addr, len, flags); info.align_mask = PAGE_MASK & ~huge_page_mask(h); info.align_offset = 0; return vm_unmapped_area(&info); } static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file, - unsigned long addr0, unsigned long len, + unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { struct hstate *h = hstate_file(file); struct vm_unmapped_area_info info; - unsigned long addr; info.flags = VM_UNMAPPED_AREA_TOPDOWN; info.length = len; info.low_limit = PAGE_SIZE; - info.high_limit = current->mm->mmap_base; + info.high_limit = arch_get_mmap_base(addr, current->mm->mmap_base); info.align_mask = PAGE_MASK & ~huge_page_mask(h); info.align_offset = 0; addr = vm_unmapped_area(&info); @@ -250,7 +250,7 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file, VM_BUG_ON(addr != -ENOMEM); info.flags = 0; info.low_limit = TASK_UNMAPPED_BASE; - info.high_limit = TASK_SIZE; + info.high_limit = arch_get_mmap_end(addr, len, flags); addr = vm_unmapped_area(&info); } diff --git a/arch/sw_64/mm/hugetlbpage_c4.c b/arch/sw_64/mm/hugetlbpage_c4.c index 8ca1c429f46ca368c86addbe629e3544af739d05..af9d20e14041f000bb2f872babfe0a82aa164a4b 100644 --- a/arch/sw_64/mm/hugetlbpage_c4.c +++ b/arch/sw_64/mm/hugetlbpage_c4.c @@ -280,7 +280,8 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm, } pte_t huge_ptep_get_and_clear(struct mm_struct *mm, - unsigned long addr, pte_t *ptep) + unsigned long addr, pte_t *ptep, + unsigned long sz) { int ncontig; size_t pgsize; diff --git a/arch/sw_64/mm/mmap.c b/arch/sw_64/mm/mmap.c index a7a189fc36d675c44bdf4f9192867de1409dc480..d4bf9a7d262794e69ee88fb2f29657c586aac08b 100644 --- a/arch/sw_64/mm/mmap.c +++ b/arch/sw_64/mm/mmap.c @@ -5,10 +5,20 @@ #include #include #include +#include #include +#include #include +/* + * Top of mmap area (just below the process stack). + * Leave at least a ~128 MB hole. + */ + +#define MIN_GAP (SZ_128M) +#define MAX_GAP (STACK_TOP / 6 * 5) + unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, @@ -17,15 +27,9 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, struct mm_struct *mm = current->mm; struct vm_area_struct *vma; struct vm_unmapped_area_info info; - unsigned long limit; + const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags); - /* Support 32 bit heap. */ - if (current->personality & ADDR_LIMIT_32BIT) - limit = 0x80000000; - else - limit = TASK_SIZE; - - if (len > limit) + if (unlikely(len > mmap_end - mmap_min_addr)) return -ENOMEM; if (flags & MAP_FIXED) { @@ -47,26 +51,100 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, info.flags = 0; info.length = len; info.low_limit = mm->mmap_base; - info.high_limit = limit; + info.high_limit = mmap_end; info.align_mask = 0; info.align_offset = pgoff << PAGE_SHIFT; return vm_unmapped_area(&info); } -unsigned long arch_mmap_rnd(void) +unsigned long +arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, + unsigned long flags) { - unsigned long rnd; + struct mm_struct *mm = current->mm; + struct vm_area_struct *vma; + struct vm_unmapped_area_info info; + const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags); + + if (unlikely(len > mmap_end - mmap_min_addr)) + return -ENOMEM; - /* 8MB for 32bit, 256MB for 64bit */ - if (current->personality & ADDR_LIMIT_32BIT) - rnd = get_random_long() & 0x7ffffful; - else - rnd = get_random_long() & 0xffffffful; + if (flags & MAP_FIXED) { + if (addr + len > TASK_SIZE) + return -EINVAL; + + return addr; + } + + if (addr) { + addr = PAGE_ALIGN(addr); + + vma = find_vma(mm, addr); + if (TASK_SIZE - len >= addr && + (!vma || addr + len <= vm_start_gap(vma))) + return addr; + } + + info.flags = VM_UNMAPPED_AREA_TOPDOWN; + info.length = len; + info.low_limit = FIRST_USER_ADDRESS; + info.high_limit = arch_get_mmap_base(addr, mm->mmap_base); + info.align_mask = 0; + info.align_offset = pgoff << PAGE_SHIFT; + addr = vm_unmapped_area(&info); + + /* + * A failed mmap() very likely causes application failure, + * so fall back to the bottom-up function here. This scenario + * can happen with large stack limits and large mmap() + * allocations. + */ + if (addr & ~PAGE_MASK) { + VM_BUG_ON(addr != -ENOMEM); + info.flags = 0; + info.low_limit = mm->mmap_base; + info.high_limit = mmap_end; + addr = vm_unmapped_area(&info); + } + return addr; +} + +unsigned long arch_mmap_rnd(void) +{ + unsigned long rnd = get_random_long() & 0x7fffffful; return rnd << PAGE_SHIFT; } +unsigned long mmap_is_legacy(struct rlimit *rlim_stack) +{ + if (current->personality & ADDR_COMPAT_LAYOUT) + return 1; + if (rlim_stack->rlim_cur == RLIM_INFINITY) + return 1; + + return sysctl_legacy_va_layout; +} + +static unsigned long mmap_base(unsigned long rnd, struct rlimit *rlim_stack) +{ + unsigned long gap = rlim_stack->rlim_cur; + unsigned long pad = stack_guard_gap; + + /* Account for stack randomization if necessary. 8M of VA. */ + if (current->flags & PF_RANDOMIZE) + pad += 0x7ff00; + /* Values close to RLIM_INFINITY can overflow. */ + if (gap + pad > gap) + gap = MIN_GAP; + else if (gap > MAX_GAP) + gap = MAX_GAP; + + return PAGE_ALIGN(STACK_TOP - gap - rnd); +} + /* * This function, called very early during the creation of a new process VM * image, sets up which VM layout function to use: @@ -82,8 +160,13 @@ void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack) * Fall back to the standard layout if the personality bit is set, or * if the expected stack growth is unlimited: */ - mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; - mm->get_unmapped_area = arch_get_unmapped_area; + if (mmap_is_legacy(rlim_stack)) { + mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; + mm->get_unmapped_area = arch_get_unmapped_area; + } else { + mm->mmap_base = mmap_base(random_factor, rlim_stack); + mm->get_unmapped_area = arch_get_unmapped_area_topdown; + } } SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, diff --git a/arch/sw_64/net/bpf_jit_comp.c b/arch/sw_64/net/bpf_jit_comp.c index 3144456cd843a464d20f8172590c2941e999448c..a4f273e7725d27d0dc71e933cdaaf7281c32e0e9 100644 --- a/arch/sw_64/net/bpf_jit_comp.c +++ b/arch/sw_64/net/bpf_jit_comp.c @@ -227,10 +227,9 @@ static void emit_sw64_ldu64(const int dst, const u64 imm, struct jit_ctx *ctx) } /* constant insn count */ -static void emit_sw64_load_call_addr(u64 addr, struct jit_ctx *ctx) +static void emit_sw64_load_call_addr(u8 dst, u64 addr, struct jit_ctx *ctx) { u16 imm_tmp; - u8 dst = SW64_BPF_REG_PV; u8 reg_tmp = get_tmp_reg(ctx); imm_tmp = (addr >> 60) & 0xf; @@ -1192,7 +1191,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, if (ret < 0) return ret; - emit_sw64_load_call_addr(func, ctx); + emit_sw64_load_call_addr(SW64_BPF_REG_PV, func, ctx); emit(SW64_BPF_CALL(SW64_BPF_REG_RA, SW64_BPF_REG_PV), ctx); break; } @@ -1224,7 +1223,10 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, case BPF_LD | BPF_IMM | BPF_DW: insn1 = insn[1]; imm64 = ((u64)insn1.imm << 32) | (u32)imm; - emit_sw64_ldu64(dst, imm64, ctx); + if (bpf_pseudo_func(insn)) + emit_sw64_load_call_addr(SW64_BPF_REG_A1, imm64, ctx); + else + emit_sw64_ldu64(dst, imm64, ctx); put_tmp_reg(ctx); put_tmp_reg(ctx); return 1; diff --git a/drivers/cpufreq/sunway-cpufreq.c b/drivers/cpufreq/sunway-cpufreq.c index ba22843d8eed3872f279205e6424b3fc39b63e77..41a6b21ff8276984f4e4d51ddcff1bc93e42b197 100644 --- a/drivers/cpufreq/sunway-cpufreq.c +++ b/drivers/cpufreq/sunway-cpufreq.c @@ -135,26 +135,23 @@ static void __init fill_freq_table(struct cpufreq_frequency_table *ft) static unsigned int sunway_get_rate(struct cpufreq_policy *policy) { - int i, clu_lv1_sel; + int i; u64 val; void __iomem *spbu_base = misc_platform_get_spbu_base(0); struct cpufreq_frequency_table *ft = policy->freq_table; - clu_lv1_sel = (readq(spbu_base + OFFSET_CLU_LV1_SEL) >> 2) & 0x3; - - if (clu_lv1_sel == 0) - val = readq(spbu_base + OFFSET_CLK_CTL) >> CORE_PLL0_CFG_SHIFT; - else if (clu_lv1_sel == 2) - val = readq(spbu_base + OFFSET_CLK_CTL) >> CORE_PLL1_CFG_SHIFT; - else - val = readq(spbu_base + OFFSET_CLK_CTL) >> CORE_PLL2_CFG_SHIFT; - + /* PLL2 provides working frequency for core */ + val = readq(spbu_base + OFFSET_CLK_CTL) >> CORE_PLL2_CFG_SHIFT; val &= CORE_PLL2_CFG_MASK; for (i = 0; ft[i].frequency != CPUFREQ_TABLE_END; i++) { - if (val == i) + if (val == i) { + if (ft[i].frequency == CPUFREQ_ENTRY_INVALID) + return cpuid(GET_CPU_FREQ, 0) * 1000UL; return ft[i].frequency; + } } + return 0; } @@ -252,6 +249,7 @@ static struct freq_attr *sunway_table_attr[] = { static struct cpufreq_driver sunway_cpufreq_driver = { .name = "sunway-cpufreq", + .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK, .init = sunway_cpufreq_init, .verify = sunway_cpufreq_verify, .target_index = sunway_cpufreq_target, diff --git a/drivers/iommu/sw64/iommu.c b/drivers/iommu/sw64/iommu.c index e9f871270afb486d3bc6dbab9170e963502fc5c3..0a3d2a6b1feace32a8af7af065934159e462f559 100644 --- a/drivers/iommu/sw64/iommu.c +++ b/drivers/iommu/sw64/iommu.c @@ -857,7 +857,6 @@ sunway_iommu_unmap_page(struct sunway_iommu_domain *sunway_domain, unsigned long *pte_l2, unmapped; pr_debug("%s iova %#lx, page_size %#lx\n", __func__, iova, page_size); - BUG_ON(!is_power_of_2(page_size)); unmapped = 0; while (unmapped < page_size) { @@ -1162,39 +1161,73 @@ sunway_iommu_iova_to_phys(struct iommu_domain *dom, dma_addr_t iova) return paddr; } -static int -sunway_iommu_map(struct iommu_domain *dom, unsigned long iova, - phys_addr_t paddr, size_t page_size, int iommu_prot, gfp_t gfp) +static int sunway_iommu_map_pages(struct iommu_domain *domain, unsigned long iova, + phys_addr_t paddr, size_t pgsize, size_t pgcount, + int prot, gfp_t gfp, size_t *mapped) { - struct sunway_iommu_domain *sdomain = to_sunway_domain(dom); - int ret; + struct sunway_iommu_domain *sdomain = to_sunway_domain(domain); + size_t size = pgcount << __ffs(pgsize); + unsigned long mapped_size = 0; + int ret = 0; /* * As VFIO cannot distinguish between normal DMA request * and pci device BAR, check should be introduced manually * to avoid VFIO trying to map pci config space. */ - if (iova >= SW64_BAR_ADDRESS) + if (iova >= SW64_BAR_ADDRESS) { + if (mapped) + *mapped = size; return 0; + } + + if (!(pgsize & domain->pgsize_bitmap)) { + pr_err("pgsize: %lx not supported.\n", pgsize); + return -EINVAL; + } + + while (mapped_size < size) { + ret = sunway_iommu_map_page(sdomain, iova, paddr, pgsize, prot); + if (ret) + goto out; + + iova += pgsize; + paddr += pgsize; + mapped_size += pgsize; + } - ret = sunway_iommu_map_page(sdomain, iova, paddr, page_size, iommu_prot); + if (mapped) + *mapped = size; +out: return ret; } -static size_t -sunway_iommu_unmap(struct iommu_domain *dom, unsigned long iova, - size_t page_size, struct iommu_iotlb_gather *gather) +static size_t sunway_iommu_unmap_pages(struct iommu_domain *domain, unsigned long iova, + size_t pgsize, size_t pgcount, + struct iommu_iotlb_gather *iotlb_gather) { - struct sunway_iommu_domain *sdomain = to_sunway_domain(dom); - size_t unmap_size; + struct sunway_iommu_domain *sdomain = to_sunway_domain(domain); + size_t size = pgcount << __ffs(pgsize); + unsigned long unmapped_size = 0; + unsigned long unmap_size; if (iova >= SW64_BAR_ADDRESS) - return page_size; + return size; - unmap_size = sunway_iommu_unmap_page(sdomain, iova, page_size); + if (!(pgsize & domain->pgsize_bitmap)) { + pr_err("pgsize: %lx not supported.\n", pgsize); + return -EINVAL; + } + + while (unmapped_size < size) { + unmap_size = sunway_iommu_unmap_page(sdomain, iova, pgsize); + + iova += unmap_size; + unmapped_size += unmap_size; + } - return unmap_size; + return size; } static struct iommu_group *sunway_iommu_device_group(struct device *dev) @@ -1364,8 +1397,8 @@ const struct iommu_ops sunway_iommu_ops = { .def_domain_type = sunway_iommu_def_domain_type, .default_domain_ops = &(const struct iommu_domain_ops) { .attach_dev = sunway_iommu_attach_device, - .map = sunway_iommu_map, - .unmap = sunway_iommu_unmap, + .map_pages = sunway_iommu_map_pages, + .unmap_pages = sunway_iommu_unmap_pages, .iova_to_phys = sunway_iommu_iova_to_phys, .free = sunway_iommu_domain_free, } diff --git a/drivers/iommu/sw64/iommu_v2.c b/drivers/iommu/sw64/iommu_v2.c index b73439dd13e576035f5eacd018cb178462406b87..7e363bfbdaafb8e0cc73a43796cc25581f577e1d 100644 --- a/drivers/iommu/sw64/iommu_v2.c +++ b/drivers/iommu/sw64/iommu_v2.c @@ -1117,7 +1117,6 @@ sunway_iommu_unmap_page(struct sunway_iommu_domain *sunway_domain, int tmp = 1; pr_debug("%s iova %#lx, page_size %#lx\n", __func__, iova, page_size); - BUG_ON(!is_power_of_2(page_size)); switch (page_size) { case (1UL << 33): @@ -1445,12 +1444,15 @@ sunway_iommu_iova_to_phys(struct iommu_domain *dom, dma_addr_t iova) paddr += iova & ~PAGE_MASK; return paddr; } -static int -sunway_iommu_map(struct iommu_domain *dom, unsigned long iova, - phys_addr_t paddr, size_t page_size, int iommu_prot, gfp_t gfp) + +static int sunway_iommu_map_pages(struct iommu_domain *domain, unsigned long iova, + phys_addr_t paddr, size_t pgsize, size_t pgcount, + int prot, gfp_t gfp, size_t *mapped) { - struct sunway_iommu_domain *sdomain = to_sunway_domain(dom); - int ret; + struct sunway_iommu_domain *sdomain = to_sunway_domain(domain); + size_t size = pgcount << __ffs(pgsize); + unsigned long mapped_size = 0; + int ret = 0; /* * 3.5G ~ 4G currently is seen as PCI 32-bit MEMIO space. In theory, @@ -1470,7 +1472,7 @@ sunway_iommu_map(struct iommu_domain *dom, unsigned long iova, * users at the same time. So users can quickly learn if they are using * these "illegal" IOVA and thus change their strategies accordingly. */ - if ((SW64_32BIT_DMA_LIMIT < iova + page_size) + if ((SW64_32BIT_DMA_LIMIT < iova + size) && (iova <= DMA_BIT_MASK(32))) { pr_warn_once("process %s (pid:%d) is using domain %d with IOVA: %lx\n", current->comm, current->pid, sdomain->id, iova); @@ -1482,6 +1484,8 @@ sunway_iommu_map(struct iommu_domain *dom, unsigned long iova, */ if (iova >= SW64_BAR_ADDRESS) { pr_warn_once("Domain %d are using IOVA: %lx\n", sdomain->id, iova); + if (mapped) + *mapped = size; return 0; } @@ -1491,20 +1495,39 @@ sunway_iommu_map(struct iommu_domain *dom, unsigned long iova, return -EFAULT; } - ret = sunway_iommu_map_page(sdomain, iova, paddr, page_size, iommu_prot); + if (!(pgsize & domain->pgsize_bitmap)) { + pr_err("pgsize: %lx not supported\n", pgsize); + return -EINVAL; + } + while (mapped_size < size) { + ret = sunway_iommu_map_page(sdomain, iova, paddr, pgsize, prot); + if (ret) + goto out; + + iova += pgsize; + paddr += pgsize; + mapped_size += pgsize; + } + + if (mapped) + *mapped = size; + +out: return ret; } -static size_t -sunway_iommu_unmap(struct iommu_domain *dom, unsigned long iova, - size_t page_size, struct iommu_iotlb_gather *gather) +static size_t sunway_iommu_unmap_pages(struct iommu_domain *domain, unsigned long iova, + size_t pgsize, size_t pgcount, + struct iommu_iotlb_gather *iotlb_gather) { - struct sunway_iommu_domain *sdomain = to_sunway_domain(dom); - size_t unmap_size; + struct sunway_iommu_domain *sdomain = to_sunway_domain(domain); + size_t size = pgcount << __ffs(pgsize); + unsigned long unmapped_size = 0; + unsigned long unmap_size; if (iova >= SW64_BAR_ADDRESS) - return page_size; + return size; /* IOMMU v2 supports 42 bit mapped address width */ if (iova >= MAX_IOVA_WIDTH) { @@ -1512,9 +1535,19 @@ sunway_iommu_unmap(struct iommu_domain *dom, unsigned long iova, return 0; } - unmap_size = sunway_iommu_unmap_page(sdomain, iova, page_size); + if (!(pgsize & domain->pgsize_bitmap)) { + pr_err("pgsize: %lx not supported\n", pgsize); + return -EINVAL; + } + + while (unmapped_size < size) { + unmap_size = sunway_iommu_unmap_page(sdomain, iova, pgsize); + + iova += unmap_size; + unmapped_size += unmap_size; + } - return unmap_size; + return size; } static struct iommu_group *sunway_iommu_device_group(struct device *dev) @@ -1700,8 +1733,8 @@ const struct iommu_ops sunway_iommu_ops = { .def_domain_type = sunway_iommu_def_domain_type, .default_domain_ops = &(const struct iommu_domain_ops) { .attach_dev = sunway_iommu_attach_device, - .map = sunway_iommu_map, - .unmap = sunway_iommu_unmap, + .map_pages = sunway_iommu_map_pages, + .unmap_pages = sunway_iommu_unmap_pages, .iova_to_phys = sunway_iommu_iova_to_phys, .free = sunway_iommu_domain_free, } diff --git a/drivers/pci/controller/pci-sunway.c b/drivers/pci/controller/pci-sunway.c index a4535c61c04e009a7b71549e8246bc98932f12ae..76514c5695cb16f6d4d2e65f0254982d86df04ea 100644 --- a/drivers/pci/controller/pci-sunway.c +++ b/drivers/pci/controller/pci-sunway.c @@ -865,10 +865,9 @@ static int pci_prepare_controller(struct pci_controller *hose, hose->dense_mem_base = props[PROP_PCIE_IO_BASE]; hose->dense_io_base = props[PROP_EP_IO_BASE]; - hose->rc_config_space_base = __va(props[PROP_RC_CONFIG_BASE]); - hose->ep_config_space_base = __va(props[PROP_EP_CONFIG_BASE]); - hose->piu_ior0_base = __va(props[PROP_PIU_IOR0_BASE]); - hose->piu_ior1_base = __va(props[PROP_PIU_IOR1_BASE]); + hose->rc_config_space_base = ioremap(props[PROP_RC_CONFIG_BASE], SUNWAY_RC_SIZE); + hose->piu_ior0_base = ioremap(props[PROP_PIU_IOR0_BASE], SUNWAY_PIU_IOR0_SIZE); + hose->piu_ior1_base = ioremap(props[PROP_PIU_IOR1_BASE], SUNWAY_PIU_IOR1_SIZE); hose->first_busno = 0xff; hose->last_busno = 0xff; @@ -964,6 +963,8 @@ static int sunway_pci_ecam_init(struct pci_config_window *cfg) if (!hose) return -ENOMEM; + hose->ep_config_space_base = cfg->win; + /* Init pci_controller */ ret = pci_prepare_controller(hose, fwnode); if (ret) { diff --git a/drivers/pci/ecam.c b/drivers/pci/ecam.c index 1c40d2506aef347a57b4f11989ce455c8529f0dd..e568ca75052213318e1b6471f4481a8415fc6c71 100644 --- a/drivers/pci/ecam.c +++ b/drivers/pci/ecam.c @@ -79,7 +79,12 @@ struct pci_config_window *pci_ecam_create(struct device *dev, if (!cfg->winp) goto err_exit_malloc; } else { +#if IS_ENABLED(CONFIG_SW64) + cfg->win = pci_remap_cfgspace(cfgres->start, + (unsigned long)bus_range * (unsigned long)bsz); +#else cfg->win = pci_remap_cfgspace(cfgres->start, bus_range * bsz); +#endif if (!cfg->win) goto err_exit_iomap; } diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 80e5ca7b940f719aa9d0d9a9546bb7347ff64e06..88c493b60d9a517b872fe2451dcac344f0f01193 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -1328,7 +1328,7 @@ fixup_usb_xhci_reset(struct pci_dev *dev) if (offset == 0) return; - base = (void *)__va(SW64_PCI_IO_BASE(hose->node, hose->index) | offset); + base = ioremap(SW64_PCI_IO_BASE(hose->node, hose->index) | offset, SZ_8K); ext_cap_offset = xhci_find_next_ext_cap(base, 0, XHCI_EXT_CAPS_LEGACY); if (!ext_cap_offset) @@ -1415,6 +1415,8 @@ fixup_usb_xhci_reset(struct pci_dev *dev) pci_read_config_dword(dev, PCI_COMMAND, &tmp); tmp &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); pci_write_config_dword(dev, PCI_COMMAND, tmp); + + iounmap(base); } DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_SERIAL_USB_XHCI, 0, fixup_usb_xhci_reset); diff --git a/samples/ftrace/ftrace-direct-modify.c b/samples/ftrace/ftrace-direct-modify.c index e2a6a69352dfb775ebc7d6954c98943ec2a3097f..23ea4ac065822f44c6f1a0aef0adf738fbaca034 100644 --- a/samples/ftrace/ftrace-direct-modify.c +++ b/samples/ftrace/ftrace-direct-modify.c @@ -164,6 +164,74 @@ asm ( #endif /* CONFIG_LOONGARCH */ +#ifdef CONFIG_SW64 + +asm ( +" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" subl $sp, 0x10, $sp\n" +" stl $26, 0($sp)\n" +" stl $15, 0x8($sp)\n" +" ldi $15, 0($sp)\n" + /* save $28 & fp of caller */ +" subl $sp, 0x10, $sp\n" +" stl $28, 0($sp)\n" +" stl $15, 0x8($sp)\n" +" ldi $15, 0($sp)\n" + /* save other regs */ +" subl $sp, 0x18, $sp\n" +" stl $26, 0($sp)\n" +" stl $28, 0x8($sp)\n" +" stl $29, 0x10($sp)\n" +" br $27, 1f\n" +"1: ldgp $29, 0($27)\n" +" call my_direct_func1\n" + /* restore all regs */ +" ldl $26, 0x0($sp)\n" +" ldl $28, 0x8($sp)\n" +" ldl $29, 0x10($sp)\n" +" addl $sp, 0x18, $sp\n" +" ldl $15, 0x18($sp)\n" +" addl $sp, 0x20, $sp\n" +" ret $31, ($28), 1\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" subl $sp, 0x10, $sp\n" +" stl $26, 0($sp)\n" +" stl $15, 0x8($sp)\n" +" ldi $15, 0($sp)\n" + /* save $28 & fp of caller */ +" subl $sp, 0x10, $sp\n" +" stl $28, 0($sp)\n" +" stl $15, 0x8($sp)\n" +" ldi $15, 0($sp)\n" + /* save other regs */ +" subl $sp, 0x18, $sp\n" +" stl $26, 0($sp)\n" +" stl $28, 0x8($sp)\n" +" stl $29, 0x10($sp)\n" +" br $27, 1f\n" +"1: ldgp $29, 0($27)\n" +" call my_direct_func2\n" + /* restore all regs */ +" ldl $26, 0x0($sp)\n" +" ldl $28, 0x8($sp)\n" +" ldl $29, 0x10($sp)\n" +" addl $sp, 0x18, $sp\n" +" ldl $15, 0x18($sp)\n" +" addl $sp, 0x20, $sp\n" +" ret $31, ($28), 1\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_SW64 */ + static struct ftrace_ops direct; static unsigned long my_tramp = (unsigned long)my_tramp1; diff --git a/samples/ftrace/ftrace-direct-multi-modify.c b/samples/ftrace/ftrace-direct-multi-modify.c index 2e349834d63c386ef54a8d3fecb2df713e7e4f2e..455da065d89f28192425ca9affa14aa3135b1845 100644 --- a/samples/ftrace/ftrace-direct-multi-modify.c +++ b/samples/ftrace/ftrace-direct-multi-modify.c @@ -184,6 +184,80 @@ asm ( #endif /* CONFIG_LOONGARCH */ +#ifdef CONFIG_SW64 + +asm ( +" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" +" subl $sp, 0x10, $sp\n" +" stl $26, 0($sp)\n" +" stl $15, 0x8($sp)\n" +" ldi $15, 0($sp)\n" + /* save $28 & fp of caller */ +" subl $sp, 0x10, $sp\n" +" stl $28, 0($sp)\n" +" stl $15, 0x8($sp)\n" +" ldi $15, 0($sp)\n" + /* save other regs */ +" subl $sp, 0x20, $sp\n" +" stl $16, 0($sp)\n" +" stl $26, 0x8($sp)\n" +" stl $28, 0x10($sp)\n" +" stl $29, 0x18($sp)\n" +" mov $28, $16\n" +" br $27, 1f\n" +"1: ldgp $29, 0($27)\n" +" call my_direct_func1\n" + /* restore all regs */ +" ldl $16, 0($sp)\n" +" ldl $26, 0x8($sp)\n" +" ldl $28, 0x10($sp)\n" +" ldl $29, 0x18($sp)\n" +" addl $sp, 0x20, $sp\n" +" ldl $15, 0x18($sp)\n" +" addl $sp, 0x20, $sp\n" +" ret $31, ($28), 1\n" +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" +" subl $sp, 0x10, $sp\n" +" stl $26, 0($sp)\n" +" stl $15, 0x8($sp)\n" +" ldi $15, 0($sp)\n" + /* save $28 & fp of caller */ +" subl $sp, 0x10, $sp\n" +" stl $28, 0($sp)\n" +" stl $15, 0x8($sp)\n" +" ldi $15, 0($sp)\n" + /* save other regs */ +" subl $sp, 0x20, $sp\n" +" stl $16, 0($sp)\n" +" stl $26, 0x8($sp)\n" +" stl $28, 0x10($sp)\n" +" stl $29, 0x18($sp)\n" +" mov $28, $16\n" +" br $27, 1f\n" +"1: ldgp $29, 0($2)\n" +" call my_direct_func2\n" + /* restore all regs */ +" ldl $16, 0($sp)\n" +" ldl $26, 0x8($sp)\n" +" ldl $28, 0x10($sp)\n" +" ldl $29, 0x18($sp)\n" +" addl $sp, 0x20, $sp\n" +" ldl $15, 0x18($sp)\n" +" addl $sp, 0x20, $sp\n" +" ret $31, ($28), 1\n" +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_SW64 */ + static unsigned long my_tramp = (unsigned long)my_tramp1; static unsigned long tramps[2] = { (unsigned long)my_tramp1, diff --git a/samples/ftrace/ftrace-direct-multi.c b/samples/ftrace/ftrace-direct-multi.c index 9243dbfe4d0c1f72f7e9d55f5d7fb9631482018f..91b03bcf2f9c7dee054cee246604615f74b602cd 100644 --- a/samples/ftrace/ftrace-direct-multi.c +++ b/samples/ftrace/ftrace-direct-multi.c @@ -116,6 +116,47 @@ asm ( #endif /* CONFIG_LOONGARCH */ +#ifdef CONFIG_SW64 + +asm ( +" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" subl $sp, 0x10, $sp\n" +" stl $26, 0($sp)\n" +" stl $15, 0x8($sp)\n" +" ldi $15, 0($sp)\n" + /* save $28 & fp of caller */ +" subl $sp, 0x10, $sp\n" +" stl $28, 0($sp)\n" +" stl $15, 0x8($sp)\n" +" ldi $15, 0($sp)\n" + /* save other regs */ +" subl $sp, 0x20, $sp\n" +" stl $16, 0($sp)\n" +" stl $26, 0x8($sp)\n" +" stl $28, 0x10($sp)\n" +" stl $29, 0x18($sp)\n" +" mov $28, $16\n" +" br $27, 1f\n" +"1: ldgp $29, 0($27)\n" +" call my_direct_func\n" + /* restore all regs */ +" ldl $16, 0($sp)\n" +" ldl $26, 0x8($sp)\n" +" ldl $28, 0x10($sp)\n" +" ldl $29, 0x18($sp)\n" +" addl $sp, 0x20, $sp\n" +" ldl $15, 0x18($sp)\n" +" addl $sp, 0x20, $sp\n" +" ret $31, ($28), 1\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_SW64 */ + static struct ftrace_ops direct; static int __init ftrace_direct_multi_init(void) diff --git a/samples/ftrace/ftrace-direct-too.c b/samples/ftrace/ftrace-direct-too.c index e39c3563ae4e42845aa8028aafa8fce394ab7759..8d4bf161bda8b11325cbb17f46738105ccd22c98 100644 --- a/samples/ftrace/ftrace-direct-too.c +++ b/samples/ftrace/ftrace-direct-too.c @@ -125,6 +125,52 @@ asm ( #endif /* CONFIG_LOONGARCH */ +#ifdef CONFIG_SW64 + +asm ( +" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" subl $sp, 0x10, $sp\n" +" stl $26, 0($sp)\n" +" stl $15, 0x8($sp)\n" +" ldi $15, 0($sp)\n" + /* save $28 & fp of caller */ +" subl $sp, 0x10, $sp\n" +" stl $28, 0($sp)\n" +" stl $15, 0x8($sp)\n" +" ldi $15, 0($sp)\n" + /* save other regs */ +" subl $sp, 0x38, $sp\n" +" stl $16, 0($sp)\n" +" stl $17, 0x8($sp)\n" +" stl $18, 0x10($sp)\n" +" stl $19, 0x18($sp)\n" +" stl $26, 0x20($sp)\n" +" stl $28, 0x28($sp)\n" +" stl $29, 0x30($sp)\n" +" br $27, 1f\n" +"1: ldgp $29, 0($27)\n" +" call my_direct_func\n" + /* restore all regs */ +" ldl $16, 0($sp)\n" +" ldl $17, 0x8($sp)\n" +" ldl $18, 0x10($sp)\n" +" stl $19, 0x18($sp)\n" +" ldl $26, 0x20($sp)\n" +" ldl $28, 0x28($sp)\n" +" ldl $29, 0x30($sp)\n" +" addl $sp, 0x38, $sp\n" +" ldl $15, 0x18($sp)\n" +" addl $sp, 0x20, $sp\n" +" ret $31, ($28), 1\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_SW64 */ + static struct ftrace_ops direct; static int __init ftrace_direct_init(void) diff --git a/samples/ftrace/ftrace-direct.c b/samples/ftrace/ftrace-direct.c index 32c477da1e9aa3719cd1ac6997d8e774e7d84658..4e062e97fe010877a92d5d9c670de1d7844a278e 100644 --- a/samples/ftrace/ftrace-direct.c +++ b/samples/ftrace/ftrace-direct.c @@ -110,6 +110,46 @@ asm ( #endif /* CONFIG_LOONGARCH */ +#ifdef CONFIG_SW64 + +asm ( +" .pushsection .text, \"ax\", @progbits\n" +" .type my_tramp, @function\n" +" .globl my_tramp\n" +" my_tramp:\n" +" subl $sp, 0x10, $sp\n" +" stl $26, 0($sp)\n" +" stl $15, 0x8($sp)\n" +" ldi $15, 0($sp)\n" + /* save $28 & fp of caller */ +" subl $sp, 0x10, $sp\n" +" stl $28, 0($sp)\n" +" stl $15, 0x8($sp)\n" +" ldi $15, 0($sp)\n" + /* save other regs */ +" subl $sp, 0x20, $sp\n" +" stl $16, 0($sp)\n" +" stl $26, 0x8($sp)\n" +" stl $28, 0x10($sp)\n" +" stl $29, 0x18($sp)\n" +" br $27, 1f\n" +"1: ldgp $29, 0($27)\n" +" call my_direct_func\n" + /* restore all regs */ +" ldl $16, 0($sp)\n" +" ldl $26, 0x8($sp)\n" +" ldl $28, 0x10($sp)\n" +" ldl $29, 0x18($sp)\n" +" addl $sp, 0x20, $sp\n" +" ldl $15, 0x18($sp)\n" +" addl $sp, 0x20, $sp\n" +" ret $31, ($28), 1\n" +" .size my_tramp, .-my_tramp\n" +" .popsection\n" +); + +#endif /* CONFIG_SW64 */ + static struct ftrace_ops direct; static int __init ftrace_direct_init(void) diff --git a/tools/perf/util/perf-regs-arch/Build b/tools/perf/util/perf-regs-arch/Build index 48f24458e8004af529100c2ba6760d66ddb71565..d47893db426898c2d4ddf9e37dd59acfab48c3b0 100644 --- a/tools/perf/util/perf-regs-arch/Build +++ b/tools/perf/util/perf-regs-arch/Build @@ -6,5 +6,5 @@ perf-y += perf_regs_mips.o perf-y += perf_regs_powerpc.o perf-y += perf_regs_riscv.o perf-y += perf_regs_s390.o -perf-y += perf_regs_sw_64.o +perf-y += perf_regs_sw64.o perf-y += perf_regs_x86.o diff --git a/tools/perf/util/perf-regs-arch/perf_regs_sw_64.c b/tools/perf/util/perf-regs-arch/perf_regs_sw64.c similarity index 93% rename from tools/perf/util/perf-regs-arch/perf_regs_sw_64.c rename to tools/perf/util/perf-regs-arch/perf_regs_sw64.c index 1c416f540eda60f5d082815f8852e94382906825..1f81a4e67d8d5bcb437bac642e8784e8c451571b 100644 --- a/tools/perf/util/perf-regs-arch/perf_regs_sw_64.c +++ b/tools/perf/util/perf-regs-arch/perf_regs_sw64.c @@ -5,7 +5,7 @@ #include "../perf_regs.h" #include "../../../arch/sw_64/include/uapi/asm/perf_regs.h" -const char *__perf_reg_name_sw_64(int id) +const char *__perf_reg_name_sw64(int id) { switch (id) { case PERF_REG_SW64_R0: @@ -79,12 +79,12 @@ const char *__perf_reg_name_sw_64(int id) return NULL; } -uint64_t __perf_reg_ip_sw_64(void) +uint64_t __perf_reg_ip_sw64(void) { return PERF_REG_SW64_PC; } -uint64_t __perf_reg_sp_sw_64(void) +uint64_t __perf_reg_sp_sw64(void) { return PERF_REG_SW64_SP; } diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c index ee96eaaf1102584ac7567e579ee326a49ea902bf..90dd226928ad2829f37b23a70958a6ac1e1da276 100644 --- a/tools/perf/util/perf_regs.c +++ b/tools/perf/util/perf_regs.c @@ -40,7 +40,7 @@ const char *perf_reg_name(int id, const char *arch) else if (!strcmp(arch, "s390")) reg_name = __perf_reg_name_s390(id); else if (!strcmp(arch, "sw_64")) - reg_name = __perf_reg_name_sw_64(id); + reg_name = __perf_reg_name_sw64(id); else if (!strcmp(arch, "x86")) reg_name = __perf_reg_name_x86(id); else if (!strcmp(arch, "arm")) @@ -96,6 +96,8 @@ uint64_t perf_arch_reg_ip(const char *arch) return __perf_reg_ip_riscv(); else if (!strcmp(arch, "s390")) return __perf_reg_ip_s390(); + else if (!strcmp(arch, "sw_64")) + return __perf_reg_ip_sw64(); else if (!strcmp(arch, "x86")) return __perf_reg_ip_x86(); @@ -121,6 +123,8 @@ uint64_t perf_arch_reg_sp(const char *arch) return __perf_reg_sp_riscv(); else if (!strcmp(arch, "s390")) return __perf_reg_sp_s390(); + else if (!strcmp(arch, "sw_64")) + return __perf_reg_sp_sw64(); else if (!strcmp(arch, "x86")) return __perf_reg_sp_x86(); diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h index 1c79e1a75c62f352f46475df060da022261d8ab0..ea68adaa19a05502057f8ef4fe10f42752cae628 100644 --- a/tools/perf/util/perf_regs.h +++ b/tools/perf/util/perf_regs.h @@ -58,9 +58,9 @@ uint64_t __perf_reg_sp_riscv(void); const char *__perf_reg_name_s390(int id); uint64_t __perf_reg_ip_s390(void); uint64_t __perf_reg_sp_s390(void); -const char *__perf_reg_name_sw_64(int id); -uint64_t __perf_reg_ip_sw_64(void); -uint64_t __perf_reg_sp_sw_64(void); +const char *__perf_reg_name_sw64(int id); +uint64_t __perf_reg_ip_sw64(void); +uint64_t __perf_reg_sp_sw64(void); const char *__perf_reg_name_x86(int id); uint64_t __perf_reg_ip_x86(void); uint64_t __perf_reg_sp_x86(void); diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources index 26e1c8d973ea0b954d910bd9874873372a8f54b6..080a2091e53fa68bcf23b9667eb93f56a7e5cee5 100644 --- a/tools/perf/util/python-ext-sources +++ b/tools/perf/util/python-ext-sources @@ -48,4 +48,5 @@ util/perf-regs-arch/perf_regs_mips.c util/perf-regs-arch/perf_regs_powerpc.c util/perf-regs-arch/perf_regs_riscv.c util/perf-regs-arch/perf_regs_s390.c +util/perf-regs-arch/perf_regs_sw64.c util/perf-regs-arch/perf_regs_x86.c