Merge tag 'trace-v5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Nov 2019 19:42:01 +0000 (11:42 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Nov 2019 19:42:01 +0000 (11:42 -0800)
Pull tracing updates from Steven Rostedt:
 "New tracing features:

   - New PERMANENT flag to ftrace_ops when attaching a callback to a
     function.

     As /proc/sys/kernel/ftrace_enabled when set to zero will disable
     all attached callbacks in ftrace, this has a detrimental impact on
     live kernel tracing, as it disables all that it patched. If a
     ftrace_ops is registered to ftrace with the PERMANENT flag set, it
     will prevent ftrace_enabled from being disabled, and if
     ftrace_enabled is already disabled, it will prevent a ftrace_ops
     with PREMANENT flag set from being registered.

   - New register_ftrace_direct().

     As eBPF would like to register its own trampolines to be called by
     the ftrace nop locations directly, without going through the ftrace
     trampoline, this function has been added. This allows for eBPF
     trampolines to live along side of ftrace, perf, kprobe and live
     patching. It also utilizes the ftrace enabled_functions file that
     keeps track of functions that have been modified in the kernel, to
     allow for security auditing.

   - Allow for kernel internal use of ftrace instances.

     Subsystems in the kernel can now create and destroy their own
     tracing instances which allows them to have their own tracing
     buffer, and be able to record events without worrying about other
     users from writing over their data.

   - New seq_buf_hex_dump() that lets users use the hex_dump() in their
     seq_buf usage.

   - Notifications now added to tracing_max_latency to allow user space
     to know when a new max latency is hit by one of the latency
     tracers.

   - Wider spread use of generic compare operations for use of bsearch
     and friends.

   - More synthetic event fields may be defined (32 up from 16)

   - Use of xarray for architectures with sparse system calls, for the
     system call trace events.

  This along with small clean ups and fixes"

* tag 'trace-v5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: (51 commits)
  tracing: Enable syscall optimization for MIPS
  tracing: Use xarray for syscall trace events
  tracing: Sample module to demonstrate kernel access to Ftrace instances.
  tracing: Adding new functions for kernel access to Ftrace instances
  tracing: Fix Kconfig indentation
  ring-buffer: Fix typos in function ring_buffer_producer
  ftrace: Use BIT() macro
  ftrace: Return ENOTSUPP when DYNAMIC_FTRACE_WITH_DIRECT_CALLS is not configured
  ftrace: Rename ftrace_graph_stub to ftrace_stub_graph
  ftrace: Add a helper function to modify_ftrace_direct() to allow arch optimization
  ftrace: Add helper find_direct_entry() to consolidate code
  ftrace: Add another check for match in register_ftrace_direct()
  ftrace: Fix accounting bug with direct->count in register_ftrace_direct()
  ftrace/selftests: Fix spelling mistake "wakeing" -> "waking"
  tracing: Increase SYNTH_FIELDS_MAX for synthetic_events
  ftrace/samples: Add a sample module that implements modify_ftrace_direct()
  ftrace: Add modify_ftrace_direct()
  tracing: Add missing "inline" in stub function of latency_fsnotify()
  tracing: Remove stray tab in TRACE_EVAL_MAP_FILE's help text
  tracing: Use seq_buf_hex_dump() to dump buffers
  ...

12 files changed:
1  2 
arch/Kconfig
arch/mips/Kconfig
arch/x86/Kconfig
arch/x86/kernel/ftrace_64.S
include/asm-generic/vmlinux.lds.h
include/linux/ftrace.h
kernel/module.c
kernel/trace/Kconfig
kernel/trace/ftrace.c
samples/Kconfig
samples/Makefile
tools/testing/selftests/livepatch/Makefile

diff --combined arch/Kconfig
index 8bcc1c746142bc80b65ce64c98fd68d6638f8352,69c87e8608d8145b5f9e5d4e898be6f796f4af87..17c42bc363211c04dfb285bb8d2644253ba78311
@@@ -892,6 -892,27 +892,6 @@@ config STRICT_MODULE_RW
  config ARCH_HAS_PHYS_TO_DMA
        bool
  
 -config ARCH_HAS_REFCOUNT
 -      bool
 -      help
 -        An architecture selects this when it has implemented refcount_t
 -        using open coded assembly primitives that provide an optimized
 -        refcount_t implementation, possibly at the expense of some full
 -        refcount state checks of CONFIG_REFCOUNT_FULL=y.
 -
 -        The refcount overflow check behavior, however, must be retained.
 -        Catching overflows is the primary security concern for protecting
 -        against bugs in reference counts.
 -
 -config REFCOUNT_FULL
 -      bool "Perform full reference count validation at the expense of speed"
 -      help
 -        Enabling this switches the refcounting infrastructure from a fast
 -        unchecked atomic_t implementation to a fully state checked
 -        implementation, which can be (slightly) slower but provides protections
 -        against various use-after-free conditions that can be used in
 -        security flaw exploits.
 -
  config HAVE_ARCH_COMPILER_H
        bool
        help
@@@ -939,6 -960,14 +939,14 @@@ config REL
  config ARCH_HAS_MEM_ENCRYPT
        bool
  
+ config HAVE_SPARSE_SYSCALL_NR
+        bool
+        help
+           An architecture should select this if its syscall numbering is sparse
+         to save space. For example, MIPS architecture has a syscall array with
+         entries at 4000, 5000 and 6000 locations. This option turns on syscall
+         related optimizations for a given architecture.
  source "kernel/gcov/Kconfig"
  
  source "scripts/gcc-plugins/Kconfig"
diff --combined arch/mips/Kconfig
index c86be02b6d89c12f235aff0ff80d20c5a1e44f47,c7f59c4a00d8a0976d397fd200b19887dbc0943f..61b9269cdd3eb3d9022c1ad35eff5acf2453e8c4
@@@ -7,7 -7,6 +7,7 @@@ config MIP
        select ARCH_CLOCKSOURCE_DATA
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
        select ARCH_HAS_UBSAN_SANITIZE_ALL
 +      select ARCH_HAS_FORTIFY_SOURCE
        select ARCH_SUPPORTS_UPROBES
        select ARCH_USE_BUILTIN_BSWAP
        select ARCH_USE_CMPXCHG_LOCKREF if 64BIT
@@@ -74,6 -73,7 +74,7 @@@
        select HAVE_PERF_EVENTS
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_RSEQ
+       select HAVE_SPARSE_SYSCALL_NR
        select HAVE_STACKPROTECTOR
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_VIRT_CPU_ACCOUNTING_GEN if 64BIT || !SMP
@@@ -87,8 -87,6 +88,8 @@@
        select SYSCTL_EXCEPTION_TRACE
        select VIRT_TO_BUS
        select ARCH_HAS_PTE_SPECIAL if !(32BIT && CPU_HAS_RIXI)
 +      select ARCH_HAS_KCOV
 +      select HAVE_GCC_PLUGINS
  
  menu "Machine selection"
  
@@@ -362,8 -360,6 +363,8 @@@ config MACH_DECSTATIO
  
  config MACH_JAZZ
        bool "Jazz family of machines"
 +      select ARC_MEMORY
 +      select ARC_PROMLIB
        select ARCH_MIGHT_HAVE_PC_PARPORT
        select ARCH_MIGHT_HAVE_PC_SERIO
        select FW_ARC
@@@ -446,7 -442,7 +447,7 @@@ config LASA
        select SYS_SUPPORTS_LITTLE_ENDIAN
  
  config MACH_LOONGSON32
 -      bool "Loongson-1 family of machines"
 +      bool "Loongson 32-bit family of machines"
        select SYS_SUPPORTS_ZBOOT
        help
          This enables support for the Loongson-1 family of machines.
          the Institute of Computing Technology (ICT), Chinese Academy of
          Sciences (CAS).
  
 +config MACH_LOONGSON2EF
 +      bool "Loongson-2E/F family of machines"
 +      select SYS_SUPPORTS_ZBOOT
 +      help
 +        This enables the support of early Loongson-2E/F family of machines.
 +
  config MACH_LOONGSON64
 -      bool "Loongson-2/3 family of machines"
 +      bool "Loongson 64-bit family of machines"
 +      select ARCH_SPARSEMEM_ENABLE
 +      select ARCH_MIGHT_HAVE_PC_PARPORT
 +      select ARCH_MIGHT_HAVE_PC_SERIO
 +      select GENERIC_ISA_DMA_SUPPORT_BROKEN
 +      select BOOT_ELF32
 +      select BOARD_SCACHE
 +      select CSRC_R4K
 +      select CEVT_R4K
 +      select CPU_HAS_WB
 +      select FORCE_PCI
 +      select ISA
 +      select I8259
 +      select IRQ_MIPS_CPU
 +      select NR_CPUS_DEFAULT_4
 +      select USE_GENERIC_EARLY_PRINTK_8250
 +      select SYS_HAS_CPU_LOONGSON64
 +      select SYS_HAS_EARLY_PRINTK
 +      select SYS_SUPPORTS_SMP
 +      select SYS_SUPPORTS_HOTPLUG_CPU
 +      select SYS_SUPPORTS_NUMA
 +      select SYS_SUPPORTS_64BIT_KERNEL
 +      select SYS_SUPPORTS_HIGHMEM
 +      select SYS_SUPPORTS_LITTLE_ENDIAN
        select SYS_SUPPORTS_ZBOOT
 +      select LOONGSON_MC146818
 +      select ZONE_DMA32
 +      select NUMA
        help
          This enables the support of Loongson-2/3 family of machines.
  
 -        Loongson-2 is a family of single-core CPUs and Loongson-3 is a
 -        family of multi-core CPUs. They are both 64-bit general-purpose
 -        MIPS-compatible CPUs. Loongson-2/3 are developed by the Institute
 -        of Computing Technology (ICT), Chinese Academy of Sciences (CAS)
 -        in the People's Republic of China. The chief architect is Professor
 -        Weiwu Hu.
 +        Loongson-2 and Loongson-3 are 64-bit general-purpose processors with
 +        GS264/GS464/GS464E/GS464V microarchitecture (except old Loongson-2E
 +        and Loongson-2F which will be removed), developed by the Institute
 +        of Computing Technology (ICT), Chinese Academy of Sciences (CAS).
  
  config MACH_PISTACHIO
        bool "IMG Pistachio SoC based boards"
