Merge tag 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 24 Mar 2022 00:35:57 +0000 (17:35 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 24 Mar 2022 00:35:57 +0000 (17:35 -0700)
Pull ARM updates from Russell King:
 "Updates for IRQ stacks and virtually mapped stack support, and ftrace:

   - Support for IRQ and vmap'ed stacks

     This covers all the work related to implementing IRQ stacks and
     vmap'ed stacks for all 32-bit ARM systems that are currently
     supported by the Linux kernel, including RiscPC and Footbridge. It
     has been submitted for review in four different waves:

      - IRQ stacks support for v7 SMP systems [0]

      - vmap'ed stacks support for v7 SMP systems[1]

      - extending support for both IRQ stacks and vmap'ed stacks for all
        remaining configurations, including v6/v7 SMP multiplatform
        kernels and uniprocessor configurations including v7-M [2]

      - fixes and updates in [3]

   - ftrace fixes and cleanups

     Make all flavors of ftrace available on all builds, regardless of
     ISA choice, unwinder choice or compiler [4]:

      - use ADD not POP where possible

      - fix a couple of Thumb2 related issues

      - enable HAVE_FUNCTION_GRAPH_FP_TEST for robustness

      - enable the graph tracer with the EABI unwinder

      - avoid clobbering frame pointer registers to make Clang happy

   - Fixes for the above"

[0] https://lore.kernel.org/linux-arm-kernel/20211115084732.3704393-1-ardb@kernel.org/
[1] https://lore.kernel.org/linux-arm-kernel/20211122092816.2865873-1-ardb@kernel.org/
[2] https://lore.kernel.org/linux-arm-kernel/20211206164659.1495084-1-ardb@kernel.org/
[3] https://lore.kernel.org/linux-arm-kernel/20220124174744.1054712-1-ardb@kernel.org/
[4] https://lore.kernel.org/linux-arm-kernel/20220203082204.1176734-1-ardb@kernel.org/

* tag 'for-linus' of git://git.armlinux.org.uk/~rmk/linux-arm: (62 commits)
  ARM: fix building NOMMU ARMv4/v5 kernels
  ARM: unwind: only permit stack switch when unwinding call_with_stack()
  ARM: Revert "unwind: dump exception stack from calling frame"
  ARM: entry: fix unwinder problems caused by IRQ stacks
  ARM: unwind: set frame.pc correctly for current-thread unwinding
  ARM: 9184/1: return_address: disable again for CONFIG_ARM_UNWIND=y
  ARM: 9183/1: unwind: avoid spurious warnings on bogus code addresses
  Revert "ARM: 9144/1: forbid ftrace with clang and thumb2_kernel"
  ARM: mach-bcm: disable ftrace in SMC invocation routines
  ARM: cacheflush: avoid clobbering the frame pointer
  ARM: kprobes: treat R7 as the frame pointer register in Thumb2 builds
  ARM: ftrace: enable the graph tracer with the EABI unwinder
  ARM: unwind: track location of LR value in stack frame
  ARM: ftrace: enable HAVE_FUNCTION_GRAPH_FP_TEST
  ARM: ftrace: avoid unnecessary literal loads
  ARM: ftrace: avoid redundant loads or clobbering IP
  ARM: ftrace: use trampolines to keep .init.text in branching range
  ARM: ftrace: use ADD not POP to counter PUSH at entry
  ARM: ftrace: ensure that ADR takes the Thumb bit into account
  ARM: make get_current() and __my_cpu_offset() __always_inline
  ...

14 files changed:
1  2 
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/boot/compressed/Makefile
arch/arm/include/asm/assembler.h
arch/arm/include/asm/cacheflush.h
arch/arm/include/asm/switch_to.h
arch/arm/kernel/Makefile
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/smp.c
arch/arm/kernel/traps.c
arch/arm/mm/Kconfig
arch/arm/mm/ioremap.c
drivers/irqchip/irq-nvic.c

@@@ -94,8 -91,9 +95,8 @@@ config AR
        select HAVE_EXIT_THREAD
        select HAVE_FAST_GUP if ARM_LPAE
        select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL
-       select HAVE_FUNCTION_GRAPH_TRACER if !THUMB2_KERNEL && !CC_IS_CLANG
-       select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !(THUMB2_KERNEL && CC_IS_CLANG)
+       select HAVE_FUNCTION_GRAPH_TRACER
+       select HAVE_FUNCTION_TRACER if !XIP_KERNEL
 -      select HAVE_FUTEX_CMPXCHG if FUTEX
        select HAVE_GCC_PLUGINS
        select HAVE_HW_BREAKPOINT if PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7)
        select HAVE_IRQ_TIME_ACCOUNTING
