From 0e9a2a228a1ac80053d9817a8af68abcd754675e Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 14 Jul 2023 11:40:23 -0600 Subject: [PATCH 01/49] microblaze: Explicitly include correct DT includes The DT of_device.h and of_platform.h date back to the separate of_platform_bus_type before it as merged into the regular platform bus. As part of that merge prepping Arm DT support 13 years ago, they "temporarily" include each other. They also include platform_device.h and of.h. As a result, there's a pretty much random mix of those include files used throughout the tree. In order to detangle these headers and replace the implicit includes with struct declarations, users need to explicitly include the correct includes. Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20230714174023.4039938-1-robh@kernel.org Signed-off-by: Michal Simek --- arch/microblaze/kernel/reset.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c index 5f4722908164..2f66c7963084 100644 --- a/arch/microblaze/kernel/reset.c +++ b/arch/microblaze/kernel/reset.c @@ -9,7 +9,6 @@ #include #include -#include #include void machine_shutdown(void) From 232ba1630c666b37a5045781e6513cba607fb0d5 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 11 Aug 2023 09:01:17 +0200 Subject: [PATCH 02/49] openrisc: Make pfn accessors statics inlines Making virt_to_pfn() a static inline taking a strongly typed (const void *) makes the contract of a passing a pointer of that type to the function explicit and exposes any misuse of the macro virt_to_pfn() acting polymorphic and accepting many types such as (void *), (unitptr_t) or (unsigned long) as arguments without warnings. For symmetry, do the same with pfn_to_virt(). Signed-off-by: Linus Walleij Signed-off-by: Stafford Horne --- arch/openrisc/include/asm/page.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/openrisc/include/asm/page.h b/arch/openrisc/include/asm/page.h index 52b0d7e76446..44fc1fd56717 100644 --- a/arch/openrisc/include/asm/page.h +++ b/arch/openrisc/include/asm/page.h @@ -72,8 +72,15 @@ typedef struct page *pgtable_t; #define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET)) #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) -#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) -#define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT) +static inline unsigned long virt_to_pfn(const void *kaddr) +{ + return __pa(kaddr) >> PAGE_SHIFT; +} + +static inline void * pfn_to_virt(unsigned long pfn) +{ + return (void *)((unsigned long)__va(pfn) << PAGE_SHIFT); +} #define virt_to_page(addr) \ (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)) From 4d3696801bad2a037832c15a8d21dfe0c529d9cd Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Sat, 12 Aug 2023 18:23:59 -0700 Subject: [PATCH 03/49] ARC: -Wmissing-prototype warning fixes Anrd reported [1] new compiler warnings due to -Wmissing-protype. These are for non static functions mostly used in asm code hence not exported already. Fix this by adding the prototypes. [1] https://lore.kernel.org/lkml/20230810141947.1236730-1-arnd@kernel.org Reviewed-by: Arnd Bergmann Signed-off-by: Vineet Gupta --- arch/arc/include/asm/entry.h | 21 +++++++++++++++++++++ arch/arc/include/asm/irq.h | 1 + arch/arc/include/asm/mmu.h | 2 ++ arch/arc/include/asm/ptrace.h | 3 +++ arch/arc/include/asm/setup.h | 2 ++ arch/arc/include/asm/smp.h | 2 ++ arch/arc/kernel/ctx_sw.c | 2 +- arch/arc/kernel/devtree.c | 1 + arch/arc/kernel/intc-arcv2.c | 2 +- arch/arc/kernel/signal.c | 1 + arch/arc/kernel/smp.c | 7 ++++--- arch/arc/kernel/stacktrace.c | 1 + arch/arc/kernel/traps.c | 1 + arch/arc/mm/cache.c | 8 ++++---- arch/arc/mm/fault.c | 1 + arch/arc/mm/init.c | 1 + arch/arc/mm/tlb.c | 2 +- 17 files changed, 48 insertions(+), 10 deletions(-) diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h index fcdd59d77f42..2980bc9b7653 100644 --- a/arch/arc/include/asm/entry.h +++ b/arch/arc/include/asm/entry.h @@ -13,6 +13,8 @@ #include /* For VMALLOC_START */ #include +#ifdef __ASSEMBLY__ + #ifdef CONFIG_ISA_ARCOMPACT #include /* ISA specific bits */ #else @@ -295,4 +297,23 @@ #endif /* CONFIG_ARC_CURR_IN_REG */ +#else /* !__ASSEMBLY__ */ + +extern void do_signal(struct pt_regs *); +extern void do_notify_resume(struct pt_regs *); +extern int do_privilege_fault(unsigned long, struct pt_regs *); +extern int do_extension_fault(unsigned long, struct pt_regs *); +extern int insterror_is_error(unsigned long, struct pt_regs *); +extern int do_memory_error(unsigned long, struct pt_regs *); +extern int trap_is_brkpt(unsigned long, struct pt_regs *); +extern int do_misaligned_error(unsigned long, struct pt_regs *); +extern int do_trap5_error(unsigned long, struct pt_regs *); +extern int do_misaligned_access(unsigned long, struct pt_regs *, struct callee_regs *); +extern void do_machine_check_fault(unsigned long, struct pt_regs *); +extern void do_non_swi_trap(unsigned long, struct pt_regs *); +extern void do_insterror_or_kprobe(unsigned long, struct pt_regs *); +extern void do_page_fault(unsigned long, struct pt_regs *); + +#endif + #endif /* __ASM_ARC_ENTRY_H */ diff --git a/arch/arc/include/asm/irq.h b/arch/arc/include/asm/irq.h index 0309cb405cfb..c574712ad865 100644 --- a/arch/arc/include/asm/irq.h +++ b/arch/arc/include/asm/irq.h @@ -25,5 +25,6 @@ #include extern void arc_init_IRQ(void); +extern void arch_do_IRQ(unsigned int, struct pt_regs *); #endif diff --git a/arch/arc/include/asm/mmu.h b/arch/arc/include/asm/mmu.h index ca427c30f70e..9febf5bc3de6 100644 --- a/arch/arc/include/asm/mmu.h +++ b/arch/arc/include/asm/mmu.h @@ -14,6 +14,8 @@ typedef struct { unsigned long asid[NR_CPUS]; /* 8 bit MMU PID + Generation cycle */ } mm_context_t; +extern void do_tlb_overlap_fault(unsigned long, unsigned long, struct pt_regs *); + #endif #include diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index 5869a74c0db2..cf90fcd2a628 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -181,6 +181,9 @@ static inline unsigned long regs_get_register(struct pt_regs *regs, return *(unsigned long *)((unsigned long)regs + offset); } +extern int syscall_trace_entry(struct pt_regs *); +extern void syscall_trace_exit(struct pt_regs *); + #endif /* !__ASSEMBLY__ */ #endif /* __ASM_PTRACE_H */ diff --git a/arch/arc/include/asm/setup.h b/arch/arc/include/asm/setup.h index 028a8cf76206..374138832c5a 100644 --- a/arch/arc/include/asm/setup.h +++ b/arch/arc/include/asm/setup.h @@ -42,4 +42,6 @@ extern void arc_cache_init(void); extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len); extern void read_decode_cache_bcr(void); +extern void __init handle_uboot_args(void); + #endif /* __ASMARC_SETUP_H */ diff --git a/arch/arc/include/asm/smp.h b/arch/arc/include/asm/smp.h index d856491606ac..e0913f52c2cd 100644 --- a/arch/arc/include/asm/smp.h +++ b/arch/arc/include/asm/smp.h @@ -29,6 +29,8 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask); extern void __init smp_init_cpus(void); extern void first_lines_of_secondary(void); extern const char *arc_platform_smp_cpuinfo(void); +extern void arc_platform_smp_wait_to_boot(int); +extern void start_kernel_secondary(void); /* * API expected BY platform smp code (FROM arch smp code) diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c index 1a76f2d6f694..bf16f777a0bc 100644 --- a/arch/arc/kernel/ctx_sw.c +++ b/arch/arc/kernel/ctx_sw.c @@ -12,7 +12,7 @@ */ #include -#include +#include #include #define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) diff --git a/arch/arc/kernel/devtree.c b/arch/arc/kernel/devtree.c index 721d465f1580..4c9e61457b2f 100644 --- a/arch/arc/kernel/devtree.c +++ b/arch/arc/kernel/devtree.c @@ -12,6 +12,7 @@ #include #include #include +#include #ifdef CONFIG_SERIAL_EARLYCON diff --git a/arch/arc/kernel/intc-arcv2.c b/arch/arc/kernel/intc-arcv2.c index 5cda19d0aa91..678898757e47 100644 --- a/arch/arc/kernel/intc-arcv2.c +++ b/arch/arc/kernel/intc-arcv2.c @@ -108,7 +108,7 @@ static void arcv2_irq_unmask(struct irq_data *data) write_aux_reg(AUX_IRQ_ENABLE, 1); } -void arcv2_irq_enable(struct irq_data *data) +static void arcv2_irq_enable(struct irq_data *data) { /* set default priority */ write_aux_reg(AUX_IRQ_SELECT, data->hwirq); diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c index 3c1590c27fae..0b3bb529d246 100644 --- a/arch/arc/kernel/signal.c +++ b/arch/arc/kernel/signal.c @@ -53,6 +53,7 @@ #include #include +#include struct rt_sigframe { struct siginfo info; diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c index 409cfa4675b4..8d9b188caa27 100644 --- a/arch/arc/kernel/smp.c +++ b/arch/arc/kernel/smp.c @@ -23,9 +23,10 @@ #include #include -#include -#include #include +#include +#include +#include #ifndef CONFIG_ARC_HAS_LLSC arch_spinlock_t smp_atomic_ops_lock = __ARCH_SPIN_LOCK_UNLOCKED; @@ -351,7 +352,7 @@ static inline int __do_IPI(unsigned long msg) * arch-common ISR to handle for inter-processor interrupts * Has hooks for platform specific IPI */ -irqreturn_t do_IPI(int irq, void *dev_id) +static irqreturn_t do_IPI(int irq, void *dev_id) { unsigned long pending; unsigned long __maybe_unused copy; diff --git a/arch/arc/kernel/stacktrace.c b/arch/arc/kernel/stacktrace.c index 5372dc04e784..ea99c066ef25 100644 --- a/arch/arc/kernel/stacktrace.c +++ b/arch/arc/kernel/stacktrace.c @@ -29,6 +29,7 @@ #include #include +#include #include /*------------------------------------------------------------------------- diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c index 6b83e3f2b41c..2f7eb786695b 100644 --- a/arch/arc/kernel/traps.c +++ b/arch/arc/kernel/traps.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c index 55c6de138eae..bdaa4aa40947 100644 --- a/arch/arc/mm/cache.c +++ b/arch/arc/mm/cache.c @@ -581,7 +581,7 @@ static void __ic_line_inv_vaddr(phys_addr_t paddr, unsigned long vaddr, #endif /* CONFIG_ARC_HAS_ICACHE */ -noinline void slc_op_rgn(phys_addr_t paddr, unsigned long sz, const int op) +static noinline void slc_op_rgn(phys_addr_t paddr, unsigned long sz, const int op) { #ifdef CONFIG_ISA_ARCV2 /* @@ -644,7 +644,7 @@ noinline void slc_op_rgn(phys_addr_t paddr, unsigned long sz, const int op) #endif } -noinline void slc_op_line(phys_addr_t paddr, unsigned long sz, const int op) +static __maybe_unused noinline void slc_op_line(phys_addr_t paddr, unsigned long sz, const int op) { #ifdef CONFIG_ISA_ARCV2 /* @@ -1069,7 +1069,7 @@ SYSCALL_DEFINE3(cacheflush, uint32_t, start, uint32_t, sz, uint32_t, flags) * 3. All Caches need to be disabled when setting up IOC to elide any in-flight * Coherency transactions */ -noinline void __init arc_ioc_setup(void) +static noinline void __init arc_ioc_setup(void) { unsigned int ioc_base, mem_sz; @@ -1131,7 +1131,7 @@ noinline void __init arc_ioc_setup(void) * one core suffices for all * - IOC setup / dma callbacks only need to be done once */ -void __init arc_cache_init_master(void) +static noinline void __init arc_cache_init_master(void) { unsigned int __maybe_unused cpu = smp_processor_id(); diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index f59e722d147f..26e5823c5710 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c @@ -13,6 +13,7 @@ #include #include #include +#include #include /* diff --git a/arch/arc/mm/init.c b/arch/arc/mm/init.c index 9f64d729c9f8..6a71b23f1383 100644 --- a/arch/arc/mm/init.c +++ b/arch/arc/mm/init.c @@ -15,6 +15,7 @@ #include #include #include +#include #include pgd_t swapper_pg_dir[PTRS_PER_PGD] __aligned(PAGE_SIZE); diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index 5f71445f26bd..2a3105a682c3 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -389,7 +389,7 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end) /* * Routine to create a TLB entry */ -void create_tlb(struct vm_area_struct *vma, unsigned long vaddr, pte_t *ptep) +static void create_tlb(struct vm_area_struct *vma, unsigned long vaddr, pte_t *ptep) { unsigned long flags; unsigned int asid_or_sasid, rwx; From 42f51fb24fd39cc547c086ab3d8a314cc603a91c Mon Sep 17 00:00:00 2001 From: Pavel Kozlov Date: Tue, 15 Aug 2023 19:11:36 +0400 Subject: [PATCH 04/49] ARC: atomics: Add compiler barrier to atomic operations... ... to avoid unwanted gcc optimizations SMP kernels fail to boot with commit 596ff4a09b89 ("cpumask: re-introduce constant-sized cpumask optimizations"). | | percpu: BUG: failure at mm/percpu.c:2981/pcpu_build_alloc_info()! | The write operation performed by the SCOND instruction in the atomic inline asm code is not properly passed to the compiler. The compiler cannot correctly optimize a nested loop that runs through the cpumask in the pcpu_build_alloc_info() function. Fix this by add a compiler barrier (memory clobber in inline asm). Apparently atomic ops used to have memory clobber implicitly via surrounding smp_mb(). However commit b64be6836993c431e ("ARC: atomics: implement relaxed variants") removed the smp_mb() for the relaxed variants, but failed to add the explicit compiler barrier. Link: https://github.com/foss-for-synopsys-dwc-arc-processors/linux/issues/135 Cc: # v6.3+ Fixes: b64be6836993c43 ("ARC: atomics: implement relaxed variants") Signed-off-by: Pavel Kozlov Signed-off-by: Vineet Gupta [vgupta: tweaked the changelog and added Fixes tag] --- arch/arc/include/asm/atomic-llsc.h | 6 +++--- arch/arc/include/asm/atomic64-arcv2.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arc/include/asm/atomic-llsc.h b/arch/arc/include/asm/atomic-llsc.h index 1b0ffaeee16d..5258cb81a16b 100644 --- a/arch/arc/include/asm/atomic-llsc.h +++ b/arch/arc/include/asm/atomic-llsc.h @@ -18,7 +18,7 @@ static inline void arch_atomic_##op(int i, atomic_t *v) \ : [val] "=&r" (val) /* Early clobber to prevent reg reuse */ \ : [ctr] "r" (&v->counter), /* Not "m": llock only supports reg direct addr mode */ \ [i] "ir" (i) \ - : "cc"); \ + : "cc", "memory"); \ } \ #define ATOMIC_OP_RETURN(op, asm_op) \ @@ -34,7 +34,7 @@ static inline int arch_atomic_##op##_return_relaxed(int i, atomic_t *v) \ : [val] "=&r" (val) \ : [ctr] "r" (&v->counter), \ [i] "ir" (i) \ - : "cc"); \ + : "cc", "memory"); \ \ return val; \ } @@ -56,7 +56,7 @@ static inline int arch_atomic_fetch_##op##_relaxed(int i, atomic_t *v) \ [orig] "=&r" (orig) \ : [ctr] "r" (&v->counter), \ [i] "ir" (i) \ - : "cc"); \ + : "cc", "memory"); \ \ return orig; \ } diff --git a/arch/arc/include/asm/atomic64-arcv2.h b/arch/arc/include/asm/atomic64-arcv2.h index 6b6db981967a..9b5791b85471 100644 --- a/arch/arc/include/asm/atomic64-arcv2.h +++ b/arch/arc/include/asm/atomic64-arcv2.h @@ -60,7 +60,7 @@ static inline void arch_atomic64_##op(s64 a, atomic64_t *v) \ " bnz 1b \n" \ : "=&r"(val) \ : "r"(&v->counter), "ir"(a) \ - : "cc"); \ + : "cc", "memory"); \ } \ #define ATOMIC64_OP_RETURN(op, op1, op2) \ @@ -77,7 +77,7 @@ static inline s64 arch_atomic64_##op##_return_relaxed(s64 a, atomic64_t *v) \ " bnz 1b \n" \ : [val] "=&r"(val) \ : "r"(&v->counter), "ir"(a) \ - : "cc"); /* memory clobber comes from smp_mb() */ \ + : "cc", "memory"); \ \ return val; \ } @@ -99,7 +99,7 @@ static inline s64 arch_atomic64_fetch_##op##_relaxed(s64 a, atomic64_t *v) \ " bnz 1b \n" \ : "=&r"(orig), "=&r"(val) \ : "r"(&v->counter), "ir"(a) \ - : "cc"); /* memory clobber comes from smp_mb() */ \ + : "cc", "memory"); \ \ return orig; \ } From 80bfe134f0306a1ef1f6c4e884ec17b74471d4a4 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 13 Aug 2021 17:48:08 -0700 Subject: [PATCH 05/49] ARC: uaccess: remove arc specific out-of-line handles for -Os Everything is now out-of-line in lib/usercopy.c Signed-off-by: Vineet Gupta --- arch/arc/include/asm/uaccess.h | 11 ++--------- arch/arc/mm/extable.c | 11 ----------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/arch/arc/include/asm/uaccess.h b/arch/arc/include/asm/uaccess.h index 99712471c96a..d2da159bb80a 100644 --- a/arch/arc/include/asm/uaccess.h +++ b/arch/arc/include/asm/uaccess.h @@ -584,7 +584,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n) return res; } -static inline unsigned long __arc_clear_user(void __user *to, unsigned long n) +static inline unsigned long __clear_user(void __user *to, unsigned long n) { long res = n; unsigned char *d_char = to; @@ -626,17 +626,10 @@ static inline unsigned long __arc_clear_user(void __user *to, unsigned long n) return res; } -#ifndef CONFIG_CC_OPTIMIZE_FOR_SIZE - #define INLINE_COPY_TO_USER #define INLINE_COPY_FROM_USER -#define __clear_user(d, n) __arc_clear_user(d, n) -#else -extern unsigned long arc_clear_user_noinline(void __user *to, - unsigned long n); -#define __clear_user(d, n) arc_clear_user_noinline(d, n) -#endif +#define __clear_user __clear_user #include diff --git a/arch/arc/mm/extable.c b/arch/arc/mm/extable.c index 4e14c4244ea2..88fa3a4d4906 100644 --- a/arch/arc/mm/extable.c +++ b/arch/arc/mm/extable.c @@ -22,14 +22,3 @@ int fixup_exception(struct pt_regs *regs) return 0; } - -#ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE - -unsigned long arc_clear_user_noinline(void __user *to, - unsigned long n) -{ - return __arc_clear_user(to, n); -} -EXPORT_SYMBOL(arc_clear_user_noinline); - -#endif From f798f91e7f5f000285ab11696d3f4af6aa20b869 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Mon, 13 Jan 2020 15:24:34 -0800 Subject: [PATCH 06/49] ARC: uaccess: use optimized generic __strnlen_user/__strncpy_from_user The existing ARC variants have 2 issues - Use ZOL which may not be present in forthcoming architecture - Byte loop based vs. generic version which is word loop based Signed-off-by: Vineet Gupta --- arch/arc/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 96cf8720bb93..47b4acc7d0c9 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -26,6 +26,8 @@ config ARC select GENERIC_PENDING_IRQ if SMP select GENERIC_SCHED_CLOCK select GENERIC_SMP_IDLE_THREAD + select GENERIC_STRNCPY_FROM_USER if MMU + select GENERIC_STRNLEN_USER if MMU select HAVE_ARCH_KGDB select HAVE_ARCH_TRACEHOOK select HAVE_ARCH_TRANSPARENT_HUGEPAGE if ARC_MMU_V4 From c8ee610afe654da7276d4aa8ad2bb60ffff6ddfc Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Mon, 3 Feb 2020 11:43:22 -0800 Subject: [PATCH 07/49] ARC: uaccess: elide unaliged handling if hardware supports Signed-off-by: Vineet Gupta --- arch/arc/include/asm/uaccess.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/arc/include/asm/uaccess.h b/arch/arc/include/asm/uaccess.h index d2da159bb80a..1e8809ea000a 100644 --- a/arch/arc/include/asm/uaccess.h +++ b/arch/arc/include/asm/uaccess.h @@ -146,8 +146,9 @@ raw_copy_from_user(void *to, const void __user *from, unsigned long n) if (n == 0) return 0; - /* unaligned */ - if (((unsigned long)to & 0x3) || ((unsigned long)from & 0x3)) { + /* fallback for unaligned access when hardware doesn't support */ + if (!IS_ENABLED(CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS) && + (((unsigned long)to & 0x3) || ((unsigned long)from & 0x3))) { unsigned char tmp; @@ -373,8 +374,9 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n) if (n == 0) return 0; - /* unaligned */ - if (((unsigned long)to & 0x3) || ((unsigned long)from & 0x3)) { + /* fallback for unaligned access when hardware doesn't support */ + if (!IS_ENABLED(CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS) && + (((unsigned long)to & 0x3) || ((unsigned long)from & 0x3))) { unsigned char tmp; From 1918693ff1891ba57af22dbbf511cf300158a975 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 7 Feb 2020 12:27:02 -0800 Subject: [PATCH 08/49] ARCv2: memset: don't prefetch for len == 0 which happens a alot This avoids potential "bleeding" when size == 0 as cache line would be dirtied (and possibly fetched from other cores) and due to the same reaons more optimal too. Signed-off-by: Vineet Gupta --- arch/arc/lib/memset-archs.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arc/lib/memset-archs.S b/arch/arc/lib/memset-archs.S index d2e09fece5bc..d0a5cec4cdca 100644 --- a/arch/arc/lib/memset-archs.S +++ b/arch/arc/lib/memset-archs.S @@ -36,12 +36,13 @@ #endif ENTRY_CFI(memset) - PREFETCHW_INSTR r0, 0 ; Prefetch the first write location mov.f 0, r2 ;;; if size is zero jz.d [blink] mov r3, r0 ; don't clobber ret val + PREFETCHW_INSTR r0, 0 ; Prefetch the first write location + ;;; if length < 8 brls.d.nt r2, 8, .Lsmallchunk mov.f lp_count,r2 From af75504c38960d5331b8c6c83ea9981e26d659e6 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Thu, 17 Aug 2023 14:16:35 -0600 Subject: [PATCH 09/49] cpupower: Add Georgian translation to Makefile LANGUAGES Commit 4680b734e729 ("cpupower: Add Georgian translation") added new language support. This change didn't add "ka" to Makefile LANGUAGES variable. Add it now. Reported-by: Temuri Doghonadze Reported-by: Zurab Kargareteli Signed-off-by: Shuah Khan --- tools/power/cpupower/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index dc531805a570..b53753dee02f 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -57,7 +57,7 @@ LIB_MIN= 1 PACKAGE = cpupower PACKAGE_BUGREPORT = linux-pm@vger.kernel.org -LANGUAGES = de fr it cs pt +LANGUAGES = de fr it cs pt ka # Directory definitions. These are default and most probably From 72d861f2d22792eddc91d4617e410ec74db8d814 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 10 Jun 2020 23:03:22 -0700 Subject: [PATCH 10/49] ARC: boot log: eliminate struct cpuinfo_arc #1: mm This is first step in eliminating struct cpuinfo_arc[NR_CPUS] Back when we had just ARCompact ISA, the idea was to read/bit-fiddle the BCRs once and and cache decoded information in a global struct ready to use. With ARCv2 it was modified to contained abstract / ISA agnostic information. However with ARCv3 there 's too much disparity to abstract in common structures. So drop the entire decode once and store paradigm. Afterall there's only 2 users of this machinery anyways: boot printing and cat /proc/cpuinfo. None is performance critical to warrant locking away resident memory per cpu. This patch is first step in that direction - decouples struct cpuinfo_arc_mmu from global struct cpuinfo_arc - mmu code still has a trimmed down static version of struct cpuinfo_arc_mmu to cache information needed in performance critical code such as tlb flush routines - folds read_decode_mmu_bcr() into arc_mmu_mumbojumbo() - setup_processor() directly calls arc_mmu_init() and not via arc_cpu_init() Tested-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202308151213.qKZPMiyz-lkp@intel.com/ Signed-off-by: Vineet Gupta --- arch/arc/include/asm/arcregs.h | 27 +++++++--- arch/arc/include/asm/setup.h | 1 - arch/arc/kernel/setup.c | 4 +- arch/arc/mm/tlb.c | 93 +++++++++++++--------------------- 4 files changed, 58 insertions(+), 67 deletions(-) diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index 2162023195c5..af00cbe9b850 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -185,6 +185,27 @@ struct bcr_uarch_build_arcv2 { #endif }; +struct bcr_mmu_3 { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int ver:8, ways:4, sets:4, res:3, sasid:1, pg_sz:4, + u_itlb:4, u_dtlb:4; +#else + unsigned int u_dtlb:4, u_itlb:4, pg_sz:4, sasid:1, res:3, sets:4, + ways:4, ver:8; +#endif +}; + +struct bcr_mmu_4 { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int ver:8, sasid:1, sz1:4, sz0:4, res:2, pae:1, + n_ways:2, n_entry:2, n_super:2, u_itlb:3, u_dtlb:3; +#else + /* DTLB ITLB JES JE JA */ + unsigned int u_dtlb:3, u_itlb:3, n_super:2, n_entry:2, n_ways:2, + pae:1, res:2, sz0:4, sz1:4, sasid:1, ver:8; +#endif +}; + struct bcr_mpy { #ifdef CONFIG_CPU_BIG_ENDIAN unsigned int pad:8, x1616:8, dsp:4, cycles:2, type:2, ver:8; @@ -307,11 +328,6 @@ struct bcr_generic { * Generic structures to hold build configuration used at runtime */ -struct cpuinfo_arc_mmu { - unsigned int ver:4, pg_sz_k:8, s_pg_sz_m:8, pad:10, sasid:1, pae:1; - unsigned int sets:12, ways:4, u_dtlb:8, u_itlb:8; -}; - struct cpuinfo_arc_cache { unsigned int sz_k:14, line_len:8, assoc:4, alias:1, vipt:1, pad:4; }; @@ -326,7 +342,6 @@ struct cpuinfo_arc_ccm { struct cpuinfo_arc { struct cpuinfo_arc_cache icache, dcache, slc; - struct cpuinfo_arc_mmu mmu; struct cpuinfo_arc_bpu bpu; struct bcr_identity core; struct bcr_isa_arcv2 isa; diff --git a/arch/arc/include/asm/setup.h b/arch/arc/include/asm/setup.h index 374138832c5a..76443f198778 100644 --- a/arch/arc/include/asm/setup.h +++ b/arch/arc/include/asm/setup.h @@ -36,7 +36,6 @@ long __init arc_get_mem_sz(void); extern void arc_mmu_init(void); extern char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len); -extern void read_decode_mmu_bcr(void); extern void arc_cache_init(void); extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len); diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 41f07b3e594e..094461540f8a 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -186,7 +186,6 @@ static void read_arc_build_cfg_regs(void) /* Read CCM BCRs for boot reporting even if not enabled in Kconfig */ read_decode_ccm_bcr(cpu); - read_decode_mmu_bcr(); read_decode_cache_bcr(); if (is_isa_arcompact()) { @@ -256,7 +255,7 @@ static void read_arc_build_cfg_regs(void) cpu->isa.be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN); /* there's no direct way to distinguish 750 vs. 770 */ - if (unlikely(cpu->core.family < 0x34 || cpu->mmu.ver < 3)) + if (unlikely(cpu->core.family < 0x34)) cpu->name = "ARC750"; } else { cpu->isa = isa; @@ -463,6 +462,7 @@ void setup_processor(void) arc_init_IRQ(); pr_info("%s", arc_cpu_mumbojumbo(cpu_id, str, sizeof(str))); + pr_info("%s", arc_mmu_mumbojumbo(cpu_id, str, sizeof(str))); arc_mmu_init(); arc_cache_init(); diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index 2a3105a682c3..861cabe81e87 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -18,7 +18,9 @@ /* A copy of the ASID from the PID reg is kept in asid_cache */ DEFINE_PER_CPU(unsigned int, asid_cache) = MM_CTXT_FIRST_CYCLE; -static int __read_mostly pae_exists; +static struct cpuinfo_arc_mmu { + unsigned int ver, pg_sz_k, s_pg_sz_m, pae, sets, ways; +} mmuinfo; /* * Utility Routine to erase a J-TLB entry @@ -131,7 +133,7 @@ static void tlb_entry_insert(unsigned int pd0, phys_addr_t pd1) noinline void local_flush_tlb_all(void) { - struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; + struct cpuinfo_arc_mmu *mmu = &mmuinfo; unsigned long flags; unsigned int entry; int num_tlb = mmu->sets * mmu->ways; @@ -560,89 +562,64 @@ void local_flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start, * the cpuinfo structure for later use. * No Validation is done here, simply read/convert the BCRs */ -void read_decode_mmu_bcr(void) +char *arc_mmu_mumbojumbo(int c, char *buf, int len) { - struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; - unsigned int tmp; - struct bcr_mmu_3 { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int ver:8, ways:4, sets:4, res:3, sasid:1, pg_sz:4, - u_itlb:4, u_dtlb:4; -#else - unsigned int u_dtlb:4, u_itlb:4, pg_sz:4, sasid:1, res:3, sets:4, - ways:4, ver:8; -#endif - } *mmu3; + struct cpuinfo_arc_mmu *mmu = &mmuinfo; + unsigned int bcr, u_dtlb, u_itlb, sasid; + struct bcr_mmu_3 *mmu3; + struct bcr_mmu_4 *mmu4; + char super_pg[64] = ""; + int n = 0; - struct bcr_mmu_4 { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int ver:8, sasid:1, sz1:4, sz0:4, res:2, pae:1, - n_ways:2, n_entry:2, n_super:2, u_itlb:3, u_dtlb:3; -#else - /* DTLB ITLB JES JE JA */ - unsigned int u_dtlb:3, u_itlb:3, n_super:2, n_entry:2, n_ways:2, - pae:1, res:2, sz0:4, sz1:4, sasid:1, ver:8; -#endif - } *mmu4; - - tmp = read_aux_reg(ARC_REG_MMU_BCR); - mmu->ver = (tmp >> 24); + bcr = read_aux_reg(ARC_REG_MMU_BCR); + mmu->ver = (bcr >> 24); if (is_isa_arcompact() && mmu->ver == 3) { - mmu3 = (struct bcr_mmu_3 *)&tmp; + mmu3 = (struct bcr_mmu_3 *)&bcr; mmu->pg_sz_k = 1 << (mmu3->pg_sz - 1); mmu->sets = 1 << mmu3->sets; mmu->ways = 1 << mmu3->ways; - mmu->u_dtlb = mmu3->u_dtlb; - mmu->u_itlb = mmu3->u_itlb; - mmu->sasid = mmu3->sasid; + u_dtlb = mmu3->u_dtlb; + u_itlb = mmu3->u_itlb; + sasid = mmu3->sasid; } else { - mmu4 = (struct bcr_mmu_4 *)&tmp; + mmu4 = (struct bcr_mmu_4 *)&bcr; mmu->pg_sz_k = 1 << (mmu4->sz0 - 1); mmu->s_pg_sz_m = 1 << (mmu4->sz1 - 11); mmu->sets = 64 << mmu4->n_entry; mmu->ways = mmu4->n_ways * 2; - mmu->u_dtlb = mmu4->u_dtlb * 4; - mmu->u_itlb = mmu4->u_itlb * 4; - mmu->sasid = mmu4->sasid; - pae_exists = mmu->pae = mmu4->pae; + u_dtlb = mmu4->u_dtlb * 4; + u_itlb = mmu4->u_itlb * 4; + sasid = mmu4->sasid; + mmu->pae = mmu4->pae; } -} -char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len) -{ - int n = 0; - struct cpuinfo_arc_mmu *p_mmu = &cpuinfo_arc700[cpu_id].mmu; - char super_pg[64] = ""; - - if (p_mmu->s_pg_sz_m) - scnprintf(super_pg, 64, "%dM Super Page %s", - p_mmu->s_pg_sz_m, - IS_USED_CFG(CONFIG_TRANSPARENT_HUGEPAGE)); + if (mmu->s_pg_sz_m) + scnprintf(super_pg, 64, "/%dM%s", + mmu->s_pg_sz_m, + IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) ? " (THP enabled)":""); n += scnprintf(buf + n, len - n, - "MMU [v%x]\t: %dk PAGE, %s, swalk %d lvl, JTLB %d (%dx%d), uDTLB %d, uITLB %d%s%s\n", - p_mmu->ver, p_mmu->pg_sz_k, super_pg, CONFIG_PGTABLE_LEVELS, - p_mmu->sets * p_mmu->ways, p_mmu->sets, p_mmu->ways, - p_mmu->u_dtlb, p_mmu->u_itlb, - IS_AVAIL2(p_mmu->pae, ", PAE40 ", CONFIG_ARC_HAS_PAE40)); + "MMU [v%x]\t: %dk%s, swalk %d lvl, JTLB %dx%d, uDTLB %d, uITLB %d%s%s%s\n", + mmu->ver, mmu->pg_sz_k, super_pg, CONFIG_PGTABLE_LEVELS, + mmu->sets, mmu->ways, + u_dtlb, u_itlb, + IS_AVAIL1(sasid, ", SASID"), + IS_AVAIL2(mmu->pae, ", PAE40 ", CONFIG_ARC_HAS_PAE40)); return buf; } int pae40_exist_but_not_enab(void) { - return pae_exists && !is_pae40_enabled(); + return mmuinfo.pae && !is_pae40_enabled(); } void arc_mmu_init(void) { - struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; - char str[256]; + struct cpuinfo_arc_mmu *mmu = &mmuinfo; int compat = 0; - pr_info("%s", arc_mmu_mumbojumbo(0, str, sizeof(str))); - /* * Can't be done in processor.h due to header include dependencies */ @@ -719,7 +696,7 @@ volatile int dup_pd_silent; /* Be silent abt it or complain (default) */ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, struct pt_regs *regs) { - struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; + struct cpuinfo_arc_mmu *mmu = &mmuinfo; unsigned long flags; int set, n_ways = mmu->ways; From 17a5ed563aaf0d66bf0438ee2df016f636846a84 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 10 Jun 2020 23:44:59 -0700 Subject: [PATCH 11/49] ARC: boot log: eliminate struct cpuinfo_arc #2: cache Signed-off-by: Vineet Gupta --- arch/arc/include/asm/arcregs.h | 37 ++++++- arch/arc/include/asm/setup.h | 1 - arch/arc/kernel/setup.c | 3 +- arch/arc/mm/cache.c | 171 ++++++++++++--------------------- 4 files changed, 97 insertions(+), 115 deletions(-) diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index af00cbe9b850..cb1ad1bb4ece 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -206,6 +206,38 @@ struct bcr_mmu_4 { #endif }; +struct bcr_cache { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:12, line_len:4, sz:4, config:4, ver:8; +#else + unsigned int ver:8, config:4, sz:4, line_len:4, pad:12; +#endif +}; + +struct bcr_slc_cfg { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:24, way:2, lsz:2, sz:4; +#else + unsigned int sz:4, lsz:2, way:2, pad:24; +#endif +}; + +struct bcr_clust_cfg { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int pad:7, c:1, num_entries:8, num_cores:8, ver:8; +#else + unsigned int ver:8, num_cores:8, num_entries:8, c:1, pad:7; +#endif +}; + +struct bcr_volatile { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned int start:4, limit:4, pad:22, order:1, disable:1; +#else + unsigned int disable:1, order:1, pad:22, limit:4, start:4; +#endif +}; + struct bcr_mpy { #ifdef CONFIG_CPU_BIG_ENDIAN unsigned int pad:8, x1616:8, dsp:4, cycles:2, type:2, ver:8; @@ -328,10 +360,6 @@ struct bcr_generic { * Generic structures to hold build configuration used at runtime */ -struct cpuinfo_arc_cache { - unsigned int sz_k:14, line_len:8, assoc:4, alias:1, vipt:1, pad:4; -}; - struct cpuinfo_arc_bpu { unsigned int ver, full, num_cache, num_pred, ret_stk; }; @@ -341,7 +369,6 @@ struct cpuinfo_arc_ccm { }; struct cpuinfo_arc { - struct cpuinfo_arc_cache icache, dcache, slc; struct cpuinfo_arc_bpu bpu; struct bcr_identity core; struct bcr_isa_arcv2 isa; diff --git a/arch/arc/include/asm/setup.h b/arch/arc/include/asm/setup.h index 76443f198778..4c0bacd0ff5c 100644 --- a/arch/arc/include/asm/setup.h +++ b/arch/arc/include/asm/setup.h @@ -39,7 +39,6 @@ extern char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len); extern void arc_cache_init(void); extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len); -extern void read_decode_cache_bcr(void); extern void __init handle_uboot_args(void); diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 094461540f8a..3ea834941c1f 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -186,8 +186,6 @@ static void read_arc_build_cfg_regs(void) /* Read CCM BCRs for boot reporting even if not enabled in Kconfig */ read_decode_ccm_bcr(cpu); - read_decode_cache_bcr(); - if (is_isa_arcompact()) { struct bcr_fp_arcompact sp, dp; struct bcr_bpu_arcompact bpu; @@ -463,6 +461,7 @@ void setup_processor(void) pr_info("%s", arc_cpu_mumbojumbo(cpu_id, str, sizeof(str))); pr_info("%s", arc_mmu_mumbojumbo(cpu_id, str, sizeof(str))); + pr_info("%s", arc_cache_mumbojumbo(cpu_id, str, sizeof(str))); arc_mmu_init(); arc_cache_init(); diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c index bdaa4aa40947..7197bb845a40 100644 --- a/arch/arc/mm/cache.c +++ b/arch/arc/mm/cache.c @@ -28,6 +28,10 @@ int slc_enable = 1, ioc_enable = 1; unsigned long perip_base = ARC_UNCACHED_ADDR_SPACE; /* legacy value for boot */ unsigned long perip_end = 0xFFFFFFFF; /* legacy value */ +static struct cpuinfo_arc_cache { + unsigned int sz_k, line_len, colors; +} ic_info, dc_info, slc_info; + void (*_cache_line_loop_ic_fn)(phys_addr_t paddr, unsigned long vaddr, unsigned long sz, const int op, const int full_page); @@ -35,78 +39,24 @@ void (*__dma_cache_wback_inv)(phys_addr_t start, unsigned long sz); void (*__dma_cache_inv)(phys_addr_t start, unsigned long sz); void (*__dma_cache_wback)(phys_addr_t start, unsigned long sz); -char *arc_cache_mumbojumbo(int c, char *buf, int len) +static char *read_decode_cache_bcr_arcv2(int c, char *buf, int len) { - int n = 0; - struct cpuinfo_arc_cache *p; - -#define PR_CACHE(p, cfg, str) \ - if (!(p)->line_len) \ - n += scnprintf(buf + n, len - n, str"\t\t: N/A\n"); \ - else \ - n += scnprintf(buf + n, len - n, \ - str"\t\t: %uK, %dway/set, %uB Line, %s%s%s\n", \ - (p)->sz_k, (p)->assoc, (p)->line_len, \ - (p)->vipt ? "VIPT" : "PIPT", \ - (p)->alias ? " aliasing" : "", \ - IS_USED_CFG(cfg)); - - PR_CACHE(&cpuinfo_arc700[c].icache, CONFIG_ARC_HAS_ICACHE, "I-Cache"); - PR_CACHE(&cpuinfo_arc700[c].dcache, CONFIG_ARC_HAS_DCACHE, "D-Cache"); - - p = &cpuinfo_arc700[c].slc; - if (p->line_len) - n += scnprintf(buf + n, len - n, - "SLC\t\t: %uK, %uB Line%s\n", - p->sz_k, p->line_len, IS_USED_RUN(slc_enable)); - - n += scnprintf(buf + n, len - n, "Peripherals\t: %#lx%s%s\n", - perip_base, - IS_AVAIL3(ioc_exists, ioc_enable, ", IO-Coherency (per-device) ")); - - return buf; -} - -/* - * Read the Cache Build Confuration Registers, Decode them and save into - * the cpuinfo structure for later use. - * No Validation done here, simply read/convert the BCRs - */ -static void read_decode_cache_bcr_arcv2(int cpu) -{ - struct cpuinfo_arc_cache *p_slc = &cpuinfo_arc700[cpu].slc; + struct cpuinfo_arc_cache *p_slc = &slc_info; + struct bcr_identity ident; struct bcr_generic sbcr; - - struct bcr_slc_cfg { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:24, way:2, lsz:2, sz:4; -#else - unsigned int sz:4, lsz:2, way:2, pad:24; -#endif - } slc_cfg; - - struct bcr_clust_cfg { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:7, c:1, num_entries:8, num_cores:8, ver:8; -#else - unsigned int ver:8, num_cores:8, num_entries:8, c:1, pad:7; -#endif - } cbcr; - - struct bcr_volatile { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int start:4, limit:4, pad:22, order:1, disable:1; -#else - unsigned int disable:1, order:1, pad:22, limit:4, start:4; -#endif - } vol; - + struct bcr_clust_cfg cbcr; + struct bcr_volatile vol; + int n = 0; READ_BCR(ARC_REG_SLC_BCR, sbcr); if (sbcr.ver) { + struct bcr_slc_cfg slc_cfg; READ_BCR(ARC_REG_SLC_CFG, slc_cfg); p_slc->sz_k = 128 << slc_cfg.sz; l2_line_sz = p_slc->line_len = (slc_cfg.lsz == 0) ? 128 : 64; + n += scnprintf(buf + n, len - n, + "SLC\t\t: %uK, %uB Line%s\n", + p_slc->sz_k, p_slc->line_len, IS_USED_RUN(slc_enable)); } READ_BCR(ARC_REG_CLUSTER_BCR, cbcr); @@ -129,70 +79,83 @@ static void read_decode_cache_bcr_arcv2(int cpu) ioc_enable = 0; } + READ_BCR(AUX_IDENTITY, ident); + /* HS 2.0 didn't have AUX_VOL */ - if (cpuinfo_arc700[cpu].core.family > 0x51) { + if (ident.family > 0x51) { READ_BCR(AUX_VOL, vol); perip_base = vol.start << 28; /* HS 3.0 has limit and strict-ordering fields */ - if (cpuinfo_arc700[cpu].core.family > 0x52) + if (ident.family > 0x52) perip_end = (vol.limit << 28) - 1; } + + n += scnprintf(buf + n, len - n, "Peripherals\t: %#lx%s%s\n", + perip_base, + IS_AVAIL3(ioc_exists, ioc_enable, ", IO-Coherency (per-device) ")); + + return buf; } -void read_decode_cache_bcr(void) +char *arc_cache_mumbojumbo(int c, char *buf, int len) { - struct cpuinfo_arc_cache *p_ic, *p_dc; - unsigned int cpu = smp_processor_id(); - struct bcr_cache { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned int pad:12, line_len:4, sz:4, config:4, ver:8; -#else - unsigned int ver:8, config:4, sz:4, line_len:4, pad:12; -#endif - } ibcr, dbcr; + struct cpuinfo_arc_cache *p_ic = &ic_info, *p_dc = &dc_info; + struct bcr_cache ibcr, dbcr; + int vipt, assoc; + int n = 0; - p_ic = &cpuinfo_arc700[cpu].icache; READ_BCR(ARC_REG_IC_BCR, ibcr); - if (!ibcr.ver) goto dc_chk; - if (ibcr.ver <= 3) { + if (is_isa_arcompact() && (ibcr.ver <= 3)) { BUG_ON(ibcr.config != 3); - p_ic->assoc = 2; /* Fixed to 2w set assoc */ - } else if (ibcr.ver >= 4) { - p_ic->assoc = 1 << ibcr.config; /* 1,2,4,8 */ + assoc = 2; /* Fixed to 2w set assoc */ + } else if (is_isa_arcv2() && (ibcr.ver >= 4)) { + assoc = 1 << ibcr.config; /* 1,2,4,8 */ } p_ic->line_len = 8 << ibcr.line_len; p_ic->sz_k = 1 << (ibcr.sz - 1); - p_ic->vipt = 1; - p_ic->alias = p_ic->sz_k/p_ic->assoc/TO_KB(PAGE_SIZE) > 1; + p_ic->colors = p_ic->sz_k/assoc/TO_KB(PAGE_SIZE); + + n += scnprintf(buf + n, len - n, + "I-Cache\t\t: %uK, %dway/set, %uB Line, VIPT%s%s\n", + p_ic->sz_k, assoc, p_ic->line_len, + p_ic->colors > 1 ? " aliasing" : "", + IS_USED_CFG(CONFIG_ARC_HAS_ICACHE)); dc_chk: - p_dc = &cpuinfo_arc700[cpu].dcache; READ_BCR(ARC_REG_DC_BCR, dbcr); - if (!dbcr.ver) goto slc_chk; - if (dbcr.ver <= 3) { + if (is_isa_arcompact() && (dbcr.ver <= 3)) { BUG_ON(dbcr.config != 2); - p_dc->assoc = 4; /* Fixed to 4w set assoc */ - p_dc->vipt = 1; - p_dc->alias = p_dc->sz_k/p_dc->assoc/TO_KB(PAGE_SIZE) > 1; - } else if (dbcr.ver >= 4) { - p_dc->assoc = 1 << dbcr.config; /* 1,2,4,8 */ - p_dc->vipt = 0; - p_dc->alias = 0; /* PIPT so can't VIPT alias */ + vipt = 1; + assoc = 4; /* Fixed to 4w set assoc */ + p_dc->colors = p_dc->sz_k/assoc/TO_KB(PAGE_SIZE); + } else if (is_isa_arcv2() && (dbcr.ver >= 4)) { + vipt = 0; + assoc = 1 << dbcr.config; /* 1,2,4,8 */ + p_dc->colors = 1; /* PIPT so can't VIPT alias */ } p_dc->line_len = 16 << dbcr.line_len; p_dc->sz_k = 1 << (dbcr.sz - 1); + n += scnprintf(buf + n, len - n, + "D-Cache\t\t: %uK, %dway/set, %uB Line, %s%s%s\n", + p_dc->sz_k, assoc, p_dc->line_len, + vipt ? "VIPT" : "PIPT", + p_dc->colors > 1 ? " aliasing" : "", + IS_USED_CFG(CONFIG_ARC_HAS_DCACHE)); + slc_chk: if (is_isa_arcv2()) - read_decode_cache_bcr_arcv2(cpu); + read_decode_cache_bcr_arcv2(c, buf + n, len - n); + + return buf; } /* @@ -1133,10 +1096,8 @@ static noinline void __init arc_ioc_setup(void) */ static noinline void __init arc_cache_init_master(void) { - unsigned int __maybe_unused cpu = smp_processor_id(); - if (IS_ENABLED(CONFIG_ARC_HAS_ICACHE)) { - struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache; + struct cpuinfo_arc_cache *ic = &ic_info; if (!ic->line_len) panic("cache support enabled but non-existent cache\n"); @@ -1149,14 +1110,14 @@ static noinline void __init arc_cache_init_master(void) * In MMU v4 (HS38x) the aliasing icache config uses IVIL/PTAG * pair to provide vaddr/paddr respectively, just as in MMU v3 */ - if (is_isa_arcv2() && ic->alias) + if (is_isa_arcv2() && ic->colors > 1) _cache_line_loop_ic_fn = __cache_line_loop_v3; else _cache_line_loop_ic_fn = __cache_line_loop; } if (IS_ENABLED(CONFIG_ARC_HAS_DCACHE)) { - struct cpuinfo_arc_cache *dc = &cpuinfo_arc700[cpu].dcache; + struct cpuinfo_arc_cache *dc = &dc_info; if (!dc->line_len) panic("cache support enabled but non-existent cache\n"); @@ -1168,14 +1129,13 @@ static noinline void __init arc_cache_init_master(void) /* check for D-Cache aliasing on ARCompact: ARCv2 has PIPT */ if (is_isa_arcompact()) { int handled = IS_ENABLED(CONFIG_ARC_CACHE_VIPT_ALIASING); - int num_colors = dc->sz_k/dc->assoc/TO_KB(PAGE_SIZE); - if (dc->alias) { + if (dc->colors > 1) { if (!handled) panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n"); - if (CACHE_COLORS_NUM != num_colors) + if (CACHE_COLORS_NUM != dc->colors) panic("CACHE_COLORS_NUM not optimized for config\n"); - } else if (!dc->alias && handled) { + } else if (handled && dc->colors == 1) { panic("Disable CONFIG_ARC_CACHE_VIPT_ALIASING\n"); } } @@ -1218,9 +1178,6 @@ static noinline void __init arc_cache_init_master(void) void __ref arc_cache_init(void) { unsigned int __maybe_unused cpu = smp_processor_id(); - char str[256]; - - pr_info("%s", arc_cache_mumbojumbo(0, str, sizeof(str))); if (!cpu) arc_cache_init_master(); From c5b678b379e7772d553f1b4ec052420d25bf9c7a Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 12 Jun 2020 15:30:47 -0700 Subject: [PATCH 12/49] ARC: boot log: eliminate struct cpuinfo_arc #3: don't export Signed-off-by: Vineet Gupta --- arch/arc/include/asm/arcregs.h | 2 -- arch/arc/kernel/mcip.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index cb1ad1bb4ece..160ee3fab1bd 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -384,8 +384,6 @@ struct cpuinfo_arc { struct bcr_mpy extn_mpy; }; -extern struct cpuinfo_arc cpuinfo_arc700[]; - static inline int is_isa_arcv2(void) { return IS_ENABLED(CONFIG_ISA_ARCV2); diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c index f9fdb557c263..55373ca0d28b 100644 --- a/arch/arc/kernel/mcip.c +++ b/arch/arc/kernel/mcip.c @@ -165,8 +165,6 @@ static void mcip_probe_n_setup(void) IS_AVAIL1(mp.idu, "IDU "), IS_AVAIL1(mp.dbg, "DEBUG "), IS_AVAIL1(mp.gfrc, "GFRC")); - - cpuinfo_arc700[0].extn.gfrc = mp.gfrc; } struct plat_smp_ops plat_smp_ops = { From fad84e39f116035ae8d550c6020107b8ac113b45 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Thu, 11 Jun 2020 11:08:45 -0700 Subject: [PATCH 13/49] ARC: boot log: eliminate struct cpuinfo_arc #4: boot log per ISA - boot log now clearly per ISA - global struct cpuinfo_arc[] elimiated - local struct struct arcinfo kept for passing info between functions Tested-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202308162101.Ve5jBg80-lkp@intel.com Signed-off-by: Vineet Gupta --- arch/arc/include/asm/arcregs.h | 33 +- arch/arc/include/asm/setup.h | 4 +- arch/arc/kernel/setup.c | 600 +++++++++++++++------------------ arch/arc/mm/cache.c | 10 +- arch/arc/mm/tlb.c | 4 +- 5 files changed, 288 insertions(+), 363 deletions(-) diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h index 160ee3fab1bd..4b13f60fe7ca 100644 --- a/arch/arc/include/asm/arcregs.h +++ b/arch/arc/include/asm/arcregs.h @@ -23,7 +23,7 @@ #define ARC_REG_ICCM_BUILD 0x78 /* ICCM size (common) */ #define ARC_REG_XY_MEM_BCR 0x79 #define ARC_REG_MAC_BCR 0x7a -#define ARC_REG_MUL_BCR 0x7b +#define ARC_REG_MPY_BCR 0x7b #define ARC_REG_SWAP_BCR 0x7c #define ARC_REG_NORM_BCR 0x7d #define ARC_REG_MIXMAX_BCR 0x7e @@ -177,7 +177,7 @@ struct bcr_isa_arcv2 { #endif }; -struct bcr_uarch_build_arcv2 { +struct bcr_uarch_build { #ifdef CONFIG_CPU_BIG_ENDIAN unsigned int pad:8, prod:8, maj:8, min:8; #else @@ -355,35 +355,6 @@ struct bcr_generic { #endif }; -/* - ******************************************************************* - * Generic structures to hold build configuration used at runtime - */ - -struct cpuinfo_arc_bpu { - unsigned int ver, full, num_cache, num_pred, ret_stk; -}; - -struct cpuinfo_arc_ccm { - unsigned int base_addr, sz; -}; - -struct cpuinfo_arc { - struct cpuinfo_arc_bpu bpu; - struct bcr_identity core; - struct bcr_isa_arcv2 isa; - const char *release, *name; - unsigned int vec_base; - struct cpuinfo_arc_ccm iccm, dccm; - struct { - unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, swape:1, pad1:2, - fpu_sp:1, fpu_dp:1, dual:1, dual_enb:1, pad2:4, - ap_num:4, ap_full:1, smart:1, rtt:1, pad3:1, - timer0:1, timer1:1, rtc:1, gfrc:1, pad4:4; - } extn; - struct bcr_mpy extn_mpy; -}; - static inline int is_isa_arcv2(void) { return IS_ENABLED(CONFIG_ISA_ARCV2); diff --git a/arch/arc/include/asm/setup.h b/arch/arc/include/asm/setup.h index 4c0bacd0ff5c..1c6db599e1fc 100644 --- a/arch/arc/include/asm/setup.h +++ b/arch/arc/include/asm/setup.h @@ -35,10 +35,10 @@ long __init arc_get_mem_sz(void); #define IS_AVAIL3(v, v2, s) IS_AVAIL1(v, s), IS_AVAIL1(v, IS_DISABLED_RUN(v2)) extern void arc_mmu_init(void); -extern char *arc_mmu_mumbojumbo(int cpu_id, char *buf, int len); +extern int arc_mmu_mumbojumbo(int cpu_id, char *buf, int len); extern void arc_cache_init(void); -extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len); +extern int arc_cache_mumbojumbo(int cpu_id, char *buf, int len); extern void __init handle_uboot_args(void); diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 3ea834941c1f..0aa49308d792 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -29,6 +29,7 @@ #include #include #include +#include #define FIX_PTR(x) __asm__ __volatile__(";" : "+r"(x)) @@ -43,19 +44,22 @@ const struct machine_desc *machine_desc; struct task_struct *_current_task[NR_CPUS]; /* For stack switching */ -struct cpuinfo_arc cpuinfo_arc700[NR_CPUS]; +struct cpuinfo_arc { + int arcver; + unsigned int t0:1, t1:1; + struct { + unsigned long base; + unsigned int sz; + } iccm, dccm; +}; -static const struct id_to_str arc_legacy_rel[] = { +#ifdef CONFIG_ISA_ARCV2 + +static const struct id_to_str arc_hs_rel[] = { /* ID.ARCVER, Release */ -#ifdef CONFIG_ISA_ARCOMPACT - { 0x34, "R4.10"}, - { 0x35, "R4.11"}, -#else { 0x51, "R2.0" }, { 0x52, "R2.1" }, { 0x53, "R3.0" }, -#endif - { 0x00, NULL } }; static const struct id_to_str arc_hs_ver54_rel[] = { @@ -66,321 +70,295 @@ static const struct id_to_str arc_hs_ver54_rel[] = { { 3, "R4.00a"}, { 0xFF, NULL } }; +#endif -static void read_decode_ccm_bcr(struct cpuinfo_arc *cpu) +static int +arcompact_mumbojumbo(int c, struct cpuinfo_arc *info, char *buf, int len) { - if (is_isa_arcompact()) { - struct bcr_iccm_arcompact iccm; - struct bcr_dccm_arcompact dccm; + int n = 0; +#ifdef CONFIG_ISA_ARCOMPACT + char *cpu_nm, *isa_nm = "ARCompact"; + struct bcr_fp_arcompact fpu_sp, fpu_dp; + int atomic = 0, be, present; + int bpu_full, bpu_cache, bpu_pred; + struct bcr_bpu_arcompact bpu; + struct bcr_iccm_arcompact iccm; + struct bcr_dccm_arcompact dccm; + struct bcr_generic isa; - READ_BCR(ARC_REG_ICCM_BUILD, iccm); - if (iccm.ver) { - cpu->iccm.sz = 4096 << iccm.sz; /* 8K to 512K */ - cpu->iccm.base_addr = iccm.base << 16; - } + READ_BCR(ARC_REG_ISA_CFG_BCR, isa); - READ_BCR(ARC_REG_DCCM_BUILD, dccm); - if (dccm.ver) { - unsigned long base; - cpu->dccm.sz = 2048 << dccm.sz; /* 2K to 256K */ - - base = read_aux_reg(ARC_REG_DCCM_BASE_BUILD); - cpu->dccm.base_addr = base & ~0xF; - } - } else { - struct bcr_iccm_arcv2 iccm; - struct bcr_dccm_arcv2 dccm; - unsigned long region; - - READ_BCR(ARC_REG_ICCM_BUILD, iccm); - if (iccm.ver) { - cpu->iccm.sz = 256 << iccm.sz00; /* 512B to 16M */ - if (iccm.sz00 == 0xF && iccm.sz01 > 0) - cpu->iccm.sz <<= iccm.sz01; - - region = read_aux_reg(ARC_REG_AUX_ICCM); - cpu->iccm.base_addr = region & 0xF0000000; - } - - READ_BCR(ARC_REG_DCCM_BUILD, dccm); - if (dccm.ver) { - cpu->dccm.sz = 256 << dccm.sz0; - if (dccm.sz0 == 0xF && dccm.sz1 > 0) - cpu->dccm.sz <<= dccm.sz1; - - region = read_aux_reg(ARC_REG_AUX_DCCM); - cpu->dccm.base_addr = region & 0xF0000000; - } + if (!isa.ver) /* ISA BCR absent, use Kconfig info */ + atomic = IS_ENABLED(CONFIG_ARC_HAS_LLSC); + else { + /* ARC700_BUILD only has 2 bits of isa info */ + atomic = isa.info & 1; } + + be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN); + + if (info->arcver < 0x34) + cpu_nm = "ARC750"; + else + cpu_nm = "ARC770"; + + n += scnprintf(buf + n, len - n, "processor [%d]\t: %s (%s ISA) %s\n", + c, cpu_nm, isa_nm, IS_AVAIL1(be, "[Big-Endian]")); + + READ_BCR(ARC_REG_FP_BCR, fpu_sp); + READ_BCR(ARC_REG_DPFP_BCR, fpu_dp); + + if (fpu_sp.ver | fpu_dp.ver) + n += scnprintf(buf + n, len - n, "FPU\t\t: %s%s\n", + IS_AVAIL1(fpu_sp.ver, "SP "), + IS_AVAIL1(fpu_dp.ver, "DP ")); + + READ_BCR(ARC_REG_BPU_BCR, bpu); + bpu_full = bpu.fam ? 1 : 0; + bpu_cache = 256 << (bpu.ent - 1); + bpu_pred = 256 << (bpu.ent - 1); + + n += scnprintf(buf + n, len - n, + "BPU\t\t: %s%s match, cache:%d, Predict Table:%d\n", + IS_AVAIL1(bpu_full, "full"), + IS_AVAIL1(!bpu_full, "partial"), + bpu_cache, bpu_pred); + + READ_BCR(ARC_REG_ICCM_BUILD, iccm); + if (iccm.ver) { + info->iccm.sz = 4096 << iccm.sz; /* 8K to 512K */ + info->iccm.base = iccm.base << 16; + } + + READ_BCR(ARC_REG_DCCM_BUILD, dccm); + if (dccm.ver) { + unsigned long base; + info->dccm.sz = 2048 << dccm.sz; /* 2K to 256K */ + + base = read_aux_reg(ARC_REG_DCCM_BASE_BUILD); + info->dccm.base = base & ~0xF; + } + + /* ARCompact ISA specific sanity checks */ + present = fpu_dp.ver; /* SP has no arch visible regs */ + CHK_OPT_STRICT(CONFIG_ARC_FPU_SAVE_RESTORE, present); +#endif + return n; + } -static void decode_arc_core(struct cpuinfo_arc *cpu) +static int arcv2_mumbojumbo(int c, struct cpuinfo_arc *info, char *buf, int len) { - struct bcr_uarch_build_arcv2 uarch; - const struct id_to_str *tbl; - - if (cpu->core.family < 0x54) { /* includes arc700 */ - - for (tbl = &arc_legacy_rel[0]; tbl->id != 0; tbl++) { - if (cpu->core.family == tbl->id) { - cpu->release = tbl->str; - break; - } - } - - if (is_isa_arcompact()) - cpu->name = "ARC700"; - else if (tbl->str) - cpu->name = "HS38"; - else - cpu->name = cpu->release = "Unknown"; - - return; - } + int n = 0; +#ifdef CONFIG_ISA_ARCV2 + const char *release, *cpu_nm, *isa_nm = "ARCv2"; + int dual_issue = 0, dual_enb = 0, mpy_opt, present; + int bpu_full, bpu_cache, bpu_pred, bpu_ret_stk; + char mpy_nm[16], lpb_nm[32]; + struct bcr_isa_arcv2 isa; + struct bcr_mpy mpy; + struct bcr_fp_arcv2 fpu; + struct bcr_bpu_arcv2 bpu; + struct bcr_lpb lpb; + struct bcr_iccm_arcv2 iccm; + struct bcr_dccm_arcv2 dccm; + struct bcr_erp erp; /* * Initial HS cores bumped AUX IDENTITY.ARCVER for each release until * ARCVER 0x54 which introduced AUX MICRO_ARCH_BUILD and subsequent * releases only update it. */ - READ_BCR(ARC_REG_MICRO_ARCH_BCR, uarch); - if (uarch.prod == 4) { - cpu->name = "HS48"; - cpu->extn.dual = 1; + cpu_nm = "HS38"; + if (info->arcver > 0x50 && info->arcver <= 0x53) { + release = arc_hs_rel[info->arcver - 0x51].str; } else { - cpu->name = "HS38"; - } + const struct id_to_str *tbl; + struct bcr_uarch_build uarch; - for (tbl = &arc_hs_ver54_rel[0]; tbl->id != 0xFF; tbl++) { - if (uarch.maj == tbl->id) { - cpu->release = tbl->str; - break; + READ_BCR(ARC_REG_MICRO_ARCH_BCR, uarch); + + for (tbl = &arc_hs_ver54_rel[0]; tbl->id != 0xFF; tbl++) { + if (uarch.maj == tbl->id) { + release = tbl->str; + break; + } } - } -} - -static void read_arc_build_cfg_regs(void) -{ - struct bcr_timer timer; - struct bcr_generic bcr; - struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; - struct bcr_isa_arcv2 isa; - struct bcr_actionpoint ap; - - FIX_PTR(cpu); - - READ_BCR(AUX_IDENTITY, cpu->core); - decode_arc_core(cpu); - - READ_BCR(ARC_REG_TIMERS_BCR, timer); - cpu->extn.timer0 = timer.t0; - cpu->extn.timer1 = timer.t1; - cpu->extn.rtc = timer.rtc; - - cpu->vec_base = read_aux_reg(AUX_INTR_VEC_BASE); - - READ_BCR(ARC_REG_MUL_BCR, cpu->extn_mpy); - - /* Read CCM BCRs for boot reporting even if not enabled in Kconfig */ - read_decode_ccm_bcr(cpu); - - if (is_isa_arcompact()) { - struct bcr_fp_arcompact sp, dp; - struct bcr_bpu_arcompact bpu; - - READ_BCR(ARC_REG_FP_BCR, sp); - READ_BCR(ARC_REG_DPFP_BCR, dp); - cpu->extn.fpu_sp = sp.ver ? 1 : 0; - cpu->extn.fpu_dp = dp.ver ? 1 : 0; - - READ_BCR(ARC_REG_BPU_BCR, bpu); - cpu->bpu.ver = bpu.ver; - cpu->bpu.full = bpu.fam ? 1 : 0; - if (bpu.ent) { - cpu->bpu.num_cache = 256 << (bpu.ent - 1); - cpu->bpu.num_pred = 256 << (bpu.ent - 1); - } - } else { - struct bcr_fp_arcv2 spdp; - struct bcr_bpu_arcv2 bpu; - - READ_BCR(ARC_REG_FP_V2_BCR, spdp); - cpu->extn.fpu_sp = spdp.sp ? 1 : 0; - cpu->extn.fpu_dp = spdp.dp ? 1 : 0; - - READ_BCR(ARC_REG_BPU_BCR, bpu); - cpu->bpu.ver = bpu.ver; - cpu->bpu.full = bpu.ft; - cpu->bpu.num_cache = 256 << bpu.bce; - cpu->bpu.num_pred = 2048 << bpu.pte; - cpu->bpu.ret_stk = 4 << bpu.rse; - - /* if dual issue hardware, is it enabled ? */ - if (cpu->extn.dual) { + if (uarch.prod == 4) { unsigned int exec_ctrl; + cpu_nm = "HS48"; + dual_issue = 1; + /* if dual issue hardware, is it enabled ? */ READ_BCR(AUX_EXEC_CTRL, exec_ctrl); - cpu->extn.dual_enb = !(exec_ctrl & 1); + dual_enb = !(exec_ctrl & 1); } } - READ_BCR(ARC_REG_AP_BCR, ap); - if (ap.ver) { - cpu->extn.ap_num = 2 << ap.num; - cpu->extn.ap_full = !ap.min; - } - - READ_BCR(ARC_REG_SMART_BCR, bcr); - cpu->extn.smart = bcr.ver ? 1 : 0; - - READ_BCR(ARC_REG_RTT_BCR, bcr); - cpu->extn.rtt = bcr.ver ? 1 : 0; - READ_BCR(ARC_REG_ISA_CFG_BCR, isa); - /* some hacks for lack of feature BCR info in old ARC700 cores */ - if (is_isa_arcompact()) { - if (!isa.ver) /* ISA BCR absent, use Kconfig info */ - cpu->isa.atomic = IS_ENABLED(CONFIG_ARC_HAS_LLSC); - else { - /* ARC700_BUILD only has 2 bits of isa info */ - struct bcr_generic bcr = *(struct bcr_generic *)&isa; - cpu->isa.atomic = bcr.info & 1; - } + n += scnprintf(buf + n, len - n, "processor [%d]\t: %s %s (%s ISA) %s%s%s\n", + c, cpu_nm, release, isa_nm, + IS_AVAIL1(isa.be, "[Big-Endian]"), + IS_AVAIL3(dual_issue, dual_enb, " Dual-Issue ")); - cpu->isa.be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN); + READ_BCR(ARC_REG_MPY_BCR, mpy); + mpy_opt = 2; /* stock MPY/MPYH */ + if (mpy.dsp) /* OPT 7-9 */ + mpy_opt = mpy.dsp + 6; - /* there's no direct way to distinguish 750 vs. 770 */ - if (unlikely(cpu->core.family < 0x34)) - cpu->name = "ARC750"; - } else { - cpu->isa = isa; + scnprintf(mpy_nm, 16, "mpy[opt %d] ", mpy_opt); + + READ_BCR(ARC_REG_FP_V2_BCR, fpu); + + n += scnprintf(buf + n, len - n, "ISA Extn\t: %s%s%s%s%s%s%s%s%s%s%s\n", + IS_AVAIL2(isa.atomic, "atomic ", CONFIG_ARC_HAS_LLSC), + IS_AVAIL2(isa.ldd, "ll64 ", CONFIG_ARC_HAS_LL64), + IS_AVAIL2(isa.unalign, "unalign ", CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS), + IS_AVAIL1(mpy.ver, mpy_nm), + IS_AVAIL1(isa.div_rem, "div_rem "), + IS_AVAIL1((fpu.sp | fpu.dp), " FPU:"), + IS_AVAIL1(fpu.sp, " sp"), + IS_AVAIL1(fpu.dp, " dp")); + + READ_BCR(ARC_REG_BPU_BCR, bpu); + bpu_full = bpu.ft; + bpu_cache = 256 << bpu.bce; + bpu_pred = 2048 << bpu.pte; + bpu_ret_stk = 4 << bpu.rse; + + READ_BCR(ARC_REG_LPB_BUILD, lpb); + if (lpb.ver) { + unsigned int ctl; + ctl = read_aux_reg(ARC_REG_LPB_CTRL); + + scnprintf(lpb_nm, sizeof(lpb_nm), " Loop Buffer:%d %s", + lpb.entries, IS_DISABLED_RUN(!ctl)); } -} - -static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len) -{ - struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id]; - struct bcr_identity *core = &cpu->core; - char mpy_opt[16]; - int n = 0; - - FIX_PTR(cpu); n += scnprintf(buf + n, len - n, - "\nIDENTITY\t: ARCVER [%#02x] ARCNUM [%#02x] CHIPID [%#4x]\n", - core->family, core->cpu_id, core->chip_id); + "BPU\t\t: %s%s match, cache:%d, Predict Table:%d Return stk: %d%s\n", + IS_AVAIL1(bpu_full, "full"), + IS_AVAIL1(!bpu_full, "partial"), + bpu_cache, bpu_pred, bpu_ret_stk, + lpb_nm); - n += scnprintf(buf + n, len - n, "processor [%d]\t: %s %s (%s ISA) %s%s%s\n", - cpu_id, cpu->name, cpu->release, - is_isa_arcompact() ? "ARCompact" : "ARCv2", - IS_AVAIL1(cpu->isa.be, "[Big-Endian]"), - IS_AVAIL3(cpu->extn.dual, cpu->extn.dual_enb, " Dual-Issue ")); - - n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s%s%s\nISA Extn\t: ", - IS_AVAIL1(cpu->extn.timer0, "Timer0 "), - IS_AVAIL1(cpu->extn.timer1, "Timer1 "), - IS_AVAIL2(cpu->extn.rtc, "RTC [UP 64-bit] ", CONFIG_ARC_TIMERS_64BIT), - IS_AVAIL2(cpu->extn.gfrc, "GFRC [SMP 64-bit] ", CONFIG_ARC_TIMERS_64BIT)); - - if (cpu->extn_mpy.ver) { - if (is_isa_arcompact()) { - scnprintf(mpy_opt, 16, "mpy"); - } else { - - int opt = 2; /* stock MPY/MPYH */ - - if (cpu->extn_mpy.dsp) /* OPT 7-9 */ - opt = cpu->extn_mpy.dsp + 6; - - scnprintf(mpy_opt, 16, "mpy[opt %d] ", opt); - } + READ_BCR(ARC_REG_ICCM_BUILD, iccm); + if (iccm.ver) { + unsigned long base; + info->iccm.sz = 256 << iccm.sz00; /* 512B to 16M */ + if (iccm.sz00 == 0xF && iccm.sz01 > 0) + info->iccm.sz <<= iccm.sz01; + base = read_aux_reg(ARC_REG_AUX_ICCM); + info->iccm.base = base & 0xF0000000; } - n += scnprintf(buf + n, len - n, "%s%s%s%s%s%s%s%s\n", - IS_AVAIL2(cpu->isa.atomic, "atomic ", CONFIG_ARC_HAS_LLSC), - IS_AVAIL2(cpu->isa.ldd, "ll64 ", CONFIG_ARC_HAS_LL64), - IS_AVAIL2(cpu->isa.unalign, "unalign ", CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS), - IS_AVAIL1(cpu->extn_mpy.ver, mpy_opt), - IS_AVAIL1(cpu->isa.div_rem, "div_rem ")); - - if (cpu->bpu.ver) { - n += scnprintf(buf + n, len - n, - "BPU\t\t: %s%s match, cache:%d, Predict Table:%d Return stk: %d", - IS_AVAIL1(cpu->bpu.full, "full"), - IS_AVAIL1(!cpu->bpu.full, "partial"), - cpu->bpu.num_cache, cpu->bpu.num_pred, cpu->bpu.ret_stk); - - if (is_isa_arcv2()) { - struct bcr_lpb lpb; - - READ_BCR(ARC_REG_LPB_BUILD, lpb); - if (lpb.ver) { - unsigned int ctl; - ctl = read_aux_reg(ARC_REG_LPB_CTRL); - - n += scnprintf(buf + n, len - n, " Loop Buffer:%d %s", - lpb.entries, - IS_DISABLED_RUN(!ctl)); - } - } - n += scnprintf(buf + n, len - n, "\n"); + READ_BCR(ARC_REG_DCCM_BUILD, dccm); + if (dccm.ver) { + unsigned long base; + info->dccm.sz = 256 << dccm.sz0; + if (dccm.sz0 == 0xF && dccm.sz1 > 0) + info->dccm.sz <<= dccm.sz1; + base = read_aux_reg(ARC_REG_AUX_DCCM); + info->dccm.base = base & 0xF0000000; } - return buf; -} - -static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len) -{ - int n = 0; - struct cpuinfo_arc *cpu = &cpuinfo_arc700[cpu_id]; - - FIX_PTR(cpu); - - n += scnprintf(buf + n, len - n, "Vector Table\t: %#x\n", cpu->vec_base); - - if (cpu->extn.fpu_sp || cpu->extn.fpu_dp) - n += scnprintf(buf + n, len - n, "FPU\t\t: %s%s\n", - IS_AVAIL1(cpu->extn.fpu_sp, "SP "), - IS_AVAIL1(cpu->extn.fpu_dp, "DP ")); - - if (cpu->extn.ap_num | cpu->extn.smart | cpu->extn.rtt) { - n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s", - IS_AVAIL1(cpu->extn.smart, "smaRT "), - IS_AVAIL1(cpu->extn.rtt, "RTT ")); - if (cpu->extn.ap_num) { - n += scnprintf(buf + n, len - n, "ActionPoint %d/%s", - cpu->extn.ap_num, - cpu->extn.ap_full ? "full":"min"); - } - n += scnprintf(buf + n, len - n, "\n"); - } - - if (cpu->dccm.sz || cpu->iccm.sz) - n += scnprintf(buf + n, len - n, "Extn [CCM]\t: DCCM @ %x, %d KB / ICCM: @ %x, %d KB\n", - cpu->dccm.base_addr, TO_KB(cpu->dccm.sz), - cpu->iccm.base_addr, TO_KB(cpu->iccm.sz)); - - if (is_isa_arcv2()) { - - /* Error Protection: ECC/Parity */ - struct bcr_erp erp; - READ_BCR(ARC_REG_ERP_BUILD, erp); - - if (erp.ver) { - struct ctl_erp ctl; - READ_BCR(ARC_REG_ERP_CTRL, ctl); - - /* inverted bits: 0 means enabled */ - n += scnprintf(buf + n, len - n, "Extn [ECC]\t: %s%s%s%s%s%s\n", + /* Error Protection: ECC/Parity */ + READ_BCR(ARC_REG_ERP_BUILD, erp); + if (erp.ver) { + struct ctl_erp ctl; + READ_BCR(ARC_REG_ERP_CTRL, ctl); + /* inverted bits: 0 means enabled */ + n += scnprintf(buf + n, len - n, "Extn [ECC]\t: %s%s%s%s%s%s\n", IS_AVAIL3(erp.ic, !ctl.dpi, "IC "), IS_AVAIL3(erp.dc, !ctl.dpd, "DC "), IS_AVAIL3(erp.mmu, !ctl.mpd, "MMU ")); - } } + /* ARCv2 ISA specific sanity checks */ + present = fpu.sp | fpu.dp | mpy.dsp; /* DSP and/or FPU */ + CHK_OPT_STRICT(CONFIG_ARC_HAS_ACCL_REGS, present); + + dsp_config_check(); +#endif + return n; +} + +static char *arc_cpu_mumbojumbo(int c, struct cpuinfo_arc *info, char *buf, int len) +{ + struct bcr_identity ident; + struct bcr_timer timer; + struct bcr_generic bcr; + struct mcip_bcr mp; + struct bcr_actionpoint ap; + unsigned long vec_base; + int ap_num, ap_full, smart, rtt, n; + + memset(info, 0, sizeof(struct cpuinfo_arc)); + + READ_BCR(AUX_IDENTITY, ident); + info->arcver = ident.family; + + n = scnprintf(buf, len, + "\nIDENTITY\t: ARCVER [%#02x] ARCNUM [%#02x] CHIPID [%#4x]\n", + ident.family, ident.cpu_id, ident.chip_id); + + if (is_isa_arcompact()) { + n += arcompact_mumbojumbo(c, info, buf + n, len - n); + } else if (is_isa_arcv2()){ + n += arcv2_mumbojumbo(c, info, buf + n, len - n); + } + + n += arc_mmu_mumbojumbo(c, buf + n, len - n); + n += arc_cache_mumbojumbo(c, buf + n, len - n); + + READ_BCR(ARC_REG_TIMERS_BCR, timer); + info->t0 = timer.t0; + info->t1 = timer.t1; + + READ_BCR(ARC_REG_MCIP_BCR, mp); + vec_base = read_aux_reg(AUX_INTR_VEC_BASE); + + n += scnprintf(buf + n, len - n, + "Timers\t\t: %s%s%s%s%s%s\nVector Table\t: %#lx\n", + IS_AVAIL1(timer.t0, "Timer0 "), + IS_AVAIL1(timer.t1, "Timer1 "), + IS_AVAIL2(timer.rtc, "RTC [UP 64-bit] ", CONFIG_ARC_TIMERS_64BIT), + IS_AVAIL2(mp.gfrc, "GFRC [SMP 64-bit] ", CONFIG_ARC_TIMERS_64BIT), + vec_base); + + READ_BCR(ARC_REG_AP_BCR, ap); + if (ap.ver) { + ap_num = 2 << ap.num; + ap_full = !ap.min; + } + + READ_BCR(ARC_REG_SMART_BCR, bcr); + smart = bcr.ver ? 1 : 0; + + READ_BCR(ARC_REG_RTT_BCR, bcr); + rtt = bcr.ver ? 1 : 0; + + if (ap.ver | smart | rtt) { + n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s", + IS_AVAIL1(smart, "smaRT "), + IS_AVAIL1(rtt, "RTT ")); + if (ap.ver) { + n += scnprintf(buf + n, len - n, "ActionPoint %d/%s", + ap_num, + ap_full ? "full":"min"); + } + n += scnprintf(buf + n, len - n, "\n"); + } + + if (info->dccm.sz || info->iccm.sz) + n += scnprintf(buf + n, len - n, + "Extn [CCM]\t: DCCM @ %lx, %d KB / ICCM: @ %lx, %d KB\n", + info->dccm.base, TO_KB(info->dccm.sz), + info->iccm.base, TO_KB(info->iccm.sz)); + return buf; } @@ -398,15 +376,15 @@ void chk_opt_weak(char *opt_name, bool hw_exists, bool opt_ena) panic("Disable %s, hardware NOT present\n", opt_name); } -static void arc_chk_core_config(void) +/* + * ISA agnostic sanity checks + */ +static void arc_chk_core_config(struct cpuinfo_arc *info) { - struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; - int present = 0; - - if (!cpu->extn.timer0) + if (!info->t0) panic("Timer0 is not present!\n"); - if (!cpu->extn.timer1) + if (!info->t1) panic("Timer1 is not present!\n"); #ifdef CONFIG_ARC_HAS_DCCM @@ -414,35 +392,17 @@ static void arc_chk_core_config(void) * DCCM can be arbit placed in hardware. * Make sure it's placement/sz matches what Linux is built with */ - if ((unsigned int)__arc_dccm_base != cpu->dccm.base_addr) + if ((unsigned int)__arc_dccm_base != info->dccm.base) panic("Linux built with incorrect DCCM Base address\n"); - if (CONFIG_ARC_DCCM_SZ * SZ_1K != cpu->dccm.sz) + if (CONFIG_ARC_DCCM_SZ * SZ_1K != info->dccm.sz) panic("Linux built with incorrect DCCM Size\n"); #endif #ifdef CONFIG_ARC_HAS_ICCM - if (CONFIG_ARC_ICCM_SZ * SZ_1K != cpu->iccm.sz) + if (CONFIG_ARC_ICCM_SZ * SZ_1K != info->iccm.sz) panic("Linux built with incorrect ICCM Size\n"); #endif - - /* - * FP hardware/software config sanity - * -If hardware present, kernel needs to save/restore FPU state - * -If not, it will crash trying to save/restore the non-existant regs - */ - - if (is_isa_arcompact()) { - /* only DPDP checked since SP has no arch visible regs */ - present = cpu->extn.fpu_dp; - CHK_OPT_STRICT(CONFIG_ARC_FPU_SAVE_RESTORE, present); - } else { - /* Accumulator Low:High pair (r58:59) present if DSP MPY or FPU */ - present = cpu->extn_mpy.dsp | cpu->extn.fpu_sp | cpu->extn.fpu_dp; - CHK_OPT_STRICT(CONFIG_ARC_HAS_ACCL_REGS, present); - - dsp_config_check(); - } } /* @@ -453,23 +413,19 @@ static void arc_chk_core_config(void) void setup_processor(void) { + struct cpuinfo_arc info; + int c = smp_processor_id(); char str[512]; - int cpu_id = smp_processor_id(); - read_arc_build_cfg_regs(); + pr_info("%s", arc_cpu_mumbojumbo(c, &info, str, sizeof(str))); + pr_info("%s", arc_platform_smp_cpuinfo()); + + arc_chk_core_config(&info); + arc_init_IRQ(); - - pr_info("%s", arc_cpu_mumbojumbo(cpu_id, str, sizeof(str))); - pr_info("%s", arc_mmu_mumbojumbo(cpu_id, str, sizeof(str))); - pr_info("%s", arc_cache_mumbojumbo(cpu_id, str, sizeof(str))); - arc_mmu_init(); arc_cache_init(); - pr_info("%s", arc_extn_mumbojumbo(cpu_id, str, sizeof(str))); - pr_info("%s", arc_platform_smp_cpuinfo()); - - arc_chk_core_config(); } static inline bool uboot_arg_invalid(unsigned long addr) @@ -616,6 +572,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) char *str; int cpu_id = ptr_to_cpu(v); struct device *cpu_dev = get_cpu_device(cpu_id); + struct cpuinfo_arc info; struct clk *cpu_clk; unsigned long freq = 0; @@ -628,7 +585,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) if (!str) goto done; - seq_printf(m, arc_cpu_mumbojumbo(cpu_id, str, PAGE_SIZE)); + seq_printf(m, arc_cpu_mumbojumbo(cpu_id, &info, str, PAGE_SIZE)); cpu_clk = clk_get(cpu_dev, NULL); if (IS_ERR(cpu_clk)) { @@ -645,9 +602,6 @@ static int show_cpuinfo(struct seq_file *m, void *v) loops_per_jiffy / (500000 / HZ), (loops_per_jiffy / (5000 / HZ)) % 100); - seq_printf(m, arc_mmu_mumbojumbo(cpu_id, str, PAGE_SIZE)); - seq_printf(m, arc_cache_mumbojumbo(cpu_id, str, PAGE_SIZE)); - seq_printf(m, arc_extn_mumbojumbo(cpu_id, str, PAGE_SIZE)); seq_printf(m, arc_platform_smp_cpuinfo()); free_page((unsigned long)str); diff --git a/arch/arc/mm/cache.c b/arch/arc/mm/cache.c index 7197bb845a40..4510f805b21d 100644 --- a/arch/arc/mm/cache.c +++ b/arch/arc/mm/cache.c @@ -39,7 +39,7 @@ void (*__dma_cache_wback_inv)(phys_addr_t start, unsigned long sz); void (*__dma_cache_inv)(phys_addr_t start, unsigned long sz); void (*__dma_cache_wback)(phys_addr_t start, unsigned long sz); -static char *read_decode_cache_bcr_arcv2(int c, char *buf, int len) +static int read_decode_cache_bcr_arcv2(int c, char *buf, int len) { struct cpuinfo_arc_cache *p_slc = &slc_info; struct bcr_identity ident; @@ -94,10 +94,10 @@ static char *read_decode_cache_bcr_arcv2(int c, char *buf, int len) perip_base, IS_AVAIL3(ioc_exists, ioc_enable, ", IO-Coherency (per-device) ")); - return buf; + return n; } -char *arc_cache_mumbojumbo(int c, char *buf, int len) +int arc_cache_mumbojumbo(int c, char *buf, int len) { struct cpuinfo_arc_cache *p_ic = &ic_info, *p_dc = &dc_info; struct bcr_cache ibcr, dbcr; @@ -153,9 +153,9 @@ dc_chk: slc_chk: if (is_isa_arcv2()) - read_decode_cache_bcr_arcv2(c, buf + n, len - n); + n += read_decode_cache_bcr_arcv2(c, buf + n, len - n); - return buf; + return n; } /* diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index 861cabe81e87..d70eaff71759 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -562,7 +562,7 @@ void local_flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start, * the cpuinfo structure for later use. * No Validation is done here, simply read/convert the BCRs */ -char *arc_mmu_mumbojumbo(int c, char *buf, int len) +int arc_mmu_mumbojumbo(int c, char *buf, int len) { struct cpuinfo_arc_mmu *mmu = &mmuinfo; unsigned int bcr, u_dtlb, u_itlb, sasid; @@ -607,7 +607,7 @@ char *arc_mmu_mumbojumbo(int c, char *buf, int len) IS_AVAIL1(sasid, ", SASID"), IS_AVAIL2(mmu->pae, ", PAE40 ", CONFIG_ARC_HAS_PAE40)); - return buf; + return n; } int pae40_exist_but_not_enab(void) From cfca4b5abe0cc13f9d9f45f760efd8260e31200f Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Tue, 12 May 2020 22:18:08 -0700 Subject: [PATCH 14/49] ARC: entry: use gp to cache task pointer (vs. r25) The motivation is eventual ABI considerations for ARCv3 but even without it this change us worthwhile as diffstat reduces 100 net lines r25 is a callee saved register, normally not saved by entry code in pt_regs. However because of its usage in CONFIG_ARC_CURR_IN_REG it needs to be. This in turn requires a whole bunch of special casing when we need to access r25. Then there is distinction between user mode r25 vs. kernel mode r25 - hence distinct SAVE_CALLEE_SAVED_{USER,KERNEL} Instead use gp which is a scratch register and thus saved already in entry code. This cleans things up significantly and much nocer on eyes: - SAVE_CALLEE_SAVED_{USER,KERNEL} are now exactly same - no special user_r25 slot in pt_reggs Note that typical global asm registers are callee-saved (r25), but gp is not callee-saved thus needs additional -ffixed- toggle Signed-off-by: Vineet Gupta --- arch/arc/Kconfig | 6 +- arch/arc/Makefile | 6 +- arch/arc/include/asm/current.h | 2 +- arch/arc/include/asm/entry-arcv2.h | 17 ++-- arch/arc/include/asm/entry-compact.h | 35 +++------ arch/arc/include/asm/entry.h | 111 ++++++++------------------- arch/arc/include/asm/ptrace.h | 6 +- arch/arc/kernel/asm-offsets.c | 2 - arch/arc/kernel/ctx_sw.c | 13 +--- arch/arc/kernel/ctx_sw_asm.S | 2 +- arch/arc/kernel/entry.S | 3 +- arch/arc/kernel/process.c | 11 --- arch/arc/kernel/ptrace.c | 2 - 13 files changed, 60 insertions(+), 156 deletions(-) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 47b4acc7d0c9..c92bacc1ff4c 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -492,11 +492,11 @@ config ARC_KVADDR_SIZE kernel-user gutter) config ARC_CURR_IN_REG - bool "Dedicate Register r25 for current_task pointer" + bool "cache current task pointer in gp" default y help - This reserved Register R25 to point to Current Task in - kernel mode. This saves memory access for each such access + This reserves gp register to point to Current Task in + kernel mode eliding memory access for each access config ARC_EMUL_UNALIGNED diff --git a/arch/arc/Makefile b/arch/arc/Makefile index 329400a1c355..2390dd042e36 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile @@ -28,14 +28,14 @@ cflags-y += $(tune-mcpu-def-y) endif endif - ifdef CONFIG_ARC_CURR_IN_REG # For a global register definition, make sure it gets passed to every file # We had a customer reported bug where some code built in kernel was NOT using -# any kernel headers, and missing the r25 global register +# any kernel headers, and missing the global register # Can't do unconditionally because of recursive include issues # due to LINUXINCLUDE += -include $(srctree)/arch/arc/include/asm/current.h +cflags-y += -ffixed-gp endif cflags-y += -fsection-anchors @@ -67,7 +67,7 @@ cflags-$(CONFIG_ARC_DW2_UNWIND) += -fasynchronous-unwind-tables $(cfi) # small data is default for elf32 tool-chain. If not usable, disable it # This also allows repurposing GP as scratch reg to gcc reg allocator disable_small_data := y -cflags-$(disable_small_data) += -mno-sdata -fcall-used-gp +cflags-$(disable_small_data) += -mno-sdata cflags-$(CONFIG_CPU_BIG_ENDIAN) += -mbig-endian ldflags-$(CONFIG_CPU_BIG_ENDIAN) += -EB diff --git a/arch/arc/include/asm/current.h b/arch/arc/include/asm/current.h index 9b9bdd3e6538..06be89f6f2f0 100644 --- a/arch/arc/include/asm/current.h +++ b/arch/arc/include/asm/current.h @@ -13,7 +13,7 @@ #ifdef CONFIG_ARC_CURR_IN_REG -register struct task_struct *curr_arc asm("r25"); +register struct task_struct *curr_arc asm("gp"); #define current (curr_arc) #else diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h index 0ff4c0610561..858742feab71 100644 --- a/arch/arc/include/asm/entry-arcv2.h +++ b/arch/arc/include/asm/entry-arcv2.h @@ -18,7 +18,6 @@ * | orig_r0 | * | event/ECR | * | bta | - * | user_r25 | * | gp | * | fp | * | sp | @@ -56,7 +55,7 @@ ; hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE ; 4. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI ; - ; (B) Manually saved some regs: r12,r25,r30, sp,fp,gp, ACCL pair + ; (B) Manually saved some regs: r12,r30, sp,fp,gp, ACCL pair #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE ; carve pt_regs on stack (case #3), PC/STAT32 already on stack @@ -157,17 +156,17 @@ st r10, [sp, PT_sp] ; SP (pt_regs->sp) -#ifdef CONFIG_ARC_CURR_IN_REG - st r25, [sp, PT_user_r25] - GET_CURR_TASK_ON_CPU r25 -#endif - #ifdef CONFIG_ARC_HAS_ACCL_REGS ST2 r58, r59, PT_r58 #endif /* clobbers r10, r11 registers pair */ DSP_SAVE_REGFILE_IRQ + +#ifdef CONFIG_ARC_CURR_IN_REG + GET_CURR_TASK_ON_CPU gp +#endif + .endm /*------------------------------------------------------------------------*/ @@ -188,10 +187,6 @@ sr r10, [AUX_USER_SP] 1: -#ifdef CONFIG_ARC_CURR_IN_REG - ld r25, [sp, PT_user_r25] -#endif - /* clobbers r10, r11 registers pair */ DSP_RESTORE_REGFILE_IRQ diff --git a/arch/arc/include/asm/entry-compact.h b/arch/arc/include/asm/entry-compact.h index 67ff06e15cea..e3383e1cb040 100644 --- a/arch/arc/include/asm/entry-compact.h +++ b/arch/arc/include/asm/entry-compact.h @@ -151,14 +151,6 @@ /* ARC700 doesn't provide auto-stack switching */ SWITCH_TO_KERNEL_STK -#ifdef CONFIG_ARC_CURR_IN_REG - /* Treat r25 as scratch reg (save on stack) and load with "current" */ - PUSH r25 - GET_CURR_TASK_ON_CPU r25 -#else - sub sp, sp, 4 -#endif - st.a r0, [sp, -8] /* orig_r0 needed for syscall (skip ECR slot) */ sub sp, sp, 4 /* skip pt_regs->sp, already saved above */ @@ -179,6 +171,11 @@ lr r10, [ecr] st r10, [sp, PT_event] /* EV_Trap expects r10 to have ECR */ + +#ifdef CONFIG_ARC_CURR_IN_REG + /* gp already saved on stack: now load with "current" */ + GET_CURR_TASK_ON_CPU gp +#endif .endm /*-------------------------------------------------------------- @@ -208,11 +205,8 @@ POP gp RESTORE_R12_TO_R0 -#ifdef CONFIG_ARC_CURR_IN_REG - ld r25, [sp, 12] -#endif ld sp, [sp] /* restore original sp */ - /* orig_r0, ECR, user_r25 skipped automatically */ + /* orig_r0, ECR skipped automatically */ .endm /* Dummy ECR values for Interrupts */ @@ -229,13 +223,6 @@ SWITCH_TO_KERNEL_STK -#ifdef CONFIG_ARC_CURR_IN_REG - /* Treat r25 as scratch reg (save on stack) and load with "current" */ - PUSH r25 - GET_CURR_TASK_ON_CPU r25 -#else - sub sp, sp, 4 -#endif PUSH 0x003\LVL\()abcd /* Dummy ECR */ sub sp, sp, 8 /* skip orig_r0 (not needed) @@ -255,6 +242,10 @@ PUSHAX lp_start PUSHAX bta_l\LVL\() +#ifdef CONFIG_ARC_CURR_IN_REG + /* gp already saved on stack: now load with "current" */ + GET_CURR_TASK_ON_CPU gp +#endif .endm /*-------------------------------------------------------------- @@ -282,11 +273,7 @@ POP gp RESTORE_R12_TO_R0 -#ifdef CONFIG_ARC_CURR_IN_REG - ld r25, [sp, 12] -#endif - ld sp, [sp] /* restore original sp */ - /* orig_r0, ECR, user_r25 skipped automatically */ + ld sp, [sp] /* restore original sp; orig_r0, ECR skipped implicitly */ .endm /* Get thread_info of "current" tsk */ diff --git a/arch/arc/include/asm/entry.h b/arch/arc/include/asm/entry.h index 2980bc9b7653..49c2e090cb5c 100644 --- a/arch/arc/include/asm/entry.h +++ b/arch/arc/include/asm/entry.h @@ -91,7 +91,7 @@ * Helpers to save/restore callee-saved regs: * used by several macros below *-------------------------------------------------------------*/ -.macro SAVE_R13_TO_R24 +.macro SAVE_R13_TO_R25 PUSH r13 PUSH r14 PUSH r15 @@ -104,9 +104,11 @@ PUSH r22 PUSH r23 PUSH r24 + PUSH r25 .endm -.macro RESTORE_R24_TO_R13 +.macro RESTORE_R25_TO_R13 + POP r25 POP r24 POP r23 POP r22 @@ -121,81 +123,31 @@ POP r13 .endm -/*-------------------------------------------------------------- - * Collect User Mode callee regs as struct callee_regs - needed by - * fork/do_signal/unaligned-access-emulation. - * (By default only scratch regs are saved on entry to kernel) - * - * Special handling for r25 if used for caching Task Pointer. - * It would have been saved in task->thread.user_r25 already, but to keep - * the interface same it is copied into regular r25 placeholder in - * struct callee_regs. - *-------------------------------------------------------------*/ +/* + * save user mode callee regs as struct callee_regs + * - needed by fork/do_signal/unaligned-access-emulation. + */ .macro SAVE_CALLEE_SAVED_USER - - mov r12, sp ; save SP as ref to pt_regs - SAVE_R13_TO_R24 - -#ifdef CONFIG_ARC_CURR_IN_REG - ; Retrieve orig r25 and save it with rest of callee_regs - ld r12, [r12, PT_user_r25] - PUSH r12 -#else - PUSH r25 -#endif - + SAVE_R13_TO_R25 .endm -/*-------------------------------------------------------------- - * Save kernel Mode callee regs at the time of Contect Switch. - * - * Special handling for r25 if used for caching Task Pointer. - * Kernel simply skips saving it since it will be loaded with - * incoming task pointer anyways - *-------------------------------------------------------------*/ -.macro SAVE_CALLEE_SAVED_KERNEL - - SAVE_R13_TO_R24 - -#ifdef CONFIG_ARC_CURR_IN_REG - sub sp, sp, 4 -#else - PUSH r25 -#endif -.endm - -/*-------------------------------------------------------------- - * Opposite of SAVE_CALLEE_SAVED_KERNEL - *-------------------------------------------------------------*/ -.macro RESTORE_CALLEE_SAVED_KERNEL - -#ifdef CONFIG_ARC_CURR_IN_REG - add sp, sp, 4 /* skip usual r25 placeholder */ -#else - POP r25 -#endif - RESTORE_R24_TO_R13 -.endm - -/*-------------------------------------------------------------- - * Opposite of SAVE_CALLEE_SAVED_USER - * - * ptrace tracer or unaligned-access fixup might have changed a user mode - * callee reg which is saved back to usual r25 storage location - *-------------------------------------------------------------*/ +/* + * restore user mode callee regs as struct callee_regs + * - could have been changed by ptrace tracer or unaligned-access fixup + */ .macro RESTORE_CALLEE_SAVED_USER + RESTORE_R25_TO_R13 +.endm -#ifdef CONFIG_ARC_CURR_IN_REG - POP r12 -#else - POP r25 -#endif - RESTORE_R24_TO_R13 +/* + * save/restore kernel mode callee regs at the time of context switch + */ +.macro SAVE_CALLEE_SAVED_KERNEL + SAVE_R13_TO_R25 +.endm - ; SP is back to start of pt_regs -#ifdef CONFIG_ARC_CURR_IN_REG - st r12, [sp, PT_user_r25] -#endif +.macro RESTORE_CALLEE_SAVED_KERNEL + RESTORE_R25_TO_R13 .endm /*-------------------------------------------------------------- @@ -231,10 +183,10 @@ #ifdef CONFIG_SMP -/*------------------------------------------------- +/* * Retrieve the current running task on this CPU - * 1. Determine curr CPU id. - * 2. Use it to index into _current_task[ ] + * - loads it from backing _current_task[] (and can't use the + * caching reg for current task */ .macro GET_CURR_TASK_ON_CPU reg GET_CPU_ID \reg @@ -256,7 +208,7 @@ add2 \tmp, @_current_task, \tmp st \tsk, [\tmp] #ifdef CONFIG_ARC_CURR_IN_REG - mov r25, \tsk + mov gp, \tsk #endif .endm @@ -271,21 +223,20 @@ .macro SET_CURR_TASK_ON_CPU tsk, tmp st \tsk, [@_current_task] #ifdef CONFIG_ARC_CURR_IN_REG - mov r25, \tsk + mov gp, \tsk #endif .endm #endif /* SMP / UNI */ -/* ------------------------------------------------------------------ +/* * Get the ptr to some field of Current Task at @off in task struct - * -Uses r25 for Current task ptr if that is enabled + * - Uses current task cached in reg if enabled */ - #ifdef CONFIG_ARC_CURR_IN_REG .macro GET_CURR_TASK_FIELD_PTR off, reg - add \reg, r25, \off + add \reg, gp, \off .endm #else diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index cf90fcd2a628..e9798f46cdc4 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -52,11 +52,9 @@ struct pt_regs { }; unsigned long event; }; - - unsigned long user_r25; }; -#define MAX_REG_OFFSET offsetof(struct pt_regs, user_r25) +#define MAX_REG_OFFSET offsetof(struct pt_regs, event) #else @@ -79,8 +77,6 @@ struct pt_regs { unsigned long bta; /* bta_l1, bta_l2, erbta */ - unsigned long user_r25; - unsigned long r26; /* gp */ unsigned long fp; unsigned long sp; /* user/kernel sp depending on where we came from */ diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c index 0e884036ab74..37324fd9a72f 100644 --- a/arch/arc/kernel/asm-offsets.c +++ b/arch/arc/kernel/asm-offsets.c @@ -63,8 +63,6 @@ int main(void) DEFINE(PT_blink, offsetof(struct pt_regs, blink)); DEFINE(PT_lpe, offsetof(struct pt_regs, lp_end)); DEFINE(PT_lpc, offsetof(struct pt_regs, lp_count)); - DEFINE(PT_user_r25, offsetof(struct pt_regs, user_r25)); - DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs)); DEFINE(SZ_PT_REGS, sizeof(struct pt_regs)); diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c index bf16f777a0bc..40d89440b7e4 100644 --- a/arch/arc/kernel/ctx_sw.c +++ b/arch/arc/kernel/ctx_sw.c @@ -38,11 +38,7 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) "st.a r22, [sp, -4] \n\t" "st.a r23, [sp, -4] \n\t" "st.a r24, [sp, -4] \n\t" -#ifndef CONFIG_ARC_CURR_IN_REG "st.a r25, [sp, -4] \n\t" -#else - "sub sp, sp, 4 \n\t" /* usual r25 placeholder */ -#endif /* set ksp of outgoing task in tsk->thread.ksp */ #if KSP_WORD_OFF <= 255 @@ -58,7 +54,7 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) /* * setup _current_task with incoming tsk. - * optionally, set r25 to that as well + * optionally, set caching reg to that as well * For SMP extra work to get to &_current_task[cpu] * (open coded SET_CURR_TASK_ON_CPU) */ @@ -72,19 +68,14 @@ __switch_to(struct task_struct *prev_task, struct task_struct *next_task) "st %2, [r24] \n\t" #endif #ifdef CONFIG_ARC_CURR_IN_REG - "mov r25, %2 \n\t" + "mov gp, %2 \n\t" #endif /* get ksp of incoming task from tsk->thread.ksp */ "ld.as sp, [%2, %1] \n\t" /* start loading it's CALLEE reg file */ - -#ifndef CONFIG_ARC_CURR_IN_REG "ld.ab r25, [sp, 4] \n\t" -#else - "add sp, sp, 4 \n\t" -#endif "ld.ab r24, [sp, 4] \n\t" "ld.ab r23, [sp, 4] \n\t" "ld.ab r22, [sp, 4] \n\t" diff --git a/arch/arc/kernel/ctx_sw_asm.S b/arch/arc/kernel/ctx_sw_asm.S index 02c461484761..95cba6265e2b 100644 --- a/arch/arc/kernel/ctx_sw_asm.S +++ b/arch/arc/kernel/ctx_sw_asm.S @@ -49,7 +49,7 @@ __switch_to: SET_CURR_TASK_ON_CPU r1, r3 /* reload SP with kernel mode stack pointer in task->thread.ksp */ - ld.as sp, [r1, (TASK_THREAD + THREAD_KSP)/4] + ld.as sp, [r1, KSP_WORD_OFF] /* restore the registers */ RESTORE_CALLEE_SAVED_KERNEL diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index 54e91df678dd..cd26e0fa5044 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -210,7 +210,6 @@ trap_with_param: ; Save callee regs in case gdb wants to have a look ; SP will grow up by size of CALLEE Reg-File - ; NOTE: clobbers r12 SAVE_CALLEE_SAVED_USER ; save location of saved Callee Regs @ thread_struct->pc @@ -318,7 +317,7 @@ resume_user_mode_begin: ; tracer might call PEEKUSR(CALLEE reg) ; ; NOTE: SP will grow up by size of CALLEE Reg-File - SAVE_CALLEE_SAVED_USER ; clobbers r12 + SAVE_CALLEE_SAVED_USER ; save location of saved Callee Regs @ thread_struct->callee GET_CURR_TASK_FIELD_PTR TASK_THREAD, r10 diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index 980b71da2f61..96f591508142 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -162,7 +162,6 @@ asmlinkage void ret_from_fork(void); * | SP | * | orig_r0 | * | event/ECR | - * | user_r25 | * ------------------ <===== END of PAGE */ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) @@ -243,16 +242,6 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) */ c_callee->r25 = task_thread_info(p)->thr_ptr; -#ifdef CONFIG_ARC_CURR_IN_REG - /* - * setup usermode thread pointer #2: - * however for this special use of r25 in kernel, __switch_to() sets - * r25 for kernel needs and only in the final return path is usermode - * r25 setup, from pt_regs->user_r25. So set that up as well - */ - c_regs->user_r25 = c_callee->r25; -#endif - return 0; } diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c index 2abdcd9b09e8..8226df3163fe 100644 --- a/arch/arc/kernel/ptrace.c +++ b/arch/arc/kernel/ptrace.c @@ -47,7 +47,6 @@ static const struct pt_regs_offset regoffset_table[] = { REG_OFFSET_NAME(sp), REG_OFFSET_NAME(orig_r0), REG_OFFSET_NAME(event), - REG_OFFSET_NAME(user_r25), REG_OFFSET_END, }; @@ -57,7 +56,6 @@ static const struct pt_regs_offset regoffset_table[] = { REG_OFFSET_NAME(orig_r0), REG_OFFSET_NAME(event), REG_OFFSET_NAME(bta), - REG_OFFSET_NAME(user_r25), REG_OFFSET_NAME(r26), REG_OFFSET_NAME(fp), REG_OFFSET_NAME(sp), From d1d1569e89e9cc5c07a389ac859bd045b906923c Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Thu, 14 May 2020 16:26:45 -0700 Subject: [PATCH 15/49] ARC: kernel stack: INIT_THREAD need not setup @init_stack in @ksp There are 2 pointers to kernel mode stack of a task - task_struct.stack: base address of stack page (max possible stack top) - thread_info.ksp : runtime stack top in __switch_to INIT_THREAD was setting up ksp to stack base which was not really needed - it would get overwritten with dynamic value on first call to __switch_to when init is switched out for the very first time. - generic code already does init_task.stack = init_stack and ARC code uses that to retrieve task's stack base. Signed-off-by: Vineet Gupta --- arch/arc/include/asm/processor.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h index fb844fce1ab6..82ddc929d6e7 100644 --- a/arch/arc/include/asm/processor.h +++ b/arch/arc/include/asm/processor.h @@ -33,9 +33,7 @@ struct thread_struct { #endif }; -#define INIT_THREAD { \ - .ksp = sizeof(init_stack) + (unsigned long) init_stack, \ -} +#define INIT_THREAD { } /* Forward declaration, a strange C thing */ struct task_struct; From b060b7d0c105d495eb9338a3f6c7bc0c09830a2c Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Thu, 14 May 2020 00:16:34 -0700 Subject: [PATCH 16/49] ARC: __switch_to: asm with dwarf ops (vs. inline asm) __switch_to() is final step of context switch, swapping kernel modes stack (and callee regs) of outgoing task with next task. It is also the starting point of stack unwinging of a sleeping task and captures SP, FP, BLINK and the corresponding dwarf info. Back when dinosaurs still roamed around, ARC gas didn't support CFI pseudo ops and gcc was responsible for generating dwarf info. Thus it had to be written in "C" with inline asm to do the hand crafting of stack. The function prologue (and crucial saving of blink etc) was still gcc generated but not visible in code. Likewise dwarf info was missing. Now with modern tools, we can make things more obvious by writing the code in asm and adding approproate dwarf cfi pseudo ops. This is mostly non functional change, except for slight chnages to asm - ARCompact doesn't support MOV_S fp, sp, so we use MOV Signed-off-by: Vineet Gupta --- arch/arc/include/asm/dwarf.h | 32 +++++++---- arch/arc/kernel/Makefile | 9 +-- arch/arc/kernel/ctx_sw.c | 103 ----------------------------------- arch/arc/kernel/ctx_sw_asm.S | 66 ++++++++++++---------- 4 files changed, 58 insertions(+), 152 deletions(-) delete mode 100644 arch/arc/kernel/ctx_sw.c diff --git a/arch/arc/include/asm/dwarf.h b/arch/arc/include/asm/dwarf.h index 5f4de05bd4ee..a0d5ebe1bc3f 100644 --- a/arch/arc/include/asm/dwarf.h +++ b/arch/arc/include/asm/dwarf.h @@ -10,23 +10,31 @@ #ifdef ARC_DW2_UNWIND_AS_CFI -#define CFI_STARTPROC .cfi_startproc -#define CFI_ENDPROC .cfi_endproc -#define CFI_DEF_CFA .cfi_def_cfa -#define CFI_REGISTER .cfi_register -#define CFI_REL_OFFSET .cfi_rel_offset -#define CFI_UNDEFINED .cfi_undefined +#define CFI_STARTPROC .cfi_startproc +#define CFI_ENDPROC .cfi_endproc +#define CFI_DEF_CFA .cfi_def_cfa +#define CFI_DEF_CFA_OFFSET .cfi_def_cfa_offset +#define CFI_DEF_CFA_REGISTER .cfi_def_cfa_register +#define CFI_OFFSET .cfi_offset +#define CFI_REL_OFFSET .cfi_rel_offset +#define CFI_REGISTER .cfi_register +#define CFI_RESTORE .cfi_restore +#define CFI_UNDEFINED .cfi_undefined #else #define CFI_IGNORE # -#define CFI_STARTPROC CFI_IGNORE -#define CFI_ENDPROC CFI_IGNORE -#define CFI_DEF_CFA CFI_IGNORE -#define CFI_REGISTER CFI_IGNORE -#define CFI_REL_OFFSET CFI_IGNORE -#define CFI_UNDEFINED CFI_IGNORE +#define CFI_STARTPROC CFI_IGNORE +#define CFI_ENDPROC CFI_IGNORE +#define CFI_DEF_CFA CFI_IGNORE +#define CFI_DEF_CFA_OFFSET CFI_IGNORE +#define CFI_DEF_CFA_REGISTER CFI_IGNORE +#define CFI_OFFSET CFI_IGNORE +#define CFI_REL_OFFSET CFI_IGNORE +#define CFI_REGISTER CFI_IGNORE +#define CFI_RESTORE CFI_IGNORE +#define CFI_UNDEFINED CFI_IGNORE #endif /* !ARC_DW2_UNWIND_AS_CFI */ diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile index 0723d888ac44..95fbf9364c67 100644 --- a/arch/arc/kernel/Makefile +++ b/arch/arc/kernel/Makefile @@ -5,6 +5,8 @@ obj-y := head.o arcksyms.o setup.o irq.o reset.o ptrace.o process.o devtree.o obj-y += signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o +obj-y += ctx_sw_asm.o + obj-$(CONFIG_ISA_ARCOMPACT) += entry-compact.o intc-compact.o obj-$(CONFIG_ISA_ARCV2) += entry-arcv2.o intc-arcv2.o @@ -24,11 +26,4 @@ ifdef CONFIG_ISA_ARCOMPACT CFLAGS_fpu.o += -mdpfp endif -ifdef CONFIG_ARC_DW2_UNWIND -CFLAGS_ctx_sw.o += -fno-omit-frame-pointer -obj-y += ctx_sw.o -else -obj-y += ctx_sw_asm.o -endif - extra-y := vmlinux.lds diff --git a/arch/arc/kernel/ctx_sw.c b/arch/arc/kernel/ctx_sw.c deleted file mode 100644 index 40d89440b7e4..000000000000 --- a/arch/arc/kernel/ctx_sw.c +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) - * - * Vineetg: Aug 2009 - * -"C" version of lowest level context switch asm macro called by schedular - * gcc doesn't generate the dward CFI info for hand written asm, hence can't - * backtrace out of it (e.g. tasks sleeping in kernel). - * So we cheat a bit by writing almost similar code in inline-asm. - * -This is a hacky way of doing things, but there is no other simple way. - * I don't want/intend to extend unwinding code to understand raw asm - */ - -#include -#include -#include - -#define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) - -struct task_struct *__sched -__switch_to(struct task_struct *prev_task, struct task_struct *next_task) -{ - unsigned int tmp; - unsigned int prev = (unsigned int)prev_task; - unsigned int next = (unsigned int)next_task; - - __asm__ __volatile__( - /* FP/BLINK save generated by gcc (standard function prologue */ - "st.a r13, [sp, -4] \n\t" - "st.a r14, [sp, -4] \n\t" - "st.a r15, [sp, -4] \n\t" - "st.a r16, [sp, -4] \n\t" - "st.a r17, [sp, -4] \n\t" - "st.a r18, [sp, -4] \n\t" - "st.a r19, [sp, -4] \n\t" - "st.a r20, [sp, -4] \n\t" - "st.a r21, [sp, -4] \n\t" - "st.a r22, [sp, -4] \n\t" - "st.a r23, [sp, -4] \n\t" - "st.a r24, [sp, -4] \n\t" - "st.a r25, [sp, -4] \n\t" - - /* set ksp of outgoing task in tsk->thread.ksp */ -#if KSP_WORD_OFF <= 255 - "st.as sp, [%3, %1] \n\t" -#else - /* - * Workaround for NR_CPUS=4k - * %1 is bigger than 255 (S9 offset for st.as) - */ - "add2 r24, %3, %1 \n\t" - "st sp, [r24] \n\t" -#endif - - /* - * setup _current_task with incoming tsk. - * optionally, set caching reg to that as well - * For SMP extra work to get to &_current_task[cpu] - * (open coded SET_CURR_TASK_ON_CPU) - */ -#ifndef CONFIG_SMP - "st %2, [@_current_task] \n\t" -#else - "lr r24, [identity] \n\t" - "lsr r24, r24, 8 \n\t" - "bmsk r24, r24, 7 \n\t" - "add2 r24, @_current_task, r24 \n\t" - "st %2, [r24] \n\t" -#endif -#ifdef CONFIG_ARC_CURR_IN_REG - "mov gp, %2 \n\t" -#endif - - /* get ksp of incoming task from tsk->thread.ksp */ - "ld.as sp, [%2, %1] \n\t" - - /* start loading it's CALLEE reg file */ - "ld.ab r25, [sp, 4] \n\t" - "ld.ab r24, [sp, 4] \n\t" - "ld.ab r23, [sp, 4] \n\t" - "ld.ab r22, [sp, 4] \n\t" - "ld.ab r21, [sp, 4] \n\t" - "ld.ab r20, [sp, 4] \n\t" - "ld.ab r19, [sp, 4] \n\t" - "ld.ab r18, [sp, 4] \n\t" - "ld.ab r17, [sp, 4] \n\t" - "ld.ab r16, [sp, 4] \n\t" - "ld.ab r15, [sp, 4] \n\t" - "ld.ab r14, [sp, 4] \n\t" - "ld.ab r13, [sp, 4] \n\t" - - /* last (ret value) = prev : although for ARC it mov r0, r0 */ - "mov %0, %3 \n\t" - - /* FP/BLINK restore generated by gcc (standard func epilogue */ - - : "=r"(tmp) - : "n"(KSP_WORD_OFF), "r"(next), "r"(prev) - : "blink" - ); - - return (struct task_struct *)tmp; -} diff --git a/arch/arc/kernel/ctx_sw_asm.S b/arch/arc/kernel/ctx_sw_asm.S index 95cba6265e2b..59d779004e64 100644 --- a/arch/arc/kernel/ctx_sw_asm.S +++ b/arch/arc/kernel/ctx_sw_asm.S @@ -13,48 +13,54 @@ #define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) -;################### Low Level Context Switch ########################## +; IN +; - r0: prev task (also current) +; - r1: next task +; OUT +; - r0: prev task (so r0 not touched) .section .sched.text,"ax",@progbits - .align 4 - .global __switch_to - .type __switch_to, @function -__switch_to: - CFI_STARTPROC +ENTRY_CFI(__switch_to) - /* Save regs on kernel mode stack of task */ - st.a blink, [sp, -4] - st.a fp, [sp, -4] + /* save kernel stack frame regs of @prev task */ + push blink + CFI_DEF_CFA_OFFSET 4 + CFI_OFFSET r31, -4 + + push fp + CFI_DEF_CFA_OFFSET 8 + CFI_OFFSET r27, -8 + + mov fp, sp + CFI_DEF_CFA_REGISTER r27 + + /* kernel mode callee regs of @prev */ SAVE_CALLEE_SAVED_KERNEL - /* Save the now KSP in task->thread.ksp */ + /* save final SP to @prev->thread.ksp */ #if KSP_WORD_OFF <= 255 st.as sp, [r0, KSP_WORD_OFF] #else /* Workaround for NR_CPUS=4k as ST.as can only take s9 offset */ - add2 r24, r0, KSP_WORD_OFF - st sp, [r24] + add2 r10, r0, KSP_WORD_OFF + st sp, [r10] #endif - /* - * Return last task in r0 (return reg) - * On ARC, Return reg = First Arg reg = r0. - * Since we already have last task in r0, - * don't need to do anything special to return it - */ + /* update @next in _current_task[] and GP register caching it */ + SET_CURR_TASK_ON_CPU r1, r10 - /* - * switch to new task, contained in r1 - * Temp reg r3 is required to get the ptr to store val - */ - SET_CURR_TASK_ON_CPU r1, r3 + /* load SP from @next->thread.ksp */ + ld.as sp, [r1, KSP_WORD_OFF] - /* reload SP with kernel mode stack pointer in task->thread.ksp */ - ld.as sp, [r1, KSP_WORD_OFF] - - /* restore the registers */ + /* restore callee regs, stack frame regs of @next */ RESTORE_CALLEE_SAVED_KERNEL - ld.ab fp, [sp, 4] - ld.ab blink, [sp, 4] - j [blink] + pop fp + CFI_RESTORE r27 + CFI_DEF_CFA r28, 4 + + pop blink + CFI_RESTORE r31 + CFI_DEF_CFA_OFFSET 0 + + j [blink] END_CFI(__switch_to) From fd476197c63dd3aae85e286dab7da23b159562b9 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Thu, 14 May 2020 00:51:26 -0700 Subject: [PATCH 17/49] ARC: __switch_to: move ksp to thread_info from thread_struct task's arch specific bits are carried in 2 places - embedded thread_struct in task_struct - associated thread_info (hoisted in task's stack page) and syntactically: (thread_info *)(task_struct->stack) ksp (dynamic kernel stack top) currently lives in thread_struct but given its deep location in task struct likely to cache miss when accessed from __switch_to(). Moving it to thread_info would be more efficient given proximity to frequently accessed items such as preempt_count thus very likely to be in cache, specially in schedular code. Note however that currently tsk.thread.ksp takes 1 memory access (off of tsk pointer) while new code tsk->stack.ksp would take 2, but likely to be in cache. Moreover if task is current the 2nd reference can be elided and instead derived from SP as (SP & ~(THREAD_SIZE - 1)) All of this also makes __switch_to() code simpler and we can see the 2 ways of retirving ksp (descrobed above) in new code. Signed-off-by: Vineet Gupta --- arch/arc/include/asm/processor.h | 3 +-- arch/arc/include/asm/thread_info.h | 10 +++++----- arch/arc/kernel/asm-offsets.c | 2 +- arch/arc/kernel/ctx_sw_asm.S | 22 ++++++++++------------ arch/arc/kernel/process.c | 6 +++--- 5 files changed, 20 insertions(+), 23 deletions(-) diff --git a/arch/arc/include/asm/processor.h b/arch/arc/include/asm/processor.h index 82ddc929d6e7..d606658e2fe7 100644 --- a/arch/arc/include/asm/processor.h +++ b/arch/arc/include/asm/processor.h @@ -22,7 +22,6 @@ * struct thread_info */ struct thread_struct { - unsigned long ksp; /* kernel mode stack pointer */ unsigned long callee_reg; /* pointer to callee regs */ unsigned long fault_address; /* dbls as brkpt holder as well */ #ifdef CONFIG_ARC_DSP_SAVE_RESTORE_REGS @@ -54,7 +53,7 @@ struct task_struct; * Where about of Task's sp, fp, blink when it was last seen in kernel mode. * Look in process.c for details of kernel stack layout */ -#define TSK_K_ESP(tsk) (tsk->thread.ksp) +#define TSK_K_ESP(tsk) (task_thread_info(tsk)->ksp) #define TSK_K_REG(tsk, off) (*((unsigned long *)(TSK_K_ESP(tsk) + \ sizeof(struct callee_regs) + off))) diff --git a/arch/arc/include/asm/thread_info.h b/arch/arc/include/asm/thread_info.h index 6ba7fe417095..4c530cf131f3 100644 --- a/arch/arc/include/asm/thread_info.h +++ b/arch/arc/include/asm/thread_info.h @@ -37,16 +37,16 @@ */ struct thread_info { unsigned long flags; /* low level flags */ + unsigned long ksp; /* kernel mode stack top in __switch_to */ int preempt_count; /* 0 => preemptable, <0 => BUG */ - struct task_struct *task; /* main task structure */ - __u32 cpu; /* current CPU */ + int cpu; /* current CPU */ unsigned long thr_ptr; /* TLS ptr */ + struct task_struct *task; /* main task structure */ }; /* - * macros/functions for gaining access to the thread information structure - * - * preempt_count needs to be 1 initially, until the scheduler is functional. + * initilaize thread_info for any @tsk + * - this is not related to init_task per se */ #define INIT_THREAD_INFO(tsk) \ { \ diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c index 37324fd9a72f..5b47d09b925e 100644 --- a/arch/arc/kernel/asm-offsets.c +++ b/arch/arc/kernel/asm-offsets.c @@ -20,13 +20,13 @@ int main(void) BLANK(); - DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp)); DEFINE(THREAD_CALLEE_REG, offsetof(struct thread_struct, callee_reg)); DEFINE(THREAD_FAULT_ADDR, offsetof(struct thread_struct, fault_address)); BLANK(); + DEFINE(THREAD_INFO_KSP, offsetof(struct thread_info, ksp)); DEFINE(THREAD_INFO_FLAGS, offsetof(struct thread_info, flags)); DEFINE(THREAD_INFO_PREEMPT_COUNT, offsetof(struct thread_info, preempt_count)); diff --git a/arch/arc/kernel/ctx_sw_asm.S b/arch/arc/kernel/ctx_sw_asm.S index 59d779004e64..48e1f21976ed 100644 --- a/arch/arc/kernel/ctx_sw_asm.S +++ b/arch/arc/kernel/ctx_sw_asm.S @@ -11,8 +11,6 @@ #include /* For the SAVE_* macros */ #include -#define KSP_WORD_OFF ((TASK_THREAD + THREAD_KSP) / 4) - ; IN ; - r0: prev task (also current) ; - r1: next task @@ -37,19 +35,19 @@ ENTRY_CFI(__switch_to) /* kernel mode callee regs of @prev */ SAVE_CALLEE_SAVED_KERNEL - /* save final SP to @prev->thread.ksp */ -#if KSP_WORD_OFF <= 255 - st.as sp, [r0, KSP_WORD_OFF] -#else - /* Workaround for NR_CPUS=4k as ST.as can only take s9 offset */ - add2 r10, r0, KSP_WORD_OFF - st sp, [r10] -#endif + /* + * save final SP to @prev->thread_info.ksp + * @prev is "current" so thread_info derived from SP + */ + GET_CURR_THR_INFO_FROM_SP r10 + st sp, [r10, THREAD_INFO_KSP] + /* update @next in _current_task[] and GP register caching it */ SET_CURR_TASK_ON_CPU r1, r10 - /* load SP from @next->thread.ksp */ - ld.as sp, [r1, KSP_WORD_OFF] + /* load SP from @next->thread_info.ksp */ + ld r10, [r1, TASK_THREAD_INFO] + ld sp, [r10, THREAD_INFO_KSP] /* restore callee regs, stack frame regs of @next */ RESTORE_CALLEE_SAVED_KERNEL diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index 96f591508142..186ceab661eb 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -141,7 +141,7 @@ asmlinkage void ret_from_fork(void); * | unused | * | | * ------------------ - * | r25 | <==== top of Stack (thread.ksp) + * | r25 | <==== top of Stack (thread_info.ksp) * ~ ~ * | --to-- | (CALLEE Regs of kernel mode) * | r13 | @@ -181,14 +181,14 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) c_callee = ((struct callee_regs *)childksp) - 1; /* - * __switch_to() uses thread.ksp to start unwinding stack + * __switch_to() uses thread_info.ksp to start unwinding stack * For kernel threads we don't need to create callee regs, the * stack layout nevertheless needs to remain the same. * Also, since __switch_to anyways unwinds callee regs, we use * this to populate kernel thread entry-pt/args into callee regs, * so that ret_from_kernel_thread() becomes simpler. */ - p->thread.ksp = (unsigned long)c_callee; /* THREAD_KSP */ + task_thread_info(p)->ksp = (unsigned long)c_callee; /* THREAD_INFO_KSP */ /* __switch_to expects FP(0), BLINK(return addr) at top */ childksp[0] = 0; /* fp */ From c505b0da76a67139e073a5a5c4a1986b1cf168d3 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Tue, 19 May 2020 16:01:52 -0700 Subject: [PATCH 18/49] ARC: entry: rework (non-functional) - comments update - rename syscall_trace_entry - use PT_xxx in entry code Signed-off-by: Vineet Gupta --- arch/arc/include/asm/entry-arcv2.h | 23 ++++++++------ arch/arc/include/asm/entry-compact.h | 3 +- arch/arc/include/asm/ptrace.h | 2 +- arch/arc/kernel/asm-offsets.c | 1 + arch/arc/kernel/entry.S | 45 +++++++++++++--------------- arch/arc/kernel/ptrace.c | 2 +- 6 files changed, 39 insertions(+), 37 deletions(-) diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h index 858742feab71..a38ed505b3de 100644 --- a/arch/arc/include/asm/entry-arcv2.h +++ b/arch/arc/include/asm/entry-arcv2.h @@ -48,14 +48,18 @@ /*------------------------------------------------------------------------*/ .macro INTERRUPT_PROLOGUE - ; (A) Before jumping to Interrupt Vector, hardware micro-ops did following: + ; Before jumping to Interrupt Vector, hardware micro-ops did following: ; 1. SP auto-switched to kernel mode stack ; 2. STATUS32.Z flag set if in U mode at time of interrupt (U:1,K:0) ; 3. Auto save: (mandatory) Push PC and STAT32 on stack ; hardware does even if CONFIG_ARC_IRQ_NO_AUTOSAVE - ; 4. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI + ; 4a. Auto save: (optional) r0-r11, blink, LPE,LPS,LPC, JLI,LDI,EI ; - ; (B) Manually saved some regs: r12,r30, sp,fp,gp, ACCL pair + ; Now + ; 4b. If Auto-save (optional) not enabled in hw, manually save them + ; 5. Manually save: r12,r30, sp,fp,gp, ACCL pair + ; + ; At the end, SP points to pt_regs #ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE ; carve pt_regs on stack (case #3), PC/STAT32 already on stack @@ -73,13 +77,14 @@ /*------------------------------------------------------------------------*/ .macro EXCEPTION_PROLOGUE - ; (A) Before jumping to Exception Vector, hardware micro-ops did following: + ; Before jumping to Exception Vector, hardware micro-ops did following: ; 1. SP auto-switched to kernel mode stack ; 2. STATUS32.Z flag set if in U mode at time of exception (U:1,K:0) ; - ; (B) Manually save the complete reg file below + ; Now manually save rest of reg file + ; At the end, SP points to pt_regs - sub sp, sp, SZ_PT_REGS ; carve pt_regs + sub sp, sp, SZ_PT_REGS ; carve space for pt_regs ; _HARD saves r10 clobbered by _SOFT as scratch hence comes first @@ -136,8 +141,8 @@ ST2 gp, fp, PT_r26 ; gp (r26), fp (r27) - st r12, [sp, PT_sp + 4] - st r30, [sp, PT_sp + 8] + st r12, [sp, PT_r12] + st r30, [sp, PT_r30] ; Saving pt_regs->sp correctly requires some extra work due to the way ; Auto stack switch works @@ -244,7 +249,7 @@ btst r0, STATUS_U_BIT ; Z flag set if K, used in restoring SP - ld r10, [sp, PT_event + 4] + ld r10, [sp, PT_bta] sr r10, [erbta] LD2 r10, r11, PT_ret diff --git a/arch/arc/include/asm/entry-compact.h b/arch/arc/include/asm/entry-compact.h index e3383e1cb040..4e2ae82779ed 100644 --- a/arch/arc/include/asm/entry-compact.h +++ b/arch/arc/include/asm/entry-compact.h @@ -170,12 +170,13 @@ PUSHAX erbta lr r10, [ecr] - st r10, [sp, PT_event] /* EV_Trap expects r10 to have ECR */ + st r10, [sp, PT_event] #ifdef CONFIG_ARC_CURR_IN_REG /* gp already saved on stack: now load with "current" */ GET_CURR_TASK_ON_CPU gp #endif + ; OUTPUT: r10 has ECR expected by EV_Trap .endm /*-------------------------------------------------------------- diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index e9798f46cdc4..2bf8ea96ea21 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -75,7 +75,7 @@ struct pt_regs { unsigned long event; }; - unsigned long bta; /* bta_l1, bta_l2, erbta */ + unsigned long bta; /* erbta */ unsigned long r26; /* gp */ unsigned long fp; diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c index 5b47d09b925e..e46688975868 100644 --- a/arch/arc/kernel/asm-offsets.c +++ b/arch/arc/kernel/asm-offsets.c @@ -47,6 +47,7 @@ int main(void) DEFINE(PT_status32, offsetof(struct pt_regs, status32)); DEFINE(PT_event, offsetof(struct pt_regs, event)); + DEFINE(PT_bta, offsetof(struct pt_regs, bta)); DEFINE(PT_sp, offsetof(struct pt_regs, sp)); DEFINE(PT_r0, offsetof(struct pt_regs, r0)); DEFINE(PT_r1, offsetof(struct pt_regs, r1)); diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index cd26e0fa5044..f291fc8476d7 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -160,20 +160,19 @@ END(EV_Extension) ; syscall Tracing ; --------------------------------------------- tracesys: - ; save EFA in case tracer wants the PC of traced task - ; using ERET won't work since next-PC has already committed + ; safekeep EFA (r12) if syscall tracer wanted PC + ; for traps, ERET is pre-commit so points to next-PC GET_CURR_TASK_FIELD_PTR TASK_THREAD, r11 st r12, [r11, THREAD_FAULT_ADDR] ; thread.fault_address - ; PRE Sys Call Ptrace hook - mov r0, sp ; pt_regs needed - bl @syscall_trace_entry + ; PRE syscall trace hook + mov r0, sp ; pt_regs + bl @syscall_trace_enter ; Tracing code now returns the syscall num (orig or modif) mov r8, r0 ; Do the Sys Call as we normally would. - ; Validate the Sys Call number cmp r8, NR_syscalls - 1 mov.hi r0, -ENOSYS bhi tracesys_exit @@ -190,36 +189,36 @@ tracesys: ld r6, [sp, PT_r6] ld r7, [sp, PT_r7] ld.as r9, [sys_call_table, r8] - jl [r9] ; Entry into Sys Call Handler + jl [r9] tracesys_exit: - st r0, [sp, PT_r0] ; sys call return value in pt_regs + st r0, [sp, PT_r0] - ;POST Sys Call Ptrace Hook + ; POST syscall trace hook mov r0, sp ; pt_regs needed bl @syscall_trace_exit - b ret_from_exception ; NOT ret_from_system_call at is saves r0 which - ; we'd done before calling post hook above + + ; don't call ret_from_system_call as it saves r0, already done above + b ret_from_exception ; --------------------------------------------- ; Breakpoint TRAP ; --------------------------------------------- trap_with_param: mov r0, r12 ; EFA in case ptracer/gdb wants stop_pc - mov r1, sp + mov r1, sp ; pt_regs - ; Save callee regs in case gdb wants to have a look - ; SP will grow up by size of CALLEE Reg-File + ; save callee regs in case tracer/gdb wants to peek SAVE_CALLEE_SAVED_USER - ; save location of saved Callee Regs @ thread_struct->pc + ; safekeep ref to callee regs GET_CURR_TASK_FIELD_PTR TASK_THREAD, r10 st sp, [r10, THREAD_CALLEE_REG] - ; Call the trap handler + ; call the non syscall trap handler bl do_non_swi_trap - ; unwind stack to discard Callee saved Regs + ; unwind stack to discard callee regs DISCARD_CALLEE_SAVED_USER b ret_from_exception @@ -237,31 +236,27 @@ ENTRY(EV_Trap) FAKE_RET_FROM_EXCPN - ;============ TRAP 1 :breakpoints - ; Check ECR for trap with arg (PROLOGUE ensures r10 has ECR) + ;============ TRAP N : breakpoints, kprobes etc bmsk.f 0, r10, 7 bnz trap_with_param - ;============ TRAP (no param): syscall top level + ;============ TRAP 0 (no param): syscall - ; If syscall tracing ongoing, invoke pre-post-hooks + ; syscall tracing ongoing, invoke pre-post-hooks around syscall GET_CURR_THR_INFO_FLAGS r10 and.f 0, r10, _TIF_SYSCALL_WORK bnz tracesys ; this never comes back ;============ Normal syscall case - ; syscall num shd not exceed the total system calls avail cmp r8, NR_syscalls - 1 mov.hi r0, -ENOSYS bhi .Lret_from_system_call - ; Offset into the syscall_table and call handler ld.as r9,[sys_call_table, r8] - jl [r9] ; Entry into Sys Call Handler + jl [r9] .Lret_from_system_call: - st r0, [sp, PT_r0] ; sys call return value in pt_regs ; fall through to ret_from_exception diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c index 8226df3163fe..14ea7406f5cd 100644 --- a/arch/arc/kernel/ptrace.c +++ b/arch/arc/kernel/ptrace.c @@ -339,7 +339,7 @@ long arch_ptrace(struct task_struct *child, long request, return ret; } -asmlinkage int syscall_trace_entry(struct pt_regs *regs) +asmlinkage int syscall_trace_enter(struct pt_regs *regs) { if (test_thread_flag(TIF_SYSCALL_TRACE)) if (ptrace_report_syscall_entry(regs)) From 6b606c8d6625aeda0b526cb687367f72bb98cd30 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 20 May 2020 00:47:20 -0700 Subject: [PATCH 19/49] ARC: entry: ARcompact EV_ProtV to use r10 directly Signed-off-by: Vineet Gupta --- arch/arc/kernel/entry-compact.S | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arc/kernel/entry-compact.S b/arch/arc/kernel/entry-compact.S index 5cb0cd7e4eab..77f0090554c5 100644 --- a/arch/arc/kernel/entry-compact.S +++ b/arch/arc/kernel/entry-compact.S @@ -254,9 +254,8 @@ END(handle_interrupt_level1) ENTRY(EV_TLBProtV) - EXCEPTION_PROLOGUE + EXCEPTION_PROLOGUE ; ECR returned in r10 - mov r2, r10 ; ECR set into r10 already lr r0, [efa] ; Faulting Data address (not part of pt_regs saved above) ; Exception auto-disables further Intr/exceptions. @@ -273,8 +272,7 @@ ENTRY(EV_TLBProtV) ; -Access Violation : 00_23_(00|01|02|03)_00 ; x r w r+w ; -Unaligned Access : 00_23_04_00 - ; - bbit1 r2, ECR_C_BIT_PROTV_MISALIG_DATA, 4f + bbit1 r10, ECR_C_BIT_PROTV_MISALIG_DATA, 4f ;========= (6a) Access Violation Processing ======== bl do_page_fault From 0e93ecaeebd5d0f189d1fa50a614ac0816a8c703 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 20 May 2020 00:52:45 -0700 Subject: [PATCH 20/49] ARC: entry: EV_MachineCheck dont re-read ECR Signed-off-by: Vineet Gupta --- arch/arc/kernel/entry.S | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index f291fc8476d7..46582fbebcf2 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -95,16 +95,15 @@ END(instr_service) ENTRY(EV_MachineCheck) - EXCEPTION_PROLOGUE + EXCEPTION_PROLOGUE ; ECR returned in r10 - lr r2, [ecr] lr r0, [efa] mov r1, sp ; MC excpetions disable MMU ARC_MMU_REENABLE r3 - lsr r3, r2, 8 + lsr r3, r10, 8 bmsk r3, r3, 7 brne r3, ECR_C_MCHK_DUP_TLB, 1f From 13347c10396055c4c6c38a54d10bc6ed5024fbe9 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 20 May 2020 00:39:09 -0700 Subject: [PATCH 21/49] ARC: entry: Add more common chores to EXCEPTION_PROLOGUE THe high level structure of most ARC exception handlers is 1. save regfile with EXCEPTION_PROLOGUE 2. setup r0: EFA (not part of pt_regs) 3. setup r1: pointer to pt_regs (SP) 4. drop down to pure kernel mode (from exception) 5. call the Linux "C" handler Remove the boiler plate code by moving #2, #3, #4 into #1. The exceptions to most exceptions are syscall Trap and Machine check which don't do some of above for various reasons, so call a newly introduced variant EXCEPTION_PROLOGUE_KEEP_AE (same as original EXCEPTION_PROLOGUE) Tested-by: Pavel Kozlov Signed-off-by: Vineet Gupta --- arch/arc/include/asm/entry-arcv2.h | 12 +++++++++++- arch/arc/include/asm/entry-compact.h | 12 +++++++++++- arch/arc/kernel/entry-arcv2.S | 15 --------------- arch/arc/kernel/entry-compact.S | 13 ------------- arch/arc/kernel/entry.S | 19 ++----------------- 5 files changed, 24 insertions(+), 47 deletions(-) diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h index a38ed505b3de..11b48ab39154 100644 --- a/arch/arc/include/asm/entry-arcv2.h +++ b/arch/arc/include/asm/entry-arcv2.h @@ -75,7 +75,7 @@ .endm /*------------------------------------------------------------------------*/ -.macro EXCEPTION_PROLOGUE +.macro EXCEPTION_PROLOGUE_KEEP_AE ; Before jumping to Exception Vector, hardware micro-ops did following: ; 1. SP auto-switched to kernel mode stack @@ -104,6 +104,16 @@ ; OUTPUT: r10 has ECR expected by EV_Trap .endm +.macro EXCEPTION_PROLOGUE + + EXCEPTION_PROLOGUE_KEEP_AE ; return ECR in r10 + + lr r0, [efa] + mov r1, sp + + FAKE_RET_FROM_EXCPN ; clobbers r9 +.endm + /*------------------------------------------------------------------------ * This macro saves the registers manually which would normally be autosaved * by hardware on taken interrupts. It is used by diff --git a/arch/arc/include/asm/entry-compact.h b/arch/arc/include/asm/entry-compact.h index 4e2ae82779ed..a0e760eb35a8 100644 --- a/arch/arc/include/asm/entry-compact.h +++ b/arch/arc/include/asm/entry-compact.h @@ -140,7 +140,7 @@ * * After this it is safe to call the "C" handlers *-------------------------------------------------------------*/ -.macro EXCEPTION_PROLOGUE +.macro EXCEPTION_PROLOGUE_KEEP_AE /* Need at least 1 reg to code the early exception prologue */ PROLOG_FREEUP_REG r9, @ex_saved_reg1 @@ -179,6 +179,16 @@ ; OUTPUT: r10 has ECR expected by EV_Trap .endm +.macro EXCEPTION_PROLOGUE + + EXCEPTION_PROLOGUE_KEEP_AE ; return ECR in r10 + + lr r0, [efa] + mov r1, sp + + FAKE_RET_FROM_EXCPN ; clobbers r9 +.endm + /*-------------------------------------------------------------- * Restore all registers used by system call or Exceptions * SP should always be pointing to the next free stack element diff --git a/arch/arc/kernel/entry-arcv2.S b/arch/arc/kernel/entry-arcv2.S index a7e6a2174187..2e49c81c8086 100644 --- a/arch/arc/kernel/entry-arcv2.S +++ b/arch/arc/kernel/entry-arcv2.S @@ -125,11 +125,6 @@ ENTRY(mem_service) EXCEPTION_PROLOGUE - lr r0, [efa] - mov r1, sp - - FAKE_RET_FROM_EXCPN - bl do_memory_error b ret_from_exception END(mem_service) @@ -138,11 +133,6 @@ ENTRY(EV_Misaligned) EXCEPTION_PROLOGUE - lr r0, [efa] ; Faulting Data address - mov r1, sp - - FAKE_RET_FROM_EXCPN - SAVE_CALLEE_SAVED_USER mov r2, sp ; callee_regs @@ -163,11 +153,6 @@ ENTRY(EV_TLBProtV) EXCEPTION_PROLOGUE - lr r0, [efa] ; Faulting Data address - mov r1, sp ; pt_regs - - FAKE_RET_FROM_EXCPN - mov blink, ret_from_exception b do_page_fault diff --git a/arch/arc/kernel/entry-compact.S b/arch/arc/kernel/entry-compact.S index 77f0090554c5..774c03cc1d1a 100644 --- a/arch/arc/kernel/entry-compact.S +++ b/arch/arc/kernel/entry-compact.S @@ -256,16 +256,6 @@ ENTRY(EV_TLBProtV) EXCEPTION_PROLOGUE ; ECR returned in r10 - lr r0, [efa] ; Faulting Data address (not part of pt_regs saved above) - - ; Exception auto-disables further Intr/exceptions. - ; Re-enable them by pretending to return from exception - ; (so rest of handler executes in pure K mode) - - FAKE_RET_FROM_EXCPN - - mov r1, sp ; Handle to pt_regs - ;------ (5) Type of Protection Violation? ---------- ; ; ProtV Hardware Exception is triggered for Access Faults of 2 types @@ -301,9 +291,6 @@ END(EV_TLBProtV) ENTRY(call_do_page_fault) EXCEPTION_PROLOGUE - lr r0, [efa] ; Faulting Data address - mov r1, sp - FAKE_RET_FROM_EXCPN mov blink, ret_from_exception b do_page_fault diff --git a/arch/arc/kernel/entry.S b/arch/arc/kernel/entry.S index 46582fbebcf2..089f6680518f 100644 --- a/arch/arc/kernel/entry.S +++ b/arch/arc/kernel/entry.S @@ -80,11 +80,6 @@ ENTRY(instr_service) EXCEPTION_PROLOGUE - lr r0, [efa] - mov r1, sp - - FAKE_RET_FROM_EXCPN - bl do_insterror_or_kprobe b ret_from_exception END(instr_service) @@ -95,7 +90,7 @@ END(instr_service) ENTRY(EV_MachineCheck) - EXCEPTION_PROLOGUE ; ECR returned in r10 + EXCEPTION_PROLOGUE_KEEP_AE ; ECR returned in r10 lr r0, [efa] mov r1, sp @@ -128,11 +123,6 @@ ENTRY(EV_PrivilegeV) EXCEPTION_PROLOGUE - lr r0, [efa] - mov r1, sp - - FAKE_RET_FROM_EXCPN - bl do_privilege_fault b ret_from_exception END(EV_PrivilegeV) @@ -144,11 +134,6 @@ ENTRY(EV_Extension) EXCEPTION_PROLOGUE - lr r0, [efa] - mov r1, sp - - FAKE_RET_FROM_EXCPN - bl do_extension_fault b ret_from_exception END(EV_Extension) @@ -229,7 +214,7 @@ trap_with_param: ENTRY(EV_Trap) - EXCEPTION_PROLOGUE + EXCEPTION_PROLOGUE_KEEP_AE lr r12, [efa] From dfb12071dda4e28aea82d06bf9c01c403f6d0f30 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 17 Jun 2020 16:23:38 -0700 Subject: [PATCH 22/49] ARC: entry: replace 8 byte OR with 4 byte BSET FAKE_RET_FROM_EXCEPTION drops down to pure kernel mode. It currently has an 8 byte instruction which can be replaced with 4 byte BSET This is applicable to both ARCv2 and ARCv3 entr code. ARCv2 current ------------ 00000804 : ... 874: 216a 1280 lr r9,[status32] 878: 2146 1809 bic r9,r9,0x20 87c: 2105 1f89 8000 0000 or r9,r9,0x80000000 ^^^^^^^^^ 884: 2029 8240 kflag r9 ARCv2 after ---------- 000007e0 : ... 850: 216a 1280 lr r9,[status32] 854: 2150 1149 bclr r9,r9,0x5 858: 214f 17c9 bset r9,r9,0x1f 85c: 2029 8240 kflag r9 Signed-off-by: Vineet Gupta --- arch/arc/include/asm/entry-arcv2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h index 11b48ab39154..f7c9b3915d10 100644 --- a/arch/arc/include/asm/entry-arcv2.h +++ b/arch/arc/include/asm/entry-arcv2.h @@ -274,8 +274,8 @@ .macro FAKE_RET_FROM_EXCPN lr r9, [status32] - bic r9, r9, STATUS_AE_MASK - or r9, r9, STATUS_IE_MASK + bclr r9, r9, STATUS_AE_BIT + bset r9, r9, STATUS_IE_BIT kflag r9 .endm From 656f18ad8d5bc878cf05210e2fea8f13270ffcc5 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Thu, 18 Jun 2020 12:31:48 -0700 Subject: [PATCH 23/49] ARC: entry: replace 8 byte ADD.ne with 4 byte ADD2.ne ARCv2 current ------------ 000007e0 : 7e0: 2482 3c01 sub sp,sp,112 7e4: 1c28 3006 std r0r1,[sp,40] 7e8: 1c30 3086 std r2r3,[sp,48] 7ec: 1c38 3106 std r4r5,[sp,56] 7f0: 1c40 3186 std r6r7,[sp,64] 7f4: 1c48 3206 std r8r9,[sp,72] 7f8: 1c50 3286 std r10r11,[sp,80] 7fc: 1c58 37c0 st blink,[sp,88] 800: 1c0c 36c0 st fp,[sp,12] 804: 1c18 3680 st gp,[sp,24] 808: 1c10 3780 st r30,[sp,16] 80c: 1c14 3300 st r12,[sp,20] 810: 226a 1340 lr r10,[aux_user_sp] 814: 22ca 1702 mov.ne r10,sp 818: 22c0 1f82 0000 0070 add.ne r10,r10,0x70 ^^^^^^^^^ With fix -------- 000007b4 : 7b4: 2482 3c01 sub sp,sp,112 7b8: 1c28 3006 std r0r1,[sp,40] 7bc: 1c30 3086 std r2r3,[sp,48] 7c0: 1c38 3106 std r4r5,[sp,56] 7c4: 1c40 3186 std r6r7,[sp,64] 7c8: 1c48 3206 std r8r9,[sp,72] 7cc: 1c50 3286 std r10r11,[sp,80] 7d0: 1c58 37c0 st blink,[sp,88] 7d4: 1c0c 36c0 st fp,[sp,12] 7d8: 1c18 3680 st gp,[sp,24] 7dc: 1c10 3780 st r30,[sp,16] 7e0: 1c14 3300 st r12,[sp,20] 7e4: 226a 1340 lr r10,[aux_user_sp] 7e8: 22ca 1702 mov.ne r10,sp 7ec: 22d5 1722 add2.ne r10,r10,0x1c Signed-off-by: Vineet Gupta --- arch/arc/include/asm/entry-arcv2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h index f7c9b3915d10..a030eae93d35 100644 --- a/arch/arc/include/asm/entry-arcv2.h +++ b/arch/arc/include/asm/entry-arcv2.h @@ -167,7 +167,7 @@ ; ISA requires ADD.nz to have same dest and src reg operands mov.nz r10, sp - add.nz r10, r10, SZ_PT_REGS ; K mode SP + add2.nz r10, r10, SZ_PT_REGS/4 ; K mode SP st r10, [sp, PT_sp] ; SP (pt_regs->sp) From d4624bf6a6c9d9ff084eb2cba6d3cf6aeda9f974 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 22 May 2020 16:24:53 -0700 Subject: [PATCH 24/49] ARCv2: entry: rearrange pt_regs slightly Instead of r26,fp,sp,r12,r30 order as fp,r30,r12,r26,sp - keeps SP at well known position (right abive hardware autosave) - r26,r12 saved specifically for ARCv2 (and not in ARCv3) kept closer for easy ifdef'ry later Signed-off-by: Vineet Gupta --- arch/arc/include/asm/entry-arcv2.h | 12 ++++++------ arch/arc/include/asm/ptrace.h | 9 +++++---- arch/arc/kernel/asm-offsets.c | 7 ++++--- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h index a030eae93d35..4d13320e0c1b 100644 --- a/arch/arc/include/asm/entry-arcv2.h +++ b/arch/arc/include/asm/entry-arcv2.h @@ -149,10 +149,10 @@ */ .macro __SAVE_REGFILE_SOFT - ST2 gp, fp, PT_r26 ; gp (r26), fp (r27) - - st r12, [sp, PT_r12] + st fp, [sp, PT_fp] ; r27 st r30, [sp, PT_r30] + st r12, [sp, PT_r12] + st r26, [sp, PT_r26] ; gp ; Saving pt_regs->sp correctly requires some extra work due to the way ; Auto stack switch works @@ -187,10 +187,10 @@ /*------------------------------------------------------------------------*/ .macro __RESTORE_REGFILE_SOFT - LD2 gp, fp, PT_r26 ; gp (r26), fp (r27) - - ld r12, [sp, PT_r12] + ld fp, [sp, PT_fp] ld r30, [sp, PT_r30] + ld r12, [sp, PT_r12] + ld r26, [sp, PT_r26] ; Restore SP (into AUX_USER_SP) only if returning to U mode ; - for K mode, it will be implicitly restored as stack is unwound diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index 2bf8ea96ea21..3a054b695f28 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -77,11 +77,10 @@ struct pt_regs { unsigned long bta; /* erbta */ - unsigned long r26; /* gp */ unsigned long fp; - unsigned long sp; /* user/kernel sp depending on where we came from */ - - unsigned long r12, r30; + unsigned long r30; + unsigned long r12; + unsigned long r26; /* gp */ #ifdef CONFIG_ARC_HAS_ACCL_REGS unsigned long r58, r59; /* ACCL/ACCH used by FPU / DSP MPY */ @@ -90,6 +89,8 @@ struct pt_regs { unsigned long DSP_CTRL; #endif + unsigned long sp; /* user/kernel sp depending on entry */ + /*------- Below list auto saved by h/w -----------*/ unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11; diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c index e46688975868..478768c88f46 100644 --- a/arch/arc/kernel/asm-offsets.c +++ b/arch/arc/kernel/asm-offsets.c @@ -62,11 +62,9 @@ int main(void) DEFINE(PT_r26, offsetof(struct pt_regs, r26)); DEFINE(PT_ret, offsetof(struct pt_regs, ret)); DEFINE(PT_blink, offsetof(struct pt_regs, blink)); + OFFSET(PT_fp, pt_regs, fp); DEFINE(PT_lpe, offsetof(struct pt_regs, lp_end)); DEFINE(PT_lpc, offsetof(struct pt_regs, lp_count)); - DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs)); - DEFINE(SZ_PT_REGS, sizeof(struct pt_regs)); - #ifdef CONFIG_ISA_ARCV2 OFFSET(PT_r12, pt_regs, r12); OFFSET(PT_r30, pt_regs, r30); @@ -79,5 +77,8 @@ int main(void) OFFSET(PT_DSP_CTRL, pt_regs, DSP_CTRL); #endif + DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs)); + DEFINE(SZ_PT_REGS, sizeof(struct pt_regs)); + return 0; } From 58d9ceb7d9f56bd74b8e904e26511d27a4220827 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Thu, 21 May 2020 17:44:32 -0700 Subject: [PATCH 25/49] ARC: pt_regs: create seperate type for ecr Reduces duplication in each ISA specific pt_regs Tested-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202308151342.ROQ9Urvv-lkp@intel.com Signed-off-by: Vineet Gupta --- arch/arc/include/asm/ptrace.h | 47 +++++++++++++--------------------- arch/arc/kernel/asm-offsets.c | 2 +- arch/arc/kernel/kgdb.c | 2 +- arch/arc/kernel/ptrace.c | 4 +-- arch/arc/kernel/traps.c | 4 +-- arch/arc/kernel/troubleshoot.c | 13 +++++----- arch/arc/mm/fault.c | 6 ++--- 7 files changed, 33 insertions(+), 45 deletions(-) diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h index 3a054b695f28..4a2b30fb5a98 100644 --- a/arch/arc/include/asm/ptrace.h +++ b/arch/arc/include/asm/ptrace.h @@ -12,6 +12,17 @@ #ifndef __ASSEMBLY__ +typedef union { + struct { +#ifdef CONFIG_CPU_BIG_ENDIAN + unsigned long state:8, vec:8, cause:8, param:8; +#else + unsigned long param:8, cause:8, vec:8, state:8; +#endif + }; + unsigned long full; +} ecr_reg; + /* THE pt_regs: Defines how regs are saved during entry into kernel */ #ifdef CONFIG_ISA_ARCOMPACT @@ -40,21 +51,10 @@ struct pt_regs { * Last word used by Linux for extra state mgmt (syscall-restart) * For interrupts, use artificial ECR values to note current prio-level */ - union { - struct { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned long state:8, ecr_vec:8, - ecr_cause:8, ecr_param:8; -#else - unsigned long ecr_param:8, ecr_cause:8, - ecr_vec:8, state:8; -#endif - }; - unsigned long event; - }; + ecr_reg ecr; }; -#define MAX_REG_OFFSET offsetof(struct pt_regs, event) +#define MAX_REG_OFFSET offsetof(struct pt_regs, ecr) #else @@ -62,18 +62,7 @@ struct pt_regs { unsigned long orig_r0; - union { - struct { -#ifdef CONFIG_CPU_BIG_ENDIAN - unsigned long state:8, ecr_vec:8, - ecr_cause:8, ecr_param:8; -#else - unsigned long ecr_param:8, ecr_cause:8, - ecr_vec:8, state:8; -#endif - }; - unsigned long event; - }; + ecr_reg ecr; /* Exception Cause Reg */ unsigned long bta; /* erbta */ @@ -131,13 +120,13 @@ struct callee_regs { /* return 1 if PC in delay slot */ #define delay_mode(regs) ((regs->status32 & STATUS_DE_MASK) == STATUS_DE_MASK) -#define in_syscall(regs) ((regs->ecr_vec == ECR_V_TRAP) && !regs->ecr_param) -#define in_brkpt_trap(regs) ((regs->ecr_vec == ECR_V_TRAP) && regs->ecr_param) +#define in_syscall(regs) ((regs->ecr.vec == ECR_V_TRAP) && !regs->ecr.param) +#define in_brkpt_trap(regs) ((regs->ecr.vec == ECR_V_TRAP) && regs->ecr.param) #define STATE_SCALL_RESTARTED 0x01 -#define syscall_wont_restart(reg) (reg->state |= STATE_SCALL_RESTARTED) -#define syscall_restartable(reg) !(reg->state & STATE_SCALL_RESTARTED) +#define syscall_wont_restart(regs) (regs->ecr.state |= STATE_SCALL_RESTARTED) +#define syscall_restartable(regs) !(regs->ecr.state & STATE_SCALL_RESTARTED) #define current_pt_regs() \ ({ \ diff --git a/arch/arc/kernel/asm-offsets.c b/arch/arc/kernel/asm-offsets.c index 478768c88f46..f77deb799175 100644 --- a/arch/arc/kernel/asm-offsets.c +++ b/arch/arc/kernel/asm-offsets.c @@ -46,7 +46,7 @@ int main(void) BLANK(); DEFINE(PT_status32, offsetof(struct pt_regs, status32)); - DEFINE(PT_event, offsetof(struct pt_regs, event)); + DEFINE(PT_event, offsetof(struct pt_regs, ecr)); DEFINE(PT_bta, offsetof(struct pt_regs, bta)); DEFINE(PT_sp, offsetof(struct pt_regs, sp)); DEFINE(PT_r0, offsetof(struct pt_regs, r0)); diff --git a/arch/arc/kernel/kgdb.c b/arch/arc/kernel/kgdb.c index 345a0000554c..4f2b5951454f 100644 --- a/arch/arc/kernel/kgdb.c +++ b/arch/arc/kernel/kgdb.c @@ -175,7 +175,7 @@ void kgdb_trap(struct pt_regs *regs) * with trap_s 4 (compiled) breakpoints, continuation needs to * start after the breakpoint. */ - if (regs->ecr_param == 3) + if (regs->ecr.param == 3) instruction_pointer(regs) -= BREAK_INSTR_SIZE; kgdb_handle_exception(1, SIGTRAP, 0, regs); diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c index 14ea7406f5cd..e0c233c178b1 100644 --- a/arch/arc/kernel/ptrace.c +++ b/arch/arc/kernel/ptrace.c @@ -46,7 +46,7 @@ static const struct pt_regs_offset regoffset_table[] = { REG_OFFSET_NAME(r0), REG_OFFSET_NAME(sp), REG_OFFSET_NAME(orig_r0), - REG_OFFSET_NAME(event), + REG_OFFSET_NAME(ecr), REG_OFFSET_END, }; @@ -54,7 +54,7 @@ static const struct pt_regs_offset regoffset_table[] = { static const struct pt_regs_offset regoffset_table[] = { REG_OFFSET_NAME(orig_r0), - REG_OFFSET_NAME(event), + REG_OFFSET_NAME(ecr), REG_OFFSET_NAME(bta), REG_OFFSET_NAME(r26), REG_OFFSET_NAME(fp), diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c index 2f7eb786695b..9b9570b79362 100644 --- a/arch/arc/kernel/traps.c +++ b/arch/arc/kernel/traps.c @@ -110,9 +110,7 @@ void do_machine_check_fault(unsigned long address, struct pt_regs *regs) */ void do_non_swi_trap(unsigned long address, struct pt_regs *regs) { - unsigned int param = regs->ecr_param; - - switch (param) { + switch (regs->ecr.param) { case 1: trap_is_brkpt(address, regs); break; diff --git a/arch/arc/kernel/troubleshoot.c b/arch/arc/kernel/troubleshoot.c index 7654c2e42dc0..d5b3ed2c58f5 100644 --- a/arch/arc/kernel/troubleshoot.c +++ b/arch/arc/kernel/troubleshoot.c @@ -115,8 +115,8 @@ static void show_ecr_verbose(struct pt_regs *regs) /* For Data fault, this is data address not instruction addr */ address = current->thread.fault_address; - vec = regs->ecr_vec; - cause_code = regs->ecr_cause; + vec = regs->ecr.vec; + cause_code = regs->ecr.cause; /* For DTLB Miss or ProtV, display the memory involved too */ if (vec == ECR_V_DTLB_MISS) { @@ -154,7 +154,7 @@ static void show_ecr_verbose(struct pt_regs *regs) pr_cont("Misaligned r/w from 0x%08lx\n", address); #endif } else if (vec == ECR_V_TRAP) { - if (regs->ecr_param == 5) + if (regs->ecr.param == 5) pr_cont("gcc generated __builtin_trap\n"); } else { pr_cont("Check Programmer's Manual\n"); @@ -184,9 +184,10 @@ void show_regs(struct pt_regs *regs) if (user_mode(regs)) show_faulting_vma(regs->ret); /* faulting code, not data */ - pr_info("ECR: 0x%08lx EFA: 0x%08lx ERET: 0x%08lx\nSTAT: 0x%08lx", - regs->event, current->thread.fault_address, regs->ret, - regs->status32); + pr_info("ECR: 0x%08lx EFA: 0x%08lx ERET: 0x%08lx\n", + regs->ecr.full, current->thread.fault_address, regs->ret); + + pr_info("STAT32: 0x%08lx", regs->status32); #define STS_BIT(r, bit) r->status32 & STATUS_##bit##_MASK ? #bit" " : "" diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c index 26e5823c5710..95119a5e7761 100644 --- a/arch/arc/mm/fault.c +++ b/arch/arc/mm/fault.c @@ -100,10 +100,10 @@ void do_page_fault(unsigned long address, struct pt_regs *regs) if (faulthandler_disabled() || !mm) goto no_context; - if (regs->ecr_cause & ECR_C_PROTV_STORE) /* ST/EX */ + if (regs->ecr.cause & ECR_C_PROTV_STORE) /* ST/EX */ write = 1; - else if ((regs->ecr_vec == ECR_V_PROTV) && - (regs->ecr_cause == ECR_C_PROTV_INST_FETCH)) + else if ((regs->ecr.vec == ECR_V_PROTV) && + (regs->ecr.cause == ECR_C_PROTV_INST_FETCH)) exec = 1; flags = FAULT_FLAG_DEFAULT; From 1c4de499e6134ecb048bbd80133b213c705de3e5 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sun, 20 Aug 2023 09:28:19 +0100 Subject: [PATCH 26/49] openrisc: Add missing prototypes for assembly called fnctions These functions are all called from assembly files so there is no need for a prototype in a header file, but when compiling with W=1 enabling -Wmissing-prototypes the compiler warns: arch/openrisc/kernel/ptrace.c:191:17: error: no previous prototype for 'do_syscall_trace_enter' [-Werror=missing-prototypes] arch/openrisc/kernel/ptrace.c:210:17: error: no previous prototype for 'do_syscall_trace_leave' [-Werror=missing-prototypes] arch/openrisc/kernel/signal.c:293:1: error: no previous prototype for 'do_work_pending' [-Werror=missing-prototypes] arch/openrisc/kernel/signal.c:68:17: error: no previous prototype for '_sys_rt_sigreturn' [-Werror=missing-prototypes] arch/openrisc/kernel/time.c:111:25: error: no previous prototype for 'timer_interrupt' [-Werror=missing-prototypes] arch/openrisc/kernel/traps.c:239:17: error: no previous prototype for 'unhandled_exception' [-Werror=missing-prototypes] arch/openrisc/kernel/traps.c:246:17: error: no previous prototype for 'do_fpe_trap' [-Werror=missing-prototypes] arch/openrisc/kernel/traps.c:268:17: error: no previous prototype for 'do_trap' [-Werror=missing-prototypes] arch/openrisc/kernel/traps.c:273:17: error: no previous prototype for 'do_unaligned_access' [-Werror=missing-prototypes] arch/openrisc/kernel/traps.c:286:17: error: no previous prototype for 'do_bus_fault' [-Werror=missing-prototypes] arch/openrisc/kernel/traps.c:462:17: error: no previous prototype for 'do_illegal_instruction' [-Werror=missing-prototypes] arch/openrisc/mm/fault.c:44:17: error: no previous prototype for 'do_page_fault' [-Werror=missing-prototypes] Since these are not needed in header files, fix these by adding prototypes to the top of the respective C files. Reported-by: Arnd Bergmann Closes: https://lore.kernel.org/linux-kernel/20230810141947.1236730-17-arnd@kernel.org/ Signed-off-by: Stafford Horne --- arch/openrisc/kernel/ptrace.c | 4 ++++ arch/openrisc/kernel/signal.c | 5 +++++ arch/openrisc/kernel/smp.c | 2 ++ arch/openrisc/kernel/time.c | 2 ++ arch/openrisc/kernel/traps.c | 8 ++++++++ arch/openrisc/mm/fault.c | 3 +++ 6 files changed, 24 insertions(+) diff --git a/arch/openrisc/kernel/ptrace.c b/arch/openrisc/kernel/ptrace.c index 0b7d2ca6ba3b..1eeac3b62e9d 100644 --- a/arch/openrisc/kernel/ptrace.c +++ b/arch/openrisc/kernel/ptrace.c @@ -27,6 +27,10 @@ #include #include +asmlinkage long do_syscall_trace_enter(struct pt_regs *regs); + +asmlinkage void do_syscall_trace_leave(struct pt_regs *regs); + /* * Copy the thread state to a regset that can be interpreted by userspace. * diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c index 2e7257a433ff..3fbf00330043 100644 --- a/arch/openrisc/kernel/signal.c +++ b/arch/openrisc/kernel/signal.c @@ -34,6 +34,11 @@ struct rt_sigframe { unsigned char retcode[16]; /* trampoline code */ }; +asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs); + +asmlinkage int do_work_pending(struct pt_regs *regs, unsigned int thread_flags, + int syscall); + static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) { diff --git a/arch/openrisc/kernel/smp.c b/arch/openrisc/kernel/smp.c index 0a7a059e2dff..1c5a2d71d675 100644 --- a/arch/openrisc/kernel/smp.c +++ b/arch/openrisc/kernel/smp.c @@ -23,6 +23,8 @@ #include #include +asmlinkage __init void secondary_start_kernel(void); + static void (*smp_cross_call)(const struct cpumask *, unsigned int); unsigned long secondary_release = -1; diff --git a/arch/openrisc/kernel/time.c b/arch/openrisc/kernel/time.c index 8e26c1af5441..764c7bfb5df3 100644 --- a/arch/openrisc/kernel/time.c +++ b/arch/openrisc/kernel/time.c @@ -25,6 +25,8 @@ #include #include +irqreturn_t __irq_entry timer_interrupt(struct pt_regs *regs); + /* Test the timer ticks to count, used in sync routine */ inline void openrisc_timer_set(unsigned long count) { diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c index 0aa6b07efda1..afa47501118f 100644 --- a/arch/openrisc/kernel/traps.c +++ b/arch/openrisc/kernel/traps.c @@ -38,6 +38,14 @@ static int kstack_depth_to_print = 0x180; int lwa_flag; static unsigned long __user *lwa_addr; +asmlinkage void unhandled_exception(struct pt_regs *regs, int ea, int vector); +asmlinkage void do_trap(struct pt_regs *regs, unsigned long address); +asmlinkage void do_fpe_trap(struct pt_regs *regs, unsigned long address); +asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address); +asmlinkage void do_bus_fault(struct pt_regs *regs, unsigned long address); +asmlinkage void do_illegal_instruction(struct pt_regs *regs, + unsigned long address); + static void print_trace(void *data, unsigned long addr, int reliable) { const char *loglvl = data; diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c index a9dcd4381d1a..01dc18aa8410 100644 --- a/arch/openrisc/mm/fault.c +++ b/arch/openrisc/mm/fault.c @@ -32,6 +32,9 @@ volatile pgd_t *current_pgd[NR_CPUS]; extern void __noreturn die(char *, struct pt_regs *, long); +asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address, + unsigned long vector, int write_acc); + /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate From af1fc7402e560f27ea5a92b7ee0572e3d1e389c5 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sun, 20 Aug 2023 17:02:55 +0100 Subject: [PATCH 27/49] openrisc: Declare do_signal function as static When compiling with W=1 enabling -Wmissing-prototypes the compiler warns: arch/openrisc/kernel/signal.c:227:5: error: no previous prototype for 'do_signal' [-Werror=missing-prototypes] Fix this by declaring the function a static as it is not used outside of the scope of this file. Reported-by: Arnd Bergmann Closes: https://lore.kernel.org/linux-kernel/20230810141947.1236730-17-arnd@kernel.org/ Signed-off-by: Stafford Horne --- arch/openrisc/kernel/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c index 3fbf00330043..e2f21a5d8ad9 100644 --- a/arch/openrisc/kernel/signal.c +++ b/arch/openrisc/kernel/signal.c @@ -229,7 +229,7 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs) * mode below. */ -int do_signal(struct pt_regs *regs, int syscall) +static int do_signal(struct pt_regs *regs, int syscall) { struct ksignal ksig; unsigned long continue_addr = 0; From 8d4a142904f07765b7c7c46abf71f811a0811987 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sun, 20 Aug 2023 17:11:39 +0100 Subject: [PATCH 28/49] openrisc: Add prototype for show_registers to processor.h When compiling with W=1 enabling -Wmissing-prototypes the compiler warns: arch/openrisc/kernel/traps.c:67:6: error: no previous prototype for 'show_registers' [-Werror=missing-prototypes] Fix by adding the prototype to the appropriate header file and including the header file in the appropriate C files. Reported-by: Arnd Bergmann Closes: https://lore.kernel.org/linux-kernel/20230810141947.1236730-17-arnd@kernel.org/ Signed-off-by: Stafford Horne --- arch/openrisc/include/asm/processor.h | 1 + arch/openrisc/kernel/process.c | 2 -- arch/openrisc/kernel/traps.c | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h index ed9efb430afa..3b736e74e6ed 100644 --- a/arch/openrisc/include/asm/processor.h +++ b/arch/openrisc/include/asm/processor.h @@ -73,6 +73,7 @@ struct thread_struct { void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp); unsigned long __get_wchan(struct task_struct *p); +void show_registers(struct pt_regs *regs); #define cpu_relax() barrier() diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index dfa558f98ed8..a07512de0169 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -119,8 +119,6 @@ void flush_thread(void) void show_regs(struct pt_regs *regs) { - extern void show_registers(struct pt_regs *regs); - show_regs_print_info(KERN_DEFAULT); /* __PHX__ cleanup this mess */ show_registers(regs); diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c index afa47501118f..f221e4b4298f 100644 --- a/arch/openrisc/kernel/traps.c +++ b/arch/openrisc/kernel/traps.c @@ -31,6 +31,7 @@ #include #include +#include #include #include From 31c67b5fabe351644b2612c6ba75da70aeb417b1 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sun, 20 Aug 2023 21:02:02 +0100 Subject: [PATCH 29/49] openrisc: Add prototype for die to bug.h When compiling with W=1 enabling -Wmissing-prototypes the compiler warns: arch/openrisc/kernel/traps.c:221:17: sing-prototypesrror: no previous prototype for 'die' [-Werror=missing-prototypes] Fix by adding the prototype to the appropriate header file and including the header file in the appropriate C files. Reported-by: Arnd Bergmann Closes: https://lore.kernel.org/linux-kernel/20230810141947.1236730-17-arnd@kernel.org/ Signed-off-by: Stafford Horne --- arch/openrisc/include/asm/bug.h | 11 +++++++++++ arch/openrisc/kernel/traps.c | 1 + arch/openrisc/mm/fault.c | 3 +-- 3 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 arch/openrisc/include/asm/bug.h diff --git a/arch/openrisc/include/asm/bug.h b/arch/openrisc/include/asm/bug.h new file mode 100644 index 000000000000..6d04776eaf10 --- /dev/null +++ b/arch/openrisc/include/asm/bug.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __ASM_OPENRISC_BUG_H +#define __ASM_OPENRISC_BUG_H + +#include + +struct pt_regs; + +void __noreturn die(const char *str, struct pt_regs *regs, long err); + +#endif /* __ASM_OPENRISC_BUG_H */ diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c index f221e4b4298f..879fbf57c04e 100644 --- a/arch/openrisc/kernel/traps.c +++ b/arch/openrisc/kernel/traps.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include diff --git a/arch/openrisc/mm/fault.c b/arch/openrisc/mm/fault.c index 01dc18aa8410..29e232d78d82 100644 --- a/arch/openrisc/mm/fault.c +++ b/arch/openrisc/mm/fault.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -30,8 +31,6 @@ */ volatile pgd_t *current_pgd[NR_CPUS]; -extern void __noreturn die(char *, struct pt_regs *, long); - asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long vector, int write_acc); From 136a2d894105843f19170614429bf12f1789e680 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Mon, 21 Aug 2023 05:31:18 +0100 Subject: [PATCH 30/49] openrisc: Include cpu.h and switch_to.h for prototypes When compiling with W=1 enabling -Wmissing-prototypes the compiler warns: arch/openrisc/kernel/process.c:100:6: error: no previous prototype for 'arch_cpu_idle' [-Werror=missing-prototypes] arch/openrisc/kernel/process.c:240:21: error: no previous prototype for '__switch_to' [-Werror=missing-prototypes] Fix these by adding the approrpiate header files to process.c which brings in the prototype definitions. Reported-by: Arnd Bergmann Closes: https://lore.kernel.org/linux-kernel/20230810141947.1236730-17-arnd@kernel.org/ Signed-off-by: Stafford Horne --- arch/openrisc/kernel/process.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index a07512de0169..86e02929f3ac 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c @@ -14,6 +14,7 @@ */ #define __KERNEL_SYSCALLS__ +#include #include #include #include @@ -38,6 +39,7 @@ #include #include #include +#include #include From f39015504e3abb29e4fb2956f98fed17deebf487 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sun, 20 Aug 2023 17:01:24 +0100 Subject: [PATCH 31/49] openriac: Remove unused nommu_dump_state function When compiling with W=1 enabling -Wmissing-prototypes the compiler warns: arch/openrisc/kernel/traps.c:146:6: error: no previous prototype for 'nommu_dump_state' [-Werror=missing-prototypes] This function is not used so remove it. Reported-by: Arnd Bergmann Closes: https://lore.kernel.org/linux-kernel/20230810141947.1236730-17-arnd@kernel.org/ Signed-off-by: Stafford Horne --- arch/openrisc/kernel/traps.c | 75 ------------------------------------ 1 file changed, 75 deletions(-) diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c index 879fbf57c04e..9370888c9a7e 100644 --- a/arch/openrisc/kernel/traps.c +++ b/arch/openrisc/kernel/traps.c @@ -36,7 +36,6 @@ #include #include -static int kstack_depth_to_print = 0x180; int lwa_flag; static unsigned long __user *lwa_addr; @@ -153,80 +152,6 @@ bad: printk("\n"); } -void nommu_dump_state(struct pt_regs *regs, - unsigned long ea, unsigned long vector) -{ - int i; - unsigned long addr, stack = regs->sp; - - printk("\n\r[nommu_dump_state] :: ea %lx, vector %lx\n\r", ea, vector); - - printk("CPU #: %d\n" - " PC: %08lx SR: %08lx SP: %08lx\n", - 0, regs->pc, regs->sr, regs->sp); - printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n", - 0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]); - printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n", - regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]); - printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n", - regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]); - printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n", - regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]); - printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n", - regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]); - printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n", - regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]); - printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n", - regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]); - printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n", - regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]); - printk(" RES: %08lx oGPR11: %08lx\n", - regs->gpr[11], regs->orig_gpr11); - - printk("Process %s (pid: %d, stackpage=%08lx)\n", - ((struct task_struct *)(__pa(current)))->comm, - ((struct task_struct *)(__pa(current)))->pid, - (unsigned long)current); - - printk("\nStack: "); - printk("Stack dump [0x%08lx]:\n", (unsigned long)stack); - for (i = 0; i < kstack_depth_to_print; i++) { - if (((long)stack & (THREAD_SIZE - 1)) == 0) - break; - stack++; - - printk("%lx :: sp + %02d: 0x%08lx\n", stack, i * 4, - *((unsigned long *)(__pa(stack)))); - } - printk("\n"); - - printk("Call Trace: "); - i = 1; - while (((long)stack & (THREAD_SIZE - 1)) != 0) { - addr = *((unsigned long *)__pa(stack)); - stack++; - - if (kernel_text_address(addr)) { - if (i && ((i % 6) == 0)) - printk("\n "); - printk(" [<%08lx>]", addr); - i++; - } - } - printk("\n"); - - printk("\nCode: "); - - for (i = -24; i < 24; i++) { - unsigned long word; - - word = ((unsigned long *)(__pa(regs->pc)))[i]; - - print_data(regs->pc, word, i); - } - printk("\n"); -} - /* This is normally the 'Oops' routine */ void __noreturn die(const char *str, struct pt_regs *regs, long err) { From c03b12a68f4a9c91e563c909b25bd28b8f1b9414 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sun, 20 Aug 2023 20:57:14 +0100 Subject: [PATCH 32/49] openrisc: Remove unused tlb_init function When compiling with W=1 enabling -Wmissing-prototypes the compiler warns: arch/openrisc/mm/tlb.c:188:13: error: no previous prototype for 'tlb_init' [-Werror=missing-prototypes] This function is not implemented or used so remove it. Reported-by: Arnd Bergmann Closes: https://lore.kernel.org/linux-kernel/20230810141947.1236730-17-arnd@kernel.org/ Signed-off-by: Stafford Horne --- arch/openrisc/mm/init.c | 2 -- arch/openrisc/mm/tlb.c | 9 --------- 2 files changed, 11 deletions(-) diff --git a/arch/openrisc/mm/init.c b/arch/openrisc/mm/init.c index d531ab82be12..1dcd78c8f0e9 100644 --- a/arch/openrisc/mm/init.c +++ b/arch/openrisc/mm/init.c @@ -123,8 +123,6 @@ static void __init map_ram(void) void __init paging_init(void) { - extern void tlb_init(void); - int i; printk(KERN_INFO "Setting up paging and PTEs.\n"); diff --git a/arch/openrisc/mm/tlb.c b/arch/openrisc/mm/tlb.c index e2f2a3c3bb22..3115f2e4f864 100644 --- a/arch/openrisc/mm/tlb.c +++ b/arch/openrisc/mm/tlb.c @@ -182,12 +182,3 @@ void destroy_context(struct mm_struct *mm) flush_tlb_mm(mm); } - -/* called once during VM initialization, from init.c */ - -void __init tlb_init(void) -{ - /* Do nothing... */ - /* invalidate the entire TLB */ - /* flush_tlb_all(); */ -} From c289330331eb93bc6a3c68b9119ccd7d4285a4a2 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Mon, 21 Aug 2023 06:26:25 +0100 Subject: [PATCH 33/49] openrisc: Remove kernel-doc marker from ioremap comment Replace the kernel-doc marker (/**) with a regular comment to fix the warning: arch/openrisc/mm/ioremap.c:108: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst Signed-off-by: Stafford Horne --- arch/openrisc/mm/ioremap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/openrisc/mm/ioremap.c b/arch/openrisc/mm/ioremap.c index 8ec0dafecf25..c6717f876c1c 100644 --- a/arch/openrisc/mm/ioremap.c +++ b/arch/openrisc/mm/ioremap.c @@ -104,7 +104,7 @@ void iounmap(volatile void __iomem *addr) } EXPORT_SYMBOL(iounmap); -/** +/* * OK, this one's a bit tricky... ioremap can get called before memory is * initialized (early serial console does this) and will want to alloc a page * for its mapping. No userspace pages will ever get allocated before memory From b48edb8665fe7b90ff11b23bcc949fee95c035f0 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Tue, 15 Aug 2023 20:36:27 +0200 Subject: [PATCH 34/49] microblaze: Remove zalloc_maybe_bootmem() Last user of zalloc_maybe_bootmem() was removed by commit 4308e3c9e1ea ("microblaze/PCI: Remove unused allocation & free of PCI host bridge structure") Remove it. Signed-off-by: Christophe Leroy Link: https://lore.kernel.org/r/bfb1601cac24d7ef8e741c83f9301e4a5a87a0b5.1692124505.git.christophe.leroy@csgroup.eu Signed-off-by: Michal Simek --- arch/microblaze/include/asm/setup.h | 2 -- arch/microblaze/mm/init.c | 16 ---------------- 2 files changed, 18 deletions(-) diff --git a/arch/microblaze/include/asm/setup.h b/arch/microblaze/include/asm/setup.h index 3657f5e78a3d..bf2600f75959 100644 --- a/arch/microblaze/include/asm/setup.h +++ b/arch/microblaze/include/asm/setup.h @@ -25,7 +25,5 @@ void machine_shutdown(void); void machine_halt(void); void machine_power_off(void); -extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask); - # endif /* __ASSEMBLY__ */ #endif /* _ASM_MICROBLAZE_SETUP_H */ diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c index 353fabdfcbc5..3827dc76edd8 100644 --- a/arch/microblaze/mm/init.c +++ b/arch/microblaze/mm/init.c @@ -270,22 +270,6 @@ asmlinkage void __init mmu_init(void) memblock_dump_all(); } -void * __ref zalloc_maybe_bootmem(size_t size, gfp_t mask) -{ - void *p; - - if (mem_init_done) { - p = kzalloc(size, mask); - } else { - p = memblock_alloc(size, SMP_CACHE_BYTES); - if (!p) - panic("%s: Failed to allocate %zu bytes\n", - __func__, size); - } - - return p; -} - static const pgprot_t protection_map[16] = { [VM_NONE] = PAGE_NONE, [VM_READ] = PAGE_READONLY_X, From 0d2b49479bf91c857d83608da7b64328e556dff7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Aug 2023 10:40:58 +0200 Subject: [PATCH 35/49] microblaze: Make virt_to_pfn() a static inline Making virt_to_pfn() a static inline taking a strongly typed (const void *) makes the contract of a passing a pointer of that type to the function explicit and exposes any misuse of the macro virt_to_pfn() acting polymorphic and accepting many types such as (void *), (unitptr_t) or (unsigned long) as arguments without warnings. Move the function down in the file so __pa() exists in our scope, and it compiles. This in turn requires moving __pa() as it depends on __virt_to_phys() that was below. (Lazy macro evaluation conflicts with strict function ordering.) Make a symmetric change to pfn_to_virt() so we have type checking both ways. Due to this the file being included into some assembly files, some further inclusion guards are needed to make sure assembly keeps compiling. Signed-off-by: Linus Walleij Link: https://lore.kernel.org/r/20230808-virt-to-phys-microblaze-v1-1-e6df710fe0a1@linaro.org Signed-off-by: Michal Simek --- arch/microblaze/include/asm/page.h | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/arch/microblaze/include/asm/page.h b/arch/microblaze/include/asm/page.h index 337f23eabc71..86a4ce07c192 100644 --- a/arch/microblaze/include/asm/page.h +++ b/arch/microblaze/include/asm/page.h @@ -99,9 +99,6 @@ extern int page_is_ram(unsigned long pfn); # define phys_to_pfn(phys) (PFN_DOWN(phys)) # define pfn_to_phys(pfn) (PFN_PHYS(pfn)) -# define virt_to_pfn(vaddr) (phys_to_pfn((__pa(vaddr)))) -# define pfn_to_virt(pfn) __va(pfn_to_phys((pfn))) - # define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)) # define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT) # define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) @@ -109,11 +106,6 @@ extern int page_is_ram(unsigned long pfn); # define ARCH_PFN_OFFSET (memory_start >> PAGE_SHIFT) # endif /* __ASSEMBLY__ */ -#define virt_addr_valid(vaddr) (pfn_valid(virt_to_pfn(vaddr))) - -# define __pa(x) __virt_to_phys((unsigned long)(x)) -# define __va(x) ((void *)__phys_to_virt((unsigned long)(x))) - /* Convert between virtual and physical address for MMU. */ /* Handle MicroBlaze processor with virtual memory. */ #define __virt_to_phys(addr) \ @@ -125,6 +117,25 @@ extern int page_is_ram(unsigned long pfn); #define tovirt(rd, rs) \ addik rd, rs, (CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR) +#ifndef __ASSEMBLY__ + +# define __pa(x) __virt_to_phys((unsigned long)(x)) +# define __va(x) ((void *)__phys_to_virt((unsigned long)(x))) + +static inline unsigned long virt_to_pfn(const void *vaddr) +{ + return phys_to_pfn(__pa(vaddr)); +} + +static inline const void *pfn_to_virt(unsigned long pfn) +{ + return __va(pfn_to_phys((pfn))); +} + +#define virt_addr_valid(vaddr) (pfn_valid(virt_to_pfn(vaddr))) + +#endif /* __ASSEMBLY__ */ + #define TOPHYS(addr) __virt_to_phys(addr) #endif /* __KERNEL__ */ From 7ebc443d129507e079ee5ef69ed53ce7bb8a54f5 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 14 Jul 2023 11:39:49 -0600 Subject: [PATCH 36/49] arc: Explicitly include correct DT includes The DT of_device.h and of_platform.h date back to the separate of_platform_bus_type before it as merged into the regular platform bus. As part of that merge prepping Arm DT support 13 years ago, they "temporarily" include each other. They also include platform_device.h and of.h. As a result, there's a pretty much random mix of those include files used throughout the tree. In order to detangle these headers and replace the implicit includes with struct declarations, users need to explicitly include the correct includes. Signed-off-by: Rob Herring Tested-by: Alexey Brodkin Signed-off-by: Vineet Gupta --- arch/arc/plat-axs10x/axs10x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arc/plat-axs10x/axs10x.c b/arch/arc/plat-axs10x/axs10x.c index b821df7b0089..1feb990a56bc 100644 --- a/arch/arc/plat-axs10x/axs10x.c +++ b/arch/arc/plat-axs10x/axs10x.c @@ -6,7 +6,6 @@ */ #include -#include #include #include From c40cad3b0aa47d6d0995637178fb6607ac3d45c1 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Wed, 23 Aug 2023 16:02:33 -0700 Subject: [PATCH 37/49] ARC: boot log: fix warning Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202308221549.XKufWEWp-lkp@intel.com/ Signed-off-by: Vineet Gupta --- arch/arc/kernel/setup.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 0aa49308d792..4dcf8589b708 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -102,8 +102,10 @@ arcompact_mumbojumbo(int c, struct cpuinfo_arc *info, char *buf, int len) else cpu_nm = "ARC770"; - n += scnprintf(buf + n, len - n, "processor [%d]\t: %s (%s ISA) %s\n", - c, cpu_nm, isa_nm, IS_AVAIL1(be, "[Big-Endian]")); + n += scnprintf(buf + n, len - n, "processor [%d]\t: %s (%s ISA) %s%s%s\n", + c, cpu_nm, isa_nm, + IS_AVAIL2(atomic, "atomic ", CONFIG_ARC_HAS_LLSC), + IS_AVAIL1(be, "[Big-Endian]")); READ_BCR(ARC_REG_FP_BCR, fpu_sp); READ_BCR(ARC_REG_DPFP_BCR, fpu_dp); From 1f464cb4a7febcc8b5ad325f3f9a83c8d4e4c199 Mon Sep 17 00:00:00 2001 From: Liao Chang Date: Tue, 29 Aug 2023 07:01:50 +0000 Subject: [PATCH 38/49] cpufreq: Avoid printing kernel addresses in cpufreq_resume() The pointer value of policy and driver structure are currently printed in the error messages of cpufreq_resume(), this is not recommended and helpful. In order to be consistent with the error message in cpufreq_suspend() and easier to understand, print the name of driver strcture and the manage CPU of policy structure individually in the error messages of cpufreq_resume(). Link: https://lore.kernel.org/all/b7be717c-41d8-bbbf-3e97-3799948ab757@huawei.com Signed-off-by: Liao Chang Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index a757f90aa9d6..bd7bb0d58ef0 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1943,16 +1943,16 @@ void cpufreq_resume(void) for_each_active_policy(policy) { if (cpufreq_driver->resume && cpufreq_driver->resume(policy)) { - pr_err("%s: Failed to resume driver: %p\n", __func__, - policy); + pr_err("%s: Failed to resume driver: %s\n", __func__, + cpufreq_driver->name); } else if (has_target()) { down_write(&policy->rwsem); ret = cpufreq_start_governor(policy); up_write(&policy->rwsem); if (ret) - pr_err("%s: Failed to start governor for policy: %p\n", - __func__, policy); + pr_err("%s: Failed to start governor for CPU%u's policy\n", + __func__, policy->cpu); } } } From 61bfbf7951ba561dcbdd5357702d3cbc2d447812 Mon Sep 17 00:00:00 2001 From: Liao Chang Date: Tue, 29 Aug 2023 07:03:18 +0000 Subject: [PATCH 39/49] cpufreq: Fix the race condition while updating the transition_task of policy The field 'transition_task' of policy structure is used to track the task which is performing the frequency transition. Using this field to print a warning once detect a case where the same task is calling _begin() again before completing the preivous frequency transition via the _end(). However, there is a potential race condition in _end() and _begin() APIs while updating the field 'transition_task' of policy, the scenario is depicted below: Task A Task B /* 1st freq transition */ Invoke _begin() { ... ... } /* 2nd freq transition */ Invoke _begin() { ... //waiting for A to ... //clear ... //transition_ongoing ... //in _end() for ... //the 1st transition | Change the frequency | | Invoke _end() { | ... | ... | transition_ongoing = false; V transition_ongoing = true; transition_task = current; transition_task = NULL; ... //A overwrites the task ... //performing the transition ... //result in error warning. } To fix this race condition, the transition_lock of policy structure is now acquired before updating policy structure in _end() API. Which ensure that only one task can update the 'transition_task' field at a time. Link: https://lore.kernel.org/all/b3c61d8a-d52d-3136-fbf0-d1de9f1ba411@huawei.com/ Fixes: ca654dc3a93d ("cpufreq: Catch double invocations of cpufreq_freq_transition_begin/end") Signed-off-by: Liao Chang Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index bd7bb0d58ef0..d9eb036245c3 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -455,8 +455,10 @@ void cpufreq_freq_transition_end(struct cpufreq_policy *policy, policy->cur, policy->cpuinfo.max_freq); + spin_lock(&policy->transition_lock); policy->transition_ongoing = false; policy->transition_task = NULL; + spin_unlock(&policy->transition_lock); wake_up(&policy->transition_wait); } From 916f13884042f615cfbfc0b42cc68dadee826f2a Mon Sep 17 00:00:00 2001 From: Liao Chang Date: Tue, 29 Aug 2023 07:03:46 +0000 Subject: [PATCH 40/49] cpufreq: governor: Free dbs_data directly when gov->init() fails Due to the kobject embedded in the dbs_data doest not has a release() method yet, it needs to use kfree() to free dbs_data directly when governor fails to allocate the tunner field of dbs_data. Signed-off-by: Liao Chang Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq_governor.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 85da677c43d6..af44ee6a6430 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -439,7 +439,7 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) ret = gov->init(dbs_data); if (ret) - goto free_policy_dbs_info; + goto free_dbs_data; /* * The sampling interval should not be less than the transition latency @@ -474,6 +474,8 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) if (!have_governor_per_policy()) gov->gdbs_data = NULL; gov->exit(dbs_data); + +free_dbs_data: kfree(dbs_data); free_policy_dbs_info: From 4c2fdf7393647a7b01a83f49c4a331d562016640 Mon Sep 17 00:00:00 2001 From: Liao Chang Date: Sat, 26 Aug 2023 09:57:43 +0000 Subject: [PATCH 41/49] cpufreq: pcc: Fix the potentinal scheduling delays in target_index() pcc_cpufreq_target(): cpufreq_freq_transition_begin(); spin_lock(&pcc_lock); [critical section] cpufreq_freq_transition_end(); spin_unlock(&pcc_lock); Above code has a performance issue, consider that Task0 executes 'cpufreq_freq_transition_end()' to wake Task1 and preempted imediatedly without releasing 'pcc_lock', then Task1 needs to wait for Task0 to release 'pcc_lock'. In the worst case, this locking order can result in Task1 wasting two scheduling rounds before it can enter the critical section. Signed-off-by: Liao Chang Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/pcc-cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index 84fe37def0f1..6f8b5ea7aeae 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -232,8 +232,8 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy, status = ioread16(&pcch_hdr->status); iowrite16(0, &pcch_hdr->status); - cpufreq_freq_transition_end(policy, &freqs, status != CMD_COMPLETE); spin_unlock(&pcc_lock); + cpufreq_freq_transition_end(policy, &freqs, status != CMD_COMPLETE); if (status != CMD_COMPLETE) { pr_debug("target: FAILED for cpu %d, with status: 0x%x\n", From 218a06a79d9a98a96ef46bb003d4d8adb0962056 Mon Sep 17 00:00:00 2001 From: Jie Zhan Date: Tue, 22 Aug 2023 20:48:37 +0800 Subject: [PATCH 42/49] cpufreq: Support per-policy performance boost The boost control currently applies to the whole system. However, users may prefer to boost a subset of cores in order to provide prioritized performance to workloads running on the boosted cores. Enable per-policy boost by adding a 'boost' sysfs interface under each policy path. This can be found at: /sys/devices/system/cpu/cpufreq/policy<*>/boost Same to the global boost switch, writing 1/0 to the per-policy 'boost' enables/disables boost on a cpufreq policy respectively. The user view of global and per-policy boost controls should be: 1. Enabling global boost initially enables boost on all policies, and per-policy boost can then be enabled or disabled individually, given that the platform does support so. 2. Disabling global boost makes the per-policy boost interface illegal. Signed-off-by: Jie Zhan Reviewed-by: Wei Xu Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 43 +++++++++++++++++++++++++++++++++++++++ include/linux/cpufreq.h | 3 +++ 2 files changed, 46 insertions(+) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index d9eb036245c3..60ed89000e82 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -86,6 +86,7 @@ static void cpufreq_governor_limits(struct cpufreq_policy *policy); static int cpufreq_set_policy(struct cpufreq_policy *policy, struct cpufreq_governor *new_gov, unsigned int new_pol); +static bool cpufreq_boost_supported(void); /* * Two notifier lists: the "policy" list is involved in the @@ -623,6 +624,40 @@ static ssize_t store_boost(struct kobject *kobj, struct kobj_attribute *attr, } define_one_global_rw(boost); +static ssize_t show_local_boost(struct cpufreq_policy *policy, char *buf) +{ + return sysfs_emit(buf, "%d\n", policy->boost_enabled); +} + +static ssize_t store_local_boost(struct cpufreq_policy *policy, + const char *buf, size_t count) +{ + int ret, enable; + + ret = kstrtoint(buf, 10, &enable); + if (ret || enable < 0 || enable > 1) + return -EINVAL; + + if (!cpufreq_driver->boost_enabled) + return -EINVAL; + + if (policy->boost_enabled == enable) + return count; + + cpus_read_lock(); + ret = cpufreq_driver->set_boost(policy, enable); + cpus_read_unlock(); + + if (ret) + return ret; + + policy->boost_enabled = enable; + + return count; +} + +static struct freq_attr local_boost = __ATTR(boost, 0644, show_local_boost, store_local_boost); + static struct cpufreq_governor *find_governor(const char *str_governor) { struct cpufreq_governor *t; @@ -1057,6 +1092,12 @@ static int cpufreq_add_dev_interface(struct cpufreq_policy *policy) return ret; } + if (cpufreq_boost_supported()) { + ret = sysfs_create_file(&policy->kobj, &local_boost.attr); + if (ret) + return ret; + } + return 0; } @@ -2718,6 +2759,8 @@ int cpufreq_boost_trigger_state(int state) ret = cpufreq_driver->set_boost(policy, state); if (ret) goto err_reset_state; + + policy->boost_enabled = state; } cpus_read_unlock(); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 43b363a99215..71d186d6933a 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -141,6 +141,9 @@ struct cpufreq_policy { */ bool dvfs_possible_from_any_cpu; + /* Per policy boost enabled flag. */ + bool boost_enabled; + /* Cached frequency lookup from cpufreq_driver_resolve_freq. */ unsigned int cached_target_freq; unsigned int cached_resolved_idx; From 7a8817f2c96e98d5e65a59e34ba9ea1ff6ed23bc Mon Sep 17 00:00:00 2001 From: Miaohe Lin Date: Thu, 27 Jul 2023 19:56:43 +0800 Subject: [PATCH 43/49] mm: memory-failure: add PageOffline() check Memory failure is not interested in logically offlined pages. Skip this type of page. Link: https://lkml.kernel.org/r/20230727115643.639741-5-linmiaohe@huawei.com Signed-off-by: Miaohe Lin Acked-by: Naoya Horiguchi Cc: Kefeng Wang Cc: Matthew Wilcox (Oracle) Signed-off-by: Andrew Morton --- mm/memory-failure.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 881c35ef1daa..ed29d720ee76 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1562,7 +1562,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn, * Here we are interested only in user-mapped pages, so skip any * other types of pages. */ - if (PageReserved(p) || PageSlab(p) || PageTable(p)) + if (PageReserved(p) || PageSlab(p) || PageTable(p) || PageOffline(p)) return true; if (!(PageLRU(hpage) || PageHuge(p))) return true; @@ -2533,7 +2533,8 @@ int unpoison_memory(unsigned long pfn) goto unlock_mutex; } - if (folio_test_slab(folio) || PageTable(&folio->page) || folio_test_reserved(folio)) + if (folio_test_slab(folio) || PageTable(&folio->page) || + folio_test_reserved(folio) || PageOffline(&folio->page)) goto unlock_mutex; /* From 6885938c349c14b277305cd1129e7eb14f3e2c55 Mon Sep 17 00:00:00 2001 From: Jiaqi Yan Date: Thu, 13 Jul 2023 23:55:53 +0000 Subject: [PATCH 44/49] mm/hwpoison: rename hwp_walk* to hwpoison_walk* In the discussion of "Improve hugetlbfs read on HWPOISON hugepages" [1], Matthew Wilcox suggests hwp is a bad abbreviation of hwpoison, as hwp is already used as "an acronym by acpi, intel_pstate, some clock drivers, an ethernet driver, and a scsi driver"[1]. So rename hwp_walk and hwp_walk_ops to hwpoison_walk and hwpoison_walk_ops respectively. raw_hwp_(page|list), *_raw_hwp, and raw_hwp_unreliable flag are other major appearances of "hwp". However, given the "raw" hint in the name, it is easy to differentiate them from other "hwp" acronyms. Since renaming them is not as straightforward as renaming hwp_walk*, they are not covered by this commit. [1] https://lore.kernel.org/lkml/20230707201904.953262-5-jiaqiyan@google.com/T/#me6fecb8ce1ad4d5769199c9e162a44bc88f7bdec Link: https://lkml.kernel.org/r/20230713235553.4121855-1-jiaqiyan@google.com Signed-off-by: Jiaqi Yan Reviewed-by: Anshuman Khandual Acked-by: Naoya Horiguchi Cc: Matthew Wilcox (Oracle) Cc: Miaohe Lin Signed-off-by: Andrew Morton --- mm/memory-failure.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index ed29d720ee76..7b01fffe7a79 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -717,7 +717,7 @@ static void collect_procs(struct page *page, struct list_head *tokill, collect_procs_file(page, tokill, force_early); } -struct hwp_walk { +struct hwpoison_walk { struct to_kill tk; unsigned long pfn; int flags; @@ -752,7 +752,7 @@ static int check_hwpoisoned_entry(pte_t pte, unsigned long addr, short shift, #ifdef CONFIG_TRANSPARENT_HUGEPAGE static int check_hwpoisoned_pmd_entry(pmd_t *pmdp, unsigned long addr, - struct hwp_walk *hwp) + struct hwpoison_walk *hwp) { pmd_t pmd = *pmdp; unsigned long pfn; @@ -770,7 +770,7 @@ static int check_hwpoisoned_pmd_entry(pmd_t *pmdp, unsigned long addr, } #else static int check_hwpoisoned_pmd_entry(pmd_t *pmdp, unsigned long addr, - struct hwp_walk *hwp) + struct hwpoison_walk *hwp) { return 0; } @@ -779,7 +779,7 @@ static int check_hwpoisoned_pmd_entry(pmd_t *pmdp, unsigned long addr, static int hwpoison_pte_range(pmd_t *pmdp, unsigned long addr, unsigned long end, struct mm_walk *walk) { - struct hwp_walk *hwp = walk->private; + struct hwpoison_walk *hwp = walk->private; int ret = 0; pte_t *ptep, *mapped_pte; spinlock_t *ptl; @@ -813,7 +813,7 @@ static int hwpoison_hugetlb_range(pte_t *ptep, unsigned long hmask, unsigned long addr, unsigned long end, struct mm_walk *walk) { - struct hwp_walk *hwp = walk->private; + struct hwpoison_walk *hwp = walk->private; pte_t pte = huge_ptep_get(ptep); struct hstate *h = hstate_vma(walk->vma); @@ -824,7 +824,7 @@ static int hwpoison_hugetlb_range(pte_t *ptep, unsigned long hmask, #define hwpoison_hugetlb_range NULL #endif -static const struct mm_walk_ops hwp_walk_ops = { +static const struct mm_walk_ops hwpoison_walk_ops = { .pmd_entry = hwpoison_pte_range, .hugetlb_entry = hwpoison_hugetlb_range, .walk_lock = PGWALK_RDLOCK, @@ -847,7 +847,7 @@ static int kill_accessing_process(struct task_struct *p, unsigned long pfn, int flags) { int ret; - struct hwp_walk priv = { + struct hwpoison_walk priv = { .pfn = pfn, }; priv.tk.tsk = p; @@ -856,7 +856,7 @@ static int kill_accessing_process(struct task_struct *p, unsigned long pfn, return -EFAULT; mmap_read_lock(p->mm); - ret = walk_page_range(p->mm, 0, TASK_SIZE, &hwp_walk_ops, + ret = walk_page_range(p->mm, 0, TASK_SIZE, &hwpoison_walk_ops, (void *)&priv); if (ret == 1 && priv.tk.addr) kill_proc(&priv.tk, pfn, flags); From 8b47933544a68a62a9c4e35f8d8a6d2a2c935823 Mon Sep 17 00:00:00 2001 From: Stefan Roesch Date: Tue, 22 Aug 2023 11:05:39 -0700 Subject: [PATCH 45/49] proc/ksm: add ksm stats to /proc/pid/smaps With madvise and prctl KSM can be enabled for different VMA's. Once it is enabled we can query how effective KSM is overall. However we cannot easily query if an individual VMA benefits from KSM. This commit adds a KSM section to the /prod//smaps file. It reports how many of the pages are KSM pages. Note that KSM-placed zeropages are not included, only actual KSM pages. Here is a typical output: 7f420a000000-7f421a000000 rw-p 00000000 00:00 0 Size: 262144 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Rss: 51212 kB Pss: 8276 kB Shared_Clean: 172 kB Shared_Dirty: 42996 kB Private_Clean: 196 kB Private_Dirty: 7848 kB Referenced: 15388 kB Anonymous: 51212 kB KSM: 41376 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB FilePmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 202016 kB SwapPss: 3882 kB Locked: 0 kB THPeligible: 0 ProtectionKey: 0 ksm_state: 0 ksm_skip_base: 0 ksm_skip_count: 0 VmFlags: rd wr mr mw me nr mg anon This information also helps with the following workflow: - First enable KSM for all the VMA's of a process with prctl. - Then analyze with the above smaps report which VMA's benefit the most - Change the application (if possible) to add the corresponding madvise calls for the VMA's that benefit the most [shr@devkernel.io: v5] Link: https://lkml.kernel.org/r/20230823170107.1457915-1-shr@devkernel.io Link: https://lkml.kernel.org/r/20230822180539.1424843-1-shr@devkernel.io Signed-off-by: Stefan Roesch Reviewed-by: David Hildenbrand Cc: Johannes Weiner Cc: Rik van Riel Signed-off-by: Andrew Morton --- Documentation/filesystems/proc.rst | 4 ++++ fs/proc/task_mmu.c | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst index 7897a7dafcbc..d49af173b5af 100644 --- a/Documentation/filesystems/proc.rst +++ b/Documentation/filesystems/proc.rst @@ -461,6 +461,7 @@ Memory Area, or VMA) there is a series of lines such as the following:: Private_Dirty: 0 kB Referenced: 892 kB Anonymous: 0 kB + KSM: 0 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB @@ -501,6 +502,9 @@ accessed. a mapping associated with a file may contain anonymous pages: when MAP_PRIVATE and a page is modified, the file page is replaced by a private anonymous copy. +"KSM" reports how many of the pages are KSM pages. Note that KSM-placed zeropages +are not included, only actual KSM pages. + "LazyFree" shows the amount of memory which is marked by madvise(MADV_FREE). The memory isn't freed immediately with madvise(). It's freed in memory pressure if the memory is clean. Please note that the printed value might diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 15ddf4653a19..5fc732cb2350 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -396,6 +397,7 @@ struct mem_size_stats { unsigned long swap; unsigned long shared_hugetlb; unsigned long private_hugetlb; + unsigned long ksm; u64 pss; u64 pss_anon; u64 pss_file; @@ -452,6 +454,9 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page, mss->lazyfree += size; } + if (PageKsm(page)) + mss->ksm += size; + mss->resident += size; /* Accumulate the size in pages that have been accessed. */ if (young || page_is_young(page) || PageReferenced(page)) @@ -822,6 +827,7 @@ static void __show_smap(struct seq_file *m, const struct mem_size_stats *mss, SEQ_PUT_DEC(" kB\nPrivate_Dirty: ", mss->private_dirty); SEQ_PUT_DEC(" kB\nReferenced: ", mss->referenced); SEQ_PUT_DEC(" kB\nAnonymous: ", mss->anonymous); + SEQ_PUT_DEC(" kB\nKSM: ", mss->ksm); SEQ_PUT_DEC(" kB\nLazyFree: ", mss->lazyfree); SEQ_PUT_DEC(" kB\nAnonHugePages: ", mss->anonymous_thp); SEQ_PUT_DEC(" kB\nShmemPmdMapped: ", mss->shmem_thp); From 6ad11bc6ed37c6371e9e13619862709b6529b43a Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 24 Aug 2023 14:38:08 +0300 Subject: [PATCH 46/49] rmap: remove anon_vma_link() nommu stub anon_vma_link() is unused since commit 5beb49305251 ("mm: change anon_vma linking to fix multi-process server scalability issue"). Link: https://lkml.kernel.org/r/cdce9b00c9ab15f6d02eddf40dcad537d3e9676f.1692877089.git.baruch@tkos.co.il Signed-off-by: Baruch Siach Reviewed-by: David Hildenbrand Signed-off-by: Andrew Morton --- include/linux/rmap.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/rmap.h b/include/linux/rmap.h index a3825ce81102..51cc21ebb568 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -479,7 +479,6 @@ struct anon_vma *folio_lock_anon_vma_read(struct folio *folio, #define anon_vma_init() do {} while (0) #define anon_vma_prepare(vma) (0) -#define anon_vma_link(vma) do {} while (0) static inline int folio_referenced(struct folio *folio, int is_locked, struct mem_cgroup *memcg, From 12af80f6c9f2daf07bc3125605dc2e454db321a5 Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Thu, 24 Aug 2023 14:38:09 +0300 Subject: [PATCH 47/49] MAINTAINERS: add rmap.h to mm entry Make it easier to figure out where to send patches for this file. Link: https://lkml.kernel.org/r/efbc7689d35a48ff402644d696aa9a8d8bb6333a.1692877089.git.baruch@tkos.co.il Signed-off-by: Baruch Siach Reviewed-by: David Hildenbrand Signed-off-by: Andrew Morton --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 6849f4994787..70f773562053 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13622,6 +13622,7 @@ F: include/linux/memory_hotplug.h F: include/linux/mm.h F: include/linux/mmzone.h F: include/linux/pagewalk.h +F: include/linux/rmap.h F: include/trace/events/ksm.h F: mm/ F: tools/mm/ From f945116e4e191cd543ecd56d9f13e6331494847c Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Thu, 24 Aug 2023 11:38:21 -0400 Subject: [PATCH 48/49] mm: page_alloc: remove stale CMA guard code In the past, movable allocations could be disallowed from CMA through PF_MEMALLOC_PIN. As CMA pages are funneled through the MOVABLE pcplist, this required filtering that cornercase during allocations, such that pinnable allocations wouldn't accidentally get a CMA page. However, since 8e3560d963d2 ("mm: honor PF_MEMALLOC_PIN for all movable pages"), PF_MEMALLOC_PIN automatically excludes __GFP_MOVABLE. Once again, MOVABLE implies CMA is allowed. Remove the stale filtering code. Also remove a stale comment that was introduced as part of the filtering code, because the filtering let order-0 pages fall through to the buddy allocator. See 1d91df85f399 ("mm/page_alloc: handle a missing case for memalloc_nocma_{save/restore} APIs") for context. The comment's been obsolete since the introduction of the explicit ALLOC_HIGHATOMIC flag in eb2e2b425c69 ("mm/page_alloc: explicitly record high-order atomic allocations in alloc_flags"). Link: https://lkml.kernel.org/r/20230824153821.243148-1-hannes@cmpxchg.org Signed-off-by: Johannes Weiner Acked-by: Mel Gorman Cc: David Hildenbrand Cc: Joonsoo Kim Cc: Miaohe Lin Cc: Pasha Tatashin Cc: Vlastimil Babka Signed-off-by: Andrew Morton --- mm/page_alloc.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 452459836b71..0c5be12f9336 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2641,12 +2641,6 @@ struct page *rmqueue_buddy(struct zone *preferred_zone, struct zone *zone, do { page = NULL; spin_lock_irqsave(&zone->lock, flags); - /* - * order-0 request can reach here when the pcplist is skipped - * due to non-CMA allocation context. HIGHATOMIC area is - * reserved for high-order atomic allocation, so order-0 - * request should skip it. - */ if (alloc_flags & ALLOC_HIGHATOMIC) page = __rmqueue_smallest(zone, order, MIGRATE_HIGHATOMIC); if (!page) { @@ -2780,17 +2774,10 @@ struct page *rmqueue(struct zone *preferred_zone, WARN_ON_ONCE((gfp_flags & __GFP_NOFAIL) && (order > 1)); if (likely(pcp_allowed_order(order))) { - /* - * MIGRATE_MOVABLE pcplist could have the pages on CMA area and - * we need to skip it when CMA area isn't allowed. - */ - if (!IS_ENABLED(CONFIG_CMA) || alloc_flags & ALLOC_CMA || - migratetype != MIGRATE_MOVABLE) { - page = rmqueue_pcplist(preferred_zone, zone, order, - migratetype, alloc_flags); - if (likely(page)) - goto out; - } + page = rmqueue_pcplist(preferred_zone, zone, order, + migratetype, alloc_flags); + if (likely(page)) + goto out; } page = rmqueue_buddy(preferred_zone, zone, order, alloc_flags, From e68d343d2720779362cb7160cb7f4bd24979b2b4 Mon Sep 17 00:00:00 2001 From: Waiman Long Date: Fri, 25 Aug 2023 12:49:47 -0400 Subject: [PATCH 49/49] mm/kmemleak: move up cond_resched() call in page scanning loop Commit bde5f6bc68db ("kmemleak: add scheduling point to kmemleak_scan()") added a cond_resched() call to the struct page scanning loop to prevent soft lockup from happening. However, soft lockup can still happen in that loop in some corner cases when the pages that satisfy the "!(pfn & 63)" check are skipped for some reasons. Fix this corner case by moving up the cond_resched() check so that it will be called every 64 pages unconditionally. Link: https://lkml.kernel.org/r/20230825164947.1317981-1-longman@redhat.com Fixes: bde5f6bc68db ("kmemleak: add scheduling point to kmemleak_scan()") Signed-off-by: Waiman Long Cc: Catalin Marinas Cc: Yisheng Xie Signed-off-by: Andrew Morton --- mm/kmemleak.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mm/kmemleak.c b/mm/kmemleak.c index 2918150e31bd..54c2c90d3abc 100644 --- a/mm/kmemleak.c +++ b/mm/kmemleak.c @@ -1584,6 +1584,9 @@ static void kmemleak_scan(void) for (pfn = start_pfn; pfn < end_pfn; pfn++) { struct page *page = pfn_to_online_page(pfn); + if (!(pfn & 63)) + cond_resched(); + if (!page) continue; @@ -1594,8 +1597,6 @@ static void kmemleak_scan(void) if (page_count(page) == 0) continue; scan_block(page, page + 1, NULL); - if (!(pfn & 63)) - cond_resched(); } } put_online_mems();