@@@ -666,8 -632,6 +667,8 @@@ config RALIN
  
  config SGI_IP22
        bool "SGI IP22 (Indy/Indigo2)"
 +      select ARC_MEMORY
 +      select ARC_PROMLIB
        select FW_ARC
        select FW_ARC32
        select ARCH_MIGHT_HAVE_PC_SERIO
        select SWAP_IO_SPACE
        select SYS_HAS_CPU_R4X00
        select SYS_HAS_CPU_R5000
 -      #
 -      # Disable EARLY_PRINTK for now since it leads to overwritten prom
 -      # memory during early boot on some machines.
 -      #
 -      # See http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=20091119164009.GA15038%40deprecation.cyrius.com
 -      # for a more details discussion
 -      #
 -      # select SYS_HAS_EARLY_PRINTK
 +      select SYS_HAS_EARLY_PRINTK
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
  config SGI_IP27
        bool "SGI IP27 (Origin200/2000)"
        select ARCH_HAS_PHYS_TO_DMA
 +      select ARCH_SPARSEMEM_ENABLE
        select FW_ARC
        select FW_ARC64
 +      select ARC_CMDLINE_ONLY
        select BOOT_ELF64
        select DEFAULT_SGI_PARTITION
        select SYS_HAS_EARLY_PRINTK
  
  config SGI_IP28
        bool "SGI IP28 (Indigo2 R10k)"
 +      select ARC_MEMORY
 +      select ARC_PROMLIB
        select FW_ARC
        select FW_ARC64
        select ARCH_MIGHT_HAVE_PC_SERIO
        select SGI_HAS_ZILOG
        select SWAP_IO_SPACE
        select SYS_HAS_CPU_R10000
 -      #
 -      # Disable EARLY_PRINTK for now since it leads to overwritten prom
 -      # memory during early boot on some machines.
 -      #
 -      # See http://www.linux-mips.org/cgi-bin/mesg.cgi?a=linux-mips&i=20091119164009.GA15038%40deprecation.cyrius.com
 -      # for a more details discussion
 -      #
 -      # select SYS_HAS_EARLY_PRINTK
 +      select SYS_HAS_EARLY_PRINTK
        select SYS_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_BIG_ENDIAN
        select MIPS_L1_CACHE_SHIFT_7
          This is the SGI Indigo2 with R10000 processor.  To compile a Linux
          kernel that runs on these, say Y here.
  
 +config SGI_IP30
 +      bool "SGI IP30 (Octane/Octane2)"
 +      select ARCH_HAS_PHYS_TO_DMA
 +      select FW_ARC
 +      select FW_ARC64
 +      select BOOT_ELF64
 +      select CEVT_R4K
 +      select CSRC_R4K
 +      select SYNC_R4K if SMP
 +      select ZONE_DMA32
 +      select HAVE_PCI
 +      select IRQ_MIPS_CPU
 +      select IRQ_DOMAIN_HIERARCHY
 +      select NR_CPUS_DEFAULT_2
 +      select PCI_DRIVERS_GENERIC
 +      select PCI_XTALK_BRIDGE
 +      select SYS_HAS_EARLY_PRINTK
 +      select SYS_HAS_CPU_R10000
 +      select SYS_SUPPORTS_64BIT_KERNEL
 +      select SYS_SUPPORTS_BIG_ENDIAN
 +      select SYS_SUPPORTS_SMP
 +      select MIPS_L1_CACHE_SHIFT_7
 +      select ARC_MEMORY
 +      help
 +        These are the SGI Octane and Octane2 graphics workstations.  To
 +        compile a Linux kernel that runs on these, say Y here.
 +
  config SGI_IP32
        bool "SGI IP32 (O2)"
 +      select ARC_MEMORY
 +      select ARC_PROMLIB
        select ARCH_HAS_PHYS_TO_DMA
        select FW_ARC
        select FW_ARC32
@@@ -899,8 -844,6 +900,8 @@@ config SIBYTE_BIGSU
  
  config SNI_RM
        bool "SNI RM200/300/400"
 +      select ARC_MEMORY
 +      select ARC_PROMLIB
        select FW_ARC if CPU_LITTLE_ENDIAN
        select FW_ARC32 if CPU_LITTLE_ENDIAN
        select FW_SNIPROM if CPU_BIG_ENDIAN
@@@ -1096,7 -1039,6 +1097,7 @@@ source "arch/mips/sibyte/Kconfig
  source "arch/mips/txx9/Kconfig"
  source "arch/mips/vr41xx/Kconfig"
  source "arch/mips/cavium-octeon/Kconfig"
 +source "arch/mips/loongson2ef/Kconfig"
  source "arch/mips/loongson32/Kconfig"
  source "arch/mips/loongson64/Kconfig"
  source "arch/mips/netlogic/Kconfig"
@@@ -1412,18 -1354,19 +1413,18 @@@ config MIPS_L1_CACHE_SHIF
  config HAVE_STD_PC_SERIAL_PORT
        bool
  
 +config ARC_CMDLINE_ONLY
 +      bool
 +
  config ARC_CONSOLE
        bool "ARC console support"
        depends on SGI_IP22 || SGI_IP28 || (SNI_RM && CPU_LITTLE_ENDIAN)
  
  config ARC_MEMORY
        bool
 -      depends on MACH_JAZZ || SNI_RM || SGI_IP32
 -      default y
  
  config ARC_PROMLIB
        bool
 -      depends on MACH_JAZZ || SNI_RM || SGI_IP22 || SGI_IP28 || SGI_IP32
 -      default y
  
  config FW_ARC64
        bool
@@@ -1437,56 -1380,51 +1438,56 @@@ choic
        prompt "CPU type"
        default CPU_R4X00
  
 -config CPU_LOONGSON3
 -      bool "Loongson 3 CPU"
 -      depends on SYS_HAS_CPU_LOONGSON3
 +config CPU_LOONGSON64
 +      bool "Loongson 64-bit CPU"
 +      depends on SYS_HAS_CPU_LOONGSON64
        select ARCH_HAS_PHYS_TO_DMA
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
        select CPU_SUPPORTS_HUGEPAGES
 +      select CPU_SUPPORTS_MSA
        select CPU_HAS_LOAD_STORE_LR
        select WEAK_ORDERING
        select WEAK_REORDERING_BEYOND_LLSC
 +      select MIPS_ASID_BITS_VARIABLE
        select MIPS_PGD_C0_CONTEXT
        select MIPS_L1_CACHE_SHIFT_6
        select GPIOLIB
        select SWIOTLB
        help
 -              The Loongson 3 processor implements the MIPS64R2 instruction
 -              set with many extensions.
 +              The Loongson GSx64(GS264/GS464/GS464E/GS464V) series of processor
 +              cores implements the MIPS64R2 instruction set with many extensions,
 +              including most 64-bit Loongson-2 (2H, 2K) and Loongson-3 (3A1000,
 +              3B1000, 3B1500, 3A2000, 3A3000 and 3A4000) processors. However, old
 +              Loongson-2E/2F is not covered here and will be removed in future.
  
  config LOONGSON3_ENHANCEMENT
 -      bool "New Loongson 3 CPU Enhancements"
 +      bool "New Loongson-3 CPU Enhancements"
        default n
        select CPU_MIPSR2
        select CPU_HAS_PREFETCH
 -      depends on CPU_LOONGSON3
 +      depends on CPU_LOONGSON64
        help
 -        New Loongson 3 CPU (since Loongson-3A R2, as opposed to Loongson-3A
 +        New Loongson-3 cores (since Loongson-3A R2, as opposed to Loongson-3A
          R1, Loongson-3B R1 and Loongson-3B R2) has many enhancements, such as
 -        FTLB, L1-VCache, EI/DI/Wait/Prefetch instruction, DSP/DSPv2 ASE, User
 +        FTLB, L1-VCache, EI/DI/Wait/Prefetch instruction, DSP/DSPr2 ASE, User
          Local register, Read-Inhibit/Execute-Inhibit, SFB (Store Fill Buffer),
          Fast TLB refill support, etc.
  
          This option enable those enhancements which are not probed at run
          time. If you want a generic kernel to run on all Loongson 3 machines,
          please say 'N' here. If you want a high-performance kernel to run on
 -        new Loongson 3 machines only, please say 'Y' here.
 +        new Loongson-3 machines only, please say 'Y' here.
  
  config CPU_LOONGSON3_WORKAROUNDS
 -      bool "Old Loongson 3 LLSC Workarounds"
 +      bool "Old Loongson-3 LLSC Workarounds"
        default y if SMP
 -      depends on CPU_LOONGSON3
 +      depends on CPU_LOONGSON64
        help
 -        Loongson 3 processors have the llsc issues which require workarounds.
 +        Loongson-3 processors have the llsc issues which require workarounds.
          Without workarounds the system may hang unexpectedly.
  
 -        Newer Loongson 3 will fix these issues and no workarounds are needed.
 +        Newer Loongson-3 will fix these issues and no workarounds are needed.
          The workarounds have no significant side effect on them but may
          decrease the performance of the system so this option should be
          disabled unless the kernel is intended to be run on old systems.
  config CPU_LOONGSON2E
        bool "Loongson 2E"
        depends on SYS_HAS_CPU_LOONGSON2E
 -      select CPU_LOONGSON2
 +      select CPU_LOONGSON2EF
        help
          The Loongson 2E processor implements the MIPS III instruction set
          with many extensions.
  config CPU_LOONGSON2F
        bool "Loongson 2F"
        depends on SYS_HAS_CPU_LOONGSON2F
 -      select CPU_LOONGSON2
 +      select CPU_LOONGSON2EF
        select GPIOLIB
        help
          The Loongson 2F processor implements the MIPS III instruction set
  config CPU_LOONGSON1B
        bool "Loongson 1B"
        depends on SYS_HAS_CPU_LOONGSON1B
 -      select CPU_LOONGSON1
 +      select CPU_LOONGSON32
        select LEDS_GPIO_REGISTER
        help
          The Loongson 1B is a 32-bit SoC, which implements the MIPS32
  config CPU_LOONGSON1C
        bool "Loongson 1C"
        depends on SYS_HAS_CPU_LOONGSON1C
 -      select CPU_LOONGSON1
 +      select CPU_LOONGSON32
        select LEDS_GPIO_REGISTER
        help
          The Loongson 1C is a 32-bit SoC, which implements the MIPS32
@@@ -1920,7 -1858,7 +1921,7 @@@ config SYS_SUPPORTS_ZBOOT_UART_PRO
        bool
        select SYS_SUPPORTS_ZBOOT
  
 -config CPU_LOONGSON2
 +config CPU_LOONGSON2EF
        bool
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select ARCH_HAS_PHYS_TO_DMA
        select CPU_HAS_LOAD_STORE_LR
  
 -config CPU_LOONGSON1
 +config CPU_LOONGSON32
        bool
        select CPU_MIPS32
        select CPU_MIPSR2
@@@ -1963,7 -1901,7 +1964,7 @@@ config CPU_BMIPS500
        select SYS_SUPPORTS_HOTPLUG_CPU
        select CPU_HAS_RIXI
  
 -config SYS_HAS_CPU_LOONGSON3
 +config SYS_HAS_CPU_LOONGSON64
        bool
        select CPU_SUPPORTS_CPUFREQ
        select CPU_HAS_RIXI
@@@ -1975,6 -1913,7 +1976,6 @@@ config SYS_HAS_CPU_LOONGSON2
        bool
        select CPU_SUPPORTS_CPUFREQ
        select CPU_SUPPORTS_ADDRWINCFG if 64BIT
 -      select CPU_SUPPORTS_UNCACHED_ACCELERATED
  
  config SYS_HAS_CPU_LOONGSON1B
        bool
@@@ -2151,6 -2090,8 +2152,6 @@@ config CPU_SUPPORTS_ADDRWINCF
  config CPU_SUPPORTS_HUGEPAGES
        bool
        depends on !(32BIT && (ARCH_PHYS_ADDR_T_64BIT || EVA))
 -config CPU_SUPPORTS_UNCACHED_ACCELERATED
 -      bool
  config MIPS_PGD_C0_CONTEXT
        bool
        default y if 64BIT && (CPU_MIPSR2 || CPU_MIPSR6) && !CPU_XLP
@@@ -2222,7 -2163,7 +2223,7 @@@ choic
  
  config PAGE_SIZE_4KB
        bool "4kB"
 -      depends on !CPU_LOONGSON2 && !CPU_LOONGSON3
 +      depends on !CPU_LOONGSON2EF && !CPU_LOONGSON64
        help
          This option select the standard 4kB Linux page size.  On some
          R3000-family processors this is the only available page size.  Using
@@@ -2614,10 -2555,6 +2615,10 @@@ config CPU_R4000_WORKAROUND
  config CPU_R4400_WORKAROUNDS
        bool
  
 +config CPU_R4X00_BUGS64
 +      bool
 +      default y if SYS_HAS_CPU_R4X00 && 64BIT && (TARGET_ISA_REV < 1)
 +
  config MIPS_ASID_SHIFT
        int
        default 6 if CPU_R3000 || CPU_TX39XX
@@@ -2676,11 -2613,20 +2677,11 @@@ config CPU_SUPPORTS_MS
  
  config ARCH_FLATMEM_ENABLE
        def_bool y
 -      depends on !NUMA && !CPU_LOONGSON2
 -
 -config ARCH_DISCONTIGMEM_ENABLE
 -      bool
 -      default y if SGI_IP27
 -      help
 -        Say Y to support efficient handling of discontiguous physical memory,
 -        for architectures which are either NUMA (Non-Uniform Memory Access)
 -        or have huge holes in the physical address space for other reasons.
 -        See <file:Documentation/vm/numa.rst> for more.
 +      depends on !NUMA && !CPU_LOONGSON2EF
  
  config ARCH_SPARSEMEM_ENABLE
        bool
 -      select SPARSEMEM_STATIC
 +      select SPARSEMEM_STATIC if !SGI_IP27
  
  config NUMA
        bool "NUMA Support"
@@@ -2757,7 -2703,7 +2758,7 @@@ config NODES_SHIF
  
  config HW_PERF_EVENTS
        bool "Enable hardware performance counter support for perf events"
 -      depends on PERF_EVENTS && !OPROFILE && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP || CPU_LOONGSON3)
 +      depends on PERF_EVENTS && !OPROFILE && (CPU_MIPS32 || CPU_MIPS64 || CPU_R10000 || CPU_SB1 || CPU_CAVIUM_OCTEON || CPU_XLP || CPU_LOONGSON64)
        default y
        help
          Enable hardware performance counter support for perf events. If