@@@ -481,7 -481,7 +484,6 @@@ config ARCH_S3C24X
        select CLKSRC_SAMSUNG_PWM
        select GPIO_SAMSUNG
        select GPIOLIB
-       select GENERIC_IRQ_MULTI_HANDLER
 -      select HAVE_S3C2410_I2C if I2C
        select NEED_MACH_IO_H
        select S3C2410_WATCHDOG
        select SAMSUNG_ATAGS
@@@ -65,7 -65,9 +65,7 @@@ config UNWINDER_FRAME_POINTE
  
  config UNWINDER_ARM
        bool "ARM EABI stack unwinder"
-       depends on AEABI && !FUNCTION_GRAPH_TRACER
+       depends on AEABI
 -      # https://github.com/ClangBuiltLinux/linux/issues/732
 -      depends on !LD_IS_LLD || LLD_VERSION >= 110000
        select ARM_UNWIND
        help
          This option enables stack unwinding support in the kernel
@@@ -92,14 -93,12 +92,9 @@@ ifeq ($(CONFIG_USE_OF),y
  OBJS  += $(libfdt_objs) fdt_check_mem_start.o
  endif
  
- # -fstack-protector-strong triggers protection checks in this code,
- # but it is being used too early to link to meaningful stack_chk logic.
- $(foreach o, $(libfdt_objs) atags_to_fdt.o fdt_check_mem_start.o, \
-       $(eval CFLAGS_$(o) := -I $(srctree)/scripts/dtc/libfdt -fno-stack-protector))
  targets       := vmlinux vmlinux.lds piggy_data piggy.o \
 -               lib1funcs.o ashldi3.o bswapsdi2.o \
                 head.o $(OBJS)
  
 -clean-files += lib1funcs.S ashldi3.S bswapsdi2.S hyp-stub.S
 -
  KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
  
  ccflags-y := -fpic $(call cc-option,-mno-single-pic-base,) -fno-builtin \
Simple merge
Simple merge
@@@ -26,7 -27,21 +27,7 @@@ extern struct task_struct *__switch_to(
  #define switch_to(prev,next,last)                                     \
  do {                                                                  \
        __complete_pending_tlbi();                                      \
-       if (IS_ENABLED(CONFIG_CURRENT_POINTER_IN_TPIDRURO))             \
 -      set_ti_cpu(next);                                               \
+       if (IS_ENABLED(CONFIG_CURRENT_POINTER_IN_TPIDRURO) || is_smp()) \
                __this_cpu_write(__entry_task, next);                   \
        last = __switch_to(prev,task_thread_info(prev), task_thread_info(next));        \
  } while (0)
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -68,10 -66,20 +67,23 @@@ void dump_backtrace_entry(unsigned lon
  {
        unsigned long end = frame + 4 + sizeof(struct pt_regs);
  
 -#ifdef CONFIG_KALLSYMS
+       if (IS_ENABLED(CONFIG_UNWINDER_FRAME_POINTER) &&
+           IS_ENABLED(CONFIG_CC_IS_GCC) &&
+           end > ALIGN(frame, THREAD_SIZE)) {
+               /*
+                * If we are walking past the end of the stack, it may be due
+                * to the fact that we are on an IRQ or overflow stack. In this
+                * case, we can load the address of the other stack from the
+                * frame record.
+                */
+               frame = ((unsigned long *)frame)[-2] - 4;
+               end = frame + 4 + sizeof(struct pt_regs);
+       }
 +#ifndef CONFIG_KALLSYMS
 +      printk("%sFunction entered at [<%08lx>] from [<%08lx>]\n",
 +              loglvl, where, from);
 +#elif defined CONFIG_BACKTRACE_VERBOSE
        printk("%s[<%08lx>] (%ps) from [<%08lx>] (%pS)\n",
                loglvl, where, (void *)where, from, (void *)from);
  #else
@@@ -878,5 -837,72 +892,72 @@@ void __init early_trap_init(void *vecto
         * memory area. The address is configurable and so a table in the kernel
         * image can be used.
         */
 -#endif
  }
 +#endif
+ #ifdef CONFIG_VMAP_STACK
+ DECLARE_PER_CPU(u8 *, irq_stack_ptr);
+ asmlinkage DEFINE_PER_CPU(u8 *, overflow_stack_ptr);
+ static int __init allocate_overflow_stacks(void)
+ {
+       u8 *stack;
+       int cpu;
+       for_each_possible_cpu(cpu) {
+               stack = (u8 *)__get_free_page(GFP_KERNEL);
+               if (WARN_ON(!stack))
+                       return -ENOMEM;
+               per_cpu(overflow_stack_ptr, cpu) = &stack[OVERFLOW_STACK_SIZE];
+       }
+       return 0;
+ }
+ early_initcall(allocate_overflow_stacks);
+ asmlinkage void handle_bad_stack(struct pt_regs *regs)
+ {
+       unsigned long tsk_stk = (unsigned long)current->stack;
+ #ifdef CONFIG_IRQSTACKS
+       unsigned long irq_stk = (unsigned long)this_cpu_read(irq_stack_ptr);
+ #endif
+       unsigned long ovf_stk = (unsigned long)this_cpu_read(overflow_stack_ptr);
+       console_verbose();
+       pr_emerg("Insufficient stack space to handle exception!");
+       pr_emerg("Task stack:     [0x%08lx..0x%08lx]\n",
+                tsk_stk, tsk_stk + THREAD_SIZE);
+ #ifdef CONFIG_IRQSTACKS
+       pr_emerg("IRQ stack:      [0x%08lx..0x%08lx]\n",
+                irq_stk - THREAD_SIZE, irq_stk);
+ #endif
+       pr_emerg("Overflow stack: [0x%08lx..0x%08lx]\n",
+                ovf_stk - OVERFLOW_STACK_SIZE, ovf_stk);
+       die("kernel stack overflow", regs, 0);
+ }
+ #ifndef CONFIG_ARM_LPAE
+ /*
+  * Normally, we rely on the logic in do_translation_fault() to update stale PMD
+  * entries covering the vmalloc space in a task's page tables when it first
+  * accesses the region in question. Unfortunately, this is not sufficient when
+  * the task stack resides in the vmalloc region, as do_translation_fault() is a
+  * C function that needs a stack to run.
+  *
+  * So we need to ensure that these PMD entries are up to date *before* the MM
+  * switch. As we already have some logic in the MM switch path that takes care
+  * of this, let's trigger it by bumping the counter every time the core vmalloc
+  * code modifies a PMD entry in the vmalloc region. Use release semantics on
+  * the store so that other CPUs observing the counter's new value are
+  * guaranteed to see the updated page table entries as well.
+  */
+ void arch_sync_kernel_mappings(unsigned long start, unsigned long end)
+ {
+       if (start < VMALLOC_END && end > VMALLOC_START)
+               atomic_inc_return_release(&init_mm.context.vmalloc_seq);
+ }
+ #endif
+ #endif
Simple merge
Simple merge
Simple merge