diff --combined arch/x86/Kconfig
index 9c9bc348c4126c09d38bd7c87dae1f3b751dc0c1,329d9c729ba335608a4176606624cf49fb41301c..58b31ee198d966932eecfff0cc9f1d8311cd78c4
@@@ -24,7 -24,7 +24,7 @@@ config X86_6
        depends on 64BIT
        # Options that are inherently 64-bit kernel only:
        select ARCH_HAS_GIGANTIC_PAGE
 -      select ARCH_SUPPORTS_INT128
 +      select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
        select ARCH_USE_CMPXCHG_LOCKREF
        select HAVE_ARCH_SOFT_DIRTY
        select MODULES_USE_ELF_RELA
@@@ -73,6 -73,7 +73,6 @@@ config X8
        select ARCH_HAS_PMEM_API                if X86_64
        select ARCH_HAS_PTE_DEVMAP              if X86_64
        select ARCH_HAS_PTE_SPECIAL
 -      select ARCH_HAS_REFCOUNT
        select ARCH_HAS_UACCESS_FLUSHCACHE      if X86_64
        select ARCH_HAS_UACCESS_MCSAFE          if X86_64 && X86_MCE
        select ARCH_HAS_SET_MEMORY
        select HAVE_DMA_CONTIGUOUS
        select HAVE_DYNAMIC_FTRACE
        select HAVE_DYNAMIC_FTRACE_WITH_REGS
+       select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
        select HAVE_EBPF_JIT
        select HAVE_EFFICIENT_UNALIGNED_ACCESS
        select HAVE_EISA
@@@ -931,6 -933,36 +932,6 @@@ config GART_IOMM
  
          If unsure, say Y.
  
 -config CALGARY_IOMMU
 -      bool "IBM Calgary IOMMU support"
 -      select IOMMU_HELPER
 -      select SWIOTLB
 -      depends on X86_64 && PCI
 -      ---help---
 -        Support for hardware IOMMUs in IBM's xSeries x366 and x460
 -        systems. Needed to run systems with more than 3GB of memory
 -        properly with 32-bit PCI devices that do not support DAC
 -        (Double Address Cycle). Calgary also supports bus level
 -        isolation, where all DMAs pass through the IOMMU.  This
 -        prevents them from going anywhere except their intended
 -        destination. This catches hard-to-find kernel bugs and
 -        mis-behaving drivers and devices that do not use the DMA-API
 -        properly to set up their DMA buffers.  The IOMMU can be
 -        turned off at boot time with the iommu=off parameter.
 -        Normally the kernel will make the right choice by itself.
 -        If unsure, say Y.
 -
 -config CALGARY_IOMMU_ENABLED_BY_DEFAULT
 -      def_bool y
 -      prompt "Should Calgary be enabled by default?"
 -      depends on CALGARY_IOMMU
 -      ---help---
 -        Should Calgary be enabled by default? if you choose 'y', Calgary
 -        will be used (if it exists). If you choose 'n', Calgary will not be
 -        used even if it exists. If you choose 'n' and would like to use
 -        Calgary anyway, pass 'iommu=calgary' on the kernel command line.
 -        If unsure, say Y.
 -
  config MAXSMP
        bool "Enable Maximum number of SMP Processors and NUMA Nodes"
        depends on X86_64 && SMP && DEBUG_KERNEL
@@@ -969,8 -1001,8 +970,8 @@@ config NR_CPUS_RANGE_EN
  config NR_CPUS_RANGE_END
        int
        depends on X86_64
 -      default 8192 if  SMP && ( MAXSMP ||  CPUMASK_OFFSTACK)
 -      default  512 if  SMP && (!MAXSMP && !CPUMASK_OFFSTACK)
 +      default 8192 if  SMP && CPUMASK_OFFSTACK
 +      default  512 if  SMP && !CPUMASK_OFFSTACK
        default    1 if !SMP
  
  config NR_CPUS_DEFAULT
@@@ -1223,24 -1255,6 +1224,24 @@@ config X86_VSYSCALL_EMULATIO
         Disabling this option saves about 7K of kernel size and
         possibly 4K of additional runtime pagetable memory.
  
 +config X86_IOPL_IOPERM
 +      bool "IOPERM and IOPL Emulation"
 +      default y
 +      ---help---
 +        This enables the ioperm() and iopl() syscalls which are necessary
 +        for legacy applications.
 +
 +        Legacy IOPL support is an overbroad mechanism which allows user
 +        space aside of accessing all 65536 I/O ports also to disable
 +        interrupts. To gain this access the caller needs CAP_SYS_RAWIO
 +        capabilities and permission from potentially active security
 +        modules.
 +
 +        The emulation restricts the functionality of the syscall to
 +        only allowing the full range I/O port access, but prevents the
 +        ability to disable interrupts from user space which would be
 +        granted if the hardware IOPL mechanism would be used.
 +
  config TOSHIBA
        tristate "Toshiba Laptop support"
        depends on X86_32
@@@ -1479,7 -1493,6 +1480,7 @@@ config X86_PA
  
  config X86_5LEVEL
        bool "Enable 5-level page tables support"
 +      default y
        select DYNAMIC_MEMORY_LAYOUT
        select SPARSEMEM_VMEMMAP
        depends on X86_64
@@@ -1739,7 -1752,7 +1740,7 @@@ config X86_RESERVE_LO
  config MATH_EMULATION
        bool
        depends on MODIFY_LDT_SYSCALL
 -      prompt "Math emulation" if X86_32
 +      prompt "Math emulation" if X86_32 && (M486SX || MELAN)
        ---help---
          Linux can emulate a math coprocessor (used for floating point
          operations) if you don't have one. 486DX and Pentium processors have
@@@ -1868,16 -1881,16 +1869,16 @@@ config X86_SMA
  
          If unsure, say Y.
  
 -config X86_INTEL_UMIP
 +config X86_UMIP
        def_bool y
 -      depends on CPU_SUP_INTEL
 -      prompt "Intel User Mode Instruction Prevention" if EXPERT
 +      depends on CPU_SUP_INTEL || CPU_SUP_AMD
 +      prompt "User Mode Instruction Prevention" if EXPERT
        ---help---
 -        The User Mode Instruction Prevention (UMIP) is a security
 -        feature in newer Intel processors. If enabled, a general
 -        protection fault is issued if the SGDT, SLDT, SIDT, SMSW
 -        or STR instructions are executed in user mode. These instructions
 -        unnecessarily expose information about the hardware state.
 +        User Mode Instruction Prevention (UMIP) is a security feature in
 +        some x86 processors. If enabled, a general protection fault is
 +        issued if the SGDT, SLDT, SIDT, SMSW or STR instructions are
 +        executed in user mode. These instructions unnecessarily expose
 +        information about the hardware state.
  
          The vast majority of applications do not use these instructions.
          For the very few that do, software emulation is provided in
@@@ -1928,51 -1941,6 +1929,51 @@@ config X86_INTEL_MEMORY_PROTECTION_KEY
  
          If unsure, say y.
  
 +choice
 +      prompt "TSX enable mode"
 +      depends on CPU_SUP_INTEL
 +      default X86_INTEL_TSX_MODE_OFF
 +      help
 +        Intel's TSX (Transactional Synchronization Extensions) feature
 +        allows to optimize locking protocols through lock elision which
 +        can lead to a noticeable performance boost.
 +
 +        On the other hand it has been shown that TSX can be exploited
 +        to form side channel attacks (e.g. TAA) and chances are there
 +        will be more of those attacks discovered in the future.
 +
 +        Therefore TSX is not enabled by default (aka tsx=off). An admin
 +        might override this decision by tsx=on the command line parameter.
 +        Even with TSX enabled, the kernel will attempt to enable the best
 +        possible TAA mitigation setting depending on the microcode available
 +        for the particular machine.
 +
 +        This option allows to set the default tsx mode between tsx=on, =off
 +        and =auto. See Documentation/admin-guide/kernel-parameters.txt for more
 +        details.
 +
 +        Say off if not sure, auto if TSX is in use but it should be used on safe
 +        platforms or on if TSX is in use and the security aspect of tsx is not
 +        relevant.
 +
 +config X86_INTEL_TSX_MODE_OFF
 +      bool "off"
 +      help
 +        TSX is disabled if possible - equals to tsx=off command line parameter.
 +
 +config X86_INTEL_TSX_MODE_ON
 +      bool "on"
 +      help
 +        TSX is always enabled on TSX capable HW - equals the tsx=on command
 +        line parameter.
 +
 +config X86_INTEL_TSX_MODE_AUTO
 +      bool "auto"
 +      help
 +        TSX is enabled on TSX capable HW that is believed to be safe against
 +        side channel attacks- equals the tsx=auto command line parameter.
 +endchoice
 +
  config EFI
        bool "EFI runtime service support"
        depends on ACPI
index 6e8961ca3605064143df5db824fb8895a9cd1985,b33abdd0a2dbb51cec60fc6751371517aa185e03..369e61faacfe39843a060e359d2c81c8ce7f27bf
@@@ -14,6 -14,9 +14,6 @@@
        .code64
        .section .entry.text, "ax"
  
 -# define function_hook        __fentry__
 -EXPORT_SYMBOL(__fentry__)
 -
  #ifdef CONFIG_FRAME_POINTER
  /* Save parent and function stack frames (rip and rbp) */
  #  define MCOUNT_FRAME_SIZE   (8+16*2)
@@@ -85,6 -88,7 +85,7 @@@
        movq %rdi, RDI(%rsp)
        movq %r8, R8(%rsp)
        movq %r9, R9(%rsp)
+       movq $0, ORIG_RAX(%rsp)
        /*
         * Save the original RBP. Even though the mcount ABI does not
         * require this, it helps out callers.
        subq $MCOUNT_INSN_SIZE, %rdi
        .endm
  
- .macro restore_mcount_regs
+ .macro restore_mcount_regs save=0
+       /* ftrace_regs_caller or frame pointers require this */
+       movq RBP(%rsp), %rbp
        movq R9(%rsp), %r9
        movq R8(%rsp), %r8
        movq RDI(%rsp), %rdi
        movq RCX(%rsp), %rcx
        movq RAX(%rsp), %rax
  
-       /* ftrace_regs_caller can modify %rbp */
-       movq RBP(%rsp), %rbp
-       addq $MCOUNT_REG_SIZE, %rsp
+       addq $MCOUNT_REG_SIZE-\save, %rsp
  
        .endm
  
  #ifdef CONFIG_DYNAMIC_FTRACE
  
 -ENTRY(function_hook)
 +SYM_FUNC_START(__fentry__)
        retq
 -ENDPROC(function_hook)
 +SYM_FUNC_END(__fentry__)
 +EXPORT_SYMBOL(__fentry__)
  
 -ENTRY(ftrace_caller)
 +SYM_FUNC_START(ftrace_caller)
        /* save_mcount_regs fills in first two parameters */
        save_mcount_regs
  
 -GLOBAL(ftrace_caller_op_ptr)
 +SYM_INNER_LABEL(ftrace_caller_op_ptr, SYM_L_GLOBAL)
        /* Load the ftrace_ops into the 3rd parameter */
        movq function_trace_op(%rip), %rdx
  
        /* regs go into 4th parameter (but make it NULL) */
        movq $0, %rcx
  
 -GLOBAL(ftrace_call)
 +SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
        call ftrace_stub
  
        restore_mcount_regs
         * think twice before adding any new code or changing the
         * layout here.
         */
 -GLOBAL(ftrace_epilogue)
 +SYM_INNER_LABEL(ftrace_epilogue, SYM_L_GLOBAL)
  
  #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 -GLOBAL(ftrace_graph_call)
 +SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL)
        jmp ftrace_stub
  #endif
  
   * This is weak to keep gas from relaxing the jumps.
   * It is also used to copy the retq for trampolines.
   */
 -WEAK(ftrace_stub)
 +SYM_INNER_LABEL_ALIGN(ftrace_stub, SYM_L_WEAK)
        retq
 -ENDPROC(ftrace_caller)
 +SYM_FUNC_END(ftrace_caller)
  
 -ENTRY(ftrace_regs_caller)
 +SYM_FUNC_START(ftrace_regs_caller)
        /* Save the current flags before any operations that can change them */
        pushfq
  
+       UNWIND_HINT_SAVE
        /* added 8 bytes to save flags */
        save_mcount_regs 8
        /* save_mcount_regs fills in first two parameters */
  
 -GLOBAL(ftrace_regs_caller_op_ptr)
 +SYM_INNER_LABEL(ftrace_regs_caller_op_ptr, SYM_L_GLOBAL)
        /* Load the ftrace_ops into the 3rd parameter */
        movq function_trace_op(%rip), %rdx
  
        /* regs go into 4th parameter */
        leaq (%rsp), %rcx
  
 -GLOBAL(ftrace_regs_call)
 +SYM_INNER_LABEL(ftrace_regs_call, SYM_L_GLOBAL)
        call ftrace_stub
  
        /* Copy flags back to SS, to restore them */
        movq R10(%rsp), %r10
        movq RBX(%rsp), %rbx
  
-       restore_mcount_regs
+       movq ORIG_RAX(%rsp), %rax
+       movq %rax, MCOUNT_REG_SIZE-8(%rsp)
+       /* If ORIG_RAX is anything but zero, make this a call to that */
+       movq ORIG_RAX(%rsp), %rax
+       cmpq    $0, %rax
+       je      1f
+       /* Swap the flags with orig_rax */
+       movq MCOUNT_REG_SIZE(%rsp), %rdi
+       movq %rdi, MCOUNT_REG_SIZE-8(%rsp)
+       movq %rax, MCOUNT_REG_SIZE(%rsp)
+       restore_mcount_regs 8
+       jmp     2f
+ 1:    restore_mcount_regs
+ 2:
+       /*
+        * The stack layout is nondetermistic here, depending on which path was
+        * taken.  This confuses objtool and ORC, rightfully so.  For now,
+        * pretend the stack always looks like the non-direct case.
+        */
+       UNWIND_HINT_RESTORE
  
        /* Restore flags */
        popfq
         * The trampoline will add the code to jump
         * to the return.
         */
 -GLOBAL(ftrace_regs_caller_end)
 +SYM_INNER_LABEL(ftrace_regs_caller_end, SYM_L_GLOBAL)
  
        jmp ftrace_epilogue
  
 -ENDPROC(ftrace_regs_caller)
 +SYM_FUNC_END(ftrace_regs_caller)
  
  
  #else /* ! CONFIG_DYNAMIC_FTRACE */
  
 -ENTRY(function_hook)
 +SYM_FUNC_START(__fentry__)
        cmpq $ftrace_stub, ftrace_trace_function
        jnz trace
  
@@@ -259,7 -291,7 +289,7 @@@ fgraph_trace
        jnz ftrace_graph_caller
  #endif
  
 -GLOBAL(ftrace_stub)
 +SYM_INNER_LABEL(ftrace_stub, SYM_L_GLOBAL)
        retq
  
  trace:
        restore_mcount_regs
  
        jmp fgraph_trace
 -ENDPROC(function_hook)
 +SYM_FUNC_END(__fentry__)
 +EXPORT_SYMBOL(__fentry__)
  #endif /* CONFIG_DYNAMIC_FTRACE */
  
  #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 -ENTRY(ftrace_graph_caller)
 +SYM_FUNC_START(ftrace_graph_caller)
        /* Saves rbp into %rdx and fills first parameter  */
        save_mcount_regs
  
        restore_mcount_regs
  
        retq
 -ENDPROC(ftrace_graph_caller)
 +SYM_FUNC_END(ftrace_graph_caller)
  
 -ENTRY(return_to_handler)
 +SYM_CODE_START(return_to_handler)
        UNWIND_HINT_EMPTY
        subq  $24, %rsp
  
        movq (%rsp), %rax
        addq $24, %rsp
        JMP_NOSPEC %rdi
 -END(return_to_handler)
 +SYM_CODE_END(return_to_handler)
  #endif
index 63cedc3c0c7737e69077ef76b4dee4cc95f52fe9,996db32c491b9a969cd6beb5f4f58680629f3477..e00f41aa8ec4f1ef955db01e7a9a8d0c1cfdec61
   *    _etext = .;
   *
   *      _sdata = .;
 - *    RO_DATA_SECTION(PAGE_SIZE)
 - *    RW_DATA_SECTION(...)
 + *    RO_DATA(PAGE_SIZE)
 + *    RW_DATA(...)
   *    _edata = .;
   *
   *    EXCEPTION_TABLE(...)
 - *    NOTES
   *
   *    BSS_SECTION(0, 0, 0)
   *    _end = .;
  #define LOAD_OFFSET 0
  #endif
  
 +/*
 + * Only some architectures want to have the .notes segment visible in
 + * a separate PT_NOTE ELF Program Header. When this happens, it needs
 + * to be visible in both the kernel text's PT_LOAD and the PT_NOTE
 + * Program Headers. In this case, though, the PT_LOAD needs to be made
 + * the default again so that all the following sections don't also end
 + * up in the PT_NOTE Program Header.
 + */
 +#ifdef EMITS_PT_NOTE
 +#define NOTES_HEADERS         :text :note
 +#define NOTES_HEADERS_RESTORE __restore_ph : { *(.__restore_ph) } :text
 +#else
 +#define NOTES_HEADERS
 +#define NOTES_HEADERS_RESTORE
 +#endif
 +
 +/*
 + * Some architectures have non-executable read-only exception tables.
 + * They can be added to the RO_DATA segment by specifying their desired
 + * alignment.
 + */
 +#ifdef RO_EXCEPTION_TABLE_ALIGN
 +#define RO_EXCEPTION_TABLE    EXCEPTION_TABLE(RO_EXCEPTION_TABLE_ALIGN)
 +#else
 +#define RO_EXCEPTION_TABLE
 +#endif
 +
  /* Align . to a 8 byte boundary equals to maximum function alignment. */
  #define ALIGN_FUNCTION()  . = ALIGN(8)
  
  #endif
  
  #ifdef CONFIG_FTRACE_MCOUNT_RECORD
 -#ifdef CC_USING_PATCHABLE_FUNCTION_ENTRY
  /*
 + * The ftrace call sites are logged to a section whose name depends on the
 + * compiler option used. A given kernel image will only use one, AKA
 + * FTRACE_CALLSITE_SECTION. We capture all of them here to avoid header
 + * dependencies for FTRACE_CALLSITE_SECTION's definition.
++ *
+  * Need to also make ftrace_stub_graph point to ftrace_stub
+  * so that the same stub location may have different protocols
+  * and not mess up with C verifiers.
   */
 -#define MCOUNT_REC()  . = ALIGN(8);                           \
 -                      __start_mcount_loc = .;                 \
 -                      KEEP(*(__patchable_function_entries))   \
 -                      __stop_mcount_loc = .;                  \
 -                      ftrace_stub_graph = ftrace_stub;
 -#else
  #define MCOUNT_REC()  . = ALIGN(8);                           \
                        __start_mcount_loc = .;                 \
                        KEEP(*(__mcount_loc))                   \
-                       __stop_mcount_loc = .;
 +                      KEEP(*(__patchable_function_entries))   \
 -#endif
+                       __stop_mcount_loc = .;                  \
+                       ftrace_stub_graph = ftrace_stub;
  #else
- #define MCOUNT_REC()
+ # ifdef CONFIG_FUNCTION_TRACER
+ #  define MCOUNT_REC()        ftrace_stub_graph = ftrace_stub;
+ # else
+ #  define MCOUNT_REC()
+ # endif
  #endif
  
  #ifdef CONFIG_TRACE_BRANCH_PROFILING
  /*
   * Read only Data
   */
 -#define RO_DATA_SECTION(align)                                                \
 +#define RO_DATA(align)                                                        \
        . = ALIGN((align));                                             \
        .rodata           : AT(ADDR(.rodata) - LOAD_OFFSET) {           \
                __start_rodata = .;                                     \
                __start___modver = .;                                   \
                KEEP(*(__modver))                                       \
                __stop___modver = .;                                    \
 -              . = ALIGN((align));                                     \
 -              __end_rodata = .;                                       \
        }                                                               \
 -      . = ALIGN((align));
 -
 -/* RODATA & RO_DATA provided for backward compatibility.
 - * All archs are supposed to use RO_DATA() */
 -#define RODATA          RO_DATA_SECTION(4096)
 -#define RO_DATA(align)  RO_DATA_SECTION(align)
 +                                                                      \
 +      RO_EXCEPTION_TABLE                                              \
 +      NOTES                                                           \
 +                                                                      \
 +      . = ALIGN((align));                                             \
 +      __end_rodata = .;
  
  /*
   * .text section. Map to function alignment to avoid address changes
                __start_notes = .;                                      \
                KEEP(*(.note.*))                                        \
                __stop_notes = .;                                       \
 -      }
 +      } NOTES_HEADERS                                                 \
 +      NOTES_HEADERS_RESTORE
  
  #define INIT_SETUP(initsetup_align)                                   \
                . = ALIGN(initsetup_align);                             \
   * matches the requirement of PAGE_ALIGNED_DATA.
   *
   * use 0 as page_align if page_aligned data is not used */
 -#define RW_DATA_SECTION(cacheline, pagealigned, inittask)             \
 +#define RW_DATA(cacheline, pagealigned, inittask)                     \
        . = ALIGN(PAGE_SIZE);                                           \
        .data : AT(ADDR(.data) - LOAD_OFFSET) {                         \
                INIT_TASK_DATA(inittask)                                \
diff --combined include/linux/ftrace.h
index 9141f22632864d9814cabe4e7544b6401fc4cf4a,232806d5689defc9e0e93179466f60521a0f446a..7247d35c3d160af210f35e07393fd04da361326b
@@@ -51,6 -51,7 +51,7 @@@ static inline void early_trace_init(voi
  
  struct module;
  struct ftrace_hash;
+ struct ftrace_direct_func;
  
  #if defined(CONFIG_FUNCTION_TRACER) && defined(CONFIG_MODULES) && \
        defined(CONFIG_DYNAMIC_FTRACE)
@@@ -142,24 -143,30 +143,30 @@@ ftrace_func_t ftrace_ops_get_func(struc
   * PID     - Is affected by set_ftrace_pid (allows filtering on those pids)
   * RCU     - Set when the ops can only be called when RCU is watching.
   * TRACE_ARRAY - The ops->private points to a trace_array descriptor.
+  * PERMANENT - Set when the ops is permanent and should not be affected by
+  *             ftrace_enabled.
+  * DIRECT - Used by the direct ftrace_ops helper for direct functions
+  *            (internal ftrace only, should not be used by others)
   */
  enum {
-       FTRACE_OPS_FL_ENABLED                   = 1 << 0,
-       FTRACE_OPS_FL_DYNAMIC                   = 1 << 1,
-       FTRACE_OPS_FL_SAVE_REGS                 = 1 << 2,
-       FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED    = 1 << 3,
-       FTRACE_OPS_FL_RECURSION_SAFE            = 1 << 4,
-       FTRACE_OPS_FL_STUB                      = 1 << 5,
-       FTRACE_OPS_FL_INITIALIZED               = 1 << 6,
-       FTRACE_OPS_FL_DELETED                   = 1 << 7,
-       FTRACE_OPS_FL_ADDING                    = 1 << 8,
-       FTRACE_OPS_FL_REMOVING                  = 1 << 9,
-       FTRACE_OPS_FL_MODIFYING                 = 1 << 10,
-       FTRACE_OPS_FL_ALLOC_TRAMP               = 1 << 11,
-       FTRACE_OPS_FL_IPMODIFY                  = 1 << 12,
-       FTRACE_OPS_FL_PID                       = 1 << 13,
-       FTRACE_OPS_FL_RCU                       = 1 << 14,
-       FTRACE_OPS_FL_TRACE_ARRAY               = 1 << 15,
+       FTRACE_OPS_FL_ENABLED                   = BIT(0),
+       FTRACE_OPS_FL_DYNAMIC                   = BIT(1),
+       FTRACE_OPS_FL_SAVE_REGS                 = BIT(2),
+       FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED    = BIT(3),
+       FTRACE_OPS_FL_RECURSION_SAFE            = BIT(4),
+       FTRACE_OPS_FL_STUB                      = BIT(5),
+       FTRACE_OPS_FL_INITIALIZED               = BIT(6),
+       FTRACE_OPS_FL_DELETED                   = BIT(7),
+       FTRACE_OPS_FL_ADDING                    = BIT(8),
+       FTRACE_OPS_FL_REMOVING                  = BIT(9),
+       FTRACE_OPS_FL_MODIFYING                 = BIT(10),
+       FTRACE_OPS_FL_ALLOC_TRAMP               = BIT(11),
+       FTRACE_OPS_FL_IPMODIFY                  = BIT(12),
+       FTRACE_OPS_FL_PID                       = BIT(13),
+       FTRACE_OPS_FL_RCU                       = BIT(14),
+       FTRACE_OPS_FL_TRACE_ARRAY               = BIT(15),
+       FTRACE_OPS_FL_PERMANENT                 = BIT(16),
+       FTRACE_OPS_FL_DIRECT                    = BIT(17),
  };
  
  #ifdef CONFIG_DYNAMIC_FTRACE
@@@ -239,6 -246,70 +246,70 @@@ static inline void ftrace_free_init_mem
  static inline void ftrace_free_mem(struct module *mod, void *start, void *end) { }
  #endif /* CONFIG_FUNCTION_TRACER */
  
+ struct ftrace_func_entry {
+       struct hlist_node hlist;
+       unsigned long ip;
+       unsigned long direct; /* for direct lookup only */
+ };
+ struct dyn_ftrace;
+ #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+ extern int ftrace_direct_func_count;
+ int register_ftrace_direct(unsigned long ip, unsigned long addr);
+ int unregister_ftrace_direct(unsigned long ip, unsigned long addr);
+ int modify_ftrace_direct(unsigned long ip, unsigned long old_addr, unsigned long new_addr);
+ struct ftrace_direct_func *ftrace_find_direct_func(unsigned long addr);
+ int ftrace_modify_direct_caller(struct ftrace_func_entry *entry,
+                               struct dyn_ftrace *rec,
+                               unsigned long old_addr,
+                               unsigned long new_addr);
+ #else
+ # define ftrace_direct_func_count 0
+ static inline int register_ftrace_direct(unsigned long ip, unsigned long addr)
+ {
+       return -ENOTSUPP;
+ }
+ static inline int unregister_ftrace_direct(unsigned long ip, unsigned long addr)
+ {
+       return -ENOTSUPP;
+ }
+ static inline int modify_ftrace_direct(unsigned long ip,
+                                      unsigned long old_addr, unsigned long new_addr)
+ {
+       return -ENOTSUPP;
+ }
+ static inline struct ftrace_direct_func *ftrace_find_direct_func(unsigned long addr)
+ {
+       return NULL;
+ }
+ static inline int ftrace_modify_direct_caller(struct ftrace_func_entry *entry,
+                                             struct dyn_ftrace *rec,
+                                             unsigned long old_addr,
+                                             unsigned long new_addr)
+ {
+       return -ENODEV;
+ }
+ #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
+ #ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+ /*
+  * This must be implemented by the architecture.
+  * It is the way the ftrace direct_ops helper, when called
+  * via ftrace (because there's other callbacks besides the
+  * direct call), can inform the architecture's trampoline that this
+  * routine has a direct caller, and what the caller is.
+  *
+  * For example, in x86, it returns the direct caller
+  * callback function via the regs->orig_ax parameter.
+  * Then in the ftrace trampoline, if this is set, it makes
+  * the return from the trampoline jump to the direct caller
+  * instead of going back to the function it just traced.
+  */
+ static inline void arch_ftrace_set_direct_caller(struct pt_regs *regs,
+                                                unsigned long addr) { }
+ #endif /* CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
  #ifdef CONFIG_STACK_TRACER
  
  extern int stack_tracer_enabled;
@@@ -291,8 -362,6 +362,6 @@@ static inline void stack_tracer_enable(
  int ftrace_arch_code_modify_prepare(void);
  int ftrace_arch_code_modify_post_process(void);
  
- struct dyn_ftrace;
  enum ftrace_bug_type {
        FTRACE_BUG_UNKNOWN,
        FTRACE_BUG_INIT,
@@@ -330,6 -399,7 +399,7 @@@ bool is_ftrace_trampoline(unsigned lon
   *  REGS_EN - the function is set up to save regs.
   *  IPMODIFY - the record allows for the IP address to be changed.
   *  DISABLED - the record is not ready to be touched yet
+  *  DIRECT   - there is a direct function to call
   *
   * When a new ftrace_ops is registered and wants a function to save
   * pt_regs, the rec->flag REGS is set. When the function has been
@@@ -345,10 -415,12 +415,12 @@@ enum 
        FTRACE_FL_TRAMP_EN      = (1UL << 27),
        FTRACE_FL_IPMODIFY      = (1UL << 26),
        FTRACE_FL_DISABLED      = (1UL << 25),
+       FTRACE_FL_DIRECT        = (1UL << 24),
+       FTRACE_FL_DIRECT_EN     = (1UL << 23),
  };
  
- #define FTRACE_REF_MAX_SHIFT  25
- #define FTRACE_FL_BITS                7
+ #define FTRACE_REF_MAX_SHIFT  23
+ #define FTRACE_FL_BITS                9
  #define FTRACE_FL_MASKED_BITS ((1UL << FTRACE_FL_BITS) - 1)
  #define FTRACE_FL_MASK                (FTRACE_FL_MASKED_BITS << FTRACE_REF_MAX_SHIFT)
  #define FTRACE_REF_MAX                ((1UL << FTRACE_REF_MAX_SHIFT) - 1)
@@@ -499,7 -571,7 +571,7 @@@ static inline int ftrace_disable_ftrace
  /**
   * ftrace_make_nop - convert code into nop
   * @mod: module structure if called by module load initialization
 - * @rec: the mcount call site record
 + * @rec: the call site record (e.g. mcount/fentry)
   * @addr: the address that the call site should be calling
   *
   * This is a very sensitive operation and great care needs
  extern int ftrace_make_nop(struct module *mod,
                           struct dyn_ftrace *rec, unsigned long addr);
  
 +
 +/**
 + * ftrace_init_nop - initialize a nop call site
 + * @mod: module structure if called by module load initialization
 + * @rec: the call site record (e.g. mcount/fentry)
 + *
 + * This is a very sensitive operation and great care needs
 + * to be taken by the arch.  The operation should carefully
 + * read the location, check to see if what is read is indeed
 + * what we expect it to be, and then on success of the compare,
 + * it should write to the location.
 + *
 + * The code segment at @rec->ip should contain the contents created by
 + * the compiler
 + *
 + * Return must be:
 + *  0 on success
 + *  -EFAULT on error reading the location
 + *  -EINVAL on a failed compare of the contents
 + *  -EPERM  on error writing to the location
 + * Any other value will be considered a failure.
 + */
 +#ifndef ftrace_init_nop
 +static inline int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
 +{
 +      return ftrace_make_nop(mod, rec, MCOUNT_ADDR);
 +}
 +#endif
 +
  /**
   * ftrace_make_call - convert a nop call site into a call to addr
 - * @rec: the mcount call site record
 + * @rec: the call site record (e.g. mcount/fentry)
   * @addr: the address that the call site should call
   *
   * This is a very sensitive operation and great care needs
@@@ -574,7 -617,7 +646,7 @@@ extern int ftrace_make_call(struct dyn_
  #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
  /**
   * ftrace_modify_call - convert from one addr to another (no nop)
 - * @rec: the mcount call site record
 + * @rec: the call site record (e.g. mcount/fentry)
   * @old_addr: the address expected to be currently called to
   * @addr: the address to change to
   *
@@@ -738,11 -781,6 +810,11 @@@ static inline unsigned long get_lock_pa
  
  #ifdef CONFIG_FTRACE_MCOUNT_RECORD
  extern void ftrace_init(void);
 +#ifdef CC_USING_PATCHABLE_FUNCTION_ENTRY
 +#define FTRACE_CALLSITE_SECTION       "__patchable_function_entries"
 +#else
 +#define FTRACE_CALLSITE_SECTION       "__mcount_loc"
 +#endif
  #else
  static inline void ftrace_init(void) { }
  #endif
diff --combined kernel/module.c
index acf7962936c47f714805408cf556c2ece94dcbc7,6e2fd40a6ed992ece591715750d936da880ad028..052a40212b8e50ff6954fedf0c254c6fca86f559
@@@ -3222,7 -3222,7 +3222,7 @@@ static int find_module_sections(struct 
  #endif
  #ifdef CONFIG_FTRACE_MCOUNT_RECORD
        /* sechdrs[0].sh_size is always zero */
 -      mod->ftrace_callsites = section_objs(info, "__mcount_loc",
 +      mod->ftrace_callsites = section_objs(info, FTRACE_CALLSITE_SECTION,
                                             sizeof(*mod->ftrace_callsites),
                                             &mod->num_ftrace_callsites);
  #endif
@@@ -3728,7 -3728,6 +3728,6 @@@ static int complete_formation(struct mo
  
        module_enable_ro(mod, false);
        module_enable_nx(mod);
-       module_enable_x(mod);
  
        /* Mark state as coming so strong_try_module_get() ignores us,
         * but kallsyms etc. can see us. */
@@@ -3751,6 -3750,11 +3750,11 @@@ static int prepare_coming_module(struc
        if (err)
                return err;
  
+       /* Make module executable after ftrace is enabled */
+       mutex_lock(&module_mutex);
+       module_enable_x(mod);
+       mutex_unlock(&module_mutex);
        blocking_notifier_call_chain(&module_notify_list,
                                     MODULE_STATE_COMING, mod);
        return 0;
diff --combined kernel/trace/Kconfig
index 382628b9b75980e0408edeed9ecfbc2d165cd2d4,f67620499faa47fc07deee326882278a3ff0edd8..cdf5afa87f65bac9e7a51062437986b8d3fdbf99
@@@ -33,6 -33,9 +33,9 @@@ config HAVE_DYNAMIC_FTRAC
  config HAVE_DYNAMIC_FTRACE_WITH_REGS
        bool
  
+ config HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+       bool
  config HAVE_FTRACE_MCOUNT_RECORD
        bool
        help
@@@ -76,7 -79,7 +79,7 @@@ config FTRACE_NMI_ENTE
  
  config EVENT_TRACING
        select CONTEXT_SWITCH_TRACER
-         select GLOB
+       select GLOB
        bool
  
  config CONTEXT_SWITCH_TRACER
@@@ -106,6 -109,7 +109,6 @@@ config PREEMPTIRQ_TRACEPOINT
  
  config TRACING
        bool
 -      select DEBUG_FS
        select RING_BUFFER
        select STACKTRACE if STACKTRACE_SUPPORT
        select TRACEPOINTS
@@@ -307,7 -311,7 +310,7 @@@ config TRACER_SNAPSHO
              cat snapshot
  
  config TRACER_SNAPSHOT_PER_CPU_SWAP
-         bool "Allow snapshot to swap per CPU"
+       bool "Allow snapshot to swap per CPU"
        depends on TRACER_SNAPSHOT
        select RING_BUFFER_ALLOW_SWAP
        help
@@@ -556,6 -560,11 +559,11 @@@ config DYNAMIC_FTRACE_WITH_REG
        depends on DYNAMIC_FTRACE
        depends on HAVE_DYNAMIC_FTRACE_WITH_REGS
  
+ config DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+       def_bool y
+       depends on DYNAMIC_FTRACE
+       depends on HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
  config FUNCTION_PROFILER
        bool "Kernel function profiler"
        depends on FUNCTION_TRACER
@@@ -674,7 -683,7 +682,7 @@@ config MMIOTRACE_TES
          Say N, unless you absolutely know what you are doing.
  
  config TRACEPOINT_BENCHMARK
-         bool "Add tracepoint that benchmarks tracepoints"
+       bool "Add tracepoint that benchmarks tracepoints"
        help
         This option creates the tracepoint "benchmark:benchmark_event".
         When the tracepoint is enabled, it kicks off a kernel thread that
@@@ -723,7 -732,7 +731,7 @@@ config RING_BUFFER_STARTUP_TES
         bool "Ring buffer startup self test"
         depends on RING_BUFFER
         help
-          Run a simple self test on the ring buffer on boot up. Late in the
+        Run a simple self test on the ring buffer on boot up. Late in the
         kernel boot sequence, the test will start that kicks off
         a thread per cpu. Each thread will write various size events
         into the ring buffer. Another thread is created to send IPIs
@@@ -751,9 -760,9 +759,9 @@@ config PREEMPTIRQ_DELAY_TES
          configurable delay. The module busy waits for the duration of the
          critical section.
  
-         For example, the following invocation forces a one-time irq-disabled
-         critical section for 500us:
-         modprobe preemptirq_delay_test test_mode=irq delay=500000
+         For example, the following invocation generates a burst of three
+         irq-disabled critical sections for 500us:
+         modprobe preemptirq_delay_test test_mode=irq delay=500 burst_size=3
  
          If unsure, say N
  
@@@ -762,7 -771,7 +770,7 @@@ config TRACE_EVAL_MAP_FIL
         depends on TRACING
         help
        The "print fmt" of the trace events will show the enum/sizeof names
-       instead of their values. This can cause problems for user space tools
+       instead of their values. This can cause problems for user space tools
        that use this string to parse the raw data as user space does not know
        how to convert the string to its value.
  
        they are needed for the "eval_map" file. Enabling this option will
        increase the memory footprint of the running kernel.
  
-       If unsure, say N
+       If unsure, say N.
  
  config GCOV_PROFILE_FTRACE
        bool "Enable GCOV profiling on ftrace subsystem"
diff --combined kernel/trace/ftrace.c
index 5259d4dea675a0dc7d859d05a47fee0e2845ade9,caae523f4ef3af1ffd8f34c9773960b90b54afb9..74439ab5c2b660cb05302176cd56ee8489579749
@@@ -326,6 -326,8 +326,8 @@@ int __register_ftrace_function(struct f
        if (ops->flags & FTRACE_OPS_FL_SAVE_REGS_IF_SUPPORTED)
                ops->flags |= FTRACE_OPS_FL_SAVE_REGS;
  #endif
+       if (!ftrace_enabled && (ops->flags & FTRACE_OPS_FL_PERMANENT))
+               return -EBUSY;
  
        if (!core_kernel_data((unsigned long)ops))
                ops->flags |= FTRACE_OPS_FL_DYNAMIC;
@@@ -463,10 -465,10 +465,10 @@@ static void *function_stat_start(struc
  
  #ifdef CONFIG_FUNCTION_GRAPH_TRACER
  /* function graph compares on total time */
- static int function_stat_cmp(void *p1, void *p2)
+ static int function_stat_cmp(const void *p1, const void *p2)
  {
-       struct ftrace_profile *a = p1;
-       struct ftrace_profile *b = p2;
+       const struct ftrace_profile *a = p1;
+       const struct ftrace_profile *b = p2;
  
        if (a->time < b->time)
                return -1;
  }
  #else
  /* not function graph compares against hits */
- static int function_stat_cmp(void *p1, void *p2)
+ static int function_stat_cmp(const void *p1, const void *p2)
  {
-       struct ftrace_profile *a = p1;
-       struct ftrace_profile *b = p2;
+       const struct ftrace_profile *a = p1;
+       const struct ftrace_profile *b = p2;
  
        if (a->counter < b->counter)
                return -1;
@@@ -1018,11 -1020,6 +1020,6 @@@ static bool update_all_ops
  # error Dynamic ftrace depends on MCOUNT_RECORD
  #endif
  
- struct ftrace_func_entry {
-       struct hlist_node hlist;
-       unsigned long ip;
- };
  struct ftrace_func_probe {
        struct ftrace_probe_ops *probe_ops;
        struct ftrace_ops       ops;
@@@ -1370,23 -1367,15 +1367,15 @@@ ftrace_hash_rec_enable_modify(struct ft
  static int ftrace_hash_ipmodify_update(struct ftrace_ops *ops,
                                       struct ftrace_hash *new_hash);
  
- static struct ftrace_hash *
- __ftrace_hash_move(struct ftrace_hash *src)
+ static struct ftrace_hash *dup_hash(struct ftrace_hash *src, int size)
  {
        struct ftrace_func_entry *entry;
-       struct hlist_node *tn;
-       struct hlist_head *hhd;
        struct ftrace_hash *new_hash;
-       int size = src->count;
+       struct hlist_head *hhd;
+       struct hlist_node *tn;
        int bits = 0;
        int i;
  
-       /*
-        * If the new source is empty, just return the empty_hash.
-        */
-       if (ftrace_hash_empty(src))
-               return EMPTY_HASH;
        /*
         * Make the hash size about 1/2 the # found
         */
                        __add_hash_entry(new_hash, entry);
                }
        }
        return new_hash;
  }
  
+ static struct ftrace_hash *
+ __ftrace_hash_move(struct ftrace_hash *src)
+ {
+       int size = src->count;
+       /*
+        * If the new source is empty, just return the empty_hash.
+        */
+       if (ftrace_hash_empty(src))
+               return EMPTY_HASH;
+       return dup_hash(src, size);
+ }
  static int
  ftrace_hash_move(struct ftrace_ops *ops, int enable,
                 struct ftrace_hash **dst, struct ftrace_hash *src)
@@@ -1534,6 -1536,26 +1536,26 @@@ static int ftrace_cmp_recs(const void *
        return 0;
  }
  
+ static struct dyn_ftrace *lookup_rec(unsigned long start, unsigned long end)
+ {
+       struct ftrace_page *pg;
+       struct dyn_ftrace *rec = NULL;
+       struct dyn_ftrace key;
+       key.ip = start;
+       key.flags = end;        /* overload flags, as it is unsigned long */
+       for (pg = ftrace_pages_start; pg; pg = pg->next) {
+               if (end < pg->records[0].ip ||
+                   start >= (pg->records[pg->index - 1].ip + MCOUNT_INSN_SIZE))
+                       continue;
+               rec = bsearch(&key, pg->records, pg->index,
+                             sizeof(struct dyn_ftrace),
+                             ftrace_cmp_recs);
+       }
+       return rec;
+ }
  /**
   * ftrace_location_range - return the first address of a traced location
   *    if it touches the given ip range
   */
  unsigned long ftrace_location_range(unsigned long start, unsigned long end)
  {
-       struct ftrace_page *pg;
        struct dyn_ftrace *rec;
-       struct dyn_ftrace key;
-       key.ip = start;
-       key.flags = end;        /* overload flags, as it is unsigned long */
  
-       for (pg = ftrace_pages_start; pg; pg = pg->next) {
-               if (end < pg->records[0].ip ||
-                   start >= (pg->records[pg->index - 1].ip + MCOUNT_INSN_SIZE))
-                       continue;
-               rec = bsearch(&key, pg->records, pg->index,
-                             sizeof(struct dyn_ftrace),
-                             ftrace_cmp_recs);
-               if (rec)
-                       return rec->ip;
-       }
+       rec = lookup_rec(start, end);
+       if (rec)
+               return rec->ip;
  
        return 0;
  }
@@@ -1715,6 -1725,9 +1725,9 @@@ static bool __ftrace_hash_rec_update(st
                        if (FTRACE_WARN_ON(ftrace_rec_count(rec) == FTRACE_REF_MAX))
                                return false;
  
+                       if (ops->flags & FTRACE_OPS_FL_DIRECT)
+                               rec->flags |= FTRACE_FL_DIRECT;
                        /*
                         * If there's only a single callback registered to a
                         * function, and the ops has a trampoline registered
                                return false;
                        rec->flags--;
  
+                       /*
+                        * Only the internal direct_ops should have the
+                        * DIRECT flag set. Thus, if it is removing a
+                        * function, then that function should no longer
+                        * be direct.
+                        */
+                       if (ops->flags & FTRACE_OPS_FL_DIRECT)
+                               rec->flags &= ~FTRACE_FL_DIRECT;
                        /*
                         * If the rec had REGS enabled and the ops that is
                         * being removed had REGS set, then see if there is
@@@ -2077,15 -2099,34 +2099,34 @@@ static int ftrace_check_record(struct d
         * If enabling and the REGS flag does not match the REGS_EN, or
         * the TRAMP flag doesn't match the TRAMP_EN, then do not ignore
         * this record. Set flags to fail the compare against ENABLED.
+        * Same for direct calls.
         */
        if (flag) {
-               if (!(rec->flags & FTRACE_FL_REGS) != 
+               if (!(rec->flags & FTRACE_FL_REGS) !=
                    !(rec->flags & FTRACE_FL_REGS_EN))
                        flag |= FTRACE_FL_REGS;
  
-               if (!(rec->flags & FTRACE_FL_TRAMP) != 
+               if (!(rec->flags & FTRACE_FL_TRAMP) !=
                    !(rec->flags & FTRACE_FL_TRAMP_EN))
                        flag |= FTRACE_FL_TRAMP;
+               /*
+                * Direct calls are special, as count matters.
+                * We must test the record for direct, if the
+                * DIRECT and DIRECT_EN do not match, but only
+                * if the count is 1. That's because, if the
+                * count is something other than one, we do not
+                * want the direct enabled (it will be done via the
+                * direct helper). But if DIRECT_EN is set, and
+                * the count is not one, we need to clear it.
+                */
+               if (ftrace_rec_count(rec) == 1) {
+                       if (!(rec->flags & FTRACE_FL_DIRECT) !=
+                           !(rec->flags & FTRACE_FL_DIRECT_EN))
+                               flag |= FTRACE_FL_DIRECT;
+               } else if (rec->flags & FTRACE_FL_DIRECT_EN) {
+                       flag |= FTRACE_FL_DIRECT;
+               }
        }
  
        /* If the state of this record hasn't changed, then do nothing */
                                else
                                        rec->flags &= ~FTRACE_FL_TRAMP_EN;
                        }
+                       if (flag & FTRACE_FL_DIRECT) {
+                               /*
+                                * If there's only one user (direct_ops helper)
+                                * then we can call the direct function
+                                * directly (no ftrace trampoline).
+                                */
+                               if (ftrace_rec_count(rec) == 1) {
+                                       if (rec->flags & FTRACE_FL_DIRECT)
+                                               rec->flags |= FTRACE_FL_DIRECT_EN;
+                                       else
+                                               rec->flags &= ~FTRACE_FL_DIRECT_EN;
+                               } else {
+                                       /*
+                                        * Can only call directly if there's
+                                        * only one callback to the function.
+                                        */
+                                       rec->flags &= ~FTRACE_FL_DIRECT_EN;
+                               }
+                       }
                }
  
                /*
                         * and REGS states. The _EN flags must be disabled though.
                         */
                        rec->flags &= ~(FTRACE_FL_ENABLED | FTRACE_FL_TRAMP_EN |
-                                       FTRACE_FL_REGS_EN);
+                                       FTRACE_FL_REGS_EN | FTRACE_FL_DIRECT_EN);
        }
  
        ftrace_bug_type = FTRACE_BUG_NOP;
@@@ -2294,6 -2354,52 +2354,52 @@@ ftrace_find_tramp_ops_new(struct dyn_ft
        return NULL;
  }
  
+ #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+ /* Protected by rcu_tasks for reading, and direct_mutex for writing */
+ static struct ftrace_hash *direct_functions = EMPTY_HASH;
+ static DEFINE_MUTEX(direct_mutex);
+ int ftrace_direct_func_count;
+ /*
+  * Search the direct_functions hash to see if the given instruction pointer
+  * has a direct caller attached to it.
+  */
+ static unsigned long find_rec_direct(unsigned long ip)
+ {
+       struct ftrace_func_entry *entry;
+       entry = __ftrace_lookup_ip(direct_functions, ip);
+       if (!entry)
+               return 0;
+       return entry->direct;
+ }
+ static void call_direct_funcs(unsigned long ip, unsigned long pip,
+                             struct ftrace_ops *ops, struct pt_regs *regs)
+ {
+       unsigned long addr;
+       addr = find_rec_direct(ip);
+       if (!addr)
+               return;
+       arch_ftrace_set_direct_caller(regs, addr);
+ }
+ struct ftrace_ops direct_ops = {
+       .func           = call_direct_funcs,
+       .flags          = FTRACE_OPS_FL_IPMODIFY | FTRACE_OPS_FL_RECURSION_SAFE
+                         | FTRACE_OPS_FL_DIRECT | FTRACE_OPS_FL_SAVE_REGS
+                         | FTRACE_OPS_FL_PERMANENT,
+ };
+ #else
+ static inline unsigned long find_rec_direct(unsigned long ip)
+ {
+       return 0;
+ }
+ #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
  /**
   * ftrace_get_addr_new - Get the call address to set to
   * @rec:  The ftrace record descriptor
  unsigned long ftrace_get_addr_new(struct dyn_ftrace *rec)
  {
        struct ftrace_ops *ops;
+       unsigned long addr;
+       if ((rec->flags & FTRACE_FL_DIRECT) &&
+           (ftrace_rec_count(rec) == 1)) {
+               addr = find_rec_direct(rec->ip);
+               if (addr)
+                       return addr;
+               WARN_ON_ONCE(1);
+       }
  
        /* Trampolines take precedence over regs */
        if (rec->flags & FTRACE_FL_TRAMP) {
  unsigned long ftrace_get_addr_curr(struct dyn_ftrace *rec)
  {
        struct ftrace_ops *ops;
+       unsigned long addr;
+       /* Direct calls take precedence over trampolines */
+       if (rec->flags & FTRACE_FL_DIRECT_EN) {
+               addr = find_rec_direct(rec->ip);
+               if (addr)
+                       return addr;
+               WARN_ON_ONCE(1);
+       }
  
        /* Trampolines take precedence over regs */
        if (rec->flags & FTRACE_FL_TRAMP_EN) {
@@@ -2494,14 -2618,14 +2618,14 @@@ struct dyn_ftrace *ftrace_rec_iter_reco
  }
  
  static int
 -ftrace_code_disable(struct module *mod, struct dyn_ftrace *rec)
 +ftrace_nop_initialize(struct module *mod, struct dyn_ftrace *rec)
  {
        int ret;
  
        if (unlikely(ftrace_disabled))
                return 0;
  
 -      ret = ftrace_make_nop(mod, rec, MCOUNT_ADDR);
 +      ret = ftrace_init_nop(mod, rec);
        if (ret) {
                ftrace_bug_type = FTRACE_BUG_INIT;
                ftrace_bug(ret, rec);
@@@ -2861,6 -2985,8 +2985,8 @@@ static void ftrace_shutdown_sysctl(void
  
  static u64            ftrace_update_time;
  unsigned long         ftrace_update_tot_cnt;
+ unsigned long         ftrace_number_of_pages;
+ unsigned long         ftrace_number_of_groups;
  
  static inline int ops_traces_mod(struct ftrace_ops *ops)
  {
@@@ -2943,7 -3069,7 +3069,7 @@@ static int ftrace_update_code(struct mo
                         * to the NOP instructions.
                         */
                        if (!__is_defined(CC_USING_NOP_MCOUNT) &&
 -                          !ftrace_code_disable(mod, p))
 +                          !ftrace_nop_initialize(mod, p))
                                break;
  
                        update_cnt++;
@@@ -2985,6 -3111,9 +3111,9 @@@ static int ftrace_allocate_records(stru
                goto again;
        }
  
+       ftrace_number_of_pages += 1 << order;
+       ftrace_number_of_groups++;
        cnt = (PAGE_SIZE << order) / ENTRY_SIZE;
        pg->size = cnt;
  
@@@ -3040,6 -3169,8 +3169,8 @@@ ftrace_allocate_pages(unsigned long num
                start_pg = pg->next;
                kfree(pg);
                pg = start_pg;
+               ftrace_number_of_pages -= 1 << order;
+               ftrace_number_of_groups--;
        }
        pr_info("ftrace: FAILED to allocate memory for functions\n");
        return NULL;
@@@ -3450,10 -3581,11 +3581,11 @@@ static int t_show(struct seq_file *m, v
        if (iter->flags & FTRACE_ITER_ENABLED) {
                struct ftrace_ops *ops;
  
-               seq_printf(m, " (%ld)%s%s",
+               seq_printf(m, " (%ld)%s%s%s",
                           ftrace_rec_count(rec),
                           rec->flags & FTRACE_FL_REGS ? " R" : "  ",
-                          rec->flags & FTRACE_FL_IPMODIFY ? " I" : "  ");
+                          rec->flags & FTRACE_FL_IPMODIFY ? " I" : "  ",
+                          rec->flags & FTRACE_FL_DIRECT ? " D" : "  ");
                if (rec->flags & FTRACE_FL_TRAMP_EN) {
                        ops = ftrace_find_tramp_ops_any(rec);
                        if (ops) {
                } else {
                        add_trampoline_func(m, NULL, rec);
                }
+               if (rec->flags & FTRACE_FL_DIRECT) {
+                       unsigned long direct;
+                       direct = find_rec_direct(rec->ip);
+                       if (direct)
+                               seq_printf(m, "\n\tdirect-->%pS", (void *)direct);
+               }
        }       
  
        seq_putc(m, '\n');
@@@ -4800,6 -4939,366 +4939,366 @@@ ftrace_set_addr(struct ftrace_ops *ops
        return ftrace_set_hash(ops, NULL, 0, ip, remove, reset, enable);
  }
  
+ #ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+ struct ftrace_direct_func {
+       struct list_head        next;
+       unsigned long           addr;
+       int                     count;
+ };
+ static LIST_HEAD(ftrace_direct_funcs);
+ /**
+  * ftrace_find_direct_func - test an address if it is a registered direct caller
+  * @addr: The address of a registered direct caller
+  *
+  * This searches to see if a ftrace direct caller has been registered
+  * at a specific address, and if so, it returns a descriptor for it.
+  *
+  * This can be used by architecture code to see if an address is
+  * a direct caller (trampoline) attached to a fentry/mcount location.
+  * This is useful for the function_graph tracer, as it may need to
+  * do adjustments if it traced a location that also has a direct
+  * trampoline attached to it.
+  */
+ struct ftrace_direct_func *ftrace_find_direct_func(unsigned long addr)
+ {
+       struct ftrace_direct_func *entry;
+       bool found = false;
+       /* May be called by fgraph trampoline (protected by rcu tasks) */
+       list_for_each_entry_rcu(entry, &ftrace_direct_funcs, next) {
+               if (entry->addr == addr) {
+                       found = true;
+                       break;
+               }
+       }
+       if (found)
+               return entry;
+       return NULL;
+ }
+ /**
+  * register_ftrace_direct - Call a custom trampoline directly
+  * @ip: The address of the nop at the beginning of a function
+  * @addr: The address of the trampoline to call at @ip
+  *
+  * This is used to connect a direct call from the nop location (@ip)
+  * at the start of ftrace traced functions. The location that it calls
+  * (@addr) must be able to handle a direct call, and save the parameters
+  * of the function being traced, and restore them (or inject new ones
+  * if needed), before returning.
+  *
+  * Returns:
+  *  0 on success
+  *  -EBUSY - Another direct function is already attached (there can be only one)
+  *  -ENODEV - @ip does not point to a ftrace nop location (or not supported)
+  *  -ENOMEM - There was an allocation failure.
+  */
+ int register_ftrace_direct(unsigned long ip, unsigned long addr)
+ {
+       struct ftrace_direct_func *direct;
+       struct ftrace_func_entry *entry;
+       struct ftrace_hash *free_hash = NULL;
+       struct dyn_ftrace *rec;
+       int ret = -EBUSY;
+       mutex_lock(&direct_mutex);
+       /* See if there's a direct function at @ip already */
+       if (find_rec_direct(ip))
+               goto out_unlock;
+       ret = -ENODEV;
+       rec = lookup_rec(ip, ip);
+       if (!rec)
+               goto out_unlock;
+       /*
+        * Check if the rec says it has a direct call but we didn't
+        * find one earlier?
+        */
+       if (WARN_ON(rec->flags & FTRACE_FL_DIRECT))
+               goto out_unlock;
+       /* Make sure the ip points to the exact record */
+       if (ip != rec->ip) {
+               ip = rec->ip;
+               /* Need to check this ip for a direct. */
+               if (find_rec_direct(ip))
+                       goto out_unlock;
+       }
+       ret = -ENOMEM;
+       if (ftrace_hash_empty(direct_functions) ||
+           direct_functions->count > 2 * (1 << direct_functions->size_bits)) {
+               struct ftrace_hash *new_hash;
+               int size = ftrace_hash_empty(direct_functions) ? 0 :
+                       direct_functions->count + 1;
+               if (size < 32)
+                       size = 32;
+               new_hash = dup_hash(direct_functions, size);
+               if (!new_hash)
+                       goto out_unlock;
+               free_hash = direct_functions;
+               direct_functions = new_hash;
+       }
+       entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+       if (!entry)
+               goto out_unlock;
+       direct = ftrace_find_direct_func(addr);
+       if (!direct) {
+               direct = kmalloc(sizeof(*direct), GFP_KERNEL);
+               if (!direct) {
+                       kfree(entry);
+                       goto out_unlock;
+               }
+               direct->addr = addr;
+               direct->count = 0;
+               list_add_rcu(&direct->next, &ftrace_direct_funcs);
+               ftrace_direct_func_count++;
+       }
+       entry->ip = ip;
+       entry->direct = addr;
+       __add_hash_entry(direct_functions, entry);
+       ret = ftrace_set_filter_ip(&direct_ops, ip, 0, 0);
+       if (ret)
+               remove_hash_entry(direct_functions, entry);
+       if (!ret && !(direct_ops.flags & FTRACE_OPS_FL_ENABLED)) {
+               ret = register_ftrace_function(&direct_ops);
+               if (ret)
+                       ftrace_set_filter_ip(&direct_ops, ip, 1, 0);
+       }
+       if (ret) {
+               kfree(entry);
+               if (!direct->count) {
+                       list_del_rcu(&direct->next);
+                       synchronize_rcu_tasks();
+                       kfree(direct);
+                       if (free_hash)
+                               free_ftrace_hash(free_hash);
+                       free_hash = NULL;
+                       ftrace_direct_func_count--;
+               }
+       } else {
+               direct->count++;
+       }
+  out_unlock:
+       mutex_unlock(&direct_mutex);
+       if (free_hash) {
+               synchronize_rcu_tasks();
+               free_ftrace_hash(free_hash);
+       }
+       return ret;
+ }
+ EXPORT_SYMBOL_GPL(register_ftrace_direct);
+ static struct ftrace_func_entry *find_direct_entry(unsigned long *ip,
+                                                  struct dyn_ftrace **recp)
+ {
+       struct ftrace_func_entry *entry;
+       struct dyn_ftrace *rec;
+       rec = lookup_rec(*ip, *ip);
+       if (!rec)
+               return NULL;
+       entry = __ftrace_lookup_ip(direct_functions, rec->ip);
+       if (!entry) {
+               WARN_ON(rec->flags & FTRACE_FL_DIRECT);
+               return NULL;
+       }
+       WARN_ON(!(rec->flags & FTRACE_FL_DIRECT));
+       /* Passed in ip just needs to be on the call site */
+       *ip = rec->ip;
+       if (recp)
+               *recp = rec;
+       return entry;
+ }
+ int unregister_ftrace_direct(unsigned long ip, unsigned long addr)
+ {
+       struct ftrace_direct_func *direct;
+       struct ftrace_func_entry *entry;
+       int ret = -ENODEV;
+       mutex_lock(&direct_mutex);
+       entry = find_direct_entry(&ip, NULL);
+       if (!entry)
+               goto out_unlock;
+       if (direct_functions->count == 1)
+               unregister_ftrace_function(&direct_ops);
+       ret = ftrace_set_filter_ip(&direct_ops, ip, 1, 0);
+       WARN_ON(ret);
+       remove_hash_entry(direct_functions, entry);
+       direct = ftrace_find_direct_func(addr);
+       if (!WARN_ON(!direct)) {
+               /* This is the good path (see the ! before WARN) */
+               direct->count--;
+               WARN_ON(direct->count < 0);
+               if (!direct->count) {
+                       list_del_rcu(&direct->next);
+                       synchronize_rcu_tasks();
+                       kfree(direct);
+                       ftrace_direct_func_count--;
+               }
+       }
+  out_unlock:
+       mutex_unlock(&direct_mutex);
+       return ret;
+ }
+ EXPORT_SYMBOL_GPL(unregister_ftrace_direct);
+ static struct ftrace_ops stub_ops = {
+       .func           = ftrace_stub,
+ };
+ /**
+  * ftrace_modify_direct_caller - modify ftrace nop directly
+  * @entry: The ftrace hash entry of the direct helper for @rec
+  * @rec: The record representing the function site to patch
+  * @old_addr: The location that the site at @rec->ip currently calls
+  * @new_addr: The location that the site at @rec->ip should call
+  *
+  * An architecture may overwrite this function to optimize the
+  * changing of the direct callback on an ftrace nop location.
+  * This is called with the ftrace_lock mutex held, and no other
+  * ftrace callbacks are on the associated record (@rec). Thus,
+  * it is safe to modify the ftrace record, where it should be
+  * currently calling @old_addr directly, to call @new_addr.
+  *
+  * Safety checks should be made to make sure that the code at
+  * @rec->ip is currently calling @old_addr. And this must
+  * also update entry->direct to @new_addr.
+  */
+ int __weak ftrace_modify_direct_caller(struct ftrace_func_entry *entry,
+                                      struct dyn_ftrace *rec,
+                                      unsigned long old_addr,
+                                      unsigned long new_addr)
+ {
+       unsigned long ip = rec->ip;
+       int ret;
+       /*
+        * The ftrace_lock was used to determine if the record
+        * had more than one registered user to it. If it did,
+        * we needed to prevent that from changing to do the quick
+        * switch. But if it did not (only a direct caller was attached)
+        * then this function is called. But this function can deal
+        * with attached callers to the rec that we care about, and
+        * since this function uses standard ftrace calls that take
+        * the ftrace_lock mutex, we need to release it.
+        */
+       mutex_unlock(&ftrace_lock);
+       /*
+        * By setting a stub function at the same address, we force
+        * the code to call the iterator and the direct_ops helper.
+        * This means that @ip does not call the direct call, and
+        * we can simply modify it.
+        */
+       ret = ftrace_set_filter_ip(&stub_ops, ip, 0, 0);
+       if (ret)
+               goto out_lock;
+       ret = register_ftrace_function(&stub_ops);
+       if (ret) {
+               ftrace_set_filter_ip(&stub_ops, ip, 1, 0);
+               goto out_lock;
+       }
+       entry->direct = new_addr;
+       /*
+        * By removing the stub, we put back the direct call, calling
+        * the @new_addr.
+        */
+       unregister_ftrace_function(&stub_ops);
+       ftrace_set_filter_ip(&stub_ops, ip, 1, 0);
+  out_lock:
+       mutex_lock(&ftrace_lock);
+       return ret;
+ }
+ /**
+  * modify_ftrace_direct - Modify an existing direct call to call something else
+  * @ip: The instruction pointer to modify
+  * @old_addr: The address that the current @ip calls directly
+  * @new_addr: The address that the @ip should call
+  *
+  * This modifies a ftrace direct caller at an instruction pointer without
+  * having to disable it first. The direct call will switch over to the
+  * @new_addr without missing anything.
+  *
+  * Returns: zero on success. Non zero on error, which includes:
+  *  -ENODEV : the @ip given has no direct caller attached
+  *  -EINVAL : the @old_addr does not match the current direct caller
+  */
+ int modify_ftrace_direct(unsigned long ip,
+                        unsigned long old_addr, unsigned long new_addr)
+ {
+       struct ftrace_func_entry *entry;
+       struct dyn_ftrace *rec;
+       int ret = -ENODEV;
+       mutex_lock(&direct_mutex);
+       mutex_lock(&ftrace_lock);
+       entry = find_direct_entry(&ip, &rec);
+       if (!entry)
+               goto out_unlock;
+       ret = -EINVAL;
+       if (entry->direct != old_addr)
+               goto out_unlock;
+       /*
+        * If there's no other ftrace callback on the rec->ip location,
+        * then it can be changed directly by the architecture.
+        * If there is another caller, then we just need to change the
+        * direct caller helper to point to @new_addr.
+        */
+       if (ftrace_rec_count(rec) == 1) {
+               ret = ftrace_modify_direct_caller(entry, rec, old_addr, new_addr);
+       } else {
+               entry->direct = new_addr;
+               ret = 0;
+       }
+  out_unlock:
+       mutex_unlock(&ftrace_lock);
+       mutex_unlock(&direct_mutex);
+       return ret;
+ }
+ EXPORT_SYMBOL_GPL(modify_ftrace_direct);
+ #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
  /**
   * ftrace_set_filter_ip - set a function to filter on in ftrace by address
   * @ops - the ops to set the filter with
@@@ -5818,6 -6317,8 +6317,8 @@@ void ftrace_release_mod(struct module *
                free_pages((unsigned long)pg->records, order);
                tmp_page = pg->next;
                kfree(pg);
+               ftrace_number_of_pages -= 1 << order;
+               ftrace_number_of_groups--;
        }
  }
  
@@@ -6159,6 -6660,8 +6660,8 @@@ void ftrace_free_mem(struct module *mod
                        *last_pg = pg->next;
                        order = get_count_order(pg->size / ENTRIES_PER_PAGE);
                        free_pages((unsigned long)pg->records, order);
+                       ftrace_number_of_pages -= 1 << order;
+                       ftrace_number_of_groups--;
                        kfree(pg);
                        pg = container_of(last_pg, struct ftrace_page, next);
                        if (!(*last_pg))
@@@ -6214,6 -6717,9 +6717,9 @@@ void __init ftrace_init(void
                                  __start_mcount_loc,
                                  __stop_mcount_loc);
  
+       pr_info("ftrace: allocated %ld pages with %ld groups\n",
+               ftrace_number_of_pages, ftrace_number_of_groups);
        set_ftrace_early_filters();
  
        return;
@@@ -6754,6 -7260,18 +7260,18 @@@ int unregister_ftrace_function(struct f
  }
  EXPORT_SYMBOL_GPL(unregister_ftrace_function);
  
+ static bool is_permanent_ops_registered(void)
+ {
+       struct ftrace_ops *op;
+       do_for_each_ftrace_op(op, ftrace_ops_list) {
+               if (op->flags & FTRACE_OPS_FL_PERMANENT)
+                       return true;
+       } while_for_each_ftrace_op(op);
+       return false;
+ }
  int
  ftrace_enable_sysctl(struct ctl_table *table, int write,
                     void __user *buffer, size_t *lenp,
        if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled))
                goto out;
  
-       last_ftrace_enabled = !!ftrace_enabled;
        if (ftrace_enabled) {
  
                /* we are starting ftrace again */
                ftrace_startup_sysctl();
  
        } else {
+               if (is_permanent_ops_registered()) {
+                       ftrace_enabled = true;
+                       ret = -EBUSY;
+                       goto out;
+               }
                /* stopping ftrace calls (just send to ftrace_stub) */
                ftrace_trace_function = ftrace_stub;
  
                ftrace_shutdown_sysctl();
        }
  
+       last_ftrace_enabled = !!ftrace_enabled;
   out:
        mutex_unlock(&ftrace_lock);
        return ret;
diff --combined samples/Kconfig
index b663d9d241145a59f6ff928cf38dbfb1de59815c,ad64b223f3d0019d69a366e8092eeca6a45e5205..9d236c346de506dfcf65cba58dbec3507659bc18
@@@ -19,6 -19,21 +19,21 @@@ config SAMPLE_TRACE_PRINT
         This builds a module that calls trace_printk() and can be used to
         test various trace_printk() calls from a module.
  
+ config SAMPLE_FTRACE_DIRECT
+       tristate "Build register_ftrace_direct() example"
+       depends on DYNAMIC_FTRACE_WITH_DIRECT_CALLS && m
+       depends on X86_64 # has x86_64 inlined asm
+       help
+         This builds an ftrace direct function example
+         that hooks to wake_up_process and prints the parameters.
+ config SAMPLE_TRACE_ARRAY
+         tristate "Build sample module for kernel access to Ftrace instancess"
+       depends on EVENT_TRACING && m
+       help
+        This builds a module that demonstrates the use of various APIs to
+        access Ftrace instances from within the kernel.
  config SAMPLE_KOBJECT
        tristate "Build kobject examples"
        help
@@@ -169,11 -184,4 +184,11 @@@ config SAMPLE_VF
          as mount API and statx().  Note that this is restricted to the x86
          arch whilst it accesses system calls that aren't yet in all arches.
  
 +config SAMPLE_INTEL_MEI
 +      bool "Build example program working with intel mei driver"
 +      depends on INTEL_MEI
 +      help
 +        Build a sample program to work with mei device.
 +
 +
  endif # SAMPLES
diff --combined samples/Makefile
index d6062ab25347d89e50f4db77bb6758643bd15986,297f8934773fda45644f642f8f3b6fc20aacdff8..5ce50ef0f2b2eed9b48ec06aba1202afd3f0e515
@@@ -17,7 -17,8 +17,9 @@@ obj-$(CONFIG_SAMPLE_RPMSG_CLIENT)     += rp
  subdir-$(CONFIG_SAMPLE_SECCOMP)               += seccomp
  obj-$(CONFIG_SAMPLE_TRACE_EVENTS)     += trace_events/
  obj-$(CONFIG_SAMPLE_TRACE_PRINTK)     += trace_printk/
+ obj-$(CONFIG_SAMPLE_FTRACE_DIRECT)    += ftrace/
+ obj-$(CONFIG_SAMPLE_TRACE_ARRAY)      += ftrace/
  obj-$(CONFIG_VIDEO_PCI_SKELETON)      += v4l/
  obj-y                                 += vfio-mdev/
  subdir-$(CONFIG_SAMPLE_VFS)           += vfs
 +obj-$(CONFIG_SAMPLE_INTEL_MEI)                += mei/
index 1cf40a9e718525cd98973a8495745b5cfaa03c99,1886d9d94b88988033c76a652e95e4016771bcc2..3876d8d62494443297b0da55cb88bbe5f2da5210
@@@ -5,6 -5,6 +5,7 @@@ TEST_PROGS := 
        test-livepatch.sh \
        test-callbacks.sh \
        test-shadow-vars.sh \
-       test-state.sh
++      test-state.sh \
+       test-ftrace.sh
  
  include ../lib.mk