diff options
author | Waldemar Brodkorb <wbx@openadk.org> | 2015-06-03 16:53:31 -0500 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2015-06-03 16:54:21 -0500 |
commit | e38204a8348094cf703ad70680d4b50b865759e0 (patch) | |
tree | 1ebb31885a3d30075c030c8c42ce3c678f96689f /target/linux | |
parent | f81fe6f2d52cc051f11a9be53e937b242390a2d1 (diff) |
update kernel to 3.18.14, refresh realtime and rpi patches
Diffstat (limited to 'target/linux')
-rw-r--r-- | target/linux/patches/3.18.14/bsd-compatibility.patch (renamed from target/linux/patches/3.18.12/bsd-compatibility.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/cleankernel.patch (renamed from target/linux/patches/3.18.12/cleankernel.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/cris-header.patch (renamed from target/linux/patches/3.18.12/cris-header.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/cris-initramfs.patch (renamed from target/linux/patches/3.18.12/cris-initramfs.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/defaults.patch (renamed from target/linux/patches/3.18.12/defaults.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/export-symbol-for-exmap.patch (renamed from target/linux/patches/3.18.12/export-symbol-for-exmap.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/fblogo.patch (renamed from target/linux/patches/3.18.12/fblogo.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/gemalto.patch (renamed from target/linux/patches/3.18.12/gemalto.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/initramfs-nosizelimit.patch (renamed from target/linux/patches/3.18.12/initramfs-nosizelimit.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/lemote-rfkill.patch (renamed from target/linux/patches/3.18.12/lemote-rfkill.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/microblaze-ethernet.patch (renamed from target/linux/patches/3.18.12/microblaze-ethernet.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/mkpiggy.patch (renamed from target/linux/patches/3.18.12/mkpiggy.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/mtd-rootfs.patch (renamed from target/linux/patches/3.18.12/mtd-rootfs.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/nfsv3-tcp.patch (renamed from target/linux/patches/3.18.12/nfsv3-tcp.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/non-static.patch (renamed from target/linux/patches/3.18.12/non-static.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/ppc64-missing-zlib.patch (renamed from target/linux/patches/3.18.12/ppc64-missing-zlib.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/realtime.patch (renamed from target/linux/patches/3.18.12/realtime.patch) | 25536 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/regmap-bool.patch (renamed from target/linux/patches/3.18.12/regmap-bool.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/relocs.patch (renamed from target/linux/patches/3.18.12/relocs.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/sgidefs.patch (renamed from target/linux/patches/3.18.12/sgidefs.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/sortext.patch (renamed from target/linux/patches/3.18.12/sortext.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/startup.patch (renamed from target/linux/patches/3.18.12/startup.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/wlan-cf.patch (renamed from target/linux/patches/3.18.12/wlan-cf.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/xargs.patch (renamed from target/linux/patches/3.18.12/xargs.patch) | 0 | ||||
-rw-r--r-- | target/linux/patches/3.18.14/yaffs2.patch (renamed from target/linux/patches/3.18.12/yaffs2.patch) | 0 |
25 files changed, 13026 insertions, 12510 deletions
diff --git a/target/linux/patches/3.18.12/bsd-compatibility.patch b/target/linux/patches/3.18.14/bsd-compatibility.patch index b954b658f..b954b658f 100644 --- a/target/linux/patches/3.18.12/bsd-compatibility.patch +++ b/target/linux/patches/3.18.14/bsd-compatibility.patch diff --git a/target/linux/patches/3.18.12/cleankernel.patch b/target/linux/patches/3.18.14/cleankernel.patch index d8c055dc3..d8c055dc3 100644 --- a/target/linux/patches/3.18.12/cleankernel.patch +++ b/target/linux/patches/3.18.14/cleankernel.patch diff --git a/target/linux/patches/3.18.12/cris-header.patch b/target/linux/patches/3.18.14/cris-header.patch index 3db07e530..3db07e530 100644 --- a/target/linux/patches/3.18.12/cris-header.patch +++ b/target/linux/patches/3.18.14/cris-header.patch diff --git a/target/linux/patches/3.18.12/cris-initramfs.patch b/target/linux/patches/3.18.14/cris-initramfs.patch index b709e705e..b709e705e 100644 --- a/target/linux/patches/3.18.12/cris-initramfs.patch +++ b/target/linux/patches/3.18.14/cris-initramfs.patch diff --git a/target/linux/patches/3.18.12/defaults.patch b/target/linux/patches/3.18.14/defaults.patch index 6cdca084e..6cdca084e 100644 --- a/target/linux/patches/3.18.12/defaults.patch +++ b/target/linux/patches/3.18.14/defaults.patch diff --git a/target/linux/patches/3.18.12/export-symbol-for-exmap.patch b/target/linux/patches/3.18.14/export-symbol-for-exmap.patch index 4f0fc8449..4f0fc8449 100644 --- a/target/linux/patches/3.18.12/export-symbol-for-exmap.patch +++ b/target/linux/patches/3.18.14/export-symbol-for-exmap.patch diff --git a/target/linux/patches/3.18.12/fblogo.patch b/target/linux/patches/3.18.14/fblogo.patch index 5b9070242..5b9070242 100644 --- a/target/linux/patches/3.18.12/fblogo.patch +++ b/target/linux/patches/3.18.14/fblogo.patch diff --git a/target/linux/patches/3.18.12/gemalto.patch b/target/linux/patches/3.18.14/gemalto.patch index 65f7af1d7..65f7af1d7 100644 --- a/target/linux/patches/3.18.12/gemalto.patch +++ b/target/linux/patches/3.18.14/gemalto.patch diff --git a/target/linux/patches/3.18.12/initramfs-nosizelimit.patch b/target/linux/patches/3.18.14/initramfs-nosizelimit.patch index 40d2f6bd8..40d2f6bd8 100644 --- a/target/linux/patches/3.18.12/initramfs-nosizelimit.patch +++ b/target/linux/patches/3.18.14/initramfs-nosizelimit.patch diff --git a/target/linux/patches/3.18.12/lemote-rfkill.patch b/target/linux/patches/3.18.14/lemote-rfkill.patch index a61488434..a61488434 100644 --- a/target/linux/patches/3.18.12/lemote-rfkill.patch +++ b/target/linux/patches/3.18.14/lemote-rfkill.patch diff --git a/target/linux/patches/3.18.12/microblaze-ethernet.patch b/target/linux/patches/3.18.14/microblaze-ethernet.patch index 742ab477e..742ab477e 100644 --- a/target/linux/patches/3.18.12/microblaze-ethernet.patch +++ b/target/linux/patches/3.18.14/microblaze-ethernet.patch diff --git a/target/linux/patches/3.18.12/mkpiggy.patch b/target/linux/patches/3.18.14/mkpiggy.patch index 751678b74..751678b74 100644 --- a/target/linux/patches/3.18.12/mkpiggy.patch +++ b/target/linux/patches/3.18.14/mkpiggy.patch diff --git a/target/linux/patches/3.18.12/mtd-rootfs.patch b/target/linux/patches/3.18.14/mtd-rootfs.patch index 775d5fc80..775d5fc80 100644 --- a/target/linux/patches/3.18.12/mtd-rootfs.patch +++ b/target/linux/patches/3.18.14/mtd-rootfs.patch diff --git a/target/linux/patches/3.18.12/nfsv3-tcp.patch b/target/linux/patches/3.18.14/nfsv3-tcp.patch index d5e07e1c2..d5e07e1c2 100644 --- a/target/linux/patches/3.18.12/nfsv3-tcp.patch +++ b/target/linux/patches/3.18.14/nfsv3-tcp.patch diff --git a/target/linux/patches/3.18.12/non-static.patch b/target/linux/patches/3.18.14/non-static.patch index a967703d0..a967703d0 100644 --- a/target/linux/patches/3.18.12/non-static.patch +++ b/target/linux/patches/3.18.14/non-static.patch diff --git a/target/linux/patches/3.18.12/ppc64-missing-zlib.patch b/target/linux/patches/3.18.14/ppc64-missing-zlib.patch index c6e0616be..c6e0616be 100644 --- a/target/linux/patches/3.18.12/ppc64-missing-zlib.patch +++ b/target/linux/patches/3.18.14/ppc64-missing-zlib.patch diff --git a/target/linux/patches/3.18.12/realtime.patch b/target/linux/patches/3.18.14/realtime.patch index e91381e07..28b9b271c 100644 --- a/target/linux/patches/3.18.12/realtime.patch +++ b/target/linux/patches/3.18.14/realtime.patch @@ -1,6 +1,6 @@ -diff -Nur linux-3.18.12.orig/arch/alpha/mm/fault.c linux-3.18.12/arch/alpha/mm/fault.c ---- linux-3.18.12.orig/arch/alpha/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/alpha/mm/fault.c 2015-04-26 13:32:22.351684003 -0500 +diff -Nur linux-3.18.14.orig/arch/alpha/mm/fault.c linux-3.18.14-rt/arch/alpha/mm/fault.c +--- linux-3.18.14.orig/arch/alpha/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/alpha/mm/fault.c 2015-05-31 15:32:45.517635394 -0500 @@ -107,7 +107,7 @@ /* If we're in an interrupt context, or have no user context, @@ -10,9 +10,9 @@ diff -Nur linux-3.18.12.orig/arch/alpha/mm/fault.c linux-3.18.12/arch/alpha/mm/f goto no_context; #ifdef CONFIG_ALPHA_LARGE_VMALLOC -diff -Nur linux-3.18.12.orig/arch/arm/include/asm/cmpxchg.h linux-3.18.12/arch/arm/include/asm/cmpxchg.h ---- linux-3.18.12.orig/arch/arm/include/asm/cmpxchg.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/include/asm/cmpxchg.h 2015-04-26 13:32:22.351684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/include/asm/cmpxchg.h linux-3.18.14-rt/arch/arm/include/asm/cmpxchg.h +--- linux-3.18.14.orig/arch/arm/include/asm/cmpxchg.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/include/asm/cmpxchg.h 2015-05-31 15:32:45.557635393 -0500 @@ -129,6 +129,8 @@ #else /* min ARCH >= ARMv6 */ @@ -22,9 +22,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/include/asm/cmpxchg.h linux-3.18.12/arch/a extern void __bad_cmpxchg(volatile void *ptr, int size); /* -diff -Nur linux-3.18.12.orig/arch/arm/include/asm/futex.h linux-3.18.12/arch/arm/include/asm/futex.h ---- linux-3.18.12.orig/arch/arm/include/asm/futex.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/include/asm/futex.h 2015-04-26 13:32:22.351684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/include/asm/futex.h linux-3.18.14-rt/arch/arm/include/asm/futex.h +--- linux-3.18.14.orig/arch/arm/include/asm/futex.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/include/asm/futex.h 2015-05-31 15:32:45.561635393 -0500 @@ -93,6 +93,8 @@ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) return -EFAULT; @@ -43,9 +43,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/include/asm/futex.h linux-3.18.12/arch/arm return ret; } -diff -Nur linux-3.18.12.orig/arch/arm/include/asm/switch_to.h linux-3.18.12/arch/arm/include/asm/switch_to.h ---- linux-3.18.12.orig/arch/arm/include/asm/switch_to.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/include/asm/switch_to.h 2015-04-26 13:32:22.355684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/include/asm/switch_to.h linux-3.18.14-rt/arch/arm/include/asm/switch_to.h +--- linux-3.18.14.orig/arch/arm/include/asm/switch_to.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/include/asm/switch_to.h 2015-05-31 15:32:45.565635393 -0500 @@ -3,6 +3,13 @@ #include <linux/thread_info.h> @@ -68,9 +68,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/include/asm/switch_to.h linux-3.18.12/arch last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \ } while (0) -diff -Nur linux-3.18.12.orig/arch/arm/include/asm/thread_info.h linux-3.18.12/arch/arm/include/asm/thread_info.h ---- linux-3.18.12.orig/arch/arm/include/asm/thread_info.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/include/asm/thread_info.h 2015-04-26 13:32:22.355684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/include/asm/thread_info.h linux-3.18.14-rt/arch/arm/include/asm/thread_info.h +--- linux-3.18.14.orig/arch/arm/include/asm/thread_info.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/include/asm/thread_info.h 2015-05-31 15:32:45.585635393 -0500 @@ -51,6 +51,7 @@ struct thread_info { unsigned long flags; /* low level flags */ @@ -95,9 +95,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/include/asm/thread_info.h linux-3.18.12/ar #define _TIF_UPROBE (1 << TIF_UPROBE) #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) -diff -Nur linux-3.18.12.orig/arch/arm/Kconfig linux-3.18.12/arch/arm/Kconfig ---- linux-3.18.12.orig/arch/arm/Kconfig 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/Kconfig 2015-04-26 13:32:22.351684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/Kconfig linux-3.18.14-rt/arch/arm/Kconfig +--- linux-3.18.14.orig/arch/arm/Kconfig 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/Kconfig 2015-05-31 15:32:45.529635394 -0500 @@ -62,6 +62,7 @@ select HAVE_PERF_EVENTS select HAVE_PERF_REGS @@ -106,9 +106,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/Kconfig linux-3.18.12/arch/arm/Kconfig select HAVE_RCU_TABLE_FREE if (SMP && ARM_LPAE) select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_SYSCALL_TRACEPOINTS -diff -Nur linux-3.18.12.orig/arch/arm/kernel/asm-offsets.c linux-3.18.12/arch/arm/kernel/asm-offsets.c ---- linux-3.18.12.orig/arch/arm/kernel/asm-offsets.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/kernel/asm-offsets.c 2015-04-26 13:32:22.355684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/kernel/asm-offsets.c linux-3.18.14-rt/arch/arm/kernel/asm-offsets.c +--- linux-3.18.14.orig/arch/arm/kernel/asm-offsets.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/kernel/asm-offsets.c 2015-05-31 15:32:45.605635393 -0500 @@ -64,6 +64,7 @@ BLANK(); DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); @@ -117,9 +117,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/kernel/asm-offsets.c linux-3.18.12/arch/ar DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); DEFINE(TI_TASK, offsetof(struct thread_info, task)); DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain)); -diff -Nur linux-3.18.12.orig/arch/arm/kernel/entry-armv.S linux-3.18.12/arch/arm/kernel/entry-armv.S ---- linux-3.18.12.orig/arch/arm/kernel/entry-armv.S 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/kernel/entry-armv.S 2015-04-26 13:32:22.355684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/kernel/entry-armv.S linux-3.18.14-rt/arch/arm/kernel/entry-armv.S +--- linux-3.18.14.orig/arch/arm/kernel/entry-armv.S 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/kernel/entry-armv.S 2015-05-31 15:32:45.613635393 -0500 @@ -207,11 +207,18 @@ #ifdef CONFIG_PREEMPT get_thread_info tsk @@ -150,10 +150,10 @@ diff -Nur linux-3.18.12.orig/arch/arm/kernel/entry-armv.S linux-3.18.12/arch/arm reteq r8 @ go again b 1b #endif -diff -Nur linux-3.18.12.orig/arch/arm/kernel/process.c linux-3.18.12/arch/arm/kernel/process.c ---- linux-3.18.12.orig/arch/arm/kernel/process.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/kernel/process.c 2015-04-26 13:32:22.355684003 -0500 -@@ -431,6 +431,30 @@ +diff -Nur linux-3.18.14.orig/arch/arm/kernel/process.c linux-3.18.14-rt/arch/arm/kernel/process.c +--- linux-3.18.14.orig/arch/arm/kernel/process.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/kernel/process.c 2015-05-31 15:32:45.617635393 -0500 +@@ -437,6 +437,30 @@ } #ifdef CONFIG_MMU @@ -184,9 +184,573 @@ diff -Nur linux-3.18.12.orig/arch/arm/kernel/process.c linux-3.18.12/arch/arm/ke #ifdef CONFIG_KUSER_HELPERS /* * The vectors page is always readable from user space for the -diff -Nur linux-3.18.12.orig/arch/arm/kernel/signal.c linux-3.18.12/arch/arm/kernel/signal.c ---- linux-3.18.12.orig/arch/arm/kernel/signal.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/kernel/signal.c 2015-04-26 13:32:22.359684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/kernel/process.c.orig linux-3.18.14-rt/arch/arm/kernel/process.c.orig +--- linux-3.18.14.orig/arch/arm/kernel/process.c.orig 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/arch/arm/kernel/process.c.orig 2015-05-20 10:04:50.000000000 -0500 +@@ -0,0 +1,560 @@ ++/* ++ * linux/arch/arm/kernel/process.c ++ * ++ * Copyright (C) 1996-2000 Russell King - Converted to ARM. ++ * Original Copyright (C) 1995 Linus Torvalds ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++#include <stdarg.h> ++ ++#include <linux/export.h> ++#include <linux/sched.h> ++#include <linux/kernel.h> ++#include <linux/mm.h> ++#include <linux/stddef.h> ++#include <linux/unistd.h> ++#include <linux/user.h> ++#include <linux/delay.h> ++#include <linux/reboot.h> ++#include <linux/interrupt.h> ++#include <linux/kallsyms.h> ++#include <linux/init.h> ++#include <linux/cpu.h> ++#include <linux/elfcore.h> ++#include <linux/pm.h> ++#include <linux/tick.h> ++#include <linux/utsname.h> ++#include <linux/uaccess.h> ++#include <linux/random.h> ++#include <linux/hw_breakpoint.h> ++#include <linux/leds.h> ++#include <linux/reboot.h> ++ ++#include <asm/cacheflush.h> ++#include <asm/idmap.h> ++#include <asm/processor.h> ++#include <asm/thread_notify.h> ++#include <asm/stacktrace.h> ++#include <asm/system_misc.h> ++#include <asm/mach/time.h> ++#include <asm/tls.h> ++#include "reboot.h" ++ ++#ifdef CONFIG_CC_STACKPROTECTOR ++#include <linux/stackprotector.h> ++unsigned long __stack_chk_guard __read_mostly; ++EXPORT_SYMBOL(__stack_chk_guard); ++#endif ++ ++static const char *processor_modes[] __maybe_unused = { ++ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , ++ "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", ++ "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" , ++ "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" ++}; ++ ++static const char *isa_modes[] __maybe_unused = { ++ "ARM" , "Thumb" , "Jazelle", "ThumbEE" ++}; ++ ++extern void call_with_stack(void (*fn)(void *), void *arg, void *sp); ++typedef void (*phys_reset_t)(unsigned long); ++ ++/* ++ * A temporary stack to use for CPU reset. This is static so that we ++ * don't clobber it with the identity mapping. When running with this ++ * stack, any references to the current task *will not work* so you ++ * should really do as little as possible before jumping to your reset ++ * code. ++ */ ++static u64 soft_restart_stack[16]; ++ ++static void __soft_restart(void *addr) ++{ ++ phys_reset_t phys_reset; ++ ++ /* Take out a flat memory mapping. */ ++ setup_mm_for_reboot(); ++ ++ /* Clean and invalidate caches */ ++ flush_cache_all(); ++ ++ /* Turn off caching */ ++ cpu_proc_fin(); ++ ++ /* Push out any further dirty data, and ensure cache is empty */ ++ flush_cache_all(); ++ ++ /* Switch to the identity mapping. */ ++ phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset); ++ phys_reset((unsigned long)addr); ++ ++ /* Should never get here. */ ++ BUG(); ++} ++ ++void _soft_restart(unsigned long addr, bool disable_l2) ++{ ++ u64 *stack = soft_restart_stack + ARRAY_SIZE(soft_restart_stack); ++ ++ /* Disable interrupts first */ ++ raw_local_irq_disable(); ++ local_fiq_disable(); ++ ++ /* Disable the L2 if we're the last man standing. */ ++ if (disable_l2) ++ outer_disable(); ++ ++ /* Change to the new stack and continue with the reset. */ ++ call_with_stack(__soft_restart, (void *)addr, (void *)stack); ++ ++ /* Should never get here. */ ++ BUG(); ++} ++ ++void soft_restart(unsigned long addr) ++{ ++ _soft_restart(addr, num_online_cpus() == 1); ++} ++ ++/* ++ * Function pointers to optional machine specific functions ++ */ ++void (*pm_power_off)(void); ++EXPORT_SYMBOL(pm_power_off); ++ ++void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd); ++ ++/* ++ * This is our default idle handler. ++ */ ++ ++void (*arm_pm_idle)(void); ++ ++/* ++ * Called from the core idle loop. ++ */ ++ ++void arch_cpu_idle(void) ++{ ++ if (arm_pm_idle) ++ arm_pm_idle(); ++ else ++ cpu_do_idle(); ++ local_irq_enable(); ++} ++ ++void arch_cpu_idle_prepare(void) ++{ ++ local_fiq_enable(); ++} ++ ++void arch_cpu_idle_enter(void) ++{ ++ ledtrig_cpu(CPU_LED_IDLE_START); ++#ifdef CONFIG_PL310_ERRATA_769419 ++ wmb(); ++#endif ++} ++ ++void arch_cpu_idle_exit(void) ++{ ++ ledtrig_cpu(CPU_LED_IDLE_END); ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++void arch_cpu_idle_dead(void) ++{ ++ cpu_die(); ++} ++#endif ++ ++/* ++ * Called by kexec, immediately prior to machine_kexec(). ++ * ++ * This must completely disable all secondary CPUs; simply causing those CPUs ++ * to execute e.g. a RAM-based pin loop is not sufficient. This allows the ++ * kexec'd kernel to use any and all RAM as it sees fit, without having to ++ * avoid any code or data used by any SW CPU pin loop. The CPU hotplug ++ * functionality embodied in disable_nonboot_cpus() to achieve this. ++ */ ++void machine_shutdown(void) ++{ ++ disable_nonboot_cpus(); ++} ++ ++/* ++ * Halting simply requires that the secondary CPUs stop performing any ++ * activity (executing tasks, handling interrupts). smp_send_stop() ++ * achieves this. ++ */ ++void machine_halt(void) ++{ ++ local_irq_disable(); ++ smp_send_stop(); ++ ++ local_irq_disable(); ++ while (1); ++} ++ ++/* ++ * Power-off simply requires that the secondary CPUs stop performing any ++ * activity (executing tasks, handling interrupts). smp_send_stop() ++ * achieves this. When the system power is turned off, it will take all CPUs ++ * with it. ++ */ ++void machine_power_off(void) ++{ ++ local_irq_disable(); ++ smp_send_stop(); ++ ++ if (pm_power_off) ++ pm_power_off(); ++} ++ ++/* ++ * Restart requires that the secondary CPUs stop performing any activity ++ * while the primary CPU resets the system. Systems with a single CPU can ++ * use soft_restart() as their machine descriptor's .restart hook, since that ++ * will cause the only available CPU to reset. Systems with multiple CPUs must ++ * provide a HW restart implementation, to ensure that all CPUs reset at once. ++ * This is required so that any code running after reset on the primary CPU ++ * doesn't have to co-ordinate with other CPUs to ensure they aren't still ++ * executing pre-reset code, and using RAM that the primary CPU's code wishes ++ * to use. Implementing such co-ordination would be essentially impossible. ++ */ ++void machine_restart(char *cmd) ++{ ++ local_irq_disable(); ++ smp_send_stop(); ++ ++ if (arm_pm_restart) ++ arm_pm_restart(reboot_mode, cmd); ++ else ++ do_kernel_restart(cmd); ++ ++ /* Give a grace period for failure to restart of 1s */ ++ mdelay(1000); ++ ++ /* Whoops - the platform was unable to reboot. Tell the user! */ ++ printk("Reboot failed -- System halted\n"); ++ local_irq_disable(); ++ while (1); ++} ++ ++void __show_regs(struct pt_regs *regs) ++{ ++ unsigned long flags; ++ char buf[64]; ++ ++ show_regs_print_info(KERN_DEFAULT); ++ ++ print_symbol("PC is at %s\n", instruction_pointer(regs)); ++ print_symbol("LR is at %s\n", regs->ARM_lr); ++ printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n" ++ "sp : %08lx ip : %08lx fp : %08lx\n", ++ regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr, ++ regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); ++ printk("r10: %08lx r9 : %08lx r8 : %08lx\n", ++ regs->ARM_r10, regs->ARM_r9, ++ regs->ARM_r8); ++ printk("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", ++ regs->ARM_r7, regs->ARM_r6, ++ regs->ARM_r5, regs->ARM_r4); ++ printk("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", ++ regs->ARM_r3, regs->ARM_r2, ++ regs->ARM_r1, regs->ARM_r0); ++ ++ flags = regs->ARM_cpsr; ++ buf[0] = flags & PSR_N_BIT ? 'N' : 'n'; ++ buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z'; ++ buf[2] = flags & PSR_C_BIT ? 'C' : 'c'; ++ buf[3] = flags & PSR_V_BIT ? 'V' : 'v'; ++ buf[4] = '\0'; ++ ++#ifndef CONFIG_CPU_V7M ++ printk("Flags: %s IRQs o%s FIQs o%s Mode %s ISA %s Segment %s\n", ++ buf, interrupts_enabled(regs) ? "n" : "ff", ++ fast_interrupts_enabled(regs) ? "n" : "ff", ++ processor_modes[processor_mode(regs)], ++ isa_modes[isa_mode(regs)], ++ get_fs() == get_ds() ? "kernel" : "user"); ++#else ++ printk("xPSR: %08lx\n", regs->ARM_cpsr); ++#endif ++ ++#ifdef CONFIG_CPU_CP15 ++ { ++ unsigned int ctrl; ++ ++ buf[0] = '\0'; ++#ifdef CONFIG_CPU_CP15_MMU ++ { ++ unsigned int transbase, dac; ++ asm("mrc p15, 0, %0, c2, c0\n\t" ++ "mrc p15, 0, %1, c3, c0\n" ++ : "=r" (transbase), "=r" (dac)); ++ snprintf(buf, sizeof(buf), " Table: %08x DAC: %08x", ++ transbase, dac); ++ } ++#endif ++ asm("mrc p15, 0, %0, c1, c0\n" : "=r" (ctrl)); ++ ++ printk("Control: %08x%s\n", ctrl, buf); ++ } ++#endif ++} ++ ++void show_regs(struct pt_regs * regs) ++{ ++ __show_regs(regs); ++ dump_stack(); ++} ++ ++ATOMIC_NOTIFIER_HEAD(thread_notify_head); ++ ++EXPORT_SYMBOL_GPL(thread_notify_head); ++ ++/* ++ * Free current thread data structures etc.. ++ */ ++void exit_thread(void) ++{ ++ thread_notify(THREAD_NOTIFY_EXIT, current_thread_info()); ++} ++ ++void flush_thread(void) ++{ ++ struct thread_info *thread = current_thread_info(); ++ struct task_struct *tsk = current; ++ ++ flush_ptrace_hw_breakpoint(tsk); ++ ++ memset(thread->used_cp, 0, sizeof(thread->used_cp)); ++ memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); ++ memset(&thread->fpstate, 0, sizeof(union fp_state)); ++ ++ flush_tls(); ++ ++ thread_notify(THREAD_NOTIFY_FLUSH, thread); ++} ++ ++void release_thread(struct task_struct *dead_task) ++{ ++} ++ ++asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); ++ ++int ++copy_thread(unsigned long clone_flags, unsigned long stack_start, ++ unsigned long stk_sz, struct task_struct *p) ++{ ++ struct thread_info *thread = task_thread_info(p); ++ struct pt_regs *childregs = task_pt_regs(p); ++ ++ memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); ++ ++ if (likely(!(p->flags & PF_KTHREAD))) { ++ *childregs = *current_pt_regs(); ++ childregs->ARM_r0 = 0; ++ if (stack_start) ++ childregs->ARM_sp = stack_start; ++ } else { ++ memset(childregs, 0, sizeof(struct pt_regs)); ++ thread->cpu_context.r4 = stk_sz; ++ thread->cpu_context.r5 = stack_start; ++ childregs->ARM_cpsr = SVC_MODE; ++ } ++ thread->cpu_context.pc = (unsigned long)ret_from_fork; ++ thread->cpu_context.sp = (unsigned long)childregs; ++ ++ clear_ptrace_hw_breakpoint(p); ++ ++ if (clone_flags & CLONE_SETTLS) ++ thread->tp_value[0] = childregs->ARM_r3; ++ thread->tp_value[1] = get_tpuser(); ++ ++ thread_notify(THREAD_NOTIFY_COPY, thread); ++ ++ return 0; ++} ++ ++/* ++ * Fill in the task's elfregs structure for a core dump. ++ */ ++int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs) ++{ ++ elf_core_copy_regs(elfregs, task_pt_regs(t)); ++ return 1; ++} ++ ++/* ++ * fill in the fpe structure for a core dump... ++ */ ++int dump_fpu (struct pt_regs *regs, struct user_fp *fp) ++{ ++ struct thread_info *thread = current_thread_info(); ++ int used_math = thread->used_cp[1] | thread->used_cp[2]; ++ ++ if (used_math) ++ memcpy(fp, &thread->fpstate.soft, sizeof (*fp)); ++ ++ return used_math != 0; ++} ++EXPORT_SYMBOL(dump_fpu); ++ ++unsigned long get_wchan(struct task_struct *p) ++{ ++ struct stackframe frame; ++ unsigned long stack_page; ++ int count = 0; ++ if (!p || p == current || p->state == TASK_RUNNING) ++ return 0; ++ ++ frame.fp = thread_saved_fp(p); ++ frame.sp = thread_saved_sp(p); ++ frame.lr = 0; /* recovered from the stack */ ++ frame.pc = thread_saved_pc(p); ++ stack_page = (unsigned long)task_stack_page(p); ++ do { ++ if (frame.sp < stack_page || ++ frame.sp >= stack_page + THREAD_SIZE || ++ unwind_frame(&frame) < 0) ++ return 0; ++ if (!in_sched_functions(frame.pc)) ++ return frame.pc; ++ } while (count ++ < 16); ++ return 0; ++} ++ ++unsigned long arch_randomize_brk(struct mm_struct *mm) ++{ ++ unsigned long range_end = mm->brk + 0x02000000; ++ return randomize_range(mm->brk, range_end, 0) ? : mm->brk; ++} ++ ++#ifdef CONFIG_MMU ++#ifdef CONFIG_KUSER_HELPERS ++/* ++ * The vectors page is always readable from user space for the ++ * atomic helpers. Insert it into the gate_vma so that it is visible ++ * through ptrace and /proc/<pid>/mem. ++ */ ++static struct vm_area_struct gate_vma = { ++ .vm_start = 0xffff0000, ++ .vm_end = 0xffff0000 + PAGE_SIZE, ++ .vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC, ++}; ++ ++static int __init gate_vma_init(void) ++{ ++ gate_vma.vm_page_prot = PAGE_READONLY_EXEC; ++ return 0; ++} ++arch_initcall(gate_vma_init); ++ ++struct vm_area_struct *get_gate_vma(struct mm_struct *mm) ++{ ++ return &gate_vma; ++} ++ ++int in_gate_area(struct mm_struct *mm, unsigned long addr) ++{ ++ return (addr >= gate_vma.vm_start) && (addr < gate_vma.vm_end); ++} ++ ++int in_gate_area_no_mm(unsigned long addr) ++{ ++ return in_gate_area(NULL, addr); ++} ++#define is_gate_vma(vma) ((vma) == &gate_vma) ++#else ++#define is_gate_vma(vma) 0 ++#endif ++ ++const char *arch_vma_name(struct vm_area_struct *vma) ++{ ++ return is_gate_vma(vma) ? "[vectors]" : NULL; ++} ++ ++/* If possible, provide a placement hint at a random offset from the ++ * stack for the signal page. ++ */ ++static unsigned long sigpage_addr(const struct mm_struct *mm, ++ unsigned int npages) ++{ ++ unsigned long offset; ++ unsigned long first; ++ unsigned long last; ++ unsigned long addr; ++ unsigned int slots; ++ ++ first = PAGE_ALIGN(mm->start_stack); ++ ++ last = TASK_SIZE - (npages << PAGE_SHIFT); ++ ++ /* No room after stack? */ ++ if (first > last) ++ return 0; ++ ++ /* Just enough room? */ ++ if (first == last) ++ return first; ++ ++ slots = ((last - first) >> PAGE_SHIFT) + 1; ++ ++ offset = get_random_int() % slots; ++ ++ addr = first + (offset << PAGE_SHIFT); ++ ++ return addr; ++} ++ ++static struct page *signal_page; ++extern struct page *get_signal_page(void); ++ ++static const struct vm_special_mapping sigpage_mapping = { ++ .name = "[sigpage]", ++ .pages = &signal_page, ++}; ++ ++int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) ++{ ++ struct mm_struct *mm = current->mm; ++ struct vm_area_struct *vma; ++ unsigned long addr; ++ unsigned long hint; ++ int ret = 0; ++ ++ if (!signal_page) ++ signal_page = get_signal_page(); ++ if (!signal_page) ++ return -ENOMEM; ++ ++ down_write(&mm->mmap_sem); ++ hint = sigpage_addr(mm, 1); ++ addr = get_unmapped_area(NULL, hint, PAGE_SIZE, 0, 0); ++ if (IS_ERR_VALUE(addr)) { ++ ret = addr; ++ goto up_fail; ++ } ++ ++ vma = _install_special_mapping(mm, addr, PAGE_SIZE, ++ VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, ++ &sigpage_mapping); ++ ++ if (IS_ERR(vma)) { ++ ret = PTR_ERR(vma); ++ goto up_fail; ++ } ++ ++ mm->context.sigpage = addr; ++ ++ up_fail: ++ up_write(&mm->mmap_sem); ++ return ret; ++} ++#endif +diff -Nur linux-3.18.14.orig/arch/arm/kernel/signal.c linux-3.18.14-rt/arch/arm/kernel/signal.c +--- linux-3.18.14.orig/arch/arm/kernel/signal.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/kernel/signal.c 2015-05-31 15:32:45.617635393 -0500 @@ -574,7 +574,8 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) { @@ -197,9 +761,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/kernel/signal.c linux-3.18.12/arch/arm/ker schedule(); } else { if (unlikely(!user_mode(regs))) -diff -Nur linux-3.18.12.orig/arch/arm/kernel/unwind.c linux-3.18.12/arch/arm/kernel/unwind.c ---- linux-3.18.12.orig/arch/arm/kernel/unwind.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/kernel/unwind.c 2015-04-26 13:32:22.359684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/kernel/unwind.c linux-3.18.14-rt/arch/arm/kernel/unwind.c +--- linux-3.18.14.orig/arch/arm/kernel/unwind.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/kernel/unwind.c 2015-05-31 15:32:45.653635392 -0500 @@ -93,7 +93,7 @@ static const struct unwind_idx *__origin_unwind_idx; extern const struct unwind_idx __stop_unwind_idx[]; @@ -251,10 +815,10 @@ diff -Nur linux-3.18.12.orig/arch/arm/kernel/unwind.c linux-3.18.12/arch/arm/ker kfree(tab); } -diff -Nur linux-3.18.12.orig/arch/arm/kvm/arm.c linux-3.18.12/arch/arm/kvm/arm.c ---- linux-3.18.12.orig/arch/arm/kvm/arm.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/kvm/arm.c 2015-04-26 13:32:22.359684003 -0500 -@@ -441,9 +441,9 @@ +diff -Nur linux-3.18.14.orig/arch/arm/kvm/arm.c linux-3.18.14-rt/arch/arm/kvm/arm.c +--- linux-3.18.14.orig/arch/arm/kvm/arm.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/kvm/arm.c 2015-05-31 15:32:45.669635392 -0500 +@@ -455,9 +455,9 @@ static void vcpu_pause(struct kvm_vcpu *vcpu) { @@ -266,10 +830,1074 @@ diff -Nur linux-3.18.12.orig/arch/arm/kvm/arm.c linux-3.18.12/arch/arm/kvm/arm.c } static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu) -diff -Nur linux-3.18.12.orig/arch/arm/kvm/psci.c linux-3.18.12/arch/arm/kvm/psci.c ---- linux-3.18.12.orig/arch/arm/kvm/psci.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/kvm/psci.c 2015-04-26 13:32:22.359684003 -0500 -@@ -66,7 +66,7 @@ +diff -Nur linux-3.18.14.orig/arch/arm/kvm/arm.c.orig linux-3.18.14-rt/arch/arm/kvm/arm.c.orig +--- linux-3.18.14.orig/arch/arm/kvm/arm.c.orig 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/arch/arm/kvm/arm.c.orig 2015-05-20 10:04:50.000000000 -0500 +@@ -0,0 +1,1060 @@ ++/* ++ * Copyright (C) 2012 - Virtual Open Systems and Columbia University ++ * Author: Christoffer Dall <c.dall@virtualopensystems.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License, version 2, as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ */ ++ ++#include <linux/cpu.h> ++#include <linux/cpu_pm.h> ++#include <linux/errno.h> ++#include <linux/err.h> ++#include <linux/kvm_host.h> ++#include <linux/module.h> ++#include <linux/vmalloc.h> ++#include <linux/fs.h> ++#include <linux/mman.h> ++#include <linux/sched.h> ++#include <linux/kvm.h> ++#include <trace/events/kvm.h> ++ ++#define CREATE_TRACE_POINTS ++#include "trace.h" ++ ++#include <asm/uaccess.h> ++#include <asm/ptrace.h> ++#include <asm/mman.h> ++#include <asm/tlbflush.h> ++#include <asm/cacheflush.h> ++#include <asm/virt.h> ++#include <asm/kvm_arm.h> ++#include <asm/kvm_asm.h> ++#include <asm/kvm_mmu.h> ++#include <asm/kvm_emulate.h> ++#include <asm/kvm_coproc.h> ++#include <asm/kvm_psci.h> ++ ++#ifdef REQUIRES_VIRT ++__asm__(".arch_extension virt"); ++#endif ++ ++static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page); ++static kvm_cpu_context_t __percpu *kvm_host_cpu_state; ++static unsigned long hyp_default_vectors; ++ ++/* Per-CPU variable containing the currently running vcpu. */ ++static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_arm_running_vcpu); ++ ++/* The VMID used in the VTTBR */ ++static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1); ++static u8 kvm_next_vmid; ++static DEFINE_SPINLOCK(kvm_vmid_lock); ++ ++static bool vgic_present; ++ ++static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu) ++{ ++ BUG_ON(preemptible()); ++ __this_cpu_write(kvm_arm_running_vcpu, vcpu); ++} ++ ++/** ++ * kvm_arm_get_running_vcpu - get the vcpu running on the current CPU. ++ * Must be called from non-preemptible context ++ */ ++struct kvm_vcpu *kvm_arm_get_running_vcpu(void) ++{ ++ BUG_ON(preemptible()); ++ return __this_cpu_read(kvm_arm_running_vcpu); ++} ++ ++/** ++ * kvm_arm_get_running_vcpus - get the per-CPU array of currently running vcpus. ++ */ ++struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void) ++{ ++ return &kvm_arm_running_vcpu; ++} ++ ++int kvm_arch_hardware_enable(void) ++{ ++ return 0; ++} ++ ++int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) ++{ ++ return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE; ++} ++ ++int kvm_arch_hardware_setup(void) ++{ ++ return 0; ++} ++ ++void kvm_arch_check_processor_compat(void *rtn) ++{ ++ *(int *)rtn = 0; ++} ++ ++ ++/** ++ * kvm_arch_init_vm - initializes a VM data structure ++ * @kvm: pointer to the KVM struct ++ */ ++int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) ++{ ++ int ret = 0; ++ ++ if (type) ++ return -EINVAL; ++ ++ ret = kvm_alloc_stage2_pgd(kvm); ++ if (ret) ++ goto out_fail_alloc; ++ ++ ret = create_hyp_mappings(kvm, kvm + 1); ++ if (ret) ++ goto out_free_stage2_pgd; ++ ++ kvm_timer_init(kvm); ++ ++ /* Mark the initial VMID generation invalid */ ++ kvm->arch.vmid_gen = 0; ++ ++ return ret; ++out_free_stage2_pgd: ++ kvm_free_stage2_pgd(kvm); ++out_fail_alloc: ++ return ret; ++} ++ ++int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf) ++{ ++ return VM_FAULT_SIGBUS; ++} ++ ++ ++/** ++ * kvm_arch_destroy_vm - destroy the VM data structure ++ * @kvm: pointer to the KVM struct ++ */ ++void kvm_arch_destroy_vm(struct kvm *kvm) ++{ ++ int i; ++ ++ kvm_free_stage2_pgd(kvm); ++ ++ for (i = 0; i < KVM_MAX_VCPUS; ++i) { ++ if (kvm->vcpus[i]) { ++ kvm_arch_vcpu_free(kvm->vcpus[i]); ++ kvm->vcpus[i] = NULL; ++ } ++ } ++ ++ kvm_vgic_destroy(kvm); ++} ++ ++int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) ++{ ++ int r; ++ switch (ext) { ++ case KVM_CAP_IRQCHIP: ++ r = vgic_present; ++ break; ++ case KVM_CAP_DEVICE_CTRL: ++ case KVM_CAP_USER_MEMORY: ++ case KVM_CAP_SYNC_MMU: ++ case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: ++ case KVM_CAP_ONE_REG: ++ case KVM_CAP_ARM_PSCI: ++ case KVM_CAP_ARM_PSCI_0_2: ++ case KVM_CAP_READONLY_MEM: ++ r = 1; ++ break; ++ case KVM_CAP_COALESCED_MMIO: ++ r = KVM_COALESCED_MMIO_PAGE_OFFSET; ++ break; ++ case KVM_CAP_ARM_SET_DEVICE_ADDR: ++ r = 1; ++ break; ++ case KVM_CAP_NR_VCPUS: ++ r = num_online_cpus(); ++ break; ++ case KVM_CAP_MAX_VCPUS: ++ r = KVM_MAX_VCPUS; ++ break; ++ default: ++ r = kvm_arch_dev_ioctl_check_extension(ext); ++ break; ++ } ++ return r; ++} ++ ++long kvm_arch_dev_ioctl(struct file *filp, ++ unsigned int ioctl, unsigned long arg) ++{ ++ return -EINVAL; ++} ++ ++ ++struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) ++{ ++ int err; ++ struct kvm_vcpu *vcpu; ++ ++ if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) { ++ err = -EBUSY; ++ goto out; ++ } ++ ++ vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); ++ if (!vcpu) { ++ err = -ENOMEM; ++ goto out; ++ } ++ ++ err = kvm_vcpu_init(vcpu, kvm, id); ++ if (err) ++ goto free_vcpu; ++ ++ err = create_hyp_mappings(vcpu, vcpu + 1); ++ if (err) ++ goto vcpu_uninit; ++ ++ return vcpu; ++vcpu_uninit: ++ kvm_vcpu_uninit(vcpu); ++free_vcpu: ++ kmem_cache_free(kvm_vcpu_cache, vcpu); ++out: ++ return ERR_PTR(err); ++} ++ ++int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) ++{ ++ return 0; ++} ++ ++void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) ++{ ++ kvm_mmu_free_memory_caches(vcpu); ++ kvm_timer_vcpu_terminate(vcpu); ++ kvm_vgic_vcpu_destroy(vcpu); ++ kmem_cache_free(kvm_vcpu_cache, vcpu); ++} ++ ++void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) ++{ ++ kvm_arch_vcpu_free(vcpu); ++} ++ ++int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) ++{ ++ return 0; ++} ++ ++int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) ++{ ++ /* Force users to call KVM_ARM_VCPU_INIT */ ++ vcpu->arch.target = -1; ++ ++ /* Set up the timer */ ++ kvm_timer_vcpu_init(vcpu); ++ ++ return 0; ++} ++ ++void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) ++{ ++ vcpu->cpu = cpu; ++ vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state); ++ ++ /* ++ * Check whether this vcpu requires the cache to be flushed on ++ * this physical CPU. This is a consequence of doing dcache ++ * operations by set/way on this vcpu. We do it here to be in ++ * a non-preemptible section. ++ */ ++ if (cpumask_test_and_clear_cpu(cpu, &vcpu->arch.require_dcache_flush)) ++ flush_cache_all(); /* We'd really want v7_flush_dcache_all() */ ++ ++ kvm_arm_set_running_vcpu(vcpu); ++} ++ ++void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) ++{ ++ /* ++ * The arch-generic KVM code expects the cpu field of a vcpu to be -1 ++ * if the vcpu is no longer assigned to a cpu. This is used for the ++ * optimized make_all_cpus_request path. ++ */ ++ vcpu->cpu = -1; ++ ++ kvm_arm_set_running_vcpu(NULL); ++} ++ ++int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, ++ struct kvm_guest_debug *dbg) ++{ ++ return -EINVAL; ++} ++ ++ ++int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, ++ struct kvm_mp_state *mp_state) ++{ ++ return -EINVAL; ++} ++ ++int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, ++ struct kvm_mp_state *mp_state) ++{ ++ return -EINVAL; ++} ++ ++/** ++ * kvm_arch_vcpu_runnable - determine if the vcpu can be scheduled ++ * @v: The VCPU pointer ++ * ++ * If the guest CPU is not waiting for interrupts or an interrupt line is ++ * asserted, the CPU is by definition runnable. ++ */ ++int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) ++{ ++ return !!v->arch.irq_lines || kvm_vgic_vcpu_pending_irq(v); ++} ++ ++/* Just ensure a guest exit from a particular CPU */ ++static void exit_vm_noop(void *info) ++{ ++} ++ ++void force_vm_exit(const cpumask_t *mask) ++{ ++ smp_call_function_many(mask, exit_vm_noop, NULL, true); ++} ++ ++/** ++ * need_new_vmid_gen - check that the VMID is still valid ++ * @kvm: The VM's VMID to checkt ++ * ++ * return true if there is a new generation of VMIDs being used ++ * ++ * The hardware supports only 256 values with the value zero reserved for the ++ * host, so we check if an assigned value belongs to a previous generation, ++ * which which requires us to assign a new value. If we're the first to use a ++ * VMID for the new generation, we must flush necessary caches and TLBs on all ++ * CPUs. ++ */ ++static bool need_new_vmid_gen(struct kvm *kvm) ++{ ++ return unlikely(kvm->arch.vmid_gen != atomic64_read(&kvm_vmid_gen)); ++} ++ ++/** ++ * update_vttbr - Update the VTTBR with a valid VMID before the guest runs ++ * @kvm The guest that we are about to run ++ * ++ * Called from kvm_arch_vcpu_ioctl_run before entering the guest to ensure the ++ * VM has a valid VMID, otherwise assigns a new one and flushes corresponding ++ * caches and TLBs. ++ */ ++static void update_vttbr(struct kvm *kvm) ++{ ++ phys_addr_t pgd_phys; ++ u64 vmid; ++ ++ if (!need_new_vmid_gen(kvm)) ++ return; ++ ++ spin_lock(&kvm_vmid_lock); ++ ++ /* ++ * We need to re-check the vmid_gen here to ensure that if another vcpu ++ * already allocated a valid vmid for this vm, then this vcpu should ++ * use the same vmid. ++ */ ++ if (!need_new_vmid_gen(kvm)) { ++ spin_unlock(&kvm_vmid_lock); ++ return; ++ } ++ ++ /* First user of a new VMID generation? */ ++ if (unlikely(kvm_next_vmid == 0)) { ++ atomic64_inc(&kvm_vmid_gen); ++ kvm_next_vmid = 1; ++ ++ /* ++ * On SMP we know no other CPUs can use this CPU's or each ++ * other's VMID after force_vm_exit returns since the ++ * kvm_vmid_lock blocks them from reentry to the guest. ++ */ ++ force_vm_exit(cpu_all_mask); ++ /* ++ * Now broadcast TLB + ICACHE invalidation over the inner ++ * shareable domain to make sure all data structures are ++ * clean. ++ */ ++ kvm_call_hyp(__kvm_flush_vm_context); ++ } ++ ++ kvm->arch.vmid_gen = atomic64_read(&kvm_vmid_gen); ++ kvm->arch.vmid = kvm_next_vmid; ++ kvm_next_vmid++; ++ ++ /* update vttbr to be used with the new vmid */ ++ pgd_phys = virt_to_phys(kvm_get_hwpgd(kvm)); ++ BUG_ON(pgd_phys & ~VTTBR_BADDR_MASK); ++ vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK; ++ kvm->arch.vttbr = pgd_phys | vmid; ++ ++ spin_unlock(&kvm_vmid_lock); ++} ++ ++static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) ++{ ++ struct kvm *kvm = vcpu->kvm; ++ int ret; ++ ++ if (likely(vcpu->arch.has_run_once)) ++ return 0; ++ ++ vcpu->arch.has_run_once = true; ++ ++ /* ++ * Map the VGIC hardware resources before running a vcpu the first ++ * time on this VM. ++ */ ++ if (unlikely(!vgic_initialized(kvm))) { ++ ret = kvm_vgic_map_resources(kvm); ++ if (ret) ++ return ret; ++ } ++ ++ /* ++ * Enable the arch timers only if we have an in-kernel VGIC ++ * and it has been properly initialized, since we cannot handle ++ * interrupts from the virtual timer with a userspace gic. ++ */ ++ if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) ++ kvm_timer_enable(kvm); ++ ++ return 0; ++} ++ ++static void vcpu_pause(struct kvm_vcpu *vcpu) ++{ ++ wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu); ++ ++ wait_event_interruptible(*wq, !vcpu->arch.pause); ++} ++ ++static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu) ++{ ++ return vcpu->arch.target >= 0; ++} ++ ++/** ++ * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code ++ * @vcpu: The VCPU pointer ++ * @run: The kvm_run structure pointer used for userspace state exchange ++ * ++ * This function is called through the VCPU_RUN ioctl called from user space. It ++ * will execute VM code in a loop until the time slice for the process is used ++ * or some emulation is needed from user space in which case the function will ++ * return with return value 0 and with the kvm_run structure filled in with the ++ * required data for the requested emulation. ++ */ ++int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) ++{ ++ int ret; ++ sigset_t sigsaved; ++ ++ if (unlikely(!kvm_vcpu_initialized(vcpu))) ++ return -ENOEXEC; ++ ++ ret = kvm_vcpu_first_run_init(vcpu); ++ if (ret) ++ return ret; ++ ++ if (run->exit_reason == KVM_EXIT_MMIO) { ++ ret = kvm_handle_mmio_return(vcpu, vcpu->run); ++ if (ret) ++ return ret; ++ } ++ ++ if (vcpu->sigset_active) ++ sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); ++ ++ ret = 1; ++ run->exit_reason = KVM_EXIT_UNKNOWN; ++ while (ret > 0) { ++ /* ++ * Check conditions before entering the guest ++ */ ++ cond_resched(); ++ ++ update_vttbr(vcpu->kvm); ++ ++ if (vcpu->arch.pause) ++ vcpu_pause(vcpu); ++ ++ kvm_vgic_flush_hwstate(vcpu); ++ kvm_timer_flush_hwstate(vcpu); ++ ++ local_irq_disable(); ++ ++ /* ++ * Re-check atomic conditions ++ */ ++ if (signal_pending(current)) { ++ ret = -EINTR; ++ run->exit_reason = KVM_EXIT_INTR; ++ } ++ ++ if (ret <= 0 || need_new_vmid_gen(vcpu->kvm)) { ++ local_irq_enable(); ++ kvm_timer_sync_hwstate(vcpu); ++ kvm_vgic_sync_hwstate(vcpu); ++ continue; ++ } ++ ++ /************************************************************** ++ * Enter the guest ++ */ ++ trace_kvm_entry(*vcpu_pc(vcpu)); ++ kvm_guest_enter(); ++ vcpu->mode = IN_GUEST_MODE; ++ ++ ret = kvm_call_hyp(__kvm_vcpu_run, vcpu); ++ ++ vcpu->mode = OUTSIDE_GUEST_MODE; ++ vcpu->arch.last_pcpu = smp_processor_id(); ++ kvm_guest_exit(); ++ trace_kvm_exit(*vcpu_pc(vcpu)); ++ /* ++ * We may have taken a host interrupt in HYP mode (ie ++ * while executing the guest). This interrupt is still ++ * pending, as we haven't serviced it yet! ++ * ++ * We're now back in SVC mode, with interrupts ++ * disabled. Enabling the interrupts now will have ++ * the effect of taking the interrupt again, in SVC ++ * mode this time. ++ */ ++ local_irq_enable(); ++ ++ /* ++ * Back from guest ++ *************************************************************/ ++ ++ kvm_timer_sync_hwstate(vcpu); ++ kvm_vgic_sync_hwstate(vcpu); ++ ++ ret = handle_exit(vcpu, run, ret); ++ } ++ ++ if (vcpu->sigset_active) ++ sigprocmask(SIG_SETMASK, &sigsaved, NULL); ++ return ret; ++} ++ ++static int vcpu_interrupt_line(struct kvm_vcpu *vcpu, int number, bool level) ++{ ++ int bit_index; ++ bool set; ++ unsigned long *ptr; ++ ++ if (number == KVM_ARM_IRQ_CPU_IRQ) ++ bit_index = __ffs(HCR_VI); ++ else /* KVM_ARM_IRQ_CPU_FIQ */ ++ bit_index = __ffs(HCR_VF); ++ ++ ptr = (unsigned long *)&vcpu->arch.irq_lines; ++ if (level) ++ set = test_and_set_bit(bit_index, ptr); ++ else ++ set = test_and_clear_bit(bit_index, ptr); ++ ++ /* ++ * If we didn't change anything, no need to wake up or kick other CPUs ++ */ ++ if (set == level) ++ return 0; ++ ++ /* ++ * The vcpu irq_lines field was updated, wake up sleeping VCPUs and ++ * trigger a world-switch round on the running physical CPU to set the ++ * virtual IRQ/FIQ fields in the HCR appropriately. ++ */ ++ kvm_vcpu_kick(vcpu); ++ ++ return 0; ++} ++ ++int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level, ++ bool line_status) ++{ ++ u32 irq = irq_level->irq; ++ unsigned int irq_type, vcpu_idx, irq_num; ++ int nrcpus = atomic_read(&kvm->online_vcpus); ++ struct kvm_vcpu *vcpu = NULL; ++ bool level = irq_level->level; ++ ++ irq_type = (irq >> KVM_ARM_IRQ_TYPE_SHIFT) & KVM_ARM_IRQ_TYPE_MASK; ++ vcpu_idx = (irq >> KVM_ARM_IRQ_VCPU_SHIFT) & KVM_ARM_IRQ_VCPU_MASK; ++ irq_num = (irq >> KVM_ARM_IRQ_NUM_SHIFT) & KVM_ARM_IRQ_NUM_MASK; ++ ++ trace_kvm_irq_line(irq_type, vcpu_idx, irq_num, irq_level->level); ++ ++ switch (irq_type) { ++ case KVM_ARM_IRQ_TYPE_CPU: ++ if (irqchip_in_kernel(kvm)) ++ return -ENXIO; ++ ++ if (vcpu_idx >= nrcpus) ++ return -EINVAL; ++ ++ vcpu = kvm_get_vcpu(kvm, vcpu_idx); ++ if (!vcpu) ++ return -EINVAL; ++ ++ if (irq_num > KVM_ARM_IRQ_CPU_FIQ) ++ return -EINVAL; ++ ++ return vcpu_interrupt_line(vcpu, irq_num, level); ++ case KVM_ARM_IRQ_TYPE_PPI: ++ if (!irqchip_in_kernel(kvm)) ++ return -ENXIO; ++ ++ if (vcpu_idx >= nrcpus) ++ return -EINVAL; ++ ++ vcpu = kvm_get_vcpu(kvm, vcpu_idx); ++ if (!vcpu) ++ return -EINVAL; ++ ++ if (irq_num < VGIC_NR_SGIS || irq_num >= VGIC_NR_PRIVATE_IRQS) ++ return -EINVAL; ++ ++ return kvm_vgic_inject_irq(kvm, vcpu->vcpu_id, irq_num, level); ++ case KVM_ARM_IRQ_TYPE_SPI: ++ if (!irqchip_in_kernel(kvm)) ++ return -ENXIO; ++ ++ if (irq_num < VGIC_NR_PRIVATE_IRQS) ++ return -EINVAL; ++ ++ return kvm_vgic_inject_irq(kvm, 0, irq_num, level); ++ } ++ ++ return -EINVAL; ++} ++ ++static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu, ++ struct kvm_vcpu_init *init) ++{ ++ int ret; ++ ++ ret = kvm_vcpu_set_target(vcpu, init); ++ if (ret) ++ return ret; ++ ++ /* ++ * Ensure a rebooted VM will fault in RAM pages and detect if the ++ * guest MMU is turned off and flush the caches as needed. ++ */ ++ if (vcpu->arch.has_run_once) ++ stage2_unmap_vm(vcpu->kvm); ++ ++ vcpu_reset_hcr(vcpu); ++ ++ /* ++ * Handle the "start in power-off" case by marking the VCPU as paused. ++ */ ++ if (test_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features)) ++ vcpu->arch.pause = true; ++ else ++ vcpu->arch.pause = false; ++ ++ return 0; ++} ++ ++long kvm_arch_vcpu_ioctl(struct file *filp, ++ unsigned int ioctl, unsigned long arg) ++{ ++ struct kvm_vcpu *vcpu = filp->private_data; ++ void __user *argp = (void __user *)arg; ++ ++ switch (ioctl) { ++ case KVM_ARM_VCPU_INIT: { ++ struct kvm_vcpu_init init; ++ ++ if (copy_from_user(&init, argp, sizeof(init))) ++ return -EFAULT; ++ ++ return kvm_arch_vcpu_ioctl_vcpu_init(vcpu, &init); ++ } ++ case KVM_SET_ONE_REG: ++ case KVM_GET_ONE_REG: { ++ struct kvm_one_reg reg; ++ ++ if (unlikely(!kvm_vcpu_initialized(vcpu))) ++ return -ENOEXEC; ++ ++ if (copy_from_user(®, argp, sizeof(reg))) ++ return -EFAULT; ++ if (ioctl == KVM_SET_ONE_REG) ++ return kvm_arm_set_reg(vcpu, ®); ++ else ++ return kvm_arm_get_reg(vcpu, ®); ++ } ++ case KVM_GET_REG_LIST: { ++ struct kvm_reg_list __user *user_list = argp; ++ struct kvm_reg_list reg_list; ++ unsigned n; ++ ++ if (unlikely(!kvm_vcpu_initialized(vcpu))) ++ return -ENOEXEC; ++ ++ if (copy_from_user(®_list, user_list, sizeof(reg_list))) ++ return -EFAULT; ++ n = reg_list.n; ++ reg_list.n = kvm_arm_num_regs(vcpu); ++ if (copy_to_user(user_list, ®_list, sizeof(reg_list))) ++ return -EFAULT; ++ if (n < reg_list.n) ++ return -E2BIG; ++ return kvm_arm_copy_reg_indices(vcpu, user_list->reg); ++ } ++ default: ++ return -EINVAL; ++ } ++} ++ ++int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) ++{ ++ return -EINVAL; ++} ++ ++static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm, ++ struct kvm_arm_device_addr *dev_addr) ++{ ++ unsigned long dev_id, type; ++ ++ dev_id = (dev_addr->id & KVM_ARM_DEVICE_ID_MASK) >> ++ KVM_ARM_DEVICE_ID_SHIFT; ++ type = (dev_addr->id & KVM_ARM_DEVICE_TYPE_MASK) >> ++ KVM_ARM_DEVICE_TYPE_SHIFT; ++ ++ switch (dev_id) { ++ case KVM_ARM_DEVICE_VGIC_V2: ++ if (!vgic_present) ++ return -ENXIO; ++ return kvm_vgic_addr(kvm, type, &dev_addr->addr, true); ++ default: ++ return -ENODEV; ++ } ++} ++ ++long kvm_arch_vm_ioctl(struct file *filp, ++ unsigned int ioctl, unsigned long arg) ++{ ++ struct kvm *kvm = filp->private_data; ++ void __user *argp = (void __user *)arg; ++ ++ switch (ioctl) { ++ case KVM_CREATE_IRQCHIP: { ++ if (vgic_present) ++ return kvm_vgic_create(kvm); ++ else ++ return -ENXIO; ++ } ++ case KVM_ARM_SET_DEVICE_ADDR: { ++ struct kvm_arm_device_addr dev_addr; ++ ++ if (copy_from_user(&dev_addr, argp, sizeof(dev_addr))) ++ return -EFAULT; ++ return kvm_vm_ioctl_set_device_addr(kvm, &dev_addr); ++ } ++ case KVM_ARM_PREFERRED_TARGET: { ++ int err; ++ struct kvm_vcpu_init init; ++ ++ err = kvm_vcpu_preferred_target(&init); ++ if (err) ++ return err; ++ ++ if (copy_to_user(argp, &init, sizeof(init))) ++ return -EFAULT; ++ ++ return 0; ++ } ++ default: ++ return -EINVAL; ++ } ++} ++ ++static void cpu_init_hyp_mode(void *dummy) ++{ ++ phys_addr_t boot_pgd_ptr; ++ phys_addr_t pgd_ptr; ++ unsigned long hyp_stack_ptr; ++ unsigned long stack_page; ++ unsigned long vector_ptr; ++ ++ /* Switch from the HYP stub to our own HYP init vector */ ++ __hyp_set_vectors(kvm_get_idmap_vector()); ++ ++ boot_pgd_ptr = kvm_mmu_get_boot_httbr(); ++ pgd_ptr = kvm_mmu_get_httbr(); ++ stack_page = __this_cpu_read(kvm_arm_hyp_stack_page); ++ hyp_stack_ptr = stack_page + PAGE_SIZE; ++ vector_ptr = (unsigned long)__kvm_hyp_vector; ++ ++ __cpu_init_hyp_mode(boot_pgd_ptr, pgd_ptr, hyp_stack_ptr, vector_ptr); ++} ++ ++static int hyp_init_cpu_notify(struct notifier_block *self, ++ unsigned long action, void *cpu) ++{ ++ switch (action) { ++ case CPU_STARTING: ++ case CPU_STARTING_FROZEN: ++ if (__hyp_get_vectors() == hyp_default_vectors) ++ cpu_init_hyp_mode(NULL); ++ break; ++ } ++ ++ return NOTIFY_OK; ++} ++ ++static struct notifier_block hyp_init_cpu_nb = { ++ .notifier_call = hyp_init_cpu_notify, ++}; ++ ++#ifdef CONFIG_CPU_PM ++static int hyp_init_cpu_pm_notifier(struct notifier_block *self, ++ unsigned long cmd, ++ void *v) ++{ ++ if (cmd == CPU_PM_EXIT && ++ __hyp_get_vectors() == hyp_default_vectors) { ++ cpu_init_hyp_mode(NULL); ++ return NOTIFY_OK; ++ } ++ ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block hyp_init_cpu_pm_nb = { ++ .notifier_call = hyp_init_cpu_pm_notifier, ++}; ++ ++static void __init hyp_cpu_pm_init(void) ++{ ++ cpu_pm_register_notifier(&hyp_init_cpu_pm_nb); ++} ++#else ++static inline void hyp_cpu_pm_init(void) ++{ ++} ++#endif ++ ++/** ++ * Inits Hyp-mode on all online CPUs ++ */ ++static int init_hyp_mode(void) ++{ ++ int cpu; ++ int err = 0; ++ ++ /* ++ * Allocate Hyp PGD and setup Hyp identity mapping ++ */ ++ err = kvm_mmu_init(); ++ if (err) ++ goto out_err; ++ ++ /* ++ * It is probably enough to obtain the default on one ++ * CPU. It's unlikely to be different on the others. ++ */ ++ hyp_default_vectors = __hyp_get_vectors(); ++ ++ /* ++ * Allocate stack pages for Hypervisor-mode ++ */ ++ for_each_possible_cpu(cpu) { ++ unsigned long stack_page; ++ ++ stack_page = __get_free_page(GFP_KERNEL); ++ if (!stack_page) { ++ err = -ENOMEM; ++ goto out_free_stack_pages; ++ } ++ ++ per_cpu(kvm_arm_hyp_stack_page, cpu) = stack_page; ++ } ++ ++ /* ++ * Map the Hyp-code called directly from the host ++ */ ++ err = create_hyp_mappings(__kvm_hyp_code_start, __kvm_hyp_code_end); ++ if (err) { ++ kvm_err("Cannot map world-switch code\n"); ++ goto out_free_mappings; ++ } ++ ++ /* ++ * Map the Hyp stack pages ++ */ ++ for_each_possible_cpu(cpu) { ++ char *stack_page = (char *)per_cpu(kvm_arm_hyp_stack_page, cpu); ++ err = create_hyp_mappings(stack_page, stack_page + PAGE_SIZE); ++ ++ if (err) { ++ kvm_err("Cannot map hyp stack\n"); ++ goto out_free_mappings; ++ } ++ } ++ ++ /* ++ * Map the host CPU structures ++ */ ++ kvm_host_cpu_state = alloc_percpu(kvm_cpu_context_t); ++ if (!kvm_host_cpu_state) { ++ err = -ENOMEM; ++ kvm_err("Cannot allocate host CPU state\n"); ++ goto out_free_mappings; ++ } ++ ++ for_each_possible_cpu(cpu) { ++ kvm_cpu_context_t *cpu_ctxt; ++ ++ cpu_ctxt = per_cpu_ptr(kvm_host_cpu_state, cpu); ++ err = create_hyp_mappings(cpu_ctxt, cpu_ctxt + 1); ++ ++ if (err) { ++ kvm_err("Cannot map host CPU state: %d\n", err); ++ goto out_free_context; ++ } ++ } ++ ++ /* ++ * Execute the init code on each CPU. ++ */ ++ on_each_cpu(cpu_init_hyp_mode, NULL, 1); ++ ++ /* ++ * Init HYP view of VGIC ++ */ ++ err = kvm_vgic_hyp_init(); ++ if (err) ++ goto out_free_context; ++ ++#ifdef CONFIG_KVM_ARM_VGIC ++ vgic_present = true; ++#endif ++ ++ /* ++ * Init HYP architected timer support ++ */ ++ err = kvm_timer_hyp_init(); ++ if (err) ++ goto out_free_mappings; ++ ++#ifndef CONFIG_HOTPLUG_CPU ++ free_boot_hyp_pgd(); ++#endif ++ ++ kvm_perf_init(); ++ ++ kvm_info("Hyp mode initialized successfully\n"); ++ ++ return 0; ++out_free_context: ++ free_percpu(kvm_host_cpu_state); ++out_free_mappings: ++ free_hyp_pgds(); ++out_free_stack_pages: ++ for_each_possible_cpu(cpu) ++ free_page(per_cpu(kvm_arm_hyp_stack_page, cpu)); ++out_err: ++ kvm_err("error initializing Hyp mode: %d\n", err); ++ return err; ++} ++ ++static void check_kvm_target_cpu(void *ret) ++{ ++ *(int *)ret = kvm_target_cpu(); ++} ++ ++/** ++ * Initialize Hyp-mode and memory mappings on all CPUs. ++ */ ++int kvm_arch_init(void *opaque) ++{ ++ int err; ++ int ret, cpu; ++ ++ if (!is_hyp_mode_available()) { ++ kvm_err("HYP mode not available\n"); ++ return -ENODEV; ++ } ++ ++ for_each_online_cpu(cpu) { ++ smp_call_function_single(cpu, check_kvm_target_cpu, &ret, 1); ++ if (ret < 0) { ++ kvm_err("Error, CPU %d not supported!\n", cpu); ++ return -ENODEV; ++ } ++ } ++ ++ cpu_notifier_register_begin(); ++ ++ err = init_hyp_mode(); ++ if (err) ++ goto out_err; ++ ++ err = __register_cpu_notifier(&hyp_init_cpu_nb); ++ if (err) { ++ kvm_err("Cannot register HYP init CPU notifier (%d)\n", err); ++ goto out_err; ++ } ++ ++ cpu_notifier_register_done(); ++ ++ hyp_cpu_pm_init(); ++ ++ kvm_coproc_table_init(); ++ return 0; ++out_err: ++ cpu_notifier_register_done(); ++ return err; ++} ++ ++/* NOP: Compiling as a module not supported */ ++void kvm_arch_exit(void) ++{ ++ kvm_perf_teardown(); ++} ++ ++static int arm_init(void) ++{ ++ int rc = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE); ++ return rc; ++} ++ ++module_init(arm_init); +diff -Nur linux-3.18.14.orig/arch/arm/kvm/psci.c linux-3.18.14-rt/arch/arm/kvm/psci.c +--- linux-3.18.14.orig/arch/arm/kvm/psci.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/kvm/psci.c 2015-05-31 15:32:45.673635392 -0500 +@@ -67,7 +67,7 @@ { struct kvm *kvm = source_vcpu->kvm; struct kvm_vcpu *vcpu = NULL, *tmp; @@ -278,7 +1906,7 @@ diff -Nur linux-3.18.12.orig/arch/arm/kvm/psci.c linux-3.18.12/arch/arm/kvm/psci unsigned long cpu_id; unsigned long context_id; unsigned long mpidr; -@@ -123,7 +123,7 @@ +@@ -124,7 +124,7 @@ smp_mb(); /* Make sure the above is visible */ wq = kvm_arch_vcpu_wq(vcpu); @@ -287,9 +1915,350 @@ diff -Nur linux-3.18.12.orig/arch/arm/kvm/psci.c linux-3.18.12/arch/arm/kvm/psci return PSCI_RET_SUCCESS; } -diff -Nur linux-3.18.12.orig/arch/arm/mach-at91/at91rm9200_time.c linux-3.18.12/arch/arm/mach-at91/at91rm9200_time.c ---- linux-3.18.12.orig/arch/arm/mach-at91/at91rm9200_time.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/mach-at91/at91rm9200_time.c 2015-04-26 13:32:22.359684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/kvm/psci.c.orig linux-3.18.14-rt/arch/arm/kvm/psci.c.orig +--- linux-3.18.14.orig/arch/arm/kvm/psci.c.orig 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/arch/arm/kvm/psci.c.orig 2015-05-20 10:04:50.000000000 -0500 +@@ -0,0 +1,337 @@ ++/* ++ * Copyright (C) 2012 - ARM Ltd ++ * Author: Marc Zyngier <marc.zyngier@arm.com> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see <http://www.gnu.org/licenses/>. ++ */ ++ ++#include <linux/preempt.h> ++#include <linux/kvm_host.h> ++#include <linux/wait.h> ++ ++#include <asm/cputype.h> ++#include <asm/kvm_emulate.h> ++#include <asm/kvm_psci.h> ++ ++/* ++ * This is an implementation of the Power State Coordination Interface ++ * as described in ARM document number ARM DEN 0022A. ++ */ ++ ++#define AFFINITY_MASK(level) ~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1) ++ ++static unsigned long psci_affinity_mask(unsigned long affinity_level) ++{ ++ if (affinity_level <= 3) ++ return MPIDR_HWID_BITMASK & AFFINITY_MASK(affinity_level); ++ ++ return 0; ++} ++ ++static unsigned long kvm_psci_vcpu_suspend(struct kvm_vcpu *vcpu) ++{ ++ /* ++ * NOTE: For simplicity, we make VCPU suspend emulation to be ++ * same-as WFI (Wait-for-interrupt) emulation. ++ * ++ * This means for KVM the wakeup events are interrupts and ++ * this is consistent with intended use of StateID as described ++ * in section 5.4.1 of PSCI v0.2 specification (ARM DEN 0022A). ++ * ++ * Further, we also treat power-down request to be same as ++ * stand-by request as-per section 5.4.2 clause 3 of PSCI v0.2 ++ * specification (ARM DEN 0022A). This means all suspend states ++ * for KVM will preserve the register state. ++ */ ++ kvm_vcpu_block(vcpu); ++ ++ return PSCI_RET_SUCCESS; ++} ++ ++static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu) ++{ ++ vcpu->arch.pause = true; ++} ++ ++static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) ++{ ++ struct kvm *kvm = source_vcpu->kvm; ++ struct kvm_vcpu *vcpu = NULL, *tmp; ++ wait_queue_head_t *wq; ++ unsigned long cpu_id; ++ unsigned long context_id; ++ unsigned long mpidr; ++ phys_addr_t target_pc; ++ int i; ++ ++ cpu_id = *vcpu_reg(source_vcpu, 1); ++ if (vcpu_mode_is_32bit(source_vcpu)) ++ cpu_id &= ~((u32) 0); ++ ++ kvm_for_each_vcpu(i, tmp, kvm) { ++ mpidr = kvm_vcpu_get_mpidr(tmp); ++ if ((mpidr & MPIDR_HWID_BITMASK) == (cpu_id & MPIDR_HWID_BITMASK)) { ++ vcpu = tmp; ++ break; ++ } ++ } ++ ++ /* ++ * Make sure the caller requested a valid CPU and that the CPU is ++ * turned off. ++ */ ++ if (!vcpu) ++ return PSCI_RET_INVALID_PARAMS; ++ if (!vcpu->arch.pause) { ++ if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1) ++ return PSCI_RET_ALREADY_ON; ++ else ++ return PSCI_RET_INVALID_PARAMS; ++ } ++ ++ target_pc = *vcpu_reg(source_vcpu, 2); ++ context_id = *vcpu_reg(source_vcpu, 3); ++ ++ kvm_reset_vcpu(vcpu); ++ ++ /* Gracefully handle Thumb2 entry point */ ++ if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) { ++ target_pc &= ~((phys_addr_t) 1); ++ vcpu_set_thumb(vcpu); ++ } ++ ++ /* Propagate caller endianness */ ++ if (kvm_vcpu_is_be(source_vcpu)) ++ kvm_vcpu_set_be(vcpu); ++ ++ *vcpu_pc(vcpu) = target_pc; ++ /* ++ * NOTE: We always update r0 (or x0) because for PSCI v0.1 ++ * the general puspose registers are undefined upon CPU_ON. ++ */ ++ *vcpu_reg(vcpu, 0) = context_id; ++ vcpu->arch.pause = false; ++ smp_mb(); /* Make sure the above is visible */ ++ ++ wq = kvm_arch_vcpu_wq(vcpu); ++ wake_up_interruptible(wq); ++ ++ return PSCI_RET_SUCCESS; ++} ++ ++static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu) ++{ ++ int i; ++ unsigned long mpidr; ++ unsigned long target_affinity; ++ unsigned long target_affinity_mask; ++ unsigned long lowest_affinity_level; ++ struct kvm *kvm = vcpu->kvm; ++ struct kvm_vcpu *tmp; ++ ++ target_affinity = *vcpu_reg(vcpu, 1); ++ lowest_affinity_level = *vcpu_reg(vcpu, 2); ++ ++ /* Determine target affinity mask */ ++ target_affinity_mask = psci_affinity_mask(lowest_affinity_level); ++ if (!target_affinity_mask) ++ return PSCI_RET_INVALID_PARAMS; ++ ++ /* Ignore other bits of target affinity */ ++ target_affinity &= target_affinity_mask; ++ ++ /* ++ * If one or more VCPU matching target affinity are running ++ * then ON else OFF ++ */ ++ kvm_for_each_vcpu(i, tmp, kvm) { ++ mpidr = kvm_vcpu_get_mpidr(tmp); ++ if (((mpidr & target_affinity_mask) == target_affinity) && ++ !tmp->arch.pause) { ++ return PSCI_0_2_AFFINITY_LEVEL_ON; ++ } ++ } ++ ++ return PSCI_0_2_AFFINITY_LEVEL_OFF; ++} ++ ++static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type) ++{ ++ int i; ++ struct kvm_vcpu *tmp; ++ ++ /* ++ * The KVM ABI specifies that a system event exit may call KVM_RUN ++ * again and may perform shutdown/reboot at a later time that when the ++ * actual request is made. Since we are implementing PSCI and a ++ * caller of PSCI reboot and shutdown expects that the system shuts ++ * down or reboots immediately, let's make sure that VCPUs are not run ++ * after this call is handled and before the VCPUs have been ++ * re-initialized. ++ */ ++ kvm_for_each_vcpu(i, tmp, vcpu->kvm) { ++ tmp->arch.pause = true; ++ kvm_vcpu_kick(tmp); ++ } ++ ++ memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event)); ++ vcpu->run->system_event.type = type; ++ vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT; ++} ++ ++static void kvm_psci_system_off(struct kvm_vcpu *vcpu) ++{ ++ kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_SHUTDOWN); ++} ++ ++static void kvm_psci_system_reset(struct kvm_vcpu *vcpu) ++{ ++ kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET); ++} ++ ++int kvm_psci_version(struct kvm_vcpu *vcpu) ++{ ++ if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) ++ return KVM_ARM_PSCI_0_2; ++ ++ return KVM_ARM_PSCI_0_1; ++} ++ ++static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) ++{ ++ int ret = 1; ++ unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); ++ unsigned long val; ++ ++ switch (psci_fn) { ++ case PSCI_0_2_FN_PSCI_VERSION: ++ /* ++ * Bits[31:16] = Major Version = 0 ++ * Bits[15:0] = Minor Version = 2 ++ */ ++ val = 2; ++ break; ++ case PSCI_0_2_FN_CPU_SUSPEND: ++ case PSCI_0_2_FN64_CPU_SUSPEND: ++ val = kvm_psci_vcpu_suspend(vcpu); ++ break; ++ case PSCI_0_2_FN_CPU_OFF: ++ kvm_psci_vcpu_off(vcpu); ++ val = PSCI_RET_SUCCESS; ++ break; ++ case PSCI_0_2_FN_CPU_ON: ++ case PSCI_0_2_FN64_CPU_ON: ++ val = kvm_psci_vcpu_on(vcpu); ++ break; ++ case PSCI_0_2_FN_AFFINITY_INFO: ++ case PSCI_0_2_FN64_AFFINITY_INFO: ++ val = kvm_psci_vcpu_affinity_info(vcpu); ++ break; ++ case PSCI_0_2_FN_MIGRATE: ++ case PSCI_0_2_FN64_MIGRATE: ++ val = PSCI_RET_NOT_SUPPORTED; ++ break; ++ case PSCI_0_2_FN_MIGRATE_INFO_TYPE: ++ /* ++ * Trusted OS is MP hence does not require migration ++ * or ++ * Trusted OS is not present ++ */ ++ val = PSCI_0_2_TOS_MP; ++ break; ++ case PSCI_0_2_FN_MIGRATE_INFO_UP_CPU: ++ case PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU: ++ val = PSCI_RET_NOT_SUPPORTED; ++ break; ++ case PSCI_0_2_FN_SYSTEM_OFF: ++ kvm_psci_system_off(vcpu); ++ /* ++ * We should'nt be going back to guest VCPU after ++ * receiving SYSTEM_OFF request. ++ * ++ * If user space accidently/deliberately resumes ++ * guest VCPU after SYSTEM_OFF request then guest ++ * VCPU should see internal failure from PSCI return ++ * value. To achieve this, we preload r0 (or x0) with ++ * PSCI return value INTERNAL_FAILURE. ++ */ ++ val = PSCI_RET_INTERNAL_FAILURE; ++ ret = 0; ++ break; ++ case PSCI_0_2_FN_SYSTEM_RESET: ++ kvm_psci_system_reset(vcpu); ++ /* ++ * Same reason as SYSTEM_OFF for preloading r0 (or x0) ++ * with PSCI return value INTERNAL_FAILURE. ++ */ ++ val = PSCI_RET_INTERNAL_FAILURE; ++ ret = 0; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ *vcpu_reg(vcpu, 0) = val; ++ return ret; ++} ++ ++static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) ++{ ++ unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); ++ unsigned long val; ++ ++ switch (psci_fn) { ++ case KVM_PSCI_FN_CPU_OFF: ++ kvm_psci_vcpu_off(vcpu); ++ val = PSCI_RET_SUCCESS; ++ break; ++ case KVM_PSCI_FN_CPU_ON: ++ val = kvm_psci_vcpu_on(vcpu); ++ break; ++ case KVM_PSCI_FN_CPU_SUSPEND: ++ case KVM_PSCI_FN_MIGRATE: ++ val = PSCI_RET_NOT_SUPPORTED; ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ *vcpu_reg(vcpu, 0) = val; ++ return 1; ++} ++ ++/** ++ * kvm_psci_call - handle PSCI call if r0 value is in range ++ * @vcpu: Pointer to the VCPU struct ++ * ++ * Handle PSCI calls from guests through traps from HVC instructions. ++ * The calling convention is similar to SMC calls to the secure world ++ * where the function number is placed in r0. ++ * ++ * This function returns: > 0 (success), 0 (success but exit to user ++ * space), and < 0 (errors) ++ * ++ * Errors: ++ * -EINVAL: Unrecognized PSCI function ++ */ ++int kvm_psci_call(struct kvm_vcpu *vcpu) ++{ ++ switch (kvm_psci_version(vcpu)) { ++ case KVM_ARM_PSCI_0_2: ++ return kvm_psci_0_2_call(vcpu); ++ case KVM_ARM_PSCI_0_1: ++ return kvm_psci_0_1_call(vcpu); ++ default: ++ return -EINVAL; ++ }; ++} +diff -Nur linux-3.18.14.orig/arch/arm/mach-at91/at91rm9200_time.c linux-3.18.14-rt/arch/arm/mach-at91/at91rm9200_time.c +--- linux-3.18.14.orig/arch/arm/mach-at91/at91rm9200_time.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/mach-at91/at91rm9200_time.c 2015-05-31 15:32:45.673635392 -0500 @@ -135,6 +135,7 @@ break; case CLOCK_EVT_MODE_SHUTDOWN: @@ -298,9 +2267,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-at91/at91rm9200_time.c linux-3.18.12/ case CLOCK_EVT_MODE_RESUME: irqmask = 0; break; -diff -Nur linux-3.18.12.orig/arch/arm/mach-exynos/platsmp.c linux-3.18.12/arch/arm/mach-exynos/platsmp.c ---- linux-3.18.12.orig/arch/arm/mach-exynos/platsmp.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/mach-exynos/platsmp.c 2015-04-26 13:32:22.359684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/mach-exynos/platsmp.c linux-3.18.14-rt/arch/arm/mach-exynos/platsmp.c +--- linux-3.18.14.orig/arch/arm/mach-exynos/platsmp.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/mach-exynos/platsmp.c 2015-05-31 15:32:45.673635392 -0500 @@ -137,7 +137,7 @@ return (void __iomem *)(S5P_VA_SCU); } @@ -348,9 +2317,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-exynos/platsmp.c linux-3.18.12/arch/a return pen_release != -1 ? ret : 0; } -diff -Nur linux-3.18.12.orig/arch/arm/mach-hisi/platmcpm.c linux-3.18.12/arch/arm/mach-hisi/platmcpm.c ---- linux-3.18.12.orig/arch/arm/mach-hisi/platmcpm.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/mach-hisi/platmcpm.c 2015-04-26 13:32:22.363684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/mach-hisi/platmcpm.c linux-3.18.14-rt/arch/arm/mach-hisi/platmcpm.c +--- linux-3.18.14.orig/arch/arm/mach-hisi/platmcpm.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/mach-hisi/platmcpm.c 2015-05-31 15:32:45.677635392 -0500 @@ -57,7 +57,7 @@ static void __iomem *sysctrl, *fabric; @@ -453,9 +2422,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-hisi/platmcpm.c linux-3.18.12/arch/ar } static void __naked hip04_mcpm_power_up_setup(unsigned int affinity_level) -diff -Nur linux-3.18.12.orig/arch/arm/mach-omap2/omap-smp.c linux-3.18.12/arch/arm/mach-omap2/omap-smp.c ---- linux-3.18.12.orig/arch/arm/mach-omap2/omap-smp.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/mach-omap2/omap-smp.c 2015-04-26 13:32:22.363684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/mach-omap2/omap-smp.c linux-3.18.14-rt/arch/arm/mach-omap2/omap-smp.c +--- linux-3.18.14.orig/arch/arm/mach-omap2/omap-smp.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/mach-omap2/omap-smp.c 2015-05-31 15:32:45.697635392 -0500 @@ -43,7 +43,7 @@ /* SCU base address */ static void __iomem *scu_base; @@ -494,9 +2463,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-omap2/omap-smp.c linux-3.18.12/arch/a return 0; } -diff -Nur linux-3.18.12.orig/arch/arm/mach-prima2/platsmp.c linux-3.18.12/arch/arm/mach-prima2/platsmp.c ---- linux-3.18.12.orig/arch/arm/mach-prima2/platsmp.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/mach-prima2/platsmp.c 2015-04-26 13:32:22.363684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/mach-prima2/platsmp.c linux-3.18.14-rt/arch/arm/mach-prima2/platsmp.c +--- linux-3.18.14.orig/arch/arm/mach-prima2/platsmp.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/mach-prima2/platsmp.c 2015-05-31 15:32:45.721635392 -0500 @@ -23,7 +23,7 @@ static void __iomem *scu_base; static void __iomem *rsc_base; @@ -535,9 +2504,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-prima2/platsmp.c linux-3.18.12/arch/a return pen_release != -1 ? -ENOSYS : 0; } -diff -Nur linux-3.18.12.orig/arch/arm/mach-qcom/platsmp.c linux-3.18.12/arch/arm/mach-qcom/platsmp.c ---- linux-3.18.12.orig/arch/arm/mach-qcom/platsmp.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/mach-qcom/platsmp.c 2015-04-26 13:32:22.363684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/mach-qcom/platsmp.c linux-3.18.14-rt/arch/arm/mach-qcom/platsmp.c +--- linux-3.18.14.orig/arch/arm/mach-qcom/platsmp.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/mach-qcom/platsmp.c 2015-05-31 15:32:45.741635391 -0500 @@ -46,7 +46,7 @@ extern void secondary_startup(void); @@ -576,9 +2545,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-qcom/platsmp.c linux-3.18.12/arch/arm return ret; } -diff -Nur linux-3.18.12.orig/arch/arm/mach-spear/platsmp.c linux-3.18.12/arch/arm/mach-spear/platsmp.c ---- linux-3.18.12.orig/arch/arm/mach-spear/platsmp.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/mach-spear/platsmp.c 2015-04-26 13:32:22.363684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/mach-spear/platsmp.c linux-3.18.14-rt/arch/arm/mach-spear/platsmp.c +--- linux-3.18.14.orig/arch/arm/mach-spear/platsmp.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/mach-spear/platsmp.c 2015-05-31 15:32:45.749635392 -0500 @@ -32,7 +32,7 @@ sync_cache_w(&pen_release); } @@ -617,9 +2586,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-spear/platsmp.c linux-3.18.12/arch/ar return pen_release != -1 ? -ENOSYS : 0; } -diff -Nur linux-3.18.12.orig/arch/arm/mach-sti/platsmp.c linux-3.18.12/arch/arm/mach-sti/platsmp.c ---- linux-3.18.12.orig/arch/arm/mach-sti/platsmp.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/mach-sti/platsmp.c 2015-04-26 13:32:22.363684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/mach-sti/platsmp.c linux-3.18.14-rt/arch/arm/mach-sti/platsmp.c +--- linux-3.18.14.orig/arch/arm/mach-sti/platsmp.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/mach-sti/platsmp.c 2015-05-31 15:32:45.765635392 -0500 @@ -34,7 +34,7 @@ sync_cache_w(&pen_release); } @@ -658,9 +2627,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-sti/platsmp.c linux-3.18.12/arch/arm/ return pen_release != -1 ? -ENOSYS : 0; } -diff -Nur linux-3.18.12.orig/arch/arm/mach-ux500/platsmp.c linux-3.18.12/arch/arm/mach-ux500/platsmp.c ---- linux-3.18.12.orig/arch/arm/mach-ux500/platsmp.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/mach-ux500/platsmp.c 2015-04-26 13:32:22.363684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/mach-ux500/platsmp.c linux-3.18.14-rt/arch/arm/mach-ux500/platsmp.c +--- linux-3.18.14.orig/arch/arm/mach-ux500/platsmp.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/mach-ux500/platsmp.c 2015-05-31 15:32:45.793635391 -0500 @@ -51,7 +51,7 @@ return NULL; } @@ -699,9 +2668,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mach-ux500/platsmp.c linux-3.18.12/arch/ar return pen_release != -1 ? -ENOSYS : 0; } -diff -Nur linux-3.18.12.orig/arch/arm/mm/fault.c linux-3.18.12/arch/arm/mm/fault.c ---- linux-3.18.12.orig/arch/arm/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/mm/fault.c 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/mm/fault.c linux-3.18.14-rt/arch/arm/mm/fault.c +--- linux-3.18.14.orig/arch/arm/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/mm/fault.c 2015-05-31 15:32:45.797635391 -0500 @@ -277,7 +277,7 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. @@ -731,9 +2700,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mm/fault.c linux-3.18.12/arch/arm/mm/fault do_bad_area(addr, fsr, regs); return 0; } -diff -Nur linux-3.18.12.orig/arch/arm/mm/highmem.c linux-3.18.12/arch/arm/mm/highmem.c ---- linux-3.18.12.orig/arch/arm/mm/highmem.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/mm/highmem.c 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/mm/highmem.c linux-3.18.14-rt/arch/arm/mm/highmem.c +--- linux-3.18.14.orig/arch/arm/mm/highmem.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/mm/highmem.c 2015-05-31 15:32:45.805635391 -0500 @@ -53,6 +53,7 @@ void *kmap_atomic(struct page *page) @@ -820,9 +2789,9 @@ diff -Nur linux-3.18.12.orig/arch/arm/mm/highmem.c linux-3.18.12/arch/arm/mm/hig + } +} +#endif -diff -Nur linux-3.18.12.orig/arch/arm/plat-versatile/platsmp.c linux-3.18.12/arch/arm/plat-versatile/platsmp.c ---- linux-3.18.12.orig/arch/arm/plat-versatile/platsmp.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/arm/plat-versatile/platsmp.c 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm/plat-versatile/platsmp.c linux-3.18.14-rt/arch/arm/plat-versatile/platsmp.c +--- linux-3.18.14.orig/arch/arm/plat-versatile/platsmp.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm/plat-versatile/platsmp.c 2015-05-31 15:32:45.889635390 -0500 @@ -30,7 +30,7 @@ sync_cache_w(&pen_release); } @@ -861,9 +2830,112 @@ diff -Nur linux-3.18.12.orig/arch/arm/plat-versatile/platsmp.c linux-3.18.12/arc return pen_release != -1 ? -ENOSYS : 0; } -diff -Nur linux-3.18.12.orig/arch/avr32/mm/fault.c linux-3.18.12/arch/avr32/mm/fault.c ---- linux-3.18.12.orig/arch/avr32/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/avr32/mm/fault.c 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/arm64/include/asm/thread_info.h linux-3.18.14-rt/arch/arm64/include/asm/thread_info.h +--- linux-3.18.14.orig/arch/arm64/include/asm/thread_info.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm64/include/asm/thread_info.h 2015-05-31 15:32:45.925635390 -0500 +@@ -50,6 +50,7 @@ + struct exec_domain *exec_domain; /* execution domain */ + struct restart_block restart_block; + int preempt_count; /* 0 => preemptable, <0 => bug */ ++ int preempt_lazy_count; /* 0 => preemptable, <0 => bug */ + int cpu; /* cpu */ + }; + +@@ -108,6 +109,7 @@ + #define TIF_NEED_RESCHED 1 + #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ + #define TIF_FOREIGN_FPSTATE 3 /* CPU's FP state is not current's */ ++#define TIF_NEED_RESCHED_LAZY 4 + #define TIF_NOHZ 7 + #define TIF_SYSCALL_TRACE 8 + #define TIF_SYSCALL_AUDIT 9 +@@ -124,6 +126,7 @@ + #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) + #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) + #define _TIF_FOREIGN_FPSTATE (1 << TIF_FOREIGN_FPSTATE) ++#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY) + #define _TIF_NOHZ (1 << TIF_NOHZ) + #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) + #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) +diff -Nur linux-3.18.14.orig/arch/arm64/Kconfig linux-3.18.14-rt/arch/arm64/Kconfig +--- linux-3.18.14.orig/arch/arm64/Kconfig 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm64/Kconfig 2015-05-31 15:32:45.905635390 -0500 +@@ -59,8 +59,10 @@ + select HAVE_PERF_REGS + select HAVE_PERF_USER_STACK_DUMP + select HAVE_RCU_TABLE_FREE ++ select HAVE_PREEMPT_LAZY + select HAVE_SYSCALL_TRACEPOINTS + select IRQ_DOMAIN ++ select IRQ_FORCED_THREADING + select MODULES_USE_ELF_RELA + select NO_BOOTMEM + select OF +diff -Nur linux-3.18.14.orig/arch/arm64/kernel/asm-offsets.c linux-3.18.14-rt/arch/arm64/kernel/asm-offsets.c +--- linux-3.18.14.orig/arch/arm64/kernel/asm-offsets.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm64/kernel/asm-offsets.c 2015-05-31 15:32:45.925635390 -0500 +@@ -36,6 +36,7 @@ + BLANK(); + DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); + DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); ++ DEFINE(TI_PREEMPT_LAZY, offsetof(struct thread_info, preempt_lazy_count)); + DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); + DEFINE(TI_TASK, offsetof(struct thread_info, task)); + DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain)); +diff -Nur linux-3.18.14.orig/arch/arm64/kernel/entry.S linux-3.18.14-rt/arch/arm64/kernel/entry.S +--- linux-3.18.14.orig/arch/arm64/kernel/entry.S 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm64/kernel/entry.S 2015-05-31 15:32:45.925635390 -0500 +@@ -367,11 +367,16 @@ + #ifdef CONFIG_PREEMPT + get_thread_info tsk + ldr w24, [tsk, #TI_PREEMPT] // get preempt count +- cbnz w24, 1f // preempt count != 0 ++ cbnz w24, 2f // preempt count != 0 + ldr x0, [tsk, #TI_FLAGS] // get flags +- tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling? +- bl el1_preempt ++ tbnz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling? ++ ++ ldr w24, [tsk, #TI_PREEMPT_LAZY] // get preempt lazy count ++ cbnz w24, 2f // preempt lazy count != 0 ++ tbz x0, #TIF_NEED_RESCHED_LAZY, 2f // needs rescheduling? + 1: ++ bl el1_preempt ++2: + #endif + #ifdef CONFIG_TRACE_IRQFLAGS + bl trace_hardirqs_on +@@ -385,6 +390,7 @@ + 1: bl preempt_schedule_irq // irq en/disable is done inside + ldr x0, [tsk, #TI_FLAGS] // get new tasks TI_FLAGS + tbnz x0, #TIF_NEED_RESCHED, 1b // needs rescheduling? ++ tbnz x0, #TIF_NEED_RESCHED_LAZY, 1b // needs rescheduling? + ret x24 + #endif + +@@ -621,6 +627,7 @@ + str x0, [sp, #S_X0] // returned x0 + work_pending: + tbnz x1, #TIF_NEED_RESCHED, work_resched ++ tbnz x1, #TIF_NEED_RESCHED_LAZY, work_resched + /* TIF_SIGPENDING, TIF_NOTIFY_RESUME or TIF_FOREIGN_FPSTATE case */ + ldr x2, [sp, #S_PSTATE] + mov x0, sp // 'regs' +diff -Nur linux-3.18.14.orig/arch/arm64/kernel/perf_event.c linux-3.18.14-rt/arch/arm64/kernel/perf_event.c +--- linux-3.18.14.orig/arch/arm64/kernel/perf_event.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/arm64/kernel/perf_event.c 2015-05-31 15:32:45.925635390 -0500 +@@ -461,7 +461,7 @@ + } + + err = request_irq(irq, armpmu->handle_irq, +- IRQF_NOBALANCING, ++ IRQF_NOBALANCING | IRQF_NO_THREAD, + "arm-pmu", armpmu); + if (err) { + pr_err("unable to request IRQ%d for ARM PMU counters\n", +diff -Nur linux-3.18.14.orig/arch/avr32/mm/fault.c linux-3.18.14-rt/arch/avr32/mm/fault.c +--- linux-3.18.14.orig/arch/avr32/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/avr32/mm/fault.c 2015-05-31 15:32:45.933635390 -0500 @@ -81,7 +81,7 @@ * If we're in an interrupt or have no user context, we must * not take the fault... @@ -873,9 +2945,9 @@ diff -Nur linux-3.18.12.orig/arch/avr32/mm/fault.c linux-3.18.12/arch/avr32/mm/f goto no_context; local_irq_enable(); -diff -Nur linux-3.18.12.orig/arch/cris/mm/fault.c linux-3.18.12/arch/cris/mm/fault.c ---- linux-3.18.12.orig/arch/cris/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/cris/mm/fault.c 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/cris/mm/fault.c linux-3.18.14-rt/arch/cris/mm/fault.c +--- linux-3.18.14.orig/arch/cris/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/cris/mm/fault.c 2015-05-31 15:32:45.945635390 -0500 @@ -113,7 +113,7 @@ * user context, we must not take the fault. */ @@ -885,9 +2957,9 @@ diff -Nur linux-3.18.12.orig/arch/cris/mm/fault.c linux-3.18.12/arch/cris/mm/fau goto no_context; if (user_mode(regs)) -diff -Nur linux-3.18.12.orig/arch/frv/mm/fault.c linux-3.18.12/arch/frv/mm/fault.c ---- linux-3.18.12.orig/arch/frv/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/frv/mm/fault.c 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/frv/mm/fault.c linux-3.18.14-rt/arch/frv/mm/fault.c +--- linux-3.18.14.orig/arch/frv/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/frv/mm/fault.c 2015-05-31 15:32:45.953635390 -0500 @@ -78,7 +78,7 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. @@ -897,9 +2969,9 @@ diff -Nur linux-3.18.12.orig/arch/frv/mm/fault.c linux-3.18.12/arch/frv/mm/fault goto no_context; if (user_mode(__frame)) -diff -Nur linux-3.18.12.orig/arch/ia64/mm/fault.c linux-3.18.12/arch/ia64/mm/fault.c ---- linux-3.18.12.orig/arch/ia64/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/ia64/mm/fault.c 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/ia64/mm/fault.c linux-3.18.14-rt/arch/ia64/mm/fault.c +--- linux-3.18.14.orig/arch/ia64/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/ia64/mm/fault.c 2015-05-31 15:32:45.961635389 -0500 @@ -96,7 +96,7 @@ /* * If we're in an interrupt or have no user context, we must not take the fault.. @@ -909,9 +2981,9 @@ diff -Nur linux-3.18.12.orig/arch/ia64/mm/fault.c linux-3.18.12/arch/ia64/mm/fau goto no_context; #ifdef CONFIG_VIRTUAL_MEM_MAP -diff -Nur linux-3.18.12.orig/arch/Kconfig linux-3.18.12/arch/Kconfig ---- linux-3.18.12.orig/arch/Kconfig 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/Kconfig 2015-04-26 13:32:22.351684003 -0500 +diff -Nur linux-3.18.14.orig/arch/Kconfig linux-3.18.14-rt/arch/Kconfig +--- linux-3.18.14.orig/arch/Kconfig 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/Kconfig 2015-05-31 15:32:45.501635394 -0500 @@ -6,6 +6,7 @@ tristate "OProfile system profiling" depends on PROFILING @@ -920,9 +2992,9 @@ diff -Nur linux-3.18.12.orig/arch/Kconfig linux-3.18.12/arch/Kconfig select RING_BUFFER select RING_BUFFER_ALLOW_SWAP help -diff -Nur linux-3.18.12.orig/arch/m32r/mm/fault.c linux-3.18.12/arch/m32r/mm/fault.c ---- linux-3.18.12.orig/arch/m32r/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/m32r/mm/fault.c 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/m32r/mm/fault.c linux-3.18.14-rt/arch/m32r/mm/fault.c +--- linux-3.18.14.orig/arch/m32r/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/m32r/mm/fault.c 2015-05-31 15:32:45.985635389 -0500 @@ -114,7 +114,7 @@ * If we're in an interrupt or have no user context or are running in an * atomic region then we must not take the fault.. @@ -932,9 +3004,9 @@ diff -Nur linux-3.18.12.orig/arch/m32r/mm/fault.c linux-3.18.12/arch/m32r/mm/fau goto bad_area_nosemaphore; if (error_code & ACE_USERMODE) -diff -Nur linux-3.18.12.orig/arch/m68k/mm/fault.c linux-3.18.12/arch/m68k/mm/fault.c ---- linux-3.18.12.orig/arch/m68k/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/m68k/mm/fault.c 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/m68k/mm/fault.c linux-3.18.14-rt/arch/m68k/mm/fault.c +--- linux-3.18.14.orig/arch/m68k/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/m68k/mm/fault.c 2015-05-31 15:32:45.985635389 -0500 @@ -81,7 +81,7 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. @@ -944,9 +3016,9 @@ diff -Nur linux-3.18.12.orig/arch/m68k/mm/fault.c linux-3.18.12/arch/m68k/mm/fau goto no_context; if (user_mode(regs)) -diff -Nur linux-3.18.12.orig/arch/microblaze/mm/fault.c linux-3.18.12/arch/microblaze/mm/fault.c ---- linux-3.18.12.orig/arch/microblaze/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/microblaze/mm/fault.c 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/microblaze/mm/fault.c linux-3.18.14-rt/arch/microblaze/mm/fault.c +--- linux-3.18.14.orig/arch/microblaze/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/microblaze/mm/fault.c 2015-05-31 15:32:46.005635389 -0500 @@ -107,7 +107,7 @@ if ((error_code & 0x13) == 0x13 || (error_code & 0x11) == 0x11) is_write = 0; @@ -956,9 +3028,9 @@ diff -Nur linux-3.18.12.orig/arch/microblaze/mm/fault.c linux-3.18.12/arch/micro if (kernel_mode(regs)) goto bad_area_nosemaphore; -diff -Nur linux-3.18.12.orig/arch/mips/Kconfig linux-3.18.12/arch/mips/Kconfig ---- linux-3.18.12.orig/arch/mips/Kconfig 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/mips/Kconfig 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/mips/Kconfig linux-3.18.14-rt/arch/mips/Kconfig +--- linux-3.18.14.orig/arch/mips/Kconfig 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/mips/Kconfig 2015-05-31 15:32:46.033635389 -0500 @@ -2196,7 +2196,7 @@ # config HIGHMEM @@ -968,9 +3040,9 @@ diff -Nur linux-3.18.12.orig/arch/mips/Kconfig linux-3.18.12/arch/mips/Kconfig config CPU_SUPPORTS_HIGHMEM bool -diff -Nur linux-3.18.12.orig/arch/mips/kernel/signal.c linux-3.18.12/arch/mips/kernel/signal.c ---- linux-3.18.12.orig/arch/mips/kernel/signal.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/mips/kernel/signal.c 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/mips/kernel/signal.c linux-3.18.14-rt/arch/mips/kernel/signal.c +--- linux-3.18.14.orig/arch/mips/kernel/signal.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/mips/kernel/signal.c 2015-05-31 15:32:46.057635389 -0500 @@ -613,6 +613,7 @@ __u32 thread_info_flags) { @@ -979,9 +3051,9 @@ diff -Nur linux-3.18.12.orig/arch/mips/kernel/signal.c linux-3.18.12/arch/mips/k user_exit(); -diff -Nur linux-3.18.12.orig/arch/mips/mm/fault.c linux-3.18.12/arch/mips/mm/fault.c ---- linux-3.18.12.orig/arch/mips/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/mips/mm/fault.c 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/mips/mm/fault.c linux-3.18.14-rt/arch/mips/mm/fault.c +--- linux-3.18.14.orig/arch/mips/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/mips/mm/fault.c 2015-05-31 15:32:46.069635388 -0500 @@ -89,7 +89,7 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. @@ -991,9 +3063,9 @@ diff -Nur linux-3.18.12.orig/arch/mips/mm/fault.c linux-3.18.12/arch/mips/mm/fau goto bad_area_nosemaphore; if (user_mode(regs)) -diff -Nur linux-3.18.12.orig/arch/mips/mm/init.c linux-3.18.12/arch/mips/mm/init.c ---- linux-3.18.12.orig/arch/mips/mm/init.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/mips/mm/init.c 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/mips/mm/init.c linux-3.18.14-rt/arch/mips/mm/init.c +--- linux-3.18.14.orig/arch/mips/mm/init.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/mips/mm/init.c 2015-05-31 15:32:46.069635388 -0500 @@ -90,7 +90,7 @@ BUG_ON(Page_dcache_dirty(page)); @@ -1012,9 +3084,9 @@ diff -Nur linux-3.18.12.orig/arch/mips/mm/init.c linux-3.18.12/arch/mips/mm/init } void copy_user_highpage(struct page *to, struct page *from, -diff -Nur linux-3.18.12.orig/arch/mn10300/mm/fault.c linux-3.18.12/arch/mn10300/mm/fault.c ---- linux-3.18.12.orig/arch/mn10300/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/mn10300/mm/fault.c 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/mn10300/mm/fault.c linux-3.18.14-rt/arch/mn10300/mm/fault.c +--- linux-3.18.14.orig/arch/mn10300/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/mn10300/mm/fault.c 2015-05-31 15:32:46.113635388 -0500 @@ -168,7 +168,7 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. @@ -1024,9 +3096,9 @@ diff -Nur linux-3.18.12.orig/arch/mn10300/mm/fault.c linux-3.18.12/arch/mn10300/ goto no_context; if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) -diff -Nur linux-3.18.12.orig/arch/parisc/mm/fault.c linux-3.18.12/arch/parisc/mm/fault.c ---- linux-3.18.12.orig/arch/parisc/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/parisc/mm/fault.c 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/parisc/mm/fault.c linux-3.18.14-rt/arch/parisc/mm/fault.c +--- linux-3.18.14.orig/arch/parisc/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/parisc/mm/fault.c 2015-05-31 15:32:46.113635388 -0500 @@ -207,7 +207,7 @@ int fault; unsigned int flags; @@ -1036,9 +3108,9 @@ diff -Nur linux-3.18.12.orig/arch/parisc/mm/fault.c linux-3.18.12/arch/parisc/mm goto no_context; tsk = current; -diff -Nur linux-3.18.12.orig/arch/powerpc/include/asm/kvm_host.h linux-3.18.12/arch/powerpc/include/asm/kvm_host.h ---- linux-3.18.12.orig/arch/powerpc/include/asm/kvm_host.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/powerpc/include/asm/kvm_host.h 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/powerpc/include/asm/kvm_host.h linux-3.18.14-rt/arch/powerpc/include/asm/kvm_host.h +--- linux-3.18.14.orig/arch/powerpc/include/asm/kvm_host.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/powerpc/include/asm/kvm_host.h 2015-05-31 15:32:46.145635388 -0500 @@ -296,7 +296,7 @@ u8 in_guest; struct list_head runnable_threads; @@ -1057,9 +3129,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/include/asm/kvm_host.h linux-3.18.12/a struct kvmppc_vcore *vcore; int ret; int trap; -diff -Nur linux-3.18.12.orig/arch/powerpc/include/asm/thread_info.h linux-3.18.12/arch/powerpc/include/asm/thread_info.h ---- linux-3.18.12.orig/arch/powerpc/include/asm/thread_info.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/powerpc/include/asm/thread_info.h 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/powerpc/include/asm/thread_info.h linux-3.18.14-rt/arch/powerpc/include/asm/thread_info.h +--- linux-3.18.14.orig/arch/powerpc/include/asm/thread_info.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/powerpc/include/asm/thread_info.h 2015-05-31 15:32:46.165635388 -0500 @@ -43,6 +43,8 @@ int cpu; /* cpu we're on */ int preempt_count; /* 0 => preemptable, @@ -1106,9 +3178,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/include/asm/thread_info.h linux-3.18.1 /* Bits in local_flags */ /* Don't move TLF_NAPPING without adjusting the code in entry_32.S */ -diff -Nur linux-3.18.12.orig/arch/powerpc/Kconfig linux-3.18.12/arch/powerpc/Kconfig ---- linux-3.18.12.orig/arch/powerpc/Kconfig 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/powerpc/Kconfig 2015-04-26 13:32:22.367684003 -0500 +diff -Nur linux-3.18.14.orig/arch/powerpc/Kconfig linux-3.18.14-rt/arch/powerpc/Kconfig +--- linux-3.18.14.orig/arch/powerpc/Kconfig 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/powerpc/Kconfig 2015-05-31 15:32:46.141635388 -0500 @@ -60,10 +60,11 @@ config RWSEM_GENERIC_SPINLOCK @@ -1139,9 +3211,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/Kconfig linux-3.18.12/arch/powerpc/Kco source kernel/Kconfig.hz source kernel/Kconfig.preempt -diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/asm-offsets.c linux-3.18.12/arch/powerpc/kernel/asm-offsets.c ---- linux-3.18.12.orig/arch/powerpc/kernel/asm-offsets.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/powerpc/kernel/asm-offsets.c 2015-04-26 13:32:22.371684003 -0500 +diff -Nur linux-3.18.14.orig/arch/powerpc/kernel/asm-offsets.c linux-3.18.14-rt/arch/powerpc/kernel/asm-offsets.c +--- linux-3.18.14.orig/arch/powerpc/kernel/asm-offsets.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/powerpc/kernel/asm-offsets.c 2015-05-31 15:32:46.205635388 -0500 @@ -159,6 +159,7 @@ DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); DEFINE(TI_LOCAL_FLAGS, offsetof(struct thread_info, local_flags)); @@ -1150,9 +3222,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/asm-offsets.c linux-3.18.12/arc DEFINE(TI_TASK, offsetof(struct thread_info, task)); DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); -diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/entry_32.S linux-3.18.12/arch/powerpc/kernel/entry_32.S ---- linux-3.18.12.orig/arch/powerpc/kernel/entry_32.S 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/powerpc/kernel/entry_32.S 2015-04-26 13:32:22.371684003 -0500 +diff -Nur linux-3.18.14.orig/arch/powerpc/kernel/entry_32.S linux-3.18.14-rt/arch/powerpc/kernel/entry_32.S +--- linux-3.18.14.orig/arch/powerpc/kernel/entry_32.S 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/powerpc/kernel/entry_32.S 2015-05-31 15:32:46.217635387 -0500 @@ -890,7 +890,14 @@ cmpwi 0,r0,0 /* if non-zero, just restore regs and return */ bne restore @@ -1201,9 +3273,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/entry_32.S linux-3.18.12/arch/p bne- do_resched andi. r0,r9,_TIF_USER_WORK_MASK beq restore_user -diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/entry_64.S linux-3.18.12/arch/powerpc/kernel/entry_64.S ---- linux-3.18.12.orig/arch/powerpc/kernel/entry_64.S 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/powerpc/kernel/entry_64.S 2015-04-26 13:32:22.371684003 -0500 +diff -Nur linux-3.18.14.orig/arch/powerpc/kernel/entry_64.S linux-3.18.14-rt/arch/powerpc/kernel/entry_64.S +--- linux-3.18.14.orig/arch/powerpc/kernel/entry_64.S 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/powerpc/kernel/entry_64.S 2015-05-31 15:32:46.241635387 -0500 @@ -644,7 +644,7 @@ #else beq restore @@ -1242,9 +3314,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/entry_64.S linux-3.18.12/arch/p bne 1b /* -diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/irq.c linux-3.18.12/arch/powerpc/kernel/irq.c ---- linux-3.18.12.orig/arch/powerpc/kernel/irq.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/powerpc/kernel/irq.c 2015-04-26 13:32:22.371684003 -0500 +diff -Nur linux-3.18.14.orig/arch/powerpc/kernel/irq.c linux-3.18.14-rt/arch/powerpc/kernel/irq.c +--- linux-3.18.14.orig/arch/powerpc/kernel/irq.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/powerpc/kernel/irq.c 2015-05-31 15:32:46.245635387 -0500 @@ -615,6 +615,7 @@ } } @@ -1261,9 +3333,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/irq.c linux-3.18.12/arch/powerp irq_hw_number_t virq_to_hw(unsigned int virq) { -diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/misc_32.S linux-3.18.12/arch/powerpc/kernel/misc_32.S ---- linux-3.18.12.orig/arch/powerpc/kernel/misc_32.S 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/powerpc/kernel/misc_32.S 2015-04-26 13:32:22.371684003 -0500 +diff -Nur linux-3.18.14.orig/arch/powerpc/kernel/misc_32.S linux-3.18.14-rt/arch/powerpc/kernel/misc_32.S +--- linux-3.18.14.orig/arch/powerpc/kernel/misc_32.S 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/powerpc/kernel/misc_32.S 2015-05-31 15:32:46.261635387 -0500 @@ -40,6 +40,7 @@ * We store the saved ksp_limit in the unused part * of the STACK_FRAME_OVERHEAD @@ -1280,9 +3352,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/misc_32.S linux-3.18.12/arch/po /* * void call_do_irq(struct pt_regs *regs, struct thread_info *irqtp); -diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/misc_64.S linux-3.18.12/arch/powerpc/kernel/misc_64.S ---- linux-3.18.12.orig/arch/powerpc/kernel/misc_64.S 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/powerpc/kernel/misc_64.S 2015-04-26 13:32:22.371684003 -0500 +diff -Nur linux-3.18.14.orig/arch/powerpc/kernel/misc_64.S linux-3.18.14-rt/arch/powerpc/kernel/misc_64.S +--- linux-3.18.14.orig/arch/powerpc/kernel/misc_64.S 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/powerpc/kernel/misc_64.S 2015-05-31 15:32:46.261635387 -0500 @@ -29,6 +29,7 @@ .text @@ -1299,9 +3371,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/misc_64.S linux-3.18.12/arch/po _GLOBAL(call_do_irq) mflr r0 -diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/time.c linux-3.18.12/arch/powerpc/kernel/time.c ---- linux-3.18.12.orig/arch/powerpc/kernel/time.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/powerpc/kernel/time.c 2015-04-26 13:32:22.371684003 -0500 +diff -Nur linux-3.18.14.orig/arch/powerpc/kernel/time.c linux-3.18.14-rt/arch/powerpc/kernel/time.c +--- linux-3.18.14.orig/arch/powerpc/kernel/time.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/powerpc/kernel/time.c 2015-05-31 15:32:46.261635387 -0500 @@ -424,7 +424,7 @@ EXPORT_SYMBOL(profile_pc); #endif @@ -1311,9 +3383,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kernel/time.c linux-3.18.12/arch/power /* * 64-bit uses a byte in the PACA, 32-bit uses a per-cpu variable... -diff -Nur linux-3.18.12.orig/arch/powerpc/kvm/book3s_hv.c linux-3.18.12/arch/powerpc/kvm/book3s_hv.c ---- linux-3.18.12.orig/arch/powerpc/kvm/book3s_hv.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/powerpc/kvm/book3s_hv.c 2015-04-26 13:32:22.371684003 -0500 +diff -Nur linux-3.18.14.orig/arch/powerpc/kvm/book3s_hv.c linux-3.18.14-rt/arch/powerpc/kvm/book3s_hv.c +--- linux-3.18.14.orig/arch/powerpc/kvm/book3s_hv.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/powerpc/kvm/book3s_hv.c 2015-05-31 15:32:46.301635387 -0500 @@ -84,11 +84,11 @@ { int me; @@ -1375,9 +3447,20 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/kvm/book3s_hv.c linux-3.18.12/arch/pow } } -diff -Nur linux-3.18.12.orig/arch/powerpc/mm/fault.c linux-3.18.12/arch/powerpc/mm/fault.c ---- linux-3.18.12.orig/arch/powerpc/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/powerpc/mm/fault.c 2015-04-26 13:32:22.371684003 -0500 +diff -Nur linux-3.18.14.orig/arch/powerpc/kvm/Kconfig linux-3.18.14-rt/arch/powerpc/kvm/Kconfig +--- linux-3.18.14.orig/arch/powerpc/kvm/Kconfig 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/powerpc/kvm/Kconfig 2015-05-31 15:32:46.281635387 -0500 +@@ -157,6 +157,7 @@ + config KVM_MPIC + bool "KVM in-kernel MPIC emulation" + depends on KVM && E500 ++ depends on !PREEMPT_RT_FULL + select HAVE_KVM_IRQCHIP + select HAVE_KVM_IRQFD + select HAVE_KVM_IRQ_ROUTING +diff -Nur linux-3.18.14.orig/arch/powerpc/mm/fault.c linux-3.18.14-rt/arch/powerpc/mm/fault.c +--- linux-3.18.14.orig/arch/powerpc/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/powerpc/mm/fault.c 2015-05-31 15:32:46.325635386 -0500 @@ -273,7 +273,7 @@ if (!arch_irq_disabled_regs(regs)) local_irq_enable(); @@ -1387,9 +3470,9 @@ diff -Nur linux-3.18.12.orig/arch/powerpc/mm/fault.c linux-3.18.12/arch/powerpc/ if (!user_mode(regs)) { rc = SIGSEGV; goto bail; -diff -Nur linux-3.18.12.orig/arch/s390/include/asm/kvm_host.h linux-3.18.12/arch/s390/include/asm/kvm_host.h ---- linux-3.18.12.orig/arch/s390/include/asm/kvm_host.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/s390/include/asm/kvm_host.h 2015-04-26 13:32:22.371684003 -0500 +diff -Nur linux-3.18.14.orig/arch/s390/include/asm/kvm_host.h linux-3.18.14-rt/arch/s390/include/asm/kvm_host.h +--- linux-3.18.14.orig/arch/s390/include/asm/kvm_host.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/s390/include/asm/kvm_host.h 2015-05-31 15:32:46.369635386 -0500 @@ -311,7 +311,7 @@ struct list_head list; atomic_t active; @@ -1399,10 +3482,10 @@ diff -Nur linux-3.18.12.orig/arch/s390/include/asm/kvm_host.h linux-3.18.12/arch atomic_t *cpuflags; unsigned int action_bits; }; -diff -Nur linux-3.18.12.orig/arch/s390/kvm/interrupt.c linux-3.18.12/arch/s390/kvm/interrupt.c ---- linux-3.18.12.orig/arch/s390/kvm/interrupt.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/s390/kvm/interrupt.c 2015-04-26 13:32:22.371684003 -0500 -@@ -619,13 +619,13 @@ +diff -Nur linux-3.18.14.orig/arch/s390/kvm/interrupt.c linux-3.18.14-rt/arch/s390/kvm/interrupt.c +--- linux-3.18.14.orig/arch/s390/kvm/interrupt.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/s390/kvm/interrupt.c 2015-05-31 15:32:46.385635386 -0500 +@@ -620,13 +620,13 @@ void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu) { @@ -1418,7 +3501,7 @@ diff -Nur linux-3.18.12.orig/arch/s390/kvm/interrupt.c linux-3.18.12/arch/s390/k vcpu->stat.halt_wakeup++; } } -@@ -746,7 +746,7 @@ +@@ -747,7 +747,7 @@ spin_lock(&li->lock); list_add(&inti->list, &li->list); atomic_set(&li->active, 1); @@ -1427,7 +3510,7 @@ diff -Nur linux-3.18.12.orig/arch/s390/kvm/interrupt.c linux-3.18.12/arch/s390/k spin_unlock(&li->lock); return 0; } -@@ -771,7 +771,7 @@ +@@ -772,7 +772,7 @@ spin_lock(&li->lock); list_add(&inti->list, &li->list); atomic_set(&li->active, 1); @@ -1436,9 +3519,1554 @@ diff -Nur linux-3.18.12.orig/arch/s390/kvm/interrupt.c linux-3.18.12/arch/s390/k spin_unlock(&li->lock); return 0; } -diff -Nur linux-3.18.12.orig/arch/s390/mm/fault.c linux-3.18.12/arch/s390/mm/fault.c ---- linux-3.18.12.orig/arch/s390/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/s390/mm/fault.c 2015-04-26 13:32:22.371684003 -0500 +diff -Nur linux-3.18.14.orig/arch/s390/kvm/interrupt.c.orig linux-3.18.14-rt/arch/s390/kvm/interrupt.c.orig +--- linux-3.18.14.orig/arch/s390/kvm/interrupt.c.orig 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/arch/s390/kvm/interrupt.c.orig 2015-05-20 10:04:50.000000000 -0500 +@@ -0,0 +1,1541 @@ ++/* ++ * handling kvm guest interrupts ++ * ++ * Copyright IBM Corp. 2008,2014 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License (version 2 only) ++ * as published by the Free Software Foundation. ++ * ++ * Author(s): Carsten Otte <cotte@de.ibm.com> ++ */ ++ ++#include <linux/interrupt.h> ++#include <linux/kvm_host.h> ++#include <linux/hrtimer.h> ++#include <linux/mmu_context.h> ++#include <linux/signal.h> ++#include <linux/slab.h> ++#include <linux/vmalloc.h> ++#include <asm/asm-offsets.h> ++#include <asm/uaccess.h> ++#include "kvm-s390.h" ++#include "gaccess.h" ++#include "trace-s390.h" ++ ++#define IOINT_SCHID_MASK 0x0000ffff ++#define IOINT_SSID_MASK 0x00030000 ++#define IOINT_CSSID_MASK 0x03fc0000 ++#define IOINT_AI_MASK 0x04000000 ++#define PFAULT_INIT 0x0600 ++ ++static int __must_check deliver_ckc_interrupt(struct kvm_vcpu *vcpu); ++ ++static int is_ioint(u64 type) ++{ ++ return ((type & 0xfffe0000u) != 0xfffe0000u); ++} ++ ++int psw_extint_disabled(struct kvm_vcpu *vcpu) ++{ ++ return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_EXT); ++} ++ ++static int psw_ioint_disabled(struct kvm_vcpu *vcpu) ++{ ++ return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_IO); ++} ++ ++static int psw_mchk_disabled(struct kvm_vcpu *vcpu) ++{ ++ return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_MCHECK); ++} ++ ++static int psw_interrupts_disabled(struct kvm_vcpu *vcpu) ++{ ++ if ((vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PER) || ++ (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_IO) || ++ (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_EXT)) ++ return 0; ++ return 1; ++} ++ ++static int ckc_interrupts_enabled(struct kvm_vcpu *vcpu) ++{ ++ if (psw_extint_disabled(vcpu) || ++ !(vcpu->arch.sie_block->gcr[0] & 0x800ul)) ++ return 0; ++ if (guestdbg_enabled(vcpu) && guestdbg_sstep_enabled(vcpu)) ++ /* No timer interrupts when single stepping */ ++ return 0; ++ return 1; ++} ++ ++static u64 int_word_to_isc_bits(u32 int_word) ++{ ++ u8 isc = (int_word & 0x38000000) >> 27; ++ ++ return (0x80 >> isc) << 24; ++} ++ ++static int __must_check __interrupt_is_deliverable(struct kvm_vcpu *vcpu, ++ struct kvm_s390_interrupt_info *inti) ++{ ++ switch (inti->type) { ++ case KVM_S390_INT_EXTERNAL_CALL: ++ if (psw_extint_disabled(vcpu)) ++ return 0; ++ if (vcpu->arch.sie_block->gcr[0] & 0x2000ul) ++ return 1; ++ return 0; ++ case KVM_S390_INT_EMERGENCY: ++ if (psw_extint_disabled(vcpu)) ++ return 0; ++ if (vcpu->arch.sie_block->gcr[0] & 0x4000ul) ++ return 1; ++ return 0; ++ case KVM_S390_INT_CLOCK_COMP: ++ return ckc_interrupts_enabled(vcpu); ++ case KVM_S390_INT_CPU_TIMER: ++ if (psw_extint_disabled(vcpu)) ++ return 0; ++ if (vcpu->arch.sie_block->gcr[0] & 0x400ul) ++ return 1; ++ return 0; ++ case KVM_S390_INT_SERVICE: ++ case KVM_S390_INT_PFAULT_INIT: ++ case KVM_S390_INT_PFAULT_DONE: ++ case KVM_S390_INT_VIRTIO: ++ if (psw_extint_disabled(vcpu)) ++ return 0; ++ if (vcpu->arch.sie_block->gcr[0] & 0x200ul) ++ return 1; ++ return 0; ++ case KVM_S390_PROGRAM_INT: ++ case KVM_S390_SIGP_STOP: ++ case KVM_S390_SIGP_SET_PREFIX: ++ case KVM_S390_RESTART: ++ return 1; ++ case KVM_S390_MCHK: ++ if (psw_mchk_disabled(vcpu)) ++ return 0; ++ if (vcpu->arch.sie_block->gcr[14] & inti->mchk.cr14) ++ return 1; ++ return 0; ++ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: ++ if (psw_ioint_disabled(vcpu)) ++ return 0; ++ if (vcpu->arch.sie_block->gcr[6] & ++ int_word_to_isc_bits(inti->io.io_int_word)) ++ return 1; ++ return 0; ++ default: ++ printk(KERN_WARNING "illegal interrupt type %llx\n", ++ inti->type); ++ BUG(); ++ } ++ return 0; ++} ++ ++static void __set_cpu_idle(struct kvm_vcpu *vcpu) ++{ ++ atomic_set_mask(CPUSTAT_WAIT, &vcpu->arch.sie_block->cpuflags); ++ set_bit(vcpu->vcpu_id, vcpu->arch.local_int.float_int->idle_mask); ++} ++ ++static void __unset_cpu_idle(struct kvm_vcpu *vcpu) ++{ ++ atomic_clear_mask(CPUSTAT_WAIT, &vcpu->arch.sie_block->cpuflags); ++ clear_bit(vcpu->vcpu_id, vcpu->arch.local_int.float_int->idle_mask); ++} ++ ++static void __reset_intercept_indicators(struct kvm_vcpu *vcpu) ++{ ++ atomic_clear_mask(CPUSTAT_IO_INT | CPUSTAT_EXT_INT | CPUSTAT_STOP_INT, ++ &vcpu->arch.sie_block->cpuflags); ++ vcpu->arch.sie_block->lctl = 0x0000; ++ vcpu->arch.sie_block->ictl &= ~(ICTL_LPSW | ICTL_STCTL | ICTL_PINT); ++ ++ if (guestdbg_enabled(vcpu)) { ++ vcpu->arch.sie_block->lctl |= (LCTL_CR0 | LCTL_CR9 | ++ LCTL_CR10 | LCTL_CR11); ++ vcpu->arch.sie_block->ictl |= (ICTL_STCTL | ICTL_PINT); ++ } ++ ++ if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) ++ atomic_set_mask(CPUSTAT_STOP_INT, &vcpu->arch.sie_block->cpuflags); ++} ++ ++static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag) ++{ ++ atomic_set_mask(flag, &vcpu->arch.sie_block->cpuflags); ++} ++ ++static void __set_intercept_indicator(struct kvm_vcpu *vcpu, ++ struct kvm_s390_interrupt_info *inti) ++{ ++ switch (inti->type) { ++ case KVM_S390_INT_EXTERNAL_CALL: ++ case KVM_S390_INT_EMERGENCY: ++ case KVM_S390_INT_SERVICE: ++ case KVM_S390_INT_PFAULT_INIT: ++ case KVM_S390_INT_PFAULT_DONE: ++ case KVM_S390_INT_VIRTIO: ++ case KVM_S390_INT_CLOCK_COMP: ++ case KVM_S390_INT_CPU_TIMER: ++ if (psw_extint_disabled(vcpu)) ++ __set_cpuflag(vcpu, CPUSTAT_EXT_INT); ++ else ++ vcpu->arch.sie_block->lctl |= LCTL_CR0; ++ break; ++ case KVM_S390_SIGP_STOP: ++ __set_cpuflag(vcpu, CPUSTAT_STOP_INT); ++ break; ++ case KVM_S390_MCHK: ++ if (psw_mchk_disabled(vcpu)) ++ vcpu->arch.sie_block->ictl |= ICTL_LPSW; ++ else ++ vcpu->arch.sie_block->lctl |= LCTL_CR14; ++ break; ++ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: ++ if (psw_ioint_disabled(vcpu)) ++ __set_cpuflag(vcpu, CPUSTAT_IO_INT); ++ else ++ vcpu->arch.sie_block->lctl |= LCTL_CR6; ++ break; ++ default: ++ BUG(); ++ } ++} ++ ++static u16 get_ilc(struct kvm_vcpu *vcpu) ++{ ++ const unsigned short table[] = { 2, 4, 4, 6 }; ++ ++ switch (vcpu->arch.sie_block->icptcode) { ++ case ICPT_INST: ++ case ICPT_INSTPROGI: ++ case ICPT_OPEREXC: ++ case ICPT_PARTEXEC: ++ case ICPT_IOINST: ++ /* last instruction only stored for these icptcodes */ ++ return table[vcpu->arch.sie_block->ipa >> 14]; ++ case ICPT_PROGI: ++ return vcpu->arch.sie_block->pgmilc; ++ default: ++ return 0; ++ } ++} ++ ++static int __must_check __deliver_prog_irq(struct kvm_vcpu *vcpu, ++ struct kvm_s390_pgm_info *pgm_info) ++{ ++ int rc = 0; ++ u16 ilc = get_ilc(vcpu); ++ ++ switch (pgm_info->code & ~PGM_PER) { ++ case PGM_AFX_TRANSLATION: ++ case PGM_ASX_TRANSLATION: ++ case PGM_EX_TRANSLATION: ++ case PGM_LFX_TRANSLATION: ++ case PGM_LSTE_SEQUENCE: ++ case PGM_LSX_TRANSLATION: ++ case PGM_LX_TRANSLATION: ++ case PGM_PRIMARY_AUTHORITY: ++ case PGM_SECONDARY_AUTHORITY: ++ case PGM_SPACE_SWITCH: ++ rc = put_guest_lc(vcpu, pgm_info->trans_exc_code, ++ (u64 *)__LC_TRANS_EXC_CODE); ++ break; ++ case PGM_ALEN_TRANSLATION: ++ case PGM_ALE_SEQUENCE: ++ case PGM_ASTE_INSTANCE: ++ case PGM_ASTE_SEQUENCE: ++ case PGM_ASTE_VALIDITY: ++ case PGM_EXTENDED_AUTHORITY: ++ rc = put_guest_lc(vcpu, pgm_info->exc_access_id, ++ (u8 *)__LC_EXC_ACCESS_ID); ++ break; ++ case PGM_ASCE_TYPE: ++ case PGM_PAGE_TRANSLATION: ++ case PGM_REGION_FIRST_TRANS: ++ case PGM_REGION_SECOND_TRANS: ++ case PGM_REGION_THIRD_TRANS: ++ case PGM_SEGMENT_TRANSLATION: ++ rc = put_guest_lc(vcpu, pgm_info->trans_exc_code, ++ (u64 *)__LC_TRANS_EXC_CODE); ++ rc |= put_guest_lc(vcpu, pgm_info->exc_access_id, ++ (u8 *)__LC_EXC_ACCESS_ID); ++ rc |= put_guest_lc(vcpu, pgm_info->op_access_id, ++ (u8 *)__LC_OP_ACCESS_ID); ++ break; ++ case PGM_MONITOR: ++ rc = put_guest_lc(vcpu, pgm_info->mon_class_nr, ++ (u16 *)__LC_MON_CLASS_NR); ++ rc |= put_guest_lc(vcpu, pgm_info->mon_code, ++ (u64 *)__LC_MON_CODE); ++ break; ++ case PGM_DATA: ++ rc = put_guest_lc(vcpu, pgm_info->data_exc_code, ++ (u32 *)__LC_DATA_EXC_CODE); ++ break; ++ case PGM_PROTECTION: ++ rc = put_guest_lc(vcpu, pgm_info->trans_exc_code, ++ (u64 *)__LC_TRANS_EXC_CODE); ++ rc |= put_guest_lc(vcpu, pgm_info->exc_access_id, ++ (u8 *)__LC_EXC_ACCESS_ID); ++ break; ++ } ++ ++ if (pgm_info->code & PGM_PER) { ++ rc |= put_guest_lc(vcpu, pgm_info->per_code, ++ (u8 *) __LC_PER_CODE); ++ rc |= put_guest_lc(vcpu, pgm_info->per_atmid, ++ (u8 *)__LC_PER_ATMID); ++ rc |= put_guest_lc(vcpu, pgm_info->per_address, ++ (u64 *) __LC_PER_ADDRESS); ++ rc |= put_guest_lc(vcpu, pgm_info->per_access_id, ++ (u8 *) __LC_PER_ACCESS_ID); ++ } ++ ++ rc |= put_guest_lc(vcpu, ilc, (u16 *) __LC_PGM_ILC); ++ rc |= put_guest_lc(vcpu, pgm_info->code, ++ (u16 *)__LC_PGM_INT_CODE); ++ rc |= write_guest_lc(vcpu, __LC_PGM_OLD_PSW, ++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); ++ rc |= read_guest_lc(vcpu, __LC_PGM_NEW_PSW, ++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); ++ ++ return rc; ++} ++ ++static int __must_check __do_deliver_interrupt(struct kvm_vcpu *vcpu, ++ struct kvm_s390_interrupt_info *inti) ++{ ++ const unsigned short table[] = { 2, 4, 4, 6 }; ++ int rc = 0; ++ ++ switch (inti->type) { ++ case KVM_S390_INT_EMERGENCY: ++ VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp emerg"); ++ vcpu->stat.deliver_emergency_signal++; ++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, ++ inti->emerg.code, 0); ++ rc = put_guest_lc(vcpu, 0x1201, (u16 *)__LC_EXT_INT_CODE); ++ rc |= put_guest_lc(vcpu, inti->emerg.code, ++ (u16 *)__LC_EXT_CPU_ADDR); ++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, ++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); ++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, ++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); ++ break; ++ case KVM_S390_INT_EXTERNAL_CALL: ++ VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call"); ++ vcpu->stat.deliver_external_call++; ++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, ++ inti->extcall.code, 0); ++ rc = put_guest_lc(vcpu, 0x1202, (u16 *)__LC_EXT_INT_CODE); ++ rc |= put_guest_lc(vcpu, inti->extcall.code, ++ (u16 *)__LC_EXT_CPU_ADDR); ++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, ++ &vcpu->arch.sie_block->gpsw, ++ sizeof(psw_t)); ++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, ++ &vcpu->arch.sie_block->gpsw, ++ sizeof(psw_t)); ++ break; ++ case KVM_S390_INT_CLOCK_COMP: ++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, ++ inti->ext.ext_params, 0); ++ rc = deliver_ckc_interrupt(vcpu); ++ break; ++ case KVM_S390_INT_CPU_TIMER: ++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, ++ inti->ext.ext_params, 0); ++ rc = put_guest_lc(vcpu, EXT_IRQ_CPU_TIMER, ++ (u16 *)__LC_EXT_INT_CODE); ++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, ++ &vcpu->arch.sie_block->gpsw, ++ sizeof(psw_t)); ++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, ++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); ++ rc |= put_guest_lc(vcpu, inti->ext.ext_params, ++ (u32 *)__LC_EXT_PARAMS); ++ break; ++ case KVM_S390_INT_SERVICE: ++ VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x", ++ inti->ext.ext_params); ++ vcpu->stat.deliver_service_signal++; ++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, ++ inti->ext.ext_params, 0); ++ rc = put_guest_lc(vcpu, 0x2401, (u16 *)__LC_EXT_INT_CODE); ++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, ++ &vcpu->arch.sie_block->gpsw, ++ sizeof(psw_t)); ++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, ++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); ++ rc |= put_guest_lc(vcpu, inti->ext.ext_params, ++ (u32 *)__LC_EXT_PARAMS); ++ break; ++ case KVM_S390_INT_PFAULT_INIT: ++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 0, ++ inti->ext.ext_params2); ++ rc = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE, ++ (u16 *) __LC_EXT_INT_CODE); ++ rc |= put_guest_lc(vcpu, PFAULT_INIT, (u16 *) __LC_EXT_CPU_ADDR); ++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, ++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); ++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, ++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); ++ rc |= put_guest_lc(vcpu, inti->ext.ext_params2, ++ (u64 *) __LC_EXT_PARAMS2); ++ break; ++ case KVM_S390_INT_PFAULT_DONE: ++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, 0, ++ inti->ext.ext_params2); ++ rc = put_guest_lc(vcpu, 0x2603, (u16 *)__LC_EXT_INT_CODE); ++ rc |= put_guest_lc(vcpu, 0x0680, (u16 *)__LC_EXT_CPU_ADDR); ++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, ++ &vcpu->arch.sie_block->gpsw, ++ sizeof(psw_t)); ++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, ++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); ++ rc |= put_guest_lc(vcpu, inti->ext.ext_params2, ++ (u64 *)__LC_EXT_PARAMS2); ++ break; ++ case KVM_S390_INT_VIRTIO: ++ VCPU_EVENT(vcpu, 4, "interrupt: virtio parm:%x,parm64:%llx", ++ inti->ext.ext_params, inti->ext.ext_params2); ++ vcpu->stat.deliver_virtio_interrupt++; ++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, ++ inti->ext.ext_params, ++ inti->ext.ext_params2); ++ rc = put_guest_lc(vcpu, 0x2603, (u16 *)__LC_EXT_INT_CODE); ++ rc |= put_guest_lc(vcpu, 0x0d00, (u16 *)__LC_EXT_CPU_ADDR); ++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, ++ &vcpu->arch.sie_block->gpsw, ++ sizeof(psw_t)); ++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, ++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); ++ rc |= put_guest_lc(vcpu, inti->ext.ext_params, ++ (u32 *)__LC_EXT_PARAMS); ++ rc |= put_guest_lc(vcpu, inti->ext.ext_params2, ++ (u64 *)__LC_EXT_PARAMS2); ++ break; ++ case KVM_S390_SIGP_STOP: ++ VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu stop"); ++ vcpu->stat.deliver_stop_signal++; ++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, ++ 0, 0); ++ __set_intercept_indicator(vcpu, inti); ++ break; ++ ++ case KVM_S390_SIGP_SET_PREFIX: ++ VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x", ++ inti->prefix.address); ++ vcpu->stat.deliver_prefix_signal++; ++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, ++ inti->prefix.address, 0); ++ kvm_s390_set_prefix(vcpu, inti->prefix.address); ++ break; ++ ++ case KVM_S390_RESTART: ++ VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart"); ++ vcpu->stat.deliver_restart_signal++; ++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, ++ 0, 0); ++ rc = write_guest_lc(vcpu, ++ offsetof(struct _lowcore, restart_old_psw), ++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); ++ rc |= read_guest_lc(vcpu, offsetof(struct _lowcore, restart_psw), ++ &vcpu->arch.sie_block->gpsw, ++ sizeof(psw_t)); ++ break; ++ case KVM_S390_PROGRAM_INT: ++ VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x", ++ inti->pgm.code, ++ table[vcpu->arch.sie_block->ipa >> 14]); ++ vcpu->stat.deliver_program_int++; ++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, ++ inti->pgm.code, 0); ++ rc = __deliver_prog_irq(vcpu, &inti->pgm); ++ break; ++ ++ case KVM_S390_MCHK: ++ VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx", ++ inti->mchk.mcic); ++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, ++ inti->mchk.cr14, ++ inti->mchk.mcic); ++ rc = kvm_s390_vcpu_store_status(vcpu, ++ KVM_S390_STORE_STATUS_PREFIXED); ++ rc |= put_guest_lc(vcpu, inti->mchk.mcic, (u64 *)__LC_MCCK_CODE); ++ rc |= write_guest_lc(vcpu, __LC_MCK_OLD_PSW, ++ &vcpu->arch.sie_block->gpsw, ++ sizeof(psw_t)); ++ rc |= read_guest_lc(vcpu, __LC_MCK_NEW_PSW, ++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); ++ break; ++ ++ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: ++ { ++ __u32 param0 = ((__u32)inti->io.subchannel_id << 16) | ++ inti->io.subchannel_nr; ++ __u64 param1 = ((__u64)inti->io.io_int_parm << 32) | ++ inti->io.io_int_word; ++ VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->type); ++ vcpu->stat.deliver_io_int++; ++ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, ++ param0, param1); ++ rc = put_guest_lc(vcpu, inti->io.subchannel_id, ++ (u16 *)__LC_SUBCHANNEL_ID); ++ rc |= put_guest_lc(vcpu, inti->io.subchannel_nr, ++ (u16 *)__LC_SUBCHANNEL_NR); ++ rc |= put_guest_lc(vcpu, inti->io.io_int_parm, ++ (u32 *)__LC_IO_INT_PARM); ++ rc |= put_guest_lc(vcpu, inti->io.io_int_word, ++ (u32 *)__LC_IO_INT_WORD); ++ rc |= write_guest_lc(vcpu, __LC_IO_OLD_PSW, ++ &vcpu->arch.sie_block->gpsw, ++ sizeof(psw_t)); ++ rc |= read_guest_lc(vcpu, __LC_IO_NEW_PSW, ++ &vcpu->arch.sie_block->gpsw, ++ sizeof(psw_t)); ++ break; ++ } ++ default: ++ BUG(); ++ } ++ ++ return rc; ++} ++ ++static int __must_check deliver_ckc_interrupt(struct kvm_vcpu *vcpu) ++{ ++ int rc; ++ ++ rc = put_guest_lc(vcpu, 0x1004, (u16 __user *)__LC_EXT_INT_CODE); ++ rc |= write_guest_lc(vcpu, __LC_EXT_OLD_PSW, ++ &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); ++ rc |= read_guest_lc(vcpu, __LC_EXT_NEW_PSW, ++ &vcpu->arch.sie_block->gpsw, ++ sizeof(psw_t)); ++ return rc; ++} ++ ++/* Check whether SIGP interpretation facility has an external call pending */ ++int kvm_s390_si_ext_call_pending(struct kvm_vcpu *vcpu) ++{ ++ atomic_t *sigp_ctrl = &vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].ctrl; ++ ++ if (!psw_extint_disabled(vcpu) && ++ (vcpu->arch.sie_block->gcr[0] & 0x2000ul) && ++ (atomic_read(sigp_ctrl) & SIGP_CTRL_C) && ++ (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_ECALL_PEND)) ++ return 1; ++ ++ return 0; ++} ++ ++int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu) ++{ ++ struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; ++ struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int; ++ struct kvm_s390_interrupt_info *inti; ++ int rc = 0; ++ ++ if (atomic_read(&li->active)) { ++ spin_lock(&li->lock); ++ list_for_each_entry(inti, &li->list, list) ++ if (__interrupt_is_deliverable(vcpu, inti)) { ++ rc = 1; ++ break; ++ } ++ spin_unlock(&li->lock); ++ } ++ ++ if ((!rc) && atomic_read(&fi->active)) { ++ spin_lock(&fi->lock); ++ list_for_each_entry(inti, &fi->list, list) ++ if (__interrupt_is_deliverable(vcpu, inti)) { ++ rc = 1; ++ break; ++ } ++ spin_unlock(&fi->lock); ++ } ++ ++ if (!rc && kvm_cpu_has_pending_timer(vcpu)) ++ rc = 1; ++ ++ if (!rc && kvm_s390_si_ext_call_pending(vcpu)) ++ rc = 1; ++ ++ return rc; ++} ++ ++int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) ++{ ++ if (!(vcpu->arch.sie_block->ckc < ++ get_tod_clock_fast() + vcpu->arch.sie_block->epoch)) ++ return 0; ++ if (!ckc_interrupts_enabled(vcpu)) ++ return 0; ++ return 1; ++} ++ ++int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) ++{ ++ u64 now, sltime; ++ ++ vcpu->stat.exit_wait_state++; ++ ++ /* fast path */ ++ if (kvm_cpu_has_pending_timer(vcpu) || kvm_arch_vcpu_runnable(vcpu)) ++ return 0; ++ ++ if (psw_interrupts_disabled(vcpu)) { ++ VCPU_EVENT(vcpu, 3, "%s", "disabled wait"); ++ return -EOPNOTSUPP; /* disabled wait */ ++ } ++ ++ __set_cpu_idle(vcpu); ++ if (!ckc_interrupts_enabled(vcpu)) { ++ VCPU_EVENT(vcpu, 3, "%s", "enabled wait w/o timer"); ++ goto no_timer; ++ } ++ ++ now = get_tod_clock_fast() + vcpu->arch.sie_block->epoch; ++ sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now); ++ hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL); ++ VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime); ++no_timer: ++ srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); ++ kvm_vcpu_block(vcpu); ++ __unset_cpu_idle(vcpu); ++ vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); ++ ++ hrtimer_cancel(&vcpu->arch.ckc_timer); ++ return 0; ++} ++ ++void kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu) ++{ ++ if (waitqueue_active(&vcpu->wq)) { ++ /* ++ * The vcpu gave up the cpu voluntarily, mark it as a good ++ * yield-candidate. ++ */ ++ vcpu->preempted = true; ++ wake_up_interruptible(&vcpu->wq); ++ vcpu->stat.halt_wakeup++; ++ } ++} ++ ++enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer) ++{ ++ struct kvm_vcpu *vcpu; ++ u64 now, sltime; ++ ++ vcpu = container_of(timer, struct kvm_vcpu, arch.ckc_timer); ++ now = get_tod_clock_fast() + vcpu->arch.sie_block->epoch; ++ sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now); ++ ++ /* ++ * If the monotonic clock runs faster than the tod clock we might be ++ * woken up too early and have to go back to sleep to avoid deadlocks. ++ */ ++ if (vcpu->arch.sie_block->ckc > now && ++ hrtimer_forward_now(timer, ns_to_ktime(sltime))) ++ return HRTIMER_RESTART; ++ kvm_s390_vcpu_wakeup(vcpu); ++ return HRTIMER_NORESTART; ++} ++ ++void kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu) ++{ ++ struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; ++ struct kvm_s390_interrupt_info *n, *inti = NULL; ++ ++ spin_lock(&li->lock); ++ list_for_each_entry_safe(inti, n, &li->list, list) { ++ list_del(&inti->list); ++ kfree(inti); ++ } ++ atomic_set(&li->active, 0); ++ spin_unlock(&li->lock); ++ ++ /* clear pending external calls set by sigp interpretation facility */ ++ atomic_clear_mask(CPUSTAT_ECALL_PEND, &vcpu->arch.sie_block->cpuflags); ++ atomic_clear_mask(SIGP_CTRL_C, ++ &vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].ctrl); ++} ++ ++int __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu) ++{ ++ struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; ++ struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int; ++ struct kvm_s390_interrupt_info *n, *inti = NULL; ++ int deliver; ++ int rc = 0; ++ ++ __reset_intercept_indicators(vcpu); ++ if (atomic_read(&li->active)) { ++ do { ++ deliver = 0; ++ spin_lock(&li->lock); ++ list_for_each_entry_safe(inti, n, &li->list, list) { ++ if (__interrupt_is_deliverable(vcpu, inti)) { ++ list_del(&inti->list); ++ deliver = 1; ++ break; ++ } ++ __set_intercept_indicator(vcpu, inti); ++ } ++ if (list_empty(&li->list)) ++ atomic_set(&li->active, 0); ++ spin_unlock(&li->lock); ++ if (deliver) { ++ rc = __do_deliver_interrupt(vcpu, inti); ++ kfree(inti); ++ } ++ } while (!rc && deliver); ++ } ++ ++ if (!rc && kvm_cpu_has_pending_timer(vcpu)) ++ rc = deliver_ckc_interrupt(vcpu); ++ ++ if (!rc && atomic_read(&fi->active)) { ++ do { ++ deliver = 0; ++ spin_lock(&fi->lock); ++ list_for_each_entry_safe(inti, n, &fi->list, list) { ++ if (__interrupt_is_deliverable(vcpu, inti)) { ++ list_del(&inti->list); ++ fi->irq_count--; ++ deliver = 1; ++ break; ++ } ++ __set_intercept_indicator(vcpu, inti); ++ } ++ if (list_empty(&fi->list)) ++ atomic_set(&fi->active, 0); ++ spin_unlock(&fi->lock); ++ if (deliver) { ++ rc = __do_deliver_interrupt(vcpu, inti); ++ kfree(inti); ++ } ++ } while (!rc && deliver); ++ } ++ ++ return rc; ++} ++ ++int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code) ++{ ++ struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; ++ struct kvm_s390_interrupt_info *inti; ++ ++ inti = kzalloc(sizeof(*inti), GFP_KERNEL); ++ if (!inti) ++ return -ENOMEM; ++ ++ inti->type = KVM_S390_PROGRAM_INT; ++ inti->pgm.code = code; ++ ++ VCPU_EVENT(vcpu, 3, "inject: program check %d (from kernel)", code); ++ trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, inti->type, code, 0, 1); ++ spin_lock(&li->lock); ++ list_add(&inti->list, &li->list); ++ atomic_set(&li->active, 1); ++ BUG_ON(waitqueue_active(li->wq)); ++ spin_unlock(&li->lock); ++ return 0; ++} ++ ++int kvm_s390_inject_prog_irq(struct kvm_vcpu *vcpu, ++ struct kvm_s390_pgm_info *pgm_info) ++{ ++ struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; ++ struct kvm_s390_interrupt_info *inti; ++ ++ inti = kzalloc(sizeof(*inti), GFP_KERNEL); ++ if (!inti) ++ return -ENOMEM; ++ ++ VCPU_EVENT(vcpu, 3, "inject: prog irq %d (from kernel)", ++ pgm_info->code); ++ trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT, ++ pgm_info->code, 0, 1); ++ ++ inti->type = KVM_S390_PROGRAM_INT; ++ memcpy(&inti->pgm, pgm_info, sizeof(inti->pgm)); ++ spin_lock(&li->lock); ++ list_add(&inti->list, &li->list); ++ atomic_set(&li->active, 1); ++ BUG_ON(waitqueue_active(li->wq)); ++ spin_unlock(&li->lock); ++ return 0; ++} ++ ++struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, ++ u64 cr6, u64 schid) ++{ ++ struct kvm_s390_float_interrupt *fi; ++ struct kvm_s390_interrupt_info *inti, *iter; ++ ++ if ((!schid && !cr6) || (schid && cr6)) ++ return NULL; ++ fi = &kvm->arch.float_int; ++ spin_lock(&fi->lock); ++ inti = NULL; ++ list_for_each_entry(iter, &fi->list, list) { ++ if (!is_ioint(iter->type)) ++ continue; ++ if (cr6 && ++ ((cr6 & int_word_to_isc_bits(iter->io.io_int_word)) == 0)) ++ continue; ++ if (schid) { ++ if (((schid & 0x00000000ffff0000) >> 16) != ++ iter->io.subchannel_id) ++ continue; ++ if ((schid & 0x000000000000ffff) != ++ iter->io.subchannel_nr) ++ continue; ++ } ++ inti = iter; ++ break; ++ } ++ if (inti) { ++ list_del_init(&inti->list); ++ fi->irq_count--; ++ } ++ if (list_empty(&fi->list)) ++ atomic_set(&fi->active, 0); ++ spin_unlock(&fi->lock); ++ return inti; ++} ++ ++static int __inject_vm(struct kvm *kvm, struct kvm_s390_interrupt_info *inti) ++{ ++ struct kvm_s390_local_interrupt *li; ++ struct kvm_s390_float_interrupt *fi; ++ struct kvm_s390_interrupt_info *iter; ++ struct kvm_vcpu *dst_vcpu = NULL; ++ int sigcpu; ++ int rc = 0; ++ ++ fi = &kvm->arch.float_int; ++ spin_lock(&fi->lock); ++ if (fi->irq_count >= KVM_S390_MAX_FLOAT_IRQS) { ++ rc = -EINVAL; ++ goto unlock_fi; ++ } ++ fi->irq_count++; ++ if (!is_ioint(inti->type)) { ++ list_add_tail(&inti->list, &fi->list); ++ } else { ++ u64 isc_bits = int_word_to_isc_bits(inti->io.io_int_word); ++ ++ /* Keep I/O interrupts sorted in isc order. */ ++ list_for_each_entry(iter, &fi->list, list) { ++ if (!is_ioint(iter->type)) ++ continue; ++ if (int_word_to_isc_bits(iter->io.io_int_word) ++ <= isc_bits) ++ continue; ++ break; ++ } ++ list_add_tail(&inti->list, &iter->list); ++ } ++ atomic_set(&fi->active, 1); ++ if (atomic_read(&kvm->online_vcpus) == 0) ++ goto unlock_fi; ++ sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS); ++ if (sigcpu == KVM_MAX_VCPUS) { ++ do { ++ sigcpu = fi->next_rr_cpu++; ++ if (sigcpu == KVM_MAX_VCPUS) ++ sigcpu = fi->next_rr_cpu = 0; ++ } while (kvm_get_vcpu(kvm, sigcpu) == NULL); ++ } ++ dst_vcpu = kvm_get_vcpu(kvm, sigcpu); ++ li = &dst_vcpu->arch.local_int; ++ spin_lock(&li->lock); ++ atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); ++ spin_unlock(&li->lock); ++ kvm_s390_vcpu_wakeup(kvm_get_vcpu(kvm, sigcpu)); ++unlock_fi: ++ spin_unlock(&fi->lock); ++ return rc; ++} ++ ++int kvm_s390_inject_vm(struct kvm *kvm, ++ struct kvm_s390_interrupt *s390int) ++{ ++ struct kvm_s390_interrupt_info *inti; ++ int rc; ++ ++ inti = kzalloc(sizeof(*inti), GFP_KERNEL); ++ if (!inti) ++ return -ENOMEM; ++ ++ inti->type = s390int->type; ++ switch (inti->type) { ++ case KVM_S390_INT_VIRTIO: ++ VM_EVENT(kvm, 5, "inject: virtio parm:%x,parm64:%llx", ++ s390int->parm, s390int->parm64); ++ inti->ext.ext_params = s390int->parm; ++ inti->ext.ext_params2 = s390int->parm64; ++ break; ++ case KVM_S390_INT_SERVICE: ++ VM_EVENT(kvm, 5, "inject: sclp parm:%x", s390int->parm); ++ inti->ext.ext_params = s390int->parm; ++ break; ++ case KVM_S390_INT_PFAULT_DONE: ++ inti->type = s390int->type; ++ inti->ext.ext_params2 = s390int->parm64; ++ break; ++ case KVM_S390_MCHK: ++ VM_EVENT(kvm, 5, "inject: machine check parm64:%llx", ++ s390int->parm64); ++ inti->mchk.cr14 = s390int->parm; /* upper bits are not used */ ++ inti->mchk.mcic = s390int->parm64; ++ break; ++ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: ++ if (inti->type & IOINT_AI_MASK) ++ VM_EVENT(kvm, 5, "%s", "inject: I/O (AI)"); ++ else ++ VM_EVENT(kvm, 5, "inject: I/O css %x ss %x schid %04x", ++ s390int->type & IOINT_CSSID_MASK, ++ s390int->type & IOINT_SSID_MASK, ++ s390int->type & IOINT_SCHID_MASK); ++ inti->io.subchannel_id = s390int->parm >> 16; ++ inti->io.subchannel_nr = s390int->parm & 0x0000ffffu; ++ inti->io.io_int_parm = s390int->parm64 >> 32; ++ inti->io.io_int_word = s390int->parm64 & 0x00000000ffffffffull; ++ break; ++ default: ++ kfree(inti); ++ return -EINVAL; ++ } ++ trace_kvm_s390_inject_vm(s390int->type, s390int->parm, s390int->parm64, ++ 2); ++ ++ rc = __inject_vm(kvm, inti); ++ if (rc) ++ kfree(inti); ++ return rc; ++} ++ ++int kvm_s390_reinject_io_int(struct kvm *kvm, ++ struct kvm_s390_interrupt_info *inti) ++{ ++ return __inject_vm(kvm, inti); ++} ++ ++int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, ++ struct kvm_s390_interrupt *s390int) ++{ ++ struct kvm_s390_local_interrupt *li; ++ struct kvm_s390_interrupt_info *inti; ++ ++ inti = kzalloc(sizeof(*inti), GFP_KERNEL); ++ if (!inti) ++ return -ENOMEM; ++ ++ switch (s390int->type) { ++ case KVM_S390_PROGRAM_INT: ++ if (s390int->parm & 0xffff0000) { ++ kfree(inti); ++ return -EINVAL; ++ } ++ inti->type = s390int->type; ++ inti->pgm.code = s390int->parm; ++ VCPU_EVENT(vcpu, 3, "inject: program check %d (from user)", ++ s390int->parm); ++ break; ++ case KVM_S390_SIGP_SET_PREFIX: ++ inti->prefix.address = s390int->parm; ++ inti->type = s390int->type; ++ VCPU_EVENT(vcpu, 3, "inject: set prefix to %x (from user)", ++ s390int->parm); ++ break; ++ case KVM_S390_SIGP_STOP: ++ case KVM_S390_RESTART: ++ case KVM_S390_INT_CLOCK_COMP: ++ case KVM_S390_INT_CPU_TIMER: ++ VCPU_EVENT(vcpu, 3, "inject: type %x", s390int->type); ++ inti->type = s390int->type; ++ break; ++ case KVM_S390_INT_EXTERNAL_CALL: ++ if (s390int->parm & 0xffff0000) { ++ kfree(inti); ++ return -EINVAL; ++ } ++ VCPU_EVENT(vcpu, 3, "inject: external call source-cpu:%u", ++ s390int->parm); ++ inti->type = s390int->type; ++ inti->extcall.code = s390int->parm; ++ break; ++ case KVM_S390_INT_EMERGENCY: ++ if (s390int->parm & 0xffff0000) { ++ kfree(inti); ++ return -EINVAL; ++ } ++ VCPU_EVENT(vcpu, 3, "inject: emergency %u\n", s390int->parm); ++ inti->type = s390int->type; ++ inti->emerg.code = s390int->parm; ++ break; ++ case KVM_S390_MCHK: ++ VCPU_EVENT(vcpu, 5, "inject: machine check parm64:%llx", ++ s390int->parm64); ++ inti->type = s390int->type; ++ inti->mchk.mcic = s390int->parm64; ++ break; ++ case KVM_S390_INT_PFAULT_INIT: ++ inti->type = s390int->type; ++ inti->ext.ext_params2 = s390int->parm64; ++ break; ++ case KVM_S390_INT_VIRTIO: ++ case KVM_S390_INT_SERVICE: ++ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: ++ default: ++ kfree(inti); ++ return -EINVAL; ++ } ++ trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, s390int->type, s390int->parm, ++ s390int->parm64, 2); ++ ++ li = &vcpu->arch.local_int; ++ spin_lock(&li->lock); ++ if (inti->type == KVM_S390_PROGRAM_INT) ++ list_add(&inti->list, &li->list); ++ else ++ list_add_tail(&inti->list, &li->list); ++ atomic_set(&li->active, 1); ++ if (inti->type == KVM_S390_SIGP_STOP) ++ li->action_bits |= ACTION_STOP_ON_STOP; ++ atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags); ++ spin_unlock(&li->lock); ++ kvm_s390_vcpu_wakeup(vcpu); ++ return 0; ++} ++ ++void kvm_s390_clear_float_irqs(struct kvm *kvm) ++{ ++ struct kvm_s390_float_interrupt *fi; ++ struct kvm_s390_interrupt_info *n, *inti = NULL; ++ ++ fi = &kvm->arch.float_int; ++ spin_lock(&fi->lock); ++ list_for_each_entry_safe(inti, n, &fi->list, list) { ++ list_del(&inti->list); ++ kfree(inti); ++ } ++ fi->irq_count = 0; ++ atomic_set(&fi->active, 0); ++ spin_unlock(&fi->lock); ++} ++ ++static void inti_to_irq(struct kvm_s390_interrupt_info *inti, ++ struct kvm_s390_irq *irq) ++{ ++ irq->type = inti->type; ++ switch (inti->type) { ++ case KVM_S390_INT_PFAULT_INIT: ++ case KVM_S390_INT_PFAULT_DONE: ++ case KVM_S390_INT_VIRTIO: ++ case KVM_S390_INT_SERVICE: ++ irq->u.ext = inti->ext; ++ break; ++ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: ++ irq->u.io = inti->io; ++ break; ++ case KVM_S390_MCHK: ++ irq->u.mchk = inti->mchk; ++ break; ++ } ++} ++ ++static int get_all_floating_irqs(struct kvm *kvm, u8 __user *usrbuf, u64 len) ++{ ++ struct kvm_s390_interrupt_info *inti; ++ struct kvm_s390_float_interrupt *fi; ++ struct kvm_s390_irq *buf; ++ int max_irqs; ++ int ret = 0; ++ int n = 0; ++ ++ if (len > KVM_S390_FLIC_MAX_BUFFER || len == 0) ++ return -EINVAL; ++ ++ /* ++ * We are already using -ENOMEM to signal ++ * userspace it may retry with a bigger buffer, ++ * so we need to use something else for this case ++ */ ++ buf = vzalloc(len); ++ if (!buf) ++ return -ENOBUFS; ++ ++ max_irqs = len / sizeof(struct kvm_s390_irq); ++ ++ fi = &kvm->arch.float_int; ++ spin_lock(&fi->lock); ++ list_for_each_entry(inti, &fi->list, list) { ++ if (n == max_irqs) { ++ /* signal userspace to try again */ ++ ret = -ENOMEM; ++ break; ++ } ++ inti_to_irq(inti, &buf[n]); ++ n++; ++ } ++ spin_unlock(&fi->lock); ++ if (!ret && n > 0) { ++ if (copy_to_user(usrbuf, buf, sizeof(struct kvm_s390_irq) * n)) ++ ret = -EFAULT; ++ } ++ vfree(buf); ++ ++ return ret < 0 ? ret : n; ++} ++ ++static int flic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr) ++{ ++ int r; ++ ++ switch (attr->group) { ++ case KVM_DEV_FLIC_GET_ALL_IRQS: ++ r = get_all_floating_irqs(dev->kvm, (u8 __user *) attr->addr, ++ attr->attr); ++ break; ++ default: ++ r = -EINVAL; ++ } ++ ++ return r; ++} ++ ++static inline int copy_irq_from_user(struct kvm_s390_interrupt_info *inti, ++ u64 addr) ++{ ++ struct kvm_s390_irq __user *uptr = (struct kvm_s390_irq __user *) addr; ++ void *target = NULL; ++ void __user *source; ++ u64 size; ++ ++ if (get_user(inti->type, (u64 __user *)addr)) ++ return -EFAULT; ++ ++ switch (inti->type) { ++ case KVM_S390_INT_PFAULT_INIT: ++ case KVM_S390_INT_PFAULT_DONE: ++ case KVM_S390_INT_VIRTIO: ++ case KVM_S390_INT_SERVICE: ++ target = (void *) &inti->ext; ++ source = &uptr->u.ext; ++ size = sizeof(inti->ext); ++ break; ++ case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: ++ target = (void *) &inti->io; ++ source = &uptr->u.io; ++ size = sizeof(inti->io); ++ break; ++ case KVM_S390_MCHK: ++ target = (void *) &inti->mchk; ++ source = &uptr->u.mchk; ++ size = sizeof(inti->mchk); ++ break; ++ default: ++ return -EINVAL; ++ } ++ ++ if (copy_from_user(target, source, size)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++static int enqueue_floating_irq(struct kvm_device *dev, ++ struct kvm_device_attr *attr) ++{ ++ struct kvm_s390_interrupt_info *inti = NULL; ++ int r = 0; ++ int len = attr->attr; ++ ++ if (len % sizeof(struct kvm_s390_irq) != 0) ++ return -EINVAL; ++ else if (len > KVM_S390_FLIC_MAX_BUFFER) ++ return -EINVAL; ++ ++ while (len >= sizeof(struct kvm_s390_irq)) { ++ inti = kzalloc(sizeof(*inti), GFP_KERNEL); ++ if (!inti) ++ return -ENOMEM; ++ ++ r = copy_irq_from_user(inti, attr->addr); ++ if (r) { ++ kfree(inti); ++ return r; ++ } ++ r = __inject_vm(dev->kvm, inti); ++ if (r) { ++ kfree(inti); ++ return r; ++ } ++ len -= sizeof(struct kvm_s390_irq); ++ attr->addr += sizeof(struct kvm_s390_irq); ++ } ++ ++ return r; ++} ++ ++static struct s390_io_adapter *get_io_adapter(struct kvm *kvm, unsigned int id) ++{ ++ if (id >= MAX_S390_IO_ADAPTERS) ++ return NULL; ++ return kvm->arch.adapters[id]; ++} ++ ++static int register_io_adapter(struct kvm_device *dev, ++ struct kvm_device_attr *attr) ++{ ++ struct s390_io_adapter *adapter; ++ struct kvm_s390_io_adapter adapter_info; ++ ++ if (copy_from_user(&adapter_info, ++ (void __user *)attr->addr, sizeof(adapter_info))) ++ return -EFAULT; ++ ++ if ((adapter_info.id >= MAX_S390_IO_ADAPTERS) || ++ (dev->kvm->arch.adapters[adapter_info.id] != NULL)) ++ return -EINVAL; ++ ++ adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); ++ if (!adapter) ++ return -ENOMEM; ++ ++ INIT_LIST_HEAD(&adapter->maps); ++ init_rwsem(&adapter->maps_lock); ++ atomic_set(&adapter->nr_maps, 0); ++ adapter->id = adapter_info.id; ++ adapter->isc = adapter_info.isc; ++ adapter->maskable = adapter_info.maskable; ++ adapter->masked = false; ++ adapter->swap = adapter_info.swap; ++ dev->kvm->arch.adapters[adapter->id] = adapter; ++ ++ return 0; ++} ++ ++int kvm_s390_mask_adapter(struct kvm *kvm, unsigned int id, bool masked) ++{ ++ int ret; ++ struct s390_io_adapter *adapter = get_io_adapter(kvm, id); ++ ++ if (!adapter || !adapter->maskable) ++ return -EINVAL; ++ ret = adapter->masked; ++ adapter->masked = masked; ++ return ret; ++} ++ ++static int kvm_s390_adapter_map(struct kvm *kvm, unsigned int id, __u64 addr) ++{ ++ struct s390_io_adapter *adapter = get_io_adapter(kvm, id); ++ struct s390_map_info *map; ++ int ret; ++ ++ if (!adapter || !addr) ++ return -EINVAL; ++ ++ map = kzalloc(sizeof(*map), GFP_KERNEL); ++ if (!map) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ INIT_LIST_HEAD(&map->list); ++ map->guest_addr = addr; ++ map->addr = gmap_translate(kvm->arch.gmap, addr); ++ if (map->addr == -EFAULT) { ++ ret = -EFAULT; ++ goto out; ++ } ++ ret = get_user_pages_fast(map->addr, 1, 1, &map->page); ++ if (ret < 0) ++ goto out; ++ BUG_ON(ret != 1); ++ down_write(&adapter->maps_lock); ++ if (atomic_inc_return(&adapter->nr_maps) < MAX_S390_ADAPTER_MAPS) { ++ list_add_tail(&map->list, &adapter->maps); ++ ret = 0; ++ } else { ++ put_page(map->page); ++ ret = -EINVAL; ++ } ++ up_write(&adapter->maps_lock); ++out: ++ if (ret) ++ kfree(map); ++ return ret; ++} ++ ++static int kvm_s390_adapter_unmap(struct kvm *kvm, unsigned int id, __u64 addr) ++{ ++ struct s390_io_adapter *adapter = get_io_adapter(kvm, id); ++ struct s390_map_info *map, *tmp; ++ int found = 0; ++ ++ if (!adapter || !addr) ++ return -EINVAL; ++ ++ down_write(&adapter->maps_lock); ++ list_for_each_entry_safe(map, tmp, &adapter->maps, list) { ++ if (map->guest_addr == addr) { ++ found = 1; ++ atomic_dec(&adapter->nr_maps); ++ list_del(&map->list); ++ put_page(map->page); ++ kfree(map); ++ break; ++ } ++ } ++ up_write(&adapter->maps_lock); ++ ++ return found ? 0 : -EINVAL; ++} ++ ++void kvm_s390_destroy_adapters(struct kvm *kvm) ++{ ++ int i; ++ struct s390_map_info *map, *tmp; ++ ++ for (i = 0; i < MAX_S390_IO_ADAPTERS; i++) { ++ if (!kvm->arch.adapters[i]) ++ continue; ++ list_for_each_entry_safe(map, tmp, ++ &kvm->arch.adapters[i]->maps, list) { ++ list_del(&map->list); ++ put_page(map->page); ++ kfree(map); ++ } ++ kfree(kvm->arch.adapters[i]); ++ } ++} ++ ++static int modify_io_adapter(struct kvm_device *dev, ++ struct kvm_device_attr *attr) ++{ ++ struct kvm_s390_io_adapter_req req; ++ struct s390_io_adapter *adapter; ++ int ret; ++ ++ if (copy_from_user(&req, (void __user *)attr->addr, sizeof(req))) ++ return -EFAULT; ++ ++ adapter = get_io_adapter(dev->kvm, req.id); ++ if (!adapter) ++ return -EINVAL; ++ switch (req.type) { ++ case KVM_S390_IO_ADAPTER_MASK: ++ ret = kvm_s390_mask_adapter(dev->kvm, req.id, req.mask); ++ if (ret > 0) ++ ret = 0; ++ break; ++ case KVM_S390_IO_ADAPTER_MAP: ++ ret = kvm_s390_adapter_map(dev->kvm, req.id, req.addr); ++ break; ++ case KVM_S390_IO_ADAPTER_UNMAP: ++ ret = kvm_s390_adapter_unmap(dev->kvm, req.id, req.addr); ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++static int flic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) ++{ ++ int r = 0; ++ unsigned int i; ++ struct kvm_vcpu *vcpu; ++ ++ switch (attr->group) { ++ case KVM_DEV_FLIC_ENQUEUE: ++ r = enqueue_floating_irq(dev, attr); ++ break; ++ case KVM_DEV_FLIC_CLEAR_IRQS: ++ kvm_s390_clear_float_irqs(dev->kvm); ++ break; ++ case KVM_DEV_FLIC_APF_ENABLE: ++ dev->kvm->arch.gmap->pfault_enabled = 1; ++ break; ++ case KVM_DEV_FLIC_APF_DISABLE_WAIT: ++ dev->kvm->arch.gmap->pfault_enabled = 0; ++ /* ++ * Make sure no async faults are in transition when ++ * clearing the queues. So we don't need to worry ++ * about late coming workers. ++ */ ++ synchronize_srcu(&dev->kvm->srcu); ++ kvm_for_each_vcpu(i, vcpu, dev->kvm) ++ kvm_clear_async_pf_completion_queue(vcpu); ++ break; ++ case KVM_DEV_FLIC_ADAPTER_REGISTER: ++ r = register_io_adapter(dev, attr); ++ break; ++ case KVM_DEV_FLIC_ADAPTER_MODIFY: ++ r = modify_io_adapter(dev, attr); ++ break; ++ default: ++ r = -EINVAL; ++ } ++ ++ return r; ++} ++ ++static int flic_create(struct kvm_device *dev, u32 type) ++{ ++ if (!dev) ++ return -EINVAL; ++ if (dev->kvm->arch.flic) ++ return -EINVAL; ++ dev->kvm->arch.flic = dev; ++ return 0; ++} ++ ++static void flic_destroy(struct kvm_device *dev) ++{ ++ dev->kvm->arch.flic = NULL; ++ kfree(dev); ++} ++ ++/* s390 floating irq controller (flic) */ ++struct kvm_device_ops kvm_flic_ops = { ++ .name = "kvm-flic", ++ .get_attr = flic_get_attr, ++ .set_attr = flic_set_attr, ++ .create = flic_create, ++ .destroy = flic_destroy, ++}; ++ ++static unsigned long get_ind_bit(__u64 addr, unsigned long bit_nr, bool swap) ++{ ++ unsigned long bit; ++ ++ bit = bit_nr + (addr % PAGE_SIZE) * 8; ++ ++ return swap ? (bit ^ (BITS_PER_LONG - 1)) : bit; ++} ++ ++static struct s390_map_info *get_map_info(struct s390_io_adapter *adapter, ++ u64 addr) ++{ ++ struct s390_map_info *map; ++ ++ if (!adapter) ++ return NULL; ++ ++ list_for_each_entry(map, &adapter->maps, list) { ++ if (map->guest_addr == addr) ++ return map; ++ } ++ return NULL; ++} ++ ++static int adapter_indicators_set(struct kvm *kvm, ++ struct s390_io_adapter *adapter, ++ struct kvm_s390_adapter_int *adapter_int) ++{ ++ unsigned long bit; ++ int summary_set, idx; ++ struct s390_map_info *info; ++ void *map; ++ ++ info = get_map_info(adapter, adapter_int->ind_addr); ++ if (!info) ++ return -1; ++ map = page_address(info->page); ++ bit = get_ind_bit(info->addr, adapter_int->ind_offset, adapter->swap); ++ set_bit(bit, map); ++ idx = srcu_read_lock(&kvm->srcu); ++ mark_page_dirty(kvm, info->guest_addr >> PAGE_SHIFT); ++ set_page_dirty_lock(info->page); ++ info = get_map_info(adapter, adapter_int->summary_addr); ++ if (!info) { ++ srcu_read_unlock(&kvm->srcu, idx); ++ return -1; ++ } ++ map = page_address(info->page); ++ bit = get_ind_bit(info->addr, adapter_int->summary_offset, ++ adapter->swap); ++ summary_set = test_and_set_bit(bit, map); ++ mark_page_dirty(kvm, info->guest_addr >> PAGE_SHIFT); ++ set_page_dirty_lock(info->page); ++ srcu_read_unlock(&kvm->srcu, idx); ++ return summary_set ? 0 : 1; ++} ++ ++/* ++ * < 0 - not injected due to error ++ * = 0 - coalesced, summary indicator already active ++ * > 0 - injected interrupt ++ */ ++static int set_adapter_int(struct kvm_kernel_irq_routing_entry *e, ++ struct kvm *kvm, int irq_source_id, int level, ++ bool line_status) ++{ ++ int ret; ++ struct s390_io_adapter *adapter; ++ ++ /* We're only interested in the 0->1 transition. */ ++ if (!level) ++ return 0; ++ adapter = get_io_adapter(kvm, e->adapter.adapter_id); ++ if (!adapter) ++ return -1; ++ down_read(&adapter->maps_lock); ++ ret = adapter_indicators_set(kvm, adapter, &e->adapter); ++ up_read(&adapter->maps_lock); ++ if ((ret > 0) && !adapter->masked) { ++ struct kvm_s390_interrupt s390int = { ++ .type = KVM_S390_INT_IO(1, 0, 0, 0), ++ .parm = 0, ++ .parm64 = (adapter->isc << 27) | 0x80000000, ++ }; ++ ret = kvm_s390_inject_vm(kvm, &s390int); ++ if (ret == 0) ++ ret = 1; ++ } ++ return ret; ++} ++ ++int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e, ++ const struct kvm_irq_routing_entry *ue) ++{ ++ int ret; ++ ++ switch (ue->type) { ++ case KVM_IRQ_ROUTING_S390_ADAPTER: ++ e->set = set_adapter_int; ++ e->adapter.summary_addr = ue->u.adapter.summary_addr; ++ e->adapter.ind_addr = ue->u.adapter.ind_addr; ++ e->adapter.summary_offset = ue->u.adapter.summary_offset; ++ e->adapter.ind_offset = ue->u.adapter.ind_offset; ++ e->adapter.adapter_id = ue->u.adapter.adapter_id; ++ ret = 0; ++ break; ++ default: ++ ret = -EINVAL; ++ } ++ ++ return ret; ++} ++ ++int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, struct kvm *kvm, ++ int irq_source_id, int level, bool line_status) ++{ ++ return -EINVAL; ++} +diff -Nur linux-3.18.14.orig/arch/s390/mm/fault.c linux-3.18.14-rt/arch/s390/mm/fault.c +--- linux-3.18.14.orig/arch/s390/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/s390/mm/fault.c 2015-05-31 15:32:46.401635385 -0500 @@ -435,7 +435,8 @@ * user context. */ @@ -1449,9 +5077,9 @@ diff -Nur linux-3.18.12.orig/arch/s390/mm/fault.c linux-3.18.12/arch/s390/mm/fau goto out; address = trans_exc_code & __FAIL_ADDR_MASK; -diff -Nur linux-3.18.12.orig/arch/score/mm/fault.c linux-3.18.12/arch/score/mm/fault.c ---- linux-3.18.12.orig/arch/score/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/score/mm/fault.c 2015-04-26 13:32:22.371684003 -0500 +diff -Nur linux-3.18.14.orig/arch/score/mm/fault.c linux-3.18.14-rt/arch/score/mm/fault.c +--- linux-3.18.14.orig/arch/score/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/score/mm/fault.c 2015-05-31 15:32:46.413635385 -0500 @@ -73,7 +73,7 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. @@ -1461,9 +5089,9 @@ diff -Nur linux-3.18.12.orig/arch/score/mm/fault.c linux-3.18.12/arch/score/mm/f goto bad_area_nosemaphore; if (user_mode(regs)) -diff -Nur linux-3.18.12.orig/arch/sh/kernel/irq.c linux-3.18.12/arch/sh/kernel/irq.c ---- linux-3.18.12.orig/arch/sh/kernel/irq.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/sh/kernel/irq.c 2015-04-26 13:32:22.371684003 -0500 +diff -Nur linux-3.18.14.orig/arch/sh/kernel/irq.c linux-3.18.14-rt/arch/sh/kernel/irq.c +--- linux-3.18.14.orig/arch/sh/kernel/irq.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/sh/kernel/irq.c 2015-05-31 15:32:46.429635385 -0500 @@ -149,6 +149,7 @@ hardirq_ctx[cpu] = NULL; } @@ -1480,9 +5108,9 @@ diff -Nur linux-3.18.12.orig/arch/sh/kernel/irq.c linux-3.18.12/arch/sh/kernel/i #else static inline void handle_one_irq(unsigned int irq) { -diff -Nur linux-3.18.12.orig/arch/sh/mm/fault.c linux-3.18.12/arch/sh/mm/fault.c ---- linux-3.18.12.orig/arch/sh/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/sh/mm/fault.c 2015-04-26 13:32:22.371684003 -0500 +diff -Nur linux-3.18.14.orig/arch/sh/mm/fault.c linux-3.18.14-rt/arch/sh/mm/fault.c +--- linux-3.18.14.orig/arch/sh/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/sh/mm/fault.c 2015-05-31 15:32:46.469635385 -0500 @@ -440,7 +440,7 @@ * If we're in an interrupt, have no user context or are running * in an atomic region then we must not take the fault: @@ -1492,9 +5120,9 @@ diff -Nur linux-3.18.12.orig/arch/sh/mm/fault.c linux-3.18.12/arch/sh/mm/fault.c bad_area_nosemaphore(regs, error_code, address); return; } -diff -Nur linux-3.18.12.orig/arch/sparc/Kconfig linux-3.18.12/arch/sparc/Kconfig ---- linux-3.18.12.orig/arch/sparc/Kconfig 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/sparc/Kconfig 2015-04-26 13:32:22.371684003 -0500 +diff -Nur linux-3.18.14.orig/arch/sparc/Kconfig linux-3.18.14-rt/arch/sparc/Kconfig +--- linux-3.18.14.orig/arch/sparc/Kconfig 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/sparc/Kconfig 2015-05-31 15:32:46.469635385 -0500 @@ -182,12 +182,10 @@ source kernel/Kconfig.hz @@ -1521,9 +5149,9 @@ diff -Nur linux-3.18.12.orig/arch/sparc/Kconfig linux-3.18.12/arch/sparc/Kconfig config COMPAT bool depends on SPARC64 -diff -Nur linux-3.18.12.orig/arch/sparc/kernel/irq_64.c linux-3.18.12/arch/sparc/kernel/irq_64.c ---- linux-3.18.12.orig/arch/sparc/kernel/irq_64.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/sparc/kernel/irq_64.c 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/sparc/kernel/irq_64.c linux-3.18.14-rt/arch/sparc/kernel/irq_64.c +--- linux-3.18.14.orig/arch/sparc/kernel/irq_64.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/sparc/kernel/irq_64.c 2015-05-31 15:32:46.477635385 -0500 @@ -849,6 +849,7 @@ set_irq_regs(old_regs); } @@ -1540,9 +5168,9 @@ diff -Nur linux-3.18.12.orig/arch/sparc/kernel/irq_64.c linux-3.18.12/arch/sparc #ifdef CONFIG_HOTPLUG_CPU void fixup_irqs(void) -diff -Nur linux-3.18.12.orig/arch/sparc/kernel/setup_32.c linux-3.18.12/arch/sparc/kernel/setup_32.c ---- linux-3.18.12.orig/arch/sparc/kernel/setup_32.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/sparc/kernel/setup_32.c 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/sparc/kernel/setup_32.c linux-3.18.14-rt/arch/sparc/kernel/setup_32.c +--- linux-3.18.14.orig/arch/sparc/kernel/setup_32.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/sparc/kernel/setup_32.c 2015-05-31 15:32:46.489635385 -0500 @@ -309,6 +309,7 @@ boot_flags_init(*cmdline_p); @@ -1551,9 +5179,9 @@ diff -Nur linux-3.18.12.orig/arch/sparc/kernel/setup_32.c linux-3.18.12/arch/spa register_console(&prom_early_console); printk("ARCH: "); -diff -Nur linux-3.18.12.orig/arch/sparc/kernel/setup_64.c linux-3.18.12/arch/sparc/kernel/setup_64.c ---- linux-3.18.12.orig/arch/sparc/kernel/setup_64.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/sparc/kernel/setup_64.c 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/sparc/kernel/setup_64.c linux-3.18.14-rt/arch/sparc/kernel/setup_64.c +--- linux-3.18.14.orig/arch/sparc/kernel/setup_64.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/sparc/kernel/setup_64.c 2015-05-31 15:32:46.509635384 -0500 @@ -563,6 +563,12 @@ pause_patch(); } @@ -1576,9 +5204,9 @@ diff -Nur linux-3.18.12.orig/arch/sparc/kernel/setup_64.c linux-3.18.12/arch/spa if (tlb_type == hypervisor) printk("ARCH: SUN4V\n"); -diff -Nur linux-3.18.12.orig/arch/sparc/mm/fault_32.c linux-3.18.12/arch/sparc/mm/fault_32.c ---- linux-3.18.12.orig/arch/sparc/mm/fault_32.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/sparc/mm/fault_32.c 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/sparc/mm/fault_32.c linux-3.18.14-rt/arch/sparc/mm/fault_32.c +--- linux-3.18.14.orig/arch/sparc/mm/fault_32.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/sparc/mm/fault_32.c 2015-05-31 15:32:46.529635385 -0500 @@ -196,7 +196,7 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. @@ -1588,9 +5216,9 @@ diff -Nur linux-3.18.12.orig/arch/sparc/mm/fault_32.c linux-3.18.12/arch/sparc/m goto no_context; perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); -diff -Nur linux-3.18.12.orig/arch/sparc/mm/fault_64.c linux-3.18.12/arch/sparc/mm/fault_64.c ---- linux-3.18.12.orig/arch/sparc/mm/fault_64.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/sparc/mm/fault_64.c 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/sparc/mm/fault_64.c linux-3.18.14-rt/arch/sparc/mm/fault_64.c +--- linux-3.18.14.orig/arch/sparc/mm/fault_64.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/sparc/mm/fault_64.c 2015-05-31 15:32:46.529635385 -0500 @@ -330,7 +330,7 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. @@ -1600,9 +5228,9 @@ diff -Nur linux-3.18.12.orig/arch/sparc/mm/fault_64.c linux-3.18.12/arch/sparc/m goto intr_or_no_mm; perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); -diff -Nur linux-3.18.12.orig/arch/tile/mm/fault.c linux-3.18.12/arch/tile/mm/fault.c ---- linux-3.18.12.orig/arch/tile/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/tile/mm/fault.c 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/tile/mm/fault.c linux-3.18.14-rt/arch/tile/mm/fault.c +--- linux-3.18.14.orig/arch/tile/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/tile/mm/fault.c 2015-05-31 15:32:46.533635385 -0500 @@ -357,7 +357,7 @@ * If we're in an interrupt, have no user context or are running in an * atomic region then we must not take the fault. @@ -1612,9 +5240,9 @@ diff -Nur linux-3.18.12.orig/arch/tile/mm/fault.c linux-3.18.12/arch/tile/mm/fau vma = NULL; /* happy compiler */ goto bad_area_nosemaphore; } -diff -Nur linux-3.18.12.orig/arch/um/kernel/trap.c linux-3.18.12/arch/um/kernel/trap.c ---- linux-3.18.12.orig/arch/um/kernel/trap.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/um/kernel/trap.c 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/um/kernel/trap.c linux-3.18.14-rt/arch/um/kernel/trap.c +--- linux-3.18.14.orig/arch/um/kernel/trap.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/um/kernel/trap.c 2015-05-31 15:32:46.537635384 -0500 @@ -38,7 +38,7 @@ * If the fault was during atomic operation, don't take the fault, just * fail. @@ -1624,9 +5252,9 @@ diff -Nur linux-3.18.12.orig/arch/um/kernel/trap.c linux-3.18.12/arch/um/kernel/ goto out_nosemaphore; if (is_user) -diff -Nur linux-3.18.12.orig/arch/x86/crypto/aesni-intel_glue.c linux-3.18.12/arch/x86/crypto/aesni-intel_glue.c ---- linux-3.18.12.orig/arch/x86/crypto/aesni-intel_glue.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/crypto/aesni-intel_glue.c 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/crypto/aesni-intel_glue.c linux-3.18.14-rt/arch/x86/crypto/aesni-intel_glue.c +--- linux-3.18.14.orig/arch/x86/crypto/aesni-intel_glue.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/crypto/aesni-intel_glue.c 2015-05-31 15:32:46.569635384 -0500 @@ -381,14 +381,14 @@ err = blkcipher_walk_virt(desc, &walk); desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; @@ -1719,9 +5347,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/crypto/aesni-intel_glue.c linux-3.18.12/ar return err; } -diff -Nur linux-3.18.12.orig/arch/x86/crypto/cast5_avx_glue.c linux-3.18.12/arch/x86/crypto/cast5_avx_glue.c ---- linux-3.18.12.orig/arch/x86/crypto/cast5_avx_glue.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/crypto/cast5_avx_glue.c 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/crypto/cast5_avx_glue.c linux-3.18.14-rt/arch/x86/crypto/cast5_avx_glue.c +--- linux-3.18.14.orig/arch/x86/crypto/cast5_avx_glue.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/crypto/cast5_avx_glue.c 2015-05-31 15:32:46.585635384 -0500 @@ -60,7 +60,7 @@ static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk, bool enc) @@ -1801,9 +5429,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/crypto/cast5_avx_glue.c linux-3.18.12/arch if (walk.nbytes) { ctr_crypt_final(desc, &walk); err = blkcipher_walk_done(desc, &walk, 0); -diff -Nur linux-3.18.12.orig/arch/x86/crypto/glue_helper.c linux-3.18.12/arch/x86/crypto/glue_helper.c ---- linux-3.18.12.orig/arch/x86/crypto/glue_helper.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/crypto/glue_helper.c 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/crypto/glue_helper.c linux-3.18.14-rt/arch/x86/crypto/glue_helper.c +--- linux-3.18.14.orig/arch/x86/crypto/glue_helper.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/crypto/glue_helper.c 2015-05-31 15:32:46.589635384 -0500 @@ -39,7 +39,7 @@ void *ctx = crypto_blkcipher_ctx(desc->tfm); const unsigned int bsize = 128 / 8; @@ -1919,9 +5547,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/crypto/glue_helper.c linux-3.18.12/arch/x8 return err; } EXPORT_SYMBOL_GPL(glue_xts_crypt_128bit); -diff -Nur linux-3.18.12.orig/arch/x86/include/asm/preempt.h linux-3.18.12/arch/x86/include/asm/preempt.h ---- linux-3.18.12.orig/arch/x86/include/asm/preempt.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/include/asm/preempt.h 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/include/asm/preempt.h linux-3.18.14-rt/arch/x86/include/asm/preempt.h +--- linux-3.18.14.orig/arch/x86/include/asm/preempt.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/include/asm/preempt.h 2015-05-31 15:32:46.597635384 -0500 @@ -85,17 +85,33 @@ * a decrement which hits zero means we have no preempt_count and should * reschedule. @@ -1957,9 +5585,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/include/asm/preempt.h linux-3.18.12/arch/x } #ifdef CONFIG_PREEMPT -diff -Nur linux-3.18.12.orig/arch/x86/include/asm/signal.h linux-3.18.12/arch/x86/include/asm/signal.h ---- linux-3.18.12.orig/arch/x86/include/asm/signal.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/include/asm/signal.h 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/include/asm/signal.h linux-3.18.14-rt/arch/x86/include/asm/signal.h +--- linux-3.18.14.orig/arch/x86/include/asm/signal.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/include/asm/signal.h 2015-05-31 15:32:46.597635384 -0500 @@ -23,6 +23,19 @@ unsigned long sig[_NSIG_WORDS]; } sigset_t; @@ -1980,9 +5608,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/include/asm/signal.h linux-3.18.12/arch/x8 #ifndef CONFIG_COMPAT typedef sigset_t compat_sigset_t; #endif -diff -Nur linux-3.18.12.orig/arch/x86/include/asm/stackprotector.h linux-3.18.12/arch/x86/include/asm/stackprotector.h ---- linux-3.18.12.orig/arch/x86/include/asm/stackprotector.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/include/asm/stackprotector.h 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/include/asm/stackprotector.h linux-3.18.14-rt/arch/x86/include/asm/stackprotector.h +--- linux-3.18.14.orig/arch/x86/include/asm/stackprotector.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/include/asm/stackprotector.h 2015-05-31 15:32:46.613635384 -0500 @@ -57,7 +57,7 @@ */ static __always_inline void boot_init_stack_canary(void) @@ -2009,9 +5637,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/include/asm/stackprotector.h linux-3.18.12 tsc = __native_read_tsc(); canary += tsc + (tsc << 32UL); -diff -Nur linux-3.18.12.orig/arch/x86/include/asm/thread_info.h linux-3.18.12/arch/x86/include/asm/thread_info.h ---- linux-3.18.12.orig/arch/x86/include/asm/thread_info.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/include/asm/thread_info.h 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/include/asm/thread_info.h linux-3.18.14-rt/arch/x86/include/asm/thread_info.h +--- linux-3.18.14.orig/arch/x86/include/asm/thread_info.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/include/asm/thread_info.h 2015-05-31 15:32:46.621635383 -0500 @@ -30,6 +30,8 @@ __u32 status; /* thread synchronous flags */ __u32 cpu; /* current CPU */ @@ -2046,9 +5674,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/include/asm/thread_info.h linux-3.18.12/ar #define STACK_WARN (THREAD_SIZE/8) #define KERNEL_STACK_OFFSET (5*(BITS_PER_LONG/8)) -diff -Nur linux-3.18.12.orig/arch/x86/include/asm/uv/uv_bau.h linux-3.18.12/arch/x86/include/asm/uv/uv_bau.h ---- linux-3.18.12.orig/arch/x86/include/asm/uv/uv_bau.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/include/asm/uv/uv_bau.h 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/include/asm/uv/uv_bau.h linux-3.18.14-rt/arch/x86/include/asm/uv/uv_bau.h +--- linux-3.18.14.orig/arch/x86/include/asm/uv/uv_bau.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/include/asm/uv/uv_bau.h 2015-05-31 15:32:46.621635383 -0500 @@ -615,9 +615,9 @@ cycles_t send_message; cycles_t period_end; @@ -2082,9 +5710,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/include/asm/uv/uv_bau.h linux-3.18.12/arch return 1; } -diff -Nur linux-3.18.12.orig/arch/x86/include/asm/uv/uv_hub.h linux-3.18.12/arch/x86/include/asm/uv/uv_hub.h ---- linux-3.18.12.orig/arch/x86/include/asm/uv/uv_hub.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/include/asm/uv/uv_hub.h 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/include/asm/uv/uv_hub.h linux-3.18.14-rt/arch/x86/include/asm/uv/uv_hub.h +--- linux-3.18.14.orig/arch/x86/include/asm/uv/uv_hub.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/include/asm/uv/uv_hub.h 2015-05-31 15:32:46.621635383 -0500 @@ -492,7 +492,7 @@ unsigned short nr_online_cpus; unsigned short pnode; @@ -2094,9 +5722,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/include/asm/uv/uv_hub.h linux-3.18.12/arch unsigned long nmi_count; /* obsolete, see uv_hub_nmi */ }; extern struct uv_blade_info *uv_blade_info; -diff -Nur linux-3.18.12.orig/arch/x86/Kconfig linux-3.18.12/arch/x86/Kconfig ---- linux-3.18.12.orig/arch/x86/Kconfig 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/Kconfig 2015-04-26 13:32:22.375684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/Kconfig linux-3.18.14-rt/arch/x86/Kconfig +--- linux-3.18.14.orig/arch/x86/Kconfig 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/Kconfig 2015-05-31 15:32:46.561635384 -0500 @@ -21,6 +21,7 @@ ### Arch settings config X86 @@ -2127,9 +5755,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/Kconfig linux-3.18.12/arch/x86/Kconfig ---help--- Enable maximum number of CPUS and NUMA Nodes for this architecture. If unsure, say N. -diff -Nur linux-3.18.12.orig/arch/x86/kernel/apic/io_apic.c linux-3.18.12/arch/x86/kernel/apic/io_apic.c ---- linux-3.18.12.orig/arch/x86/kernel/apic/io_apic.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/kernel/apic/io_apic.c 2015-04-26 13:32:22.379684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/kernel/apic/io_apic.c linux-3.18.14-rt/arch/x86/kernel/apic/io_apic.c +--- linux-3.18.14.orig/arch/x86/kernel/apic/io_apic.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/kernel/apic/io_apic.c 2015-05-31 15:32:46.629635384 -0500 @@ -2494,7 +2494,8 @@ static inline bool ioapic_irqd_mask(struct irq_data *data, struct irq_cfg *cfg) { @@ -2140,9 +5768,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/apic/io_apic.c linux-3.18.12/arch/x mask_ioapic(cfg); return true; } -diff -Nur linux-3.18.12.orig/arch/x86/kernel/apic/x2apic_uv_x.c linux-3.18.12/arch/x86/kernel/apic/x2apic_uv_x.c ---- linux-3.18.12.orig/arch/x86/kernel/apic/x2apic_uv_x.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/kernel/apic/x2apic_uv_x.c 2015-04-26 13:32:22.379684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/kernel/apic/x2apic_uv_x.c linux-3.18.14-rt/arch/x86/kernel/apic/x2apic_uv_x.c +--- linux-3.18.14.orig/arch/x86/kernel/apic/x2apic_uv_x.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/kernel/apic/x2apic_uv_x.c 2015-05-31 15:32:46.629635384 -0500 @@ -918,7 +918,7 @@ uv_blade_info[blade].pnode = pnode; uv_blade_info[blade].nr_possible_cpus = 0; @@ -2152,9 +5780,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/apic/x2apic_uv_x.c linux-3.18.12/ar min_pnode = min(pnode, min_pnode); max_pnode = max(pnode, max_pnode); blade++; -diff -Nur linux-3.18.12.orig/arch/x86/kernel/asm-offsets.c linux-3.18.12/arch/x86/kernel/asm-offsets.c ---- linux-3.18.12.orig/arch/x86/kernel/asm-offsets.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/kernel/asm-offsets.c 2015-04-26 13:32:22.379684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/kernel/asm-offsets.c linux-3.18.14-rt/arch/x86/kernel/asm-offsets.c +--- linux-3.18.14.orig/arch/x86/kernel/asm-offsets.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/kernel/asm-offsets.c 2015-05-31 15:32:46.633635383 -0500 @@ -32,6 +32,7 @@ OFFSET(TI_flags, thread_info, flags); OFFSET(TI_status, thread_info, status); @@ -2169,9 +5797,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/asm-offsets.c linux-3.18.12/arch/x8 DEFINE(PTREGS_SIZE, sizeof(struct pt_regs)); + DEFINE(_PREEMPT_ENABLED, PREEMPT_ENABLED); } -diff -Nur linux-3.18.12.orig/arch/x86/kernel/cpu/mcheck/mce.c linux-3.18.12/arch/x86/kernel/cpu/mcheck/mce.c ---- linux-3.18.12.orig/arch/x86/kernel/cpu/mcheck/mce.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/kernel/cpu/mcheck/mce.c 2015-04-26 13:32:22.379684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/kernel/cpu/mcheck/mce.c linux-3.18.14-rt/arch/x86/kernel/cpu/mcheck/mce.c +--- linux-3.18.14.orig/arch/x86/kernel/cpu/mcheck/mce.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/kernel/cpu/mcheck/mce.c 2015-05-31 15:32:46.641635383 -0500 @@ -41,6 +41,8 @@ #include <linux/debugfs.h> #include <linux/irq_work.h> @@ -2424,9 +6052,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/cpu/mcheck/mce.c linux-3.18.12/arch if (!zalloc_cpumask_var(&mce_device_initialized, GFP_KERNEL)) { err = -ENOMEM; goto err_out; -diff -Nur linux-3.18.12.orig/arch/x86/kernel/entry_32.S linux-3.18.12/arch/x86/kernel/entry_32.S ---- linux-3.18.12.orig/arch/x86/kernel/entry_32.S 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/kernel/entry_32.S 2015-04-26 13:32:22.379684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/kernel/entry_32.S linux-3.18.14-rt/arch/x86/kernel/entry_32.S +--- linux-3.18.14.orig/arch/x86/kernel/entry_32.S 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/kernel/entry_32.S 2015-05-31 15:32:46.641635383 -0500 @@ -359,8 +359,24 @@ ENTRY(resume_kernel) DISABLE_INTERRUPTS(CLBR_ANY) @@ -2470,9 +6098,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/entry_32.S linux-3.18.12/arch/x86/k jnz work_resched work_notifysig: # deal with pending signals and -diff -Nur linux-3.18.12.orig/arch/x86/kernel/entry_64.S linux-3.18.12/arch/x86/kernel/entry_64.S ---- linux-3.18.12.orig/arch/x86/kernel/entry_64.S 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/kernel/entry_64.S 2015-04-26 13:32:22.379684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/kernel/entry_64.S linux-3.18.14-rt/arch/x86/kernel/entry_64.S +--- linux-3.18.14.orig/arch/x86/kernel/entry_64.S 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/kernel/entry_64.S 2015-05-31 15:32:46.649635383 -0500 @@ -454,8 +454,8 @@ /* Handle reschedules */ /* edx: work, edi: workmask */ @@ -2554,9 +6182,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/entry_64.S linux-3.18.12/arch/x86/k jnz paranoid_schedule movl %ebx,%edx /* arg3: thread flags */ TRACE_IRQS_ON -diff -Nur linux-3.18.12.orig/arch/x86/kernel/irq_32.c linux-3.18.12/arch/x86/kernel/irq_32.c ---- linux-3.18.12.orig/arch/x86/kernel/irq_32.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/kernel/irq_32.c 2015-04-26 13:32:22.379684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/kernel/irq_32.c linux-3.18.14-rt/arch/x86/kernel/irq_32.c +--- linux-3.18.14.orig/arch/x86/kernel/irq_32.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/kernel/irq_32.c 2015-05-31 15:32:46.653635383 -0500 @@ -142,6 +142,7 @@ cpu, per_cpu(hardirq_stack, cpu), per_cpu(softirq_stack, cpu)); } @@ -2573,9 +6201,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/irq_32.c linux-3.18.12/arch/x86/ker bool handle_irq(unsigned irq, struct pt_regs *regs) { -diff -Nur linux-3.18.12.orig/arch/x86/kernel/process_32.c linux-3.18.12/arch/x86/kernel/process_32.c ---- linux-3.18.12.orig/arch/x86/kernel/process_32.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/kernel/process_32.c 2015-04-26 13:32:22.379684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/kernel/process_32.c linux-3.18.14-rt/arch/x86/kernel/process_32.c +--- linux-3.18.14.orig/arch/x86/kernel/process_32.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/kernel/process_32.c 2015-05-31 15:32:46.653635383 -0500 @@ -35,6 +35,7 @@ #include <linux/uaccess.h> #include <linux/io.h> @@ -2629,9 +6257,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/process_32.c linux-3.18.12/arch/x86 /* * Leave lazy mode, flushing any hypercalls made here. * This must be done before restoring TLS segments so -diff -Nur linux-3.18.12.orig/arch/x86/kernel/signal.c linux-3.18.12/arch/x86/kernel/signal.c ---- linux-3.18.12.orig/arch/x86/kernel/signal.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/kernel/signal.c 2015-04-26 13:32:22.379684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/kernel/signal.c linux-3.18.14-rt/arch/x86/kernel/signal.c +--- linux-3.18.14.orig/arch/x86/kernel/signal.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/kernel/signal.c 2015-05-31 15:32:46.653635383 -0500 @@ -746,6 +746,14 @@ mce_notify_process(); #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */ @@ -2647,9 +6275,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/signal.c linux-3.18.12/arch/x86/ker if (thread_info_flags & _TIF_UPROBE) uprobe_notify_resume(regs); -diff -Nur linux-3.18.12.orig/arch/x86/kernel/traps.c linux-3.18.12/arch/x86/kernel/traps.c ---- linux-3.18.12.orig/arch/x86/kernel/traps.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/kernel/traps.c 2015-04-26 13:32:22.379684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/kernel/traps.c linux-3.18.14-rt/arch/x86/kernel/traps.c +--- linux-3.18.14.orig/arch/x86/kernel/traps.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/kernel/traps.c 2015-05-31 15:32:46.657635383 -0500 @@ -87,9 +87,21 @@ local_irq_enable(); } @@ -2724,9 +6352,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kernel/traps.c linux-3.18.12/arch/x86/kern debug_stack_usage_dec(); exit: -diff -Nur linux-3.18.12.orig/arch/x86/kvm/lapic.c linux-3.18.12/arch/x86/kvm/lapic.c ---- linux-3.18.12.orig/arch/x86/kvm/lapic.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/kvm/lapic.c 2015-04-26 13:32:22.379684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/kvm/lapic.c linux-3.18.14-rt/arch/x86/kvm/lapic.c +--- linux-3.18.14.orig/arch/x86/kvm/lapic.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/kvm/lapic.c 2015-05-31 15:32:46.693635383 -0500 @@ -1034,8 +1034,38 @@ apic->divide_count); } @@ -2829,9 +6457,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kvm/lapic.c linux-3.18.12/arch/x86/kvm/lap } /* -diff -Nur linux-3.18.12.orig/arch/x86/kvm/x86.c linux-3.18.12/arch/x86/kvm/x86.c ---- linux-3.18.12.orig/arch/x86/kvm/x86.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/kvm/x86.c 2015-04-26 13:32:22.383684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/kvm/x86.c linux-3.18.14-rt/arch/x86/kvm/x86.c +--- linux-3.18.14.orig/arch/x86/kvm/x86.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/kvm/x86.c 2015-05-31 15:32:46.697635383 -0500 @@ -5772,6 +5772,13 @@ goto out; } @@ -2846,9 +6474,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/kvm/x86.c linux-3.18.12/arch/x86/kvm/x86.c r = kvm_mmu_module_init(); if (r) goto out_free_percpu; -diff -Nur linux-3.18.12.orig/arch/x86/mm/fault.c linux-3.18.12/arch/x86/mm/fault.c ---- linux-3.18.12.orig/arch/x86/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/mm/fault.c 2015-04-26 13:32:22.383684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/mm/fault.c linux-3.18.14-rt/arch/x86/mm/fault.c +--- linux-3.18.14.orig/arch/x86/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/mm/fault.c 2015-05-31 15:32:46.729635382 -0500 @@ -1128,7 +1128,7 @@ * If we're in an interrupt, have no user context or are running * in an atomic region then we must not take the fault: @@ -2858,9 +6486,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/mm/fault.c linux-3.18.12/arch/x86/mm/fault bad_area_nosemaphore(regs, error_code, address); return; } -diff -Nur linux-3.18.12.orig/arch/x86/mm/highmem_32.c linux-3.18.12/arch/x86/mm/highmem_32.c ---- linux-3.18.12.orig/arch/x86/mm/highmem_32.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/mm/highmem_32.c 2015-04-26 13:32:22.383684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/mm/highmem_32.c linux-3.18.14-rt/arch/x86/mm/highmem_32.c +--- linux-3.18.14.orig/arch/x86/mm/highmem_32.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/mm/highmem_32.c 2015-05-31 15:32:46.729635382 -0500 @@ -32,6 +32,7 @@ */ void *kmap_atomic_prot(struct page *page, pgprot_t prot) @@ -2891,9 +6519,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/mm/highmem_32.c linux-3.18.12/arch/x86/mm/ kpte_clear_flush(kmap_pte-idx, vaddr); kmap_atomic_idx_pop(); arch_flush_lazy_mmu_mode(); -diff -Nur linux-3.18.12.orig/arch/x86/mm/iomap_32.c linux-3.18.12/arch/x86/mm/iomap_32.c ---- linux-3.18.12.orig/arch/x86/mm/iomap_32.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/mm/iomap_32.c 2015-04-26 13:32:22.383684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/mm/iomap_32.c linux-3.18.14-rt/arch/x86/mm/iomap_32.c +--- linux-3.18.14.orig/arch/x86/mm/iomap_32.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/mm/iomap_32.c 2015-05-31 15:32:46.733635383 -0500 @@ -56,6 +56,7 @@ void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot) @@ -2926,9 +6554,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/mm/iomap_32.c linux-3.18.12/arch/x86/mm/io kpte_clear_flush(kmap_pte-idx, vaddr); kmap_atomic_idx_pop(); } -diff -Nur linux-3.18.12.orig/arch/x86/platform/uv/tlb_uv.c linux-3.18.12/arch/x86/platform/uv/tlb_uv.c ---- linux-3.18.12.orig/arch/x86/platform/uv/tlb_uv.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/platform/uv/tlb_uv.c 2015-04-26 13:32:22.383684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/platform/uv/tlb_uv.c linux-3.18.14-rt/arch/x86/platform/uv/tlb_uv.c +--- linux-3.18.14.orig/arch/x86/platform/uv/tlb_uv.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/platform/uv/tlb_uv.c 2015-05-31 15:32:46.733635383 -0500 @@ -714,9 +714,9 @@ quiesce_local_uvhub(hmaster); @@ -3015,9 +6643,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/platform/uv/tlb_uv.c linux-3.18.12/arch/x8 } } -diff -Nur linux-3.18.12.orig/arch/x86/platform/uv/uv_time.c linux-3.18.12/arch/x86/platform/uv/uv_time.c ---- linux-3.18.12.orig/arch/x86/platform/uv/uv_time.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/x86/platform/uv/uv_time.c 2015-04-26 13:32:22.383684003 -0500 +diff -Nur linux-3.18.14.orig/arch/x86/platform/uv/uv_time.c linux-3.18.14-rt/arch/x86/platform/uv/uv_time.c +--- linux-3.18.14.orig/arch/x86/platform/uv/uv_time.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/x86/platform/uv/uv_time.c 2015-05-31 15:32:46.737635383 -0500 @@ -58,7 +58,7 @@ /* There is one of these allocated per node */ @@ -3098,9 +6726,9 @@ diff -Nur linux-3.18.12.orig/arch/x86/platform/uv/uv_time.c linux-3.18.12/arch/x } /* -diff -Nur linux-3.18.12.orig/arch/xtensa/mm/fault.c linux-3.18.12/arch/xtensa/mm/fault.c ---- linux-3.18.12.orig/arch/xtensa/mm/fault.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/arch/xtensa/mm/fault.c 2015-04-26 13:32:22.383684003 -0500 +diff -Nur linux-3.18.14.orig/arch/xtensa/mm/fault.c linux-3.18.14-rt/arch/xtensa/mm/fault.c +--- linux-3.18.14.orig/arch/xtensa/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/arch/xtensa/mm/fault.c 2015-05-31 15:32:46.741635382 -0500 @@ -57,7 +57,7 @@ /* If we're in an interrupt or have no user * context, we must not take the fault.. @@ -3110,9 +6738,9 @@ diff -Nur linux-3.18.12.orig/arch/xtensa/mm/fault.c linux-3.18.12/arch/xtensa/mm bad_page_fault(regs, address, SIGSEGV); return; } -diff -Nur linux-3.18.12.orig/block/blk-core.c linux-3.18.12/block/blk-core.c ---- linux-3.18.12.orig/block/blk-core.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/block/blk-core.c 2015-04-26 13:32:22.383684003 -0500 +diff -Nur linux-3.18.14.orig/block/blk-core.c linux-3.18.14-rt/block/blk-core.c +--- linux-3.18.14.orig/block/blk-core.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/block/blk-core.c 2015-05-31 15:32:46.757635382 -0500 @@ -100,6 +100,9 @@ INIT_LIST_HEAD(&rq->queuelist); @@ -3188,9 +6816,9 @@ diff -Nur linux-3.18.12.orig/block/blk-core.c linux-3.18.12/block/blk-core.c } void blk_finish_plug(struct blk_plug *plug) -diff -Nur linux-3.18.12.orig/block/blk-ioc.c linux-3.18.12/block/blk-ioc.c ---- linux-3.18.12.orig/block/blk-ioc.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/block/blk-ioc.c 2015-04-26 13:32:22.383684003 -0500 +diff -Nur linux-3.18.14.orig/block/blk-ioc.c linux-3.18.14-rt/block/blk-ioc.c +--- linux-3.18.14.orig/block/blk-ioc.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/block/blk-ioc.c 2015-05-31 15:32:46.761635382 -0500 @@ -7,6 +7,7 @@ #include <linux/bio.h> #include <linux/blkdev.h> @@ -3217,9 +6845,9 @@ diff -Nur linux-3.18.12.orig/block/blk-ioc.c linux-3.18.12/block/blk-ioc.c goto retry; } } -diff -Nur linux-3.18.12.orig/block/blk-iopoll.c linux-3.18.12/block/blk-iopoll.c ---- linux-3.18.12.orig/block/blk-iopoll.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/block/blk-iopoll.c 2015-04-26 13:32:22.383684003 -0500 +diff -Nur linux-3.18.14.orig/block/blk-iopoll.c linux-3.18.14-rt/block/blk-iopoll.c +--- linux-3.18.14.orig/block/blk-iopoll.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/block/blk-iopoll.c 2015-05-31 15:32:46.761635382 -0500 @@ -35,6 +35,7 @@ list_add_tail(&iop->list, this_cpu_ptr(&blk_cpu_iopoll)); __raise_softirq_irqoff(BLOCK_IOPOLL_SOFTIRQ); @@ -3244,9 +6872,9 @@ diff -Nur linux-3.18.12.orig/block/blk-iopoll.c linux-3.18.12/block/blk-iopoll.c } return NOTIFY_OK; -diff -Nur linux-3.18.12.orig/block/blk-mq.c linux-3.18.12/block/blk-mq.c ---- linux-3.18.12.orig/block/blk-mq.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/block/blk-mq.c 2015-04-26 13:32:22.383684003 -0500 +diff -Nur linux-3.18.14.orig/block/blk-mq.c linux-3.18.14-rt/block/blk-mq.c +--- linux-3.18.14.orig/block/blk-mq.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/block/blk-mq.c 2015-05-31 15:32:46.789635382 -0500 @@ -85,7 +85,7 @@ if (percpu_ref_tryget_live(&q->mq_usage_counter)) return 0; @@ -3391,9 +7019,9 @@ diff -Nur linux-3.18.12.orig/block/blk-mq.c linux-3.18.12/block/blk-mq.c return blk_mq_hctx_cpu_offline(hctx, cpu); else if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN) return blk_mq_hctx_cpu_online(hctx, cpu); -diff -Nur linux-3.18.12.orig/block/blk-mq-cpu.c linux-3.18.12/block/blk-mq-cpu.c ---- linux-3.18.12.orig/block/blk-mq-cpu.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/block/blk-mq-cpu.c 2015-04-26 13:32:22.383684003 -0500 +diff -Nur linux-3.18.14.orig/block/blk-mq-cpu.c linux-3.18.14-rt/block/blk-mq-cpu.c +--- linux-3.18.14.orig/block/blk-mq-cpu.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/block/blk-mq-cpu.c 2015-05-31 15:32:46.773635382 -0500 @@ -16,7 +16,7 @@ #include "blk-mq.h" @@ -3445,9 +7073,9 @@ diff -Nur linux-3.18.12.orig/block/blk-mq-cpu.c linux-3.18.12/block/blk-mq-cpu.c } void blk_mq_init_cpu_notifier(struct blk_mq_cpu_notifier *notifier, -diff -Nur linux-3.18.12.orig/block/blk-mq.h linux-3.18.12/block/blk-mq.h ---- linux-3.18.12.orig/block/blk-mq.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/block/blk-mq.h 2015-04-26 13:32:22.383684003 -0500 +diff -Nur linux-3.18.14.orig/block/blk-mq.h linux-3.18.14-rt/block/blk-mq.h +--- linux-3.18.14.orig/block/blk-mq.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/block/blk-mq.h 2015-05-31 15:32:46.789635382 -0500 @@ -73,7 +73,10 @@ static inline struct blk_mq_ctx *__blk_mq_get_ctx(struct request_queue *q, unsigned int cpu) @@ -3475,9 +7103,9 @@ diff -Nur linux-3.18.12.orig/block/blk-mq.h linux-3.18.12/block/blk-mq.h } struct blk_mq_alloc_data { -diff -Nur linux-3.18.12.orig/block/blk-softirq.c linux-3.18.12/block/blk-softirq.c ---- linux-3.18.12.orig/block/blk-softirq.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/block/blk-softirq.c 2015-04-26 13:32:22.387684003 -0500 +diff -Nur linux-3.18.14.orig/block/blk-softirq.c linux-3.18.14-rt/block/blk-softirq.c +--- linux-3.18.14.orig/block/blk-softirq.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/block/blk-softirq.c 2015-05-31 15:32:46.789635382 -0500 @@ -51,6 +51,7 @@ raise_softirq_irqoff(BLOCK_SOFTIRQ); @@ -3502,9 +7130,9 @@ diff -Nur linux-3.18.12.orig/block/blk-softirq.c linux-3.18.12/block/blk-softirq } /** -diff -Nur linux-3.18.12.orig/block/bounce.c linux-3.18.12/block/bounce.c ---- linux-3.18.12.orig/block/bounce.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/block/bounce.c 2015-04-26 13:32:22.387684003 -0500 +diff -Nur linux-3.18.14.orig/block/bounce.c linux-3.18.14-rt/block/bounce.c +--- linux-3.18.14.orig/block/bounce.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/block/bounce.c 2015-05-31 15:32:46.793635382 -0500 @@ -54,11 +54,11 @@ unsigned long flags; unsigned char *vto; @@ -3519,9 +7147,9 @@ diff -Nur linux-3.18.12.orig/block/bounce.c linux-3.18.12/block/bounce.c } #else /* CONFIG_HIGHMEM */ -diff -Nur linux-3.18.12.orig/crypto/algapi.c linux-3.18.12/crypto/algapi.c ---- linux-3.18.12.orig/crypto/algapi.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/crypto/algapi.c 2015-04-26 13:32:22.387684003 -0500 +diff -Nur linux-3.18.14.orig/crypto/algapi.c linux-3.18.14-rt/crypto/algapi.c +--- linux-3.18.14.orig/crypto/algapi.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/crypto/algapi.c 2015-05-31 15:32:46.809635382 -0500 @@ -698,13 +698,13 @@ int crypto_register_notifier(struct notifier_block *nb) @@ -3538,9 +7166,9 @@ diff -Nur linux-3.18.12.orig/crypto/algapi.c linux-3.18.12/crypto/algapi.c } EXPORT_SYMBOL_GPL(crypto_unregister_notifier); -diff -Nur linux-3.18.12.orig/crypto/api.c linux-3.18.12/crypto/api.c ---- linux-3.18.12.orig/crypto/api.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/crypto/api.c 2015-04-26 13:32:22.387684003 -0500 +diff -Nur linux-3.18.14.orig/crypto/api.c linux-3.18.14-rt/crypto/api.c +--- linux-3.18.14.orig/crypto/api.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/crypto/api.c 2015-05-31 15:32:46.861635382 -0500 @@ -31,7 +31,7 @@ DECLARE_RWSEM(crypto_alg_sem); EXPORT_SYMBOL_GPL(crypto_alg_sem); @@ -3563,9 +7191,9 @@ diff -Nur linux-3.18.12.orig/crypto/api.c linux-3.18.12/crypto/api.c } return ok; -diff -Nur linux-3.18.12.orig/crypto/internal.h linux-3.18.12/crypto/internal.h ---- linux-3.18.12.orig/crypto/internal.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/crypto/internal.h 2015-04-26 13:32:22.387684003 -0500 +diff -Nur linux-3.18.14.orig/crypto/internal.h linux-3.18.14-rt/crypto/internal.h +--- linux-3.18.14.orig/crypto/internal.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/crypto/internal.h 2015-05-31 15:32:46.865635381 -0500 @@ -48,7 +48,7 @@ extern struct list_head crypto_alg_list; @@ -3584,9 +7212,9 @@ diff -Nur linux-3.18.12.orig/crypto/internal.h linux-3.18.12/crypto/internal.h } #endif /* _CRYPTO_INTERNAL_H */ -diff -Nur linux-3.18.12.orig/Documentation/hwlat_detector.txt linux-3.18.12/Documentation/hwlat_detector.txt ---- linux-3.18.12.orig/Documentation/hwlat_detector.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/Documentation/hwlat_detector.txt 2015-04-26 13:32:22.347684003 -0500 +diff -Nur linux-3.18.14.orig/Documentation/hwlat_detector.txt linux-3.18.14-rt/Documentation/hwlat_detector.txt +--- linux-3.18.14.orig/Documentation/hwlat_detector.txt 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/Documentation/hwlat_detector.txt 2015-05-31 15:32:45.457635394 -0500 @@ -0,0 +1,64 @@ +Introduction: +------------- @@ -3652,9 +7280,9 @@ diff -Nur linux-3.18.12.orig/Documentation/hwlat_detector.txt linux-3.18.12/Docu +observe any latencies that exceed the threshold (initially 100 usecs), +then we write to a global sample ring buffer of 8K samples, which is +consumed by reading from the "sample" (pipe) debugfs file interface. -diff -Nur linux-3.18.12.orig/Documentation/sysrq.txt linux-3.18.12/Documentation/sysrq.txt ---- linux-3.18.12.orig/Documentation/sysrq.txt 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/Documentation/sysrq.txt 2015-04-26 13:32:22.347684003 -0500 +diff -Nur linux-3.18.14.orig/Documentation/sysrq.txt linux-3.18.14-rt/Documentation/sysrq.txt +--- linux-3.18.14.orig/Documentation/sysrq.txt 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/Documentation/sysrq.txt 2015-05-31 15:32:45.461635394 -0500 @@ -59,10 +59,17 @@ On other - If you know of the key combos for other architectures, please let me know so I can add them to this section. @@ -3675,9 +7303,9 @@ diff -Nur linux-3.18.12.orig/Documentation/sysrq.txt linux-3.18.12/Documentation * What are the 'command' keys? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'b' - Will immediately reboot the system without syncing or unmounting -diff -Nur linux-3.18.12.orig/Documentation/trace/histograms.txt linux-3.18.12/Documentation/trace/histograms.txt ---- linux-3.18.12.orig/Documentation/trace/histograms.txt 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/Documentation/trace/histograms.txt 2015-04-26 13:32:22.351684003 -0500 +diff -Nur linux-3.18.14.orig/Documentation/trace/histograms.txt linux-3.18.14-rt/Documentation/trace/histograms.txt +--- linux-3.18.14.orig/Documentation/trace/histograms.txt 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/Documentation/trace/histograms.txt 2015-05-31 15:32:45.461635394 -0500 @@ -0,0 +1,186 @@ + Using the Linux Kernel Latency Histograms + @@ -3865,9 +7493,9 @@ diff -Nur linux-3.18.12.orig/Documentation/trace/histograms.txt linux-3.18.12/Do +is provided. + +These data are also reset when the wakeup histogram is reset. -diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/acglobal.h linux-3.18.12/drivers/acpi/acpica/acglobal.h ---- linux-3.18.12.orig/drivers/acpi/acpica/acglobal.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/acpi/acpica/acglobal.h 2015-04-26 13:32:22.387684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/acpi/acpica/acglobal.h linux-3.18.14-rt/drivers/acpi/acpica/acglobal.h +--- linux-3.18.14.orig/drivers/acpi/acpica/acglobal.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/acpi/acpica/acglobal.h 2015-05-31 15:32:46.885635381 -0500 @@ -112,7 +112,7 @@ * interrupt level */ @@ -3877,9 +7505,9 @@ diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/acglobal.h linux-3.18.12/driver ACPI_GLOBAL(acpi_spinlock, acpi_gbl_reference_count_lock); /* Mutex for _OSI support */ -diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/hwregs.c linux-3.18.12/drivers/acpi/acpica/hwregs.c ---- linux-3.18.12.orig/drivers/acpi/acpica/hwregs.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/acpi/acpica/hwregs.c 2015-04-26 13:32:22.387684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/acpi/acpica/hwregs.c linux-3.18.14-rt/drivers/acpi/acpica/hwregs.c +--- linux-3.18.14.orig/drivers/acpi/acpica/hwregs.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/acpi/acpica/hwregs.c 2015-05-31 15:32:46.929635381 -0500 @@ -269,14 +269,14 @@ ACPI_BITMASK_ALL_FIXED_STATUS, ACPI_FORMAT_UINT64(acpi_gbl_xpm1a_status.address))); @@ -3897,9 +7525,9 @@ diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/hwregs.c linux-3.18.12/drivers/ if (ACPI_FAILURE(status)) { goto exit; -diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/hwxface.c linux-3.18.12/drivers/acpi/acpica/hwxface.c ---- linux-3.18.12.orig/drivers/acpi/acpica/hwxface.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/acpi/acpica/hwxface.c 2015-04-26 13:32:22.387684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/acpi/acpica/hwxface.c linux-3.18.14-rt/drivers/acpi/acpica/hwxface.c +--- linux-3.18.14.orig/drivers/acpi/acpica/hwxface.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/acpi/acpica/hwxface.c 2015-05-31 15:32:46.973635380 -0500 @@ -374,7 +374,7 @@ return_ACPI_STATUS(AE_BAD_PARAMETER); } @@ -3918,9 +7546,9 @@ diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/hwxface.c linux-3.18.12/drivers return_ACPI_STATUS(status); } -diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/utmutex.c linux-3.18.12/drivers/acpi/acpica/utmutex.c ---- linux-3.18.12.orig/drivers/acpi/acpica/utmutex.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/acpi/acpica/utmutex.c 2015-04-26 13:32:22.387684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/acpi/acpica/utmutex.c linux-3.18.14-rt/drivers/acpi/acpica/utmutex.c +--- linux-3.18.14.orig/drivers/acpi/acpica/utmutex.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/acpi/acpica/utmutex.c 2015-05-31 15:32:46.973635380 -0500 @@ -88,7 +88,7 @@ return_ACPI_STATUS (status); } @@ -3939,9 +7567,9 @@ diff -Nur linux-3.18.12.orig/drivers/acpi/acpica/utmutex.c linux-3.18.12/drivers acpi_os_delete_lock(acpi_gbl_reference_count_lock); /* Delete the reader/writer lock */ -diff -Nur linux-3.18.12.orig/drivers/ata/libata-sff.c linux-3.18.12/drivers/ata/libata-sff.c ---- linux-3.18.12.orig/drivers/ata/libata-sff.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/ata/libata-sff.c 2015-04-26 13:32:22.387684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/ata/libata-sff.c linux-3.18.14-rt/drivers/ata/libata-sff.c +--- linux-3.18.14.orig/drivers/ata/libata-sff.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/ata/libata-sff.c 2015-05-31 15:32:46.993635380 -0500 @@ -678,9 +678,9 @@ unsigned long flags; unsigned int consumed; @@ -3990,9 +7618,9 @@ diff -Nur linux-3.18.12.orig/drivers/ata/libata-sff.c linux-3.18.12/drivers/ata/ } else { buf = page_address(page); consumed = ap->ops->sff_data_xfer(dev, buf + offset, -diff -Nur linux-3.18.12.orig/drivers/char/random.c linux-3.18.12/drivers/char/random.c ---- linux-3.18.12.orig/drivers/char/random.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/char/random.c 2015-04-26 13:32:22.387684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/char/random.c linux-3.18.14-rt/drivers/char/random.c +--- linux-3.18.14.orig/drivers/char/random.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/char/random.c 2015-05-31 15:32:47.013635380 -0500 @@ -776,8 +776,6 @@ } sample; long delta, delta2, delta3; @@ -4044,9 +7672,9 @@ diff -Nur linux-3.18.12.orig/drivers/char/random.c linux-3.18.12/drivers/char/ra fast_mix(fast_pool); add_interrupt_bench(cycles); -diff -Nur linux-3.18.12.orig/drivers/clocksource/tcb_clksrc.c linux-3.18.12/drivers/clocksource/tcb_clksrc.c ---- linux-3.18.12.orig/drivers/clocksource/tcb_clksrc.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/clocksource/tcb_clksrc.c 2015-04-26 13:32:22.387684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/clocksource/tcb_clksrc.c linux-3.18.14-rt/drivers/clocksource/tcb_clksrc.c +--- linux-3.18.14.orig/drivers/clocksource/tcb_clksrc.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/clocksource/tcb_clksrc.c 2015-05-31 15:32:47.025635380 -0500 @@ -23,8 +23,7 @@ * this 32 bit free-running counter. the second channel is not used. * @@ -4161,9 +7789,9 @@ diff -Nur linux-3.18.12.orig/drivers/clocksource/tcb_clksrc.c linux-3.18.12/driv if (ret) goto err_unregister_clksrc; -diff -Nur linux-3.18.12.orig/drivers/clocksource/timer-atmel-pit.c linux-3.18.12/drivers/clocksource/timer-atmel-pit.c ---- linux-3.18.12.orig/drivers/clocksource/timer-atmel-pit.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/clocksource/timer-atmel-pit.c 2015-04-26 13:32:22.387684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/clocksource/timer-atmel-pit.c linux-3.18.14-rt/drivers/clocksource/timer-atmel-pit.c +--- linux-3.18.14.orig/drivers/clocksource/timer-atmel-pit.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/clocksource/timer-atmel-pit.c 2015-05-31 15:32:47.025635380 -0500 @@ -90,6 +90,7 @@ return elapsed; } @@ -4189,9 +7817,9 @@ diff -Nur linux-3.18.12.orig/drivers/clocksource/timer-atmel-pit.c linux-3.18.12 break; case CLOCK_EVT_MODE_RESUME: break; -diff -Nur linux-3.18.12.orig/drivers/cpufreq/Kconfig.x86 linux-3.18.12/drivers/cpufreq/Kconfig.x86 ---- linux-3.18.12.orig/drivers/cpufreq/Kconfig.x86 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/cpufreq/Kconfig.x86 2015-04-26 13:32:22.387684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/cpufreq/Kconfig.x86 linux-3.18.14-rt/drivers/cpufreq/Kconfig.x86 +--- linux-3.18.14.orig/drivers/cpufreq/Kconfig.x86 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/cpufreq/Kconfig.x86 2015-05-31 15:32:47.065635380 -0500 @@ -113,7 +113,7 @@ config X86_POWERNOW_K8 @@ -4201,9 +7829,9 @@ diff -Nur linux-3.18.12.orig/drivers/cpufreq/Kconfig.x86 linux-3.18.12/drivers/c help This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors. Support for K10 and newer processors is now in acpi-cpufreq. -diff -Nur linux-3.18.12.orig/drivers/gpio/gpio-omap.c linux-3.18.12/drivers/gpio/gpio-omap.c ---- linux-3.18.12.orig/drivers/gpio/gpio-omap.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/gpio/gpio-omap.c 2015-04-26 13:32:22.387684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/gpio/gpio-omap.c linux-3.18.14-rt/drivers/gpio/gpio-omap.c +--- linux-3.18.14.orig/drivers/gpio/gpio-omap.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/gpio/gpio-omap.c 2015-05-31 15:32:47.073635379 -0500 @@ -57,7 +57,7 @@ u32 saved_datain; u32 level_mask; @@ -4478,9 +8106,9 @@ diff -Nur linux-3.18.12.orig/drivers/gpio/gpio-omap.c linux-3.18.12/drivers/gpio return 0; } -diff -Nur linux-3.18.12.orig/drivers/gpu/drm/i915/i915_gem.c linux-3.18.12/drivers/gpu/drm/i915/i915_gem.c ---- linux-3.18.12.orig/drivers/gpu/drm/i915/i915_gem.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/gpu/drm/i915/i915_gem.c 2015-04-26 13:32:22.391684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/gpu/drm/i915/i915_gem.c linux-3.18.14-rt/drivers/gpu/drm/i915/i915_gem.c +--- linux-3.18.14.orig/drivers/gpu/drm/i915/i915_gem.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/gpu/drm/i915/i915_gem.c 2015-05-31 15:32:47.081635379 -0500 @@ -5144,7 +5144,7 @@ if (!mutex_is_locked(mutex)) return false; @@ -4490,9 +8118,9 @@ diff -Nur linux-3.18.12.orig/drivers/gpu/drm/i915/i915_gem.c linux-3.18.12/drive return mutex->owner == task; #else /* Since UP may be pre-empted, we cannot assume that we own the lock */ -diff -Nur linux-3.18.12.orig/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-3.18.12/drivers/gpu/drm/i915/i915_gem_execbuffer.c ---- linux-3.18.12.orig/drivers/gpu/drm/i915/i915_gem_execbuffer.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/gpu/drm/i915/i915_gem_execbuffer.c 2015-04-26 13:32:22.391684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-3.18.14-rt/drivers/gpu/drm/i915/i915_gem_execbuffer.c +--- linux-3.18.14.orig/drivers/gpu/drm/i915/i915_gem_execbuffer.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/gpu/drm/i915/i915_gem_execbuffer.c 2015-05-31 15:32:47.121635379 -0500 @@ -1170,7 +1170,9 @@ return ret; } @@ -4503,9 +8131,9 @@ diff -Nur linux-3.18.12.orig/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-3. i915_gem_execbuffer_move_to_active(vmas, ring); i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj); -diff -Nur linux-3.18.12.orig/drivers/i2c/busses/i2c-omap.c linux-3.18.12/drivers/i2c/busses/i2c-omap.c ---- linux-3.18.12.orig/drivers/i2c/busses/i2c-omap.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/i2c/busses/i2c-omap.c 2015-04-26 13:32:22.391684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/i2c/busses/i2c-omap.c linux-3.18.14-rt/drivers/i2c/busses/i2c-omap.c +--- linux-3.18.14.orig/drivers/i2c/busses/i2c-omap.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/i2c/busses/i2c-omap.c 2015-05-31 15:32:47.125635379 -0500 @@ -875,15 +875,12 @@ u16 mask; u16 stat; @@ -4523,9 +8151,9 @@ diff -Nur linux-3.18.12.orig/drivers/i2c/busses/i2c-omap.c linux-3.18.12/drivers return ret; } -diff -Nur linux-3.18.12.orig/drivers/ide/alim15x3.c linux-3.18.12/drivers/ide/alim15x3.c ---- linux-3.18.12.orig/drivers/ide/alim15x3.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/ide/alim15x3.c 2015-04-26 13:32:22.391684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/ide/alim15x3.c linux-3.18.14-rt/drivers/ide/alim15x3.c +--- linux-3.18.14.orig/drivers/ide/alim15x3.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/ide/alim15x3.c 2015-05-31 15:32:47.137635379 -0500 @@ -234,7 +234,7 @@ isa_dev = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, NULL); @@ -4544,9 +8172,9 @@ diff -Nur linux-3.18.12.orig/drivers/ide/alim15x3.c linux-3.18.12/drivers/ide/al return 0; } -diff -Nur linux-3.18.12.orig/drivers/ide/hpt366.c linux-3.18.12/drivers/ide/hpt366.c ---- linux-3.18.12.orig/drivers/ide/hpt366.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/ide/hpt366.c 2015-04-26 13:32:22.391684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/ide/hpt366.c linux-3.18.14-rt/drivers/ide/hpt366.c +--- linux-3.18.14.orig/drivers/ide/hpt366.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/ide/hpt366.c 2015-05-31 15:32:47.169635379 -0500 @@ -1241,7 +1241,7 @@ dma_old = inb(base + 2); @@ -4565,9 +8193,9 @@ diff -Nur linux-3.18.12.orig/drivers/ide/hpt366.c linux-3.18.12/drivers/ide/hpt3 printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name, base, base + 7); -diff -Nur linux-3.18.12.orig/drivers/ide/ide-io.c linux-3.18.12/drivers/ide/ide-io.c ---- linux-3.18.12.orig/drivers/ide/ide-io.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/ide/ide-io.c 2015-04-26 13:32:22.391684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/ide/ide-io.c linux-3.18.14-rt/drivers/ide/ide-io.c +--- linux-3.18.14.orig/drivers/ide/ide-io.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/ide/ide-io.c 2015-05-31 15:32:47.169635379 -0500 @@ -659,7 +659,7 @@ /* disable_irq_nosync ?? */ disable_irq(hwif->irq); @@ -4577,9 +8205,9 @@ diff -Nur linux-3.18.12.orig/drivers/ide/ide-io.c linux-3.18.12/drivers/ide/ide- if (hwif->polling) { startstop = handler(drive); } else if (drive_is_ready(drive)) { -diff -Nur linux-3.18.12.orig/drivers/ide/ide-iops.c linux-3.18.12/drivers/ide/ide-iops.c ---- linux-3.18.12.orig/drivers/ide/ide-iops.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/ide/ide-iops.c 2015-04-26 13:32:22.391684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/ide/ide-iops.c linux-3.18.14-rt/drivers/ide/ide-iops.c +--- linux-3.18.14.orig/drivers/ide/ide-iops.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/ide/ide-iops.c 2015-05-31 15:32:47.185635379 -0500 @@ -129,12 +129,12 @@ if ((stat & ATA_BUSY) == 0) break; @@ -4595,9 +8223,9 @@ diff -Nur linux-3.18.12.orig/drivers/ide/ide-iops.c linux-3.18.12/drivers/ide/id } /* * Allow status to settle, then read it again. -diff -Nur linux-3.18.12.orig/drivers/ide/ide-io-std.c linux-3.18.12/drivers/ide/ide-io-std.c ---- linux-3.18.12.orig/drivers/ide/ide-io-std.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/ide/ide-io-std.c 2015-04-26 13:32:22.391684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/ide/ide-io-std.c linux-3.18.14-rt/drivers/ide/ide-io-std.c +--- linux-3.18.14.orig/drivers/ide/ide-io-std.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/ide/ide-io-std.c 2015-05-31 15:32:47.169635379 -0500 @@ -175,7 +175,7 @@ unsigned long uninitialized_var(flags); @@ -4634,9 +8262,9 @@ diff -Nur linux-3.18.12.orig/drivers/ide/ide-io-std.c linux-3.18.12/drivers/ide/ if (((len + 1) & 3) < 2) return; -diff -Nur linux-3.18.12.orig/drivers/ide/ide-probe.c linux-3.18.12/drivers/ide/ide-probe.c ---- linux-3.18.12.orig/drivers/ide/ide-probe.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/ide/ide-probe.c 2015-04-26 13:32:22.391684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/ide/ide-probe.c linux-3.18.14-rt/drivers/ide/ide-probe.c +--- linux-3.18.14.orig/drivers/ide/ide-probe.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/ide/ide-probe.c 2015-05-31 15:32:47.185635379 -0500 @@ -196,10 +196,10 @@ int bswap = 1; @@ -4650,9 +8278,9 @@ diff -Nur linux-3.18.12.orig/drivers/ide/ide-probe.c linux-3.18.12/drivers/ide/i drive->dev_flags |= IDE_DFLAG_ID_READ; #ifdef DEBUG -diff -Nur linux-3.18.12.orig/drivers/ide/ide-taskfile.c linux-3.18.12/drivers/ide/ide-taskfile.c ---- linux-3.18.12.orig/drivers/ide/ide-taskfile.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/ide/ide-taskfile.c 2015-04-26 13:32:22.391684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/ide/ide-taskfile.c linux-3.18.14-rt/drivers/ide/ide-taskfile.c +--- linux-3.18.14.orig/drivers/ide/ide-taskfile.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/ide/ide-taskfile.c 2015-05-31 15:32:47.185635379 -0500 @@ -250,7 +250,7 @@ page_is_high = PageHighMem(page); @@ -4680,9 +8308,9 @@ diff -Nur linux-3.18.12.orig/drivers/ide/ide-taskfile.c linux-3.18.12/drivers/id ide_set_handler(drive, &task_pio_intr, WAIT_WORSTCASE); -diff -Nur linux-3.18.12.orig/drivers/infiniband/ulp/ipoib/ipoib_multicast.c linux-3.18.12/drivers/infiniband/ulp/ipoib/ipoib_multicast.c ---- linux-3.18.12.orig/drivers/infiniband/ulp/ipoib/ipoib_multicast.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/infiniband/ulp/ipoib/ipoib_multicast.c 2015-04-26 13:32:22.391684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/infiniband/ulp/ipoib/ipoib_multicast.c linux-3.18.14-rt/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +--- linux-3.18.14.orig/drivers/infiniband/ulp/ipoib/ipoib_multicast.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/infiniband/ulp/ipoib/ipoib_multicast.c 2015-05-31 15:32:47.205635378 -0500 @@ -796,7 +796,7 @@ ipoib_mcast_stop_thread(dev, 0); @@ -4701,9 +8329,9 @@ diff -Nur linux-3.18.12.orig/drivers/infiniband/ulp/ipoib/ipoib_multicast.c linu /* We have to cancel outside of the spinlock */ list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { -diff -Nur linux-3.18.12.orig/drivers/input/gameport/gameport.c linux-3.18.12/drivers/input/gameport/gameport.c ---- linux-3.18.12.orig/drivers/input/gameport/gameport.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/input/gameport/gameport.c 2015-04-26 13:32:22.391684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/input/gameport/gameport.c linux-3.18.14-rt/drivers/input/gameport/gameport.c +--- linux-3.18.14.orig/drivers/input/gameport/gameport.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/input/gameport/gameport.c 2015-05-31 15:32:47.225635378 -0500 @@ -124,12 +124,12 @@ tx = 1 << 30; @@ -4733,9 +8361,9 @@ diff -Nur linux-3.18.12.orig/drivers/input/gameport/gameport.c linux-3.18.12/dri udelay(i * 10); if (t2 - t1 < tx) tx = t2 - t1; } -diff -Nur linux-3.18.12.orig/drivers/leds/trigger/Kconfig linux-3.18.12/drivers/leds/trigger/Kconfig ---- linux-3.18.12.orig/drivers/leds/trigger/Kconfig 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/leds/trigger/Kconfig 2015-04-26 13:32:22.391684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/leds/trigger/Kconfig linux-3.18.14-rt/drivers/leds/trigger/Kconfig +--- linux-3.18.14.orig/drivers/leds/trigger/Kconfig 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/leds/trigger/Kconfig 2015-05-31 15:32:47.229635378 -0500 @@ -61,7 +61,7 @@ config LEDS_TRIGGER_CPU @@ -4745,9 +8373,9 @@ diff -Nur linux-3.18.12.orig/drivers/leds/trigger/Kconfig linux-3.18.12/drivers/ help This allows LEDs to be controlled by active CPUs. This shows the active CPUs across an array of LEDs so you can see which -diff -Nur linux-3.18.12.orig/drivers/md/bcache/Kconfig linux-3.18.12/drivers/md/bcache/Kconfig ---- linux-3.18.12.orig/drivers/md/bcache/Kconfig 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/md/bcache/Kconfig 2015-04-26 13:32:22.391684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/md/bcache/Kconfig linux-3.18.14-rt/drivers/md/bcache/Kconfig +--- linux-3.18.14.orig/drivers/md/bcache/Kconfig 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/md/bcache/Kconfig 2015-05-31 15:32:47.245635378 -0500 @@ -1,6 +1,7 @@ config BCACHE @@ -4756,9 +8384,9 @@ diff -Nur linux-3.18.12.orig/drivers/md/bcache/Kconfig linux-3.18.12/drivers/md/ ---help--- Allows a block device to be used as cache for other devices; uses a btree for indexing and the layout is optimized for SSDs. -diff -Nur linux-3.18.12.orig/drivers/md/dm.c linux-3.18.12/drivers/md/dm.c ---- linux-3.18.12.orig/drivers/md/dm.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/md/dm.c 2015-04-26 13:32:22.395684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/md/dm.c linux-3.18.14-rt/drivers/md/dm.c +--- linux-3.18.14.orig/drivers/md/dm.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/md/dm.c 2015-05-31 15:32:47.261635378 -0500 @@ -1898,14 +1898,14 @@ if (map_request(ti, clone, md)) goto requeued; @@ -4776,9 +8404,9 @@ diff -Nur linux-3.18.12.orig/drivers/md/dm.c linux-3.18.12/drivers/md/dm.c spin_lock(q->queue_lock); delay_and_out: -diff -Nur linux-3.18.12.orig/drivers/md/raid5.c linux-3.18.12/drivers/md/raid5.c ---- linux-3.18.12.orig/drivers/md/raid5.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/md/raid5.c 2015-04-26 13:32:22.395684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/md/raid5.c linux-3.18.14-rt/drivers/md/raid5.c +--- linux-3.18.14.orig/drivers/md/raid5.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/md/raid5.c 2015-05-31 15:32:47.265635378 -0500 @@ -1649,8 +1649,9 @@ struct raid5_percpu *percpu; unsigned long cpu; @@ -4808,9 +8436,9 @@ diff -Nur linux-3.18.12.orig/drivers/md/raid5.c linux-3.18.12/drivers/md/raid5.c } put_online_cpus(); -diff -Nur linux-3.18.12.orig/drivers/md/raid5.h linux-3.18.12/drivers/md/raid5.h ---- linux-3.18.12.orig/drivers/md/raid5.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/md/raid5.h 2015-04-26 13:32:22.395684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/md/raid5.h linux-3.18.14-rt/drivers/md/raid5.h +--- linux-3.18.14.orig/drivers/md/raid5.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/md/raid5.h 2015-05-31 15:32:47.293635378 -0500 @@ -457,6 +457,7 @@ int recovery_disabled; /* per cpu variables */ @@ -4819,9 +8447,9 @@ diff -Nur linux-3.18.12.orig/drivers/md/raid5.h linux-3.18.12/drivers/md/raid5.h struct page *spare_page; /* Used when checking P/Q in raid6 */ void *scribble; /* space for constructing buffer * lists and performing address -diff -Nur linux-3.18.12.orig/drivers/misc/hwlat_detector.c linux-3.18.12/drivers/misc/hwlat_detector.c ---- linux-3.18.12.orig/drivers/misc/hwlat_detector.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/drivers/misc/hwlat_detector.c 2015-04-26 13:32:22.395684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/misc/hwlat_detector.c linux-3.18.14-rt/drivers/misc/hwlat_detector.c +--- linux-3.18.14.orig/drivers/misc/hwlat_detector.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/drivers/misc/hwlat_detector.c 2015-05-31 15:32:47.377635377 -0500 @@ -0,0 +1,1240 @@ +/* + * hwlat_detector.c - A simple Hardware Latency detector. @@ -6063,9 +9691,9 @@ diff -Nur linux-3.18.12.orig/drivers/misc/hwlat_detector.c linux-3.18.12/drivers + +module_init(detector_init); +module_exit(detector_exit); -diff -Nur linux-3.18.12.orig/drivers/misc/Kconfig linux-3.18.12/drivers/misc/Kconfig ---- linux-3.18.12.orig/drivers/misc/Kconfig 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/misc/Kconfig 2015-04-26 13:32:22.395684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/misc/Kconfig linux-3.18.14-rt/drivers/misc/Kconfig +--- linux-3.18.14.orig/drivers/misc/Kconfig 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/misc/Kconfig 2015-05-31 15:32:47.297635378 -0500 @@ -54,6 +54,7 @@ config ATMEL_TCLIB bool "Atmel AT32/AT91 Timer/Counter Library" @@ -6136,9 +9764,9 @@ diff -Nur linux-3.18.12.orig/drivers/misc/Kconfig linux-3.18.12/drivers/misc/Kco config PHANTOM tristate "Sensable PHANToM (PCI)" depends on PCI -diff -Nur linux-3.18.12.orig/drivers/misc/Makefile linux-3.18.12/drivers/misc/Makefile ---- linux-3.18.12.orig/drivers/misc/Makefile 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/misc/Makefile 2015-04-26 13:32:22.395684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/misc/Makefile linux-3.18.14-rt/drivers/misc/Makefile +--- linux-3.18.14.orig/drivers/misc/Makefile 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/misc/Makefile 2015-05-31 15:32:47.349635377 -0500 @@ -38,6 +38,7 @@ obj-$(CONFIG_HMC6352) += hmc6352.o obj-y += eeprom/ @@ -6147,9 +9775,9 @@ diff -Nur linux-3.18.12.orig/drivers/misc/Makefile linux-3.18.12/drivers/misc/Ma obj-$(CONFIG_SPEAR13XX_PCIE_GADGET) += spear13xx_pcie_gadget.o obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o -diff -Nur linux-3.18.12.orig/drivers/mmc/host/mmci.c linux-3.18.12/drivers/mmc/host/mmci.c ---- linux-3.18.12.orig/drivers/mmc/host/mmci.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/mmc/host/mmci.c 2015-04-26 13:32:22.395684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/mmc/host/mmci.c linux-3.18.14-rt/drivers/mmc/host/mmci.c +--- linux-3.18.14.orig/drivers/mmc/host/mmci.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/mmc/host/mmci.c 2015-05-31 15:32:47.393635377 -0500 @@ -1153,15 +1153,12 @@ struct sg_mapping_iter *sg_miter = &host->sg_miter; struct variant_data *variant = host->variant; @@ -6175,9 +9803,9 @@ diff -Nur linux-3.18.12.orig/drivers/mmc/host/mmci.c linux-3.18.12/drivers/mmc/h /* * If we have less than the fifo 'half-full' threshold to transfer, * trigger a PIO interrupt as soon as any data is available. -diff -Nur linux-3.18.12.orig/drivers/mmc/host/sdhci.c linux-3.18.12/drivers/mmc/host/sdhci.c ---- linux-3.18.12.orig/drivers/mmc/host/sdhci.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/mmc/host/sdhci.c 2015-04-26 13:32:22.399684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/mmc/host/sdhci.c linux-3.18.14-rt/drivers/mmc/host/sdhci.c +--- linux-3.18.14.orig/drivers/mmc/host/sdhci.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/mmc/host/sdhci.c 2015-05-31 15:32:47.397635376 -0500 @@ -2565,6 +2565,31 @@ return isr ? IRQ_HANDLED : IRQ_NONE; } @@ -6231,9 +9859,9 @@ diff -Nur linux-3.18.12.orig/drivers/mmc/host/sdhci.c linux-3.18.12/drivers/mmc/ if (ret) { pr_err("%s: Failed to request IRQ %d: %d\n", mmc_hostname(mmc), host->irq, ret); -diff -Nur linux-3.18.12.orig/drivers/net/ethernet/3com/3c59x.c linux-3.18.12/drivers/net/ethernet/3com/3c59x.c ---- linux-3.18.12.orig/drivers/net/ethernet/3com/3c59x.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/net/ethernet/3com/3c59x.c 2015-04-26 13:32:22.399684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/net/ethernet/3com/3c59x.c linux-3.18.14-rt/drivers/net/ethernet/3com/3c59x.c +--- linux-3.18.14.orig/drivers/net/ethernet/3com/3c59x.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/net/ethernet/3com/3c59x.c 2015-05-31 15:32:47.425635376 -0500 @@ -842,9 +842,9 @@ { struct vortex_private *vp = netdev_priv(dev); @@ -6261,9 +9889,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/3com/3c59x.c linux-3.18.12/dri } } -diff -Nur linux-3.18.12.orig/drivers/net/ethernet/atheros/atl1c/atl1c_main.c linux-3.18.12/drivers/net/ethernet/atheros/atl1c/atl1c_main.c ---- linux-3.18.12.orig/drivers/net/ethernet/atheros/atl1c/atl1c_main.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/net/ethernet/atheros/atl1c/atl1c_main.c 2015-04-26 13:32:22.399684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/net/ethernet/atheros/atl1c/atl1c_main.c linux-3.18.14-rt/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +--- linux-3.18.14.orig/drivers/net/ethernet/atheros/atl1c/atl1c_main.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/net/ethernet/atheros/atl1c/atl1c_main.c 2015-05-31 15:32:47.437635376 -0500 @@ -2213,11 +2213,7 @@ } @@ -6277,9 +9905,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/atheros/atl1c/atl1c_main.c lin if (atl1c_tpd_avail(adapter, type) < tpd_req) { /* no enough descriptor, just stop queue */ -diff -Nur linux-3.18.12.orig/drivers/net/ethernet/atheros/atl1e/atl1e_main.c linux-3.18.12/drivers/net/ethernet/atheros/atl1e/atl1e_main.c ---- linux-3.18.12.orig/drivers/net/ethernet/atheros/atl1e/atl1e_main.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/net/ethernet/atheros/atl1e/atl1e_main.c 2015-04-26 13:32:22.399684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/net/ethernet/atheros/atl1e/atl1e_main.c linux-3.18.14-rt/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +--- linux-3.18.14.orig/drivers/net/ethernet/atheros/atl1e/atl1e_main.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/net/ethernet/atheros/atl1e/atl1e_main.c 2015-05-31 15:32:47.445635376 -0500 @@ -1880,8 +1880,7 @@ return NETDEV_TX_OK; } @@ -6290,9 +9918,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/atheros/atl1e/atl1e_main.c lin if (atl1e_tpd_avail(adapter) < tpd_req) { /* no enough descriptor, just stop queue */ -diff -Nur linux-3.18.12.orig/drivers/net/ethernet/chelsio/cxgb/sge.c linux-3.18.12/drivers/net/ethernet/chelsio/cxgb/sge.c ---- linux-3.18.12.orig/drivers/net/ethernet/chelsio/cxgb/sge.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/net/ethernet/chelsio/cxgb/sge.c 2015-04-26 13:32:22.399684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/net/ethernet/chelsio/cxgb/sge.c linux-3.18.14-rt/drivers/net/ethernet/chelsio/cxgb/sge.c +--- linux-3.18.14.orig/drivers/net/ethernet/chelsio/cxgb/sge.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/net/ethernet/chelsio/cxgb/sge.c 2015-05-31 15:32:47.493635375 -0500 @@ -1663,8 +1663,7 @@ struct cmdQ *q = &sge->cmdQ[qid]; unsigned int credits, pidx, genbit, count, use_sched_skb = 0; @@ -6303,9 +9931,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/chelsio/cxgb/sge.c linux-3.18. reclaim_completed_tx(sge, q); -diff -Nur linux-3.18.12.orig/drivers/net/ethernet/freescale/gianfar.c linux-3.18.12/drivers/net/ethernet/freescale/gianfar.c ---- linux-3.18.12.orig/drivers/net/ethernet/freescale/gianfar.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/net/ethernet/freescale/gianfar.c 2015-04-26 13:32:22.399684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/net/ethernet/freescale/gianfar.c linux-3.18.14-rt/drivers/net/ethernet/freescale/gianfar.c +--- linux-3.18.14.orig/drivers/net/ethernet/freescale/gianfar.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/net/ethernet/freescale/gianfar.c 2015-05-31 15:32:47.525635375 -0500 @@ -1483,7 +1483,7 @@ if (netif_running(ndev)) { @@ -6359,9 +9987,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/freescale/gianfar.c linux-3.18 } netif_dbg(priv, tx_err, dev, "Transmit Error\n"); } -diff -Nur linux-3.18.12.orig/drivers/net/ethernet/neterion/s2io.c linux-3.18.12/drivers/net/ethernet/neterion/s2io.c ---- linux-3.18.12.orig/drivers/net/ethernet/neterion/s2io.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/net/ethernet/neterion/s2io.c 2015-04-26 13:32:22.403684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/net/ethernet/neterion/s2io.c linux-3.18.14-rt/drivers/net/ethernet/neterion/s2io.c +--- linux-3.18.14.orig/drivers/net/ethernet/neterion/s2io.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/net/ethernet/neterion/s2io.c 2015-05-31 15:32:47.537635375 -0500 @@ -4084,12 +4084,7 @@ [skb->priority & (MAX_TX_FIFOS - 1)]; fifo = &mac_control->fifos[queue]; @@ -6376,9 +10004,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/neterion/s2io.c linux-3.18.12/ if (sp->config.multiq) { if (__netif_subqueue_stopped(dev, fifo->fifo_no)) { -diff -Nur linux-3.18.12.orig/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c linux-3.18.12/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c ---- linux-3.18.12.orig/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c 2015-04-26 13:32:22.403684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c linux-3.18.14-rt/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +--- linux-3.18.14.orig/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c 2015-05-31 15:32:47.549635375 -0500 @@ -2137,10 +2137,8 @@ struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring; unsigned long flags; @@ -6392,9 +10020,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main. if (unlikely(!PCH_GBE_DESC_UNUSED(tx_ring))) { netif_stop_queue(netdev); spin_unlock_irqrestore(&tx_ring->tx_lock, flags); -diff -Nur linux-3.18.12.orig/drivers/net/ethernet/realtek/8139too.c linux-3.18.12/drivers/net/ethernet/realtek/8139too.c ---- linux-3.18.12.orig/drivers/net/ethernet/realtek/8139too.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/net/ethernet/realtek/8139too.c 2015-04-26 13:32:22.403684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/net/ethernet/realtek/8139too.c linux-3.18.14-rt/drivers/net/ethernet/realtek/8139too.c +--- linux-3.18.14.orig/drivers/net/ethernet/realtek/8139too.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/net/ethernet/realtek/8139too.c 2015-05-31 15:32:47.557635375 -0500 @@ -2215,7 +2215,7 @@ struct rtl8139_private *tp = netdev_priv(dev); const int irq = tp->pci_dev->irq; @@ -6404,9 +10032,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/realtek/8139too.c linux-3.18.1 rtl8139_interrupt(irq, dev); enable_irq(irq); } -diff -Nur linux-3.18.12.orig/drivers/net/ethernet/tehuti/tehuti.c linux-3.18.12/drivers/net/ethernet/tehuti/tehuti.c ---- linux-3.18.12.orig/drivers/net/ethernet/tehuti/tehuti.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/net/ethernet/tehuti/tehuti.c 2015-04-26 13:32:22.403684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/net/ethernet/tehuti/tehuti.c linux-3.18.14-rt/drivers/net/ethernet/tehuti/tehuti.c +--- linux-3.18.14.orig/drivers/net/ethernet/tehuti/tehuti.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/net/ethernet/tehuti/tehuti.c 2015-05-31 15:32:47.581635375 -0500 @@ -1629,13 +1629,8 @@ unsigned long flags; @@ -6423,9 +10051,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/ethernet/tehuti/tehuti.c linux-3.18.12/ /* build tx descriptor */ BDX_ASSERT(f->m.wptr >= f->m.memsz); /* started with valid wptr */ -diff -Nur linux-3.18.12.orig/drivers/net/rionet.c linux-3.18.12/drivers/net/rionet.c ---- linux-3.18.12.orig/drivers/net/rionet.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/net/rionet.c 2015-04-26 13:32:22.403684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/net/rionet.c linux-3.18.14-rt/drivers/net/rionet.c +--- linux-3.18.14.orig/drivers/net/rionet.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/net/rionet.c 2015-05-31 15:32:47.597635374 -0500 @@ -174,11 +174,7 @@ unsigned long flags; int add_num = 1; @@ -6439,9 +10067,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/rionet.c linux-3.18.12/drivers/net/rion if (is_multicast_ether_addr(eth->h_dest)) add_num = nets[rnet->mport->id].nact; -diff -Nur linux-3.18.12.orig/drivers/net/wireless/orinoco/orinoco_usb.c linux-3.18.12/drivers/net/wireless/orinoco/orinoco_usb.c ---- linux-3.18.12.orig/drivers/net/wireless/orinoco/orinoco_usb.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/net/wireless/orinoco/orinoco_usb.c 2015-04-26 13:32:22.403684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/net/wireless/orinoco/orinoco_usb.c linux-3.18.14-rt/drivers/net/wireless/orinoco/orinoco_usb.c +--- linux-3.18.14.orig/drivers/net/wireless/orinoco/orinoco_usb.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/net/wireless/orinoco/orinoco_usb.c 2015-05-31 15:32:47.613635374 -0500 @@ -699,7 +699,7 @@ while (!ctx->done.done && msecs--) udelay(1000); @@ -6451,9 +10079,9 @@ diff -Nur linux-3.18.12.orig/drivers/net/wireless/orinoco/orinoco_usb.c linux-3. ctx->done.done); } break; -diff -Nur linux-3.18.12.orig/drivers/pci/access.c linux-3.18.12/drivers/pci/access.c ---- linux-3.18.12.orig/drivers/pci/access.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/pci/access.c 2015-04-26 13:32:22.403684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/pci/access.c linux-3.18.14-rt/drivers/pci/access.c +--- linux-3.18.14.orig/drivers/pci/access.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/pci/access.c 2015-05-31 15:32:47.665635374 -0500 @@ -434,7 +434,7 @@ WARN_ON(!dev->block_cfg_access); @@ -6463,9 +10091,9 @@ diff -Nur linux-3.18.12.orig/drivers/pci/access.c linux-3.18.12/drivers/pci/acce raw_spin_unlock_irqrestore(&pci_lock, flags); } EXPORT_SYMBOL_GPL(pci_cfg_access_unlock); -diff -Nur linux-3.18.12.orig/drivers/scsi/fcoe/fcoe.c linux-3.18.12/drivers/scsi/fcoe/fcoe.c ---- linux-3.18.12.orig/drivers/scsi/fcoe/fcoe.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/scsi/fcoe/fcoe.c 2015-04-26 13:32:22.403684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/scsi/fcoe/fcoe.c linux-3.18.14-rt/drivers/scsi/fcoe/fcoe.c +--- linux-3.18.14.orig/drivers/scsi/fcoe/fcoe.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/scsi/fcoe/fcoe.c 2015-05-31 15:32:47.677635374 -0500 @@ -1286,7 +1286,7 @@ struct sk_buff *skb; #ifdef CONFIG_SMP @@ -6529,9 +10157,9 @@ diff -Nur linux-3.18.12.orig/drivers/scsi/fcoe/fcoe.c linux-3.18.12/drivers/scsi kfree_skb(skb); } -diff -Nur linux-3.18.12.orig/drivers/scsi/fcoe/fcoe_ctlr.c linux-3.18.12/drivers/scsi/fcoe/fcoe_ctlr.c ---- linux-3.18.12.orig/drivers/scsi/fcoe/fcoe_ctlr.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/scsi/fcoe/fcoe_ctlr.c 2015-04-26 13:32:22.403684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/scsi/fcoe/fcoe_ctlr.c linux-3.18.14-rt/drivers/scsi/fcoe/fcoe_ctlr.c +--- linux-3.18.14.orig/drivers/scsi/fcoe/fcoe_ctlr.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/scsi/fcoe/fcoe_ctlr.c 2015-05-31 15:32:47.681635374 -0500 @@ -831,7 +831,7 @@ INIT_LIST_HEAD(&del_list); @@ -6550,9 +10178,9 @@ diff -Nur linux-3.18.12.orig/drivers/scsi/fcoe/fcoe_ctlr.c linux-3.18.12/drivers list_for_each_entry_safe(fcf, next, &del_list, list) { /* Removes fcf from current list */ -diff -Nur linux-3.18.12.orig/drivers/scsi/libfc/fc_exch.c linux-3.18.12/drivers/scsi/libfc/fc_exch.c ---- linux-3.18.12.orig/drivers/scsi/libfc/fc_exch.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/scsi/libfc/fc_exch.c 2015-04-26 13:32:22.403684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/scsi/libfc/fc_exch.c linux-3.18.14-rt/drivers/scsi/libfc/fc_exch.c +--- linux-3.18.14.orig/drivers/scsi/libfc/fc_exch.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/scsi/libfc/fc_exch.c 2015-05-31 15:32:47.689635374 -0500 @@ -816,10 +816,10 @@ } memset(ep, 0, sizeof(*ep)); @@ -6566,9 +10194,9 @@ diff -Nur linux-3.18.12.orig/drivers/scsi/libfc/fc_exch.c linux-3.18.12/drivers/ /* peek cache of free slot */ if (pool->left != FC_XID_UNKNOWN) { -diff -Nur linux-3.18.12.orig/drivers/scsi/libsas/sas_ata.c linux-3.18.12/drivers/scsi/libsas/sas_ata.c ---- linux-3.18.12.orig/drivers/scsi/libsas/sas_ata.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/scsi/libsas/sas_ata.c 2015-04-26 13:32:22.407684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/scsi/libsas/sas_ata.c linux-3.18.14-rt/drivers/scsi/libsas/sas_ata.c +--- linux-3.18.14.orig/drivers/scsi/libsas/sas_ata.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/scsi/libsas/sas_ata.c 2015-05-31 15:32:47.689635374 -0500 @@ -191,7 +191,7 @@ /* TODO: audit callers to ensure they are ready for qc_issue to * unconditionally re-enable interrupts @@ -6587,9 +10215,9 @@ diff -Nur linux-3.18.12.orig/drivers/scsi/libsas/sas_ata.c linux-3.18.12/drivers return ret; } -diff -Nur linux-3.18.12.orig/drivers/scsi/qla2xxx/qla_inline.h linux-3.18.12/drivers/scsi/qla2xxx/qla_inline.h ---- linux-3.18.12.orig/drivers/scsi/qla2xxx/qla_inline.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/scsi/qla2xxx/qla_inline.h 2015-04-26 13:32:22.407684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/scsi/qla2xxx/qla_inline.h linux-3.18.14-rt/drivers/scsi/qla2xxx/qla_inline.h +--- linux-3.18.14.orig/drivers/scsi/qla2xxx/qla_inline.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/scsi/qla2xxx/qla_inline.h 2015-05-31 15:32:47.693635374 -0500 @@ -59,12 +59,12 @@ { unsigned long flags; @@ -6605,9 +10233,9 @@ diff -Nur linux-3.18.12.orig/drivers/scsi/qla2xxx/qla_inline.h linux-3.18.12/dri } static inline uint8_t * -diff -Nur linux-3.18.12.orig/drivers/thermal/x86_pkg_temp_thermal.c linux-3.18.12/drivers/thermal/x86_pkg_temp_thermal.c ---- linux-3.18.12.orig/drivers/thermal/x86_pkg_temp_thermal.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/thermal/x86_pkg_temp_thermal.c 2015-04-26 13:32:22.407684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/thermal/x86_pkg_temp_thermal.c linux-3.18.14-rt/drivers/thermal/x86_pkg_temp_thermal.c +--- linux-3.18.14.orig/drivers/thermal/x86_pkg_temp_thermal.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/thermal/x86_pkg_temp_thermal.c 2015-05-31 15:32:47.701635374 -0500 @@ -29,6 +29,7 @@ #include <linux/pm.h> #include <linux/thermal.h> @@ -6710,9 +10338,9 @@ diff -Nur linux-3.18.12.orig/drivers/thermal/x86_pkg_temp_thermal.c linux-3.18.1 for_each_online_cpu(i) cancel_delayed_work_sync( &per_cpu(pkg_temp_thermal_threshold_work, i)); -diff -Nur linux-3.18.12.orig/drivers/tty/serial/8250/8250_core.c linux-3.18.12/drivers/tty/serial/8250/8250_core.c ---- linux-3.18.12.orig/drivers/tty/serial/8250/8250_core.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/tty/serial/8250/8250_core.c 2015-04-26 13:32:22.407684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/tty/serial/8250/8250_core.c linux-3.18.14-rt/drivers/tty/serial/8250/8250_core.c +--- linux-3.18.14.orig/drivers/tty/serial/8250/8250_core.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/tty/serial/8250/8250_core.c 2015-05-31 15:32:47.753635373 -0500 @@ -37,6 +37,7 @@ #include <linux/nmi.h> #include <linux/mutex.h> @@ -6748,9 +10376,9 @@ diff -Nur linux-3.18.12.orig/drivers/tty/serial/8250/8250_core.c linux-3.18.12/d locked = spin_trylock_irqsave(&port->lock, flags); else spin_lock_irqsave(&port->lock, flags); -diff -Nur linux-3.18.12.orig/drivers/tty/serial/amba-pl011.c linux-3.18.12/drivers/tty/serial/amba-pl011.c ---- linux-3.18.12.orig/drivers/tty/serial/amba-pl011.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/tty/serial/amba-pl011.c 2015-04-26 13:32:22.407684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/tty/serial/amba-pl011.c linux-3.18.14-rt/drivers/tty/serial/amba-pl011.c +--- linux-3.18.14.orig/drivers/tty/serial/amba-pl011.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/tty/serial/amba-pl011.c 2015-05-31 15:32:47.777635373 -0500 @@ -1935,13 +1935,19 @@ clk_enable(uap->clk); @@ -6784,9 +10412,9 @@ diff -Nur linux-3.18.12.orig/drivers/tty/serial/amba-pl011.c linux-3.18.12/drive clk_disable(uap->clk); } -diff -Nur linux-3.18.12.orig/drivers/tty/serial/omap-serial.c linux-3.18.12/drivers/tty/serial/omap-serial.c ---- linux-3.18.12.orig/drivers/tty/serial/omap-serial.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/tty/serial/omap-serial.c 2015-04-26 13:32:22.407684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/tty/serial/omap-serial.c linux-3.18.14-rt/drivers/tty/serial/omap-serial.c +--- linux-3.18.14.orig/drivers/tty/serial/omap-serial.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/tty/serial/omap-serial.c 2015-05-31 15:32:47.781635373 -0500 @@ -1270,13 +1270,10 @@ pm_runtime_get_sync(up->dev); @@ -6814,9 +10442,9 @@ diff -Nur linux-3.18.12.orig/drivers/tty/serial/omap-serial.c linux-3.18.12/driv } static int __init -diff -Nur linux-3.18.12.orig/drivers/usb/core/hcd.c linux-3.18.12/drivers/usb/core/hcd.c ---- linux-3.18.12.orig/drivers/usb/core/hcd.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/usb/core/hcd.c 2015-04-26 13:32:22.407684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/usb/core/hcd.c linux-3.18.14-rt/drivers/usb/core/hcd.c +--- linux-3.18.14.orig/drivers/usb/core/hcd.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/usb/core/hcd.c 2015-05-31 15:32:47.785635373 -0500 @@ -1681,9 +1681,9 @@ * and no one may trigger the above deadlock situation when * running complete() in tasklet. @@ -6829,9 +10457,9 @@ diff -Nur linux-3.18.12.orig/drivers/usb/core/hcd.c linux-3.18.12/drivers/usb/co usb_anchor_resume_wakeups(anchor); atomic_dec(&urb->use_count); -diff -Nur linux-3.18.12.orig/drivers/usb/gadget/function/f_fs.c linux-3.18.12/drivers/usb/gadget/function/f_fs.c ---- linux-3.18.12.orig/drivers/usb/gadget/function/f_fs.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/usb/gadget/function/f_fs.c 2015-04-26 13:32:22.407684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/usb/gadget/function/f_fs.c linux-3.18.14-rt/drivers/usb/gadget/function/f_fs.c +--- linux-3.18.14.orig/drivers/usb/gadget/function/f_fs.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/usb/gadget/function/f_fs.c 2015-05-31 15:32:47.809635373 -0500 @@ -1428,7 +1428,7 @@ pr_info("%s(): freeing\n", __func__); ffs_data_clear(ffs); @@ -6841,9 +10469,9 @@ diff -Nur linux-3.18.12.orig/drivers/usb/gadget/function/f_fs.c linux-3.18.12/dr kfree(ffs->dev_name); kfree(ffs); } -diff -Nur linux-3.18.12.orig/drivers/usb/gadget/legacy/inode.c linux-3.18.12/drivers/usb/gadget/legacy/inode.c ---- linux-3.18.12.orig/drivers/usb/gadget/legacy/inode.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/drivers/usb/gadget/legacy/inode.c 2015-04-26 13:32:22.407684003 -0500 +diff -Nur linux-3.18.14.orig/drivers/usb/gadget/legacy/inode.c linux-3.18.14-rt/drivers/usb/gadget/legacy/inode.c +--- linux-3.18.14.orig/drivers/usb/gadget/legacy/inode.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/drivers/usb/gadget/legacy/inode.c 2015-05-31 15:32:47.837635372 -0500 @@ -339,7 +339,7 @@ spin_unlock_irq (&epdata->dev->lock); @@ -6862,9 +10490,9 @@ diff -Nur linux-3.18.12.orig/drivers/usb/gadget/legacy/inode.c linux-3.18.12/dri if (epdata->status == -ECONNRESET) epdata->status = -EINTR; } else { -diff -Nur linux-3.18.12.orig/fs/aio.c linux-3.18.12/fs/aio.c ---- linux-3.18.12.orig/fs/aio.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/fs/aio.c 2015-04-26 13:32:22.407684003 -0500 +diff -Nur linux-3.18.14.orig/fs/aio.c linux-3.18.14-rt/fs/aio.c +--- linux-3.18.14.orig/fs/aio.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/fs/aio.c 2015-05-31 15:32:47.853635372 -0500 @@ -40,6 +40,7 @@ #include <linux/ramfs.h> #include <linux/percpu-refcount.h> @@ -6940,9 +10568,9 @@ diff -Nur linux-3.18.12.orig/fs/aio.c linux-3.18.12/fs/aio.c static int ioctx_add_table(struct kioctx *ctx, struct mm_struct *mm) { unsigned i, new_nr; -diff -Nur linux-3.18.12.orig/fs/autofs4/autofs_i.h linux-3.18.12/fs/autofs4/autofs_i.h ---- linux-3.18.12.orig/fs/autofs4/autofs_i.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/fs/autofs4/autofs_i.h 2015-04-26 13:32:22.411684003 -0500 +diff -Nur linux-3.18.14.orig/fs/autofs4/autofs_i.h linux-3.18.14-rt/fs/autofs4/autofs_i.h +--- linux-3.18.14.orig/fs/autofs4/autofs_i.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/fs/autofs4/autofs_i.h 2015-05-31 15:32:47.865635372 -0500 @@ -34,6 +34,7 @@ #include <linux/sched.h> #include <linux/mount.h> @@ -6951,9 +10579,9 @@ diff -Nur linux-3.18.12.orig/fs/autofs4/autofs_i.h linux-3.18.12/fs/autofs4/auto #include <asm/current.h> #include <asm/uaccess.h> -diff -Nur linux-3.18.12.orig/fs/autofs4/expire.c linux-3.18.12/fs/autofs4/expire.c ---- linux-3.18.12.orig/fs/autofs4/expire.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/fs/autofs4/expire.c 2015-04-26 13:32:22.411684003 -0500 +diff -Nur linux-3.18.14.orig/fs/autofs4/expire.c linux-3.18.14-rt/fs/autofs4/expire.c +--- linux-3.18.14.orig/fs/autofs4/expire.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/fs/autofs4/expire.c 2015-05-31 15:32:47.897635372 -0500 @@ -151,7 +151,7 @@ parent = p->d_parent; if (!spin_trylock(&parent->d_lock)) { @@ -6963,9 +10591,9 @@ diff -Nur linux-3.18.12.orig/fs/autofs4/expire.c linux-3.18.12/fs/autofs4/expire goto relock; } spin_unlock(&p->d_lock); -diff -Nur linux-3.18.12.orig/fs/buffer.c linux-3.18.12/fs/buffer.c ---- linux-3.18.12.orig/fs/buffer.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/fs/buffer.c 2015-04-26 13:32:22.411684003 -0500 +diff -Nur linux-3.18.14.orig/fs/buffer.c linux-3.18.14-rt/fs/buffer.c +--- linux-3.18.14.orig/fs/buffer.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/fs/buffer.c 2015-05-31 15:32:47.905635372 -0500 @@ -301,8 +301,7 @@ * decide that the page is now completely done. */ @@ -7033,9 +10661,9 @@ diff -Nur linux-3.18.12.orig/fs/buffer.c linux-3.18.12/fs/buffer.c preempt_disable(); __this_cpu_inc(bh_accounting.nr); recalc_bh_state(); -diff -Nur linux-3.18.12.orig/fs/dcache.c linux-3.18.12/fs/dcache.c ---- linux-3.18.12.orig/fs/dcache.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/fs/dcache.c 2015-04-26 13:32:22.411684003 -0500 +diff -Nur linux-3.18.14.orig/fs/dcache.c linux-3.18.14-rt/fs/dcache.c +--- linux-3.18.14.orig/fs/dcache.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/fs/dcache.c 2015-05-31 15:32:47.929635371 -0500 @@ -19,6 +19,7 @@ #include <linux/mm.h> #include <linux/fs.h> @@ -7062,9 +10690,9 @@ diff -Nur linux-3.18.12.orig/fs/dcache.c linux-3.18.12/fs/dcache.c goto again; } dentry->d_flags &= ~DCACHE_CANT_MOUNT; -diff -Nur linux-3.18.12.orig/fs/eventpoll.c linux-3.18.12/fs/eventpoll.c ---- linux-3.18.12.orig/fs/eventpoll.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/fs/eventpoll.c 2015-04-26 13:32:22.411684003 -0500 +diff -Nur linux-3.18.14.orig/fs/eventpoll.c linux-3.18.14-rt/fs/eventpoll.c +--- linux-3.18.14.orig/fs/eventpoll.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/fs/eventpoll.c 2015-05-31 15:32:47.945635371 -0500 @@ -505,12 +505,12 @@ */ static void ep_poll_safewake(wait_queue_head_t *wq) @@ -7080,9 +10708,9 @@ diff -Nur linux-3.18.12.orig/fs/eventpoll.c linux-3.18.12/fs/eventpoll.c } static void ep_remove_wait_queue(struct eppoll_entry *pwq) -diff -Nur linux-3.18.12.orig/fs/exec.c linux-3.18.12/fs/exec.c ---- linux-3.18.12.orig/fs/exec.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/fs/exec.c 2015-04-26 13:32:22.411684003 -0500 +diff -Nur linux-3.18.14.orig/fs/exec.c linux-3.18.14-rt/fs/exec.c +--- linux-3.18.14.orig/fs/exec.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/fs/exec.c 2015-05-31 15:32:47.945635371 -0500 @@ -841,12 +841,14 @@ } } @@ -7098,9 +10726,9 @@ diff -Nur linux-3.18.12.orig/fs/exec.c linux-3.18.12/fs/exec.c task_unlock(tsk); if (old_mm) { up_read(&old_mm->mmap_sem); -diff -Nur linux-3.18.12.orig/fs/jbd/checkpoint.c linux-3.18.12/fs/jbd/checkpoint.c ---- linux-3.18.12.orig/fs/jbd/checkpoint.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/fs/jbd/checkpoint.c 2015-04-26 13:32:22.411684003 -0500 +diff -Nur linux-3.18.14.orig/fs/jbd/checkpoint.c linux-3.18.14-rt/fs/jbd/checkpoint.c +--- linux-3.18.14.orig/fs/jbd/checkpoint.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/fs/jbd/checkpoint.c 2015-05-31 15:32:47.957635371 -0500 @@ -129,6 +129,8 @@ if (journal->j_flags & JFS_ABORT) return; @@ -7110,9 +10738,9 @@ diff -Nur linux-3.18.12.orig/fs/jbd/checkpoint.c linux-3.18.12/fs/jbd/checkpoint mutex_lock(&journal->j_checkpoint_mutex); /* -diff -Nur linux-3.18.12.orig/fs/jbd2/checkpoint.c linux-3.18.12/fs/jbd2/checkpoint.c ---- linux-3.18.12.orig/fs/jbd2/checkpoint.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/fs/jbd2/checkpoint.c 2015-04-26 13:32:22.411684003 -0500 +diff -Nur linux-3.18.14.orig/fs/jbd2/checkpoint.c linux-3.18.14-rt/fs/jbd2/checkpoint.c +--- linux-3.18.14.orig/fs/jbd2/checkpoint.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/fs/jbd2/checkpoint.c 2015-05-31 15:32:47.969635371 -0500 @@ -116,6 +116,8 @@ nblocks = jbd2_space_needed(journal); while (jbd2_log_space_left(journal) < nblocks) { @@ -7122,9 +10750,9 @@ diff -Nur linux-3.18.12.orig/fs/jbd2/checkpoint.c linux-3.18.12/fs/jbd2/checkpoi mutex_lock(&journal->j_checkpoint_mutex); /* -diff -Nur linux-3.18.12.orig/fs/namespace.c linux-3.18.12/fs/namespace.c ---- linux-3.18.12.orig/fs/namespace.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/fs/namespace.c 2015-04-26 13:32:22.411684003 -0500 +diff -Nur linux-3.18.14.orig/fs/namespace.c linux-3.18.14-rt/fs/namespace.c +--- linux-3.18.14.orig/fs/namespace.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/fs/namespace.c 2015-05-31 15:32:47.969635371 -0500 @@ -14,6 +14,7 @@ #include <linux/mnt_namespace.h> #include <linux/user_namespace.h> @@ -7147,9 +10775,9 @@ diff -Nur linux-3.18.12.orig/fs/namespace.c linux-3.18.12/fs/namespace.c /* * After the slowpath clears MNT_WRITE_HOLD, mnt_is_readonly will * be set to match its requirements. So we must not load that until -diff -Nur linux-3.18.12.orig/fs/ntfs/aops.c linux-3.18.12/fs/ntfs/aops.c ---- linux-3.18.12.orig/fs/ntfs/aops.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/fs/ntfs/aops.c 2015-04-26 13:32:22.411684003 -0500 +diff -Nur linux-3.18.14.orig/fs/ntfs/aops.c linux-3.18.14-rt/fs/ntfs/aops.c +--- linux-3.18.14.orig/fs/ntfs/aops.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/fs/ntfs/aops.c 2015-05-31 15:32:47.969635371 -0500 @@ -107,8 +107,7 @@ "0x%llx.", (unsigned long long)bh->b_blocknr); } @@ -7197,9 +10825,9 @@ diff -Nur linux-3.18.12.orig/fs/ntfs/aops.c linux-3.18.12/fs/ntfs/aops.c } /** -diff -Nur linux-3.18.12.orig/fs/timerfd.c linux-3.18.12/fs/timerfd.c ---- linux-3.18.12.orig/fs/timerfd.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/fs/timerfd.c 2015-04-26 13:32:22.411684003 -0500 +diff -Nur linux-3.18.14.orig/fs/timerfd.c linux-3.18.14-rt/fs/timerfd.c +--- linux-3.18.14.orig/fs/timerfd.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/fs/timerfd.c 2015-05-31 15:32:47.969635371 -0500 @@ -449,7 +449,10 @@ break; } @@ -7212,9 +10840,21 @@ diff -Nur linux-3.18.12.orig/fs/timerfd.c linux-3.18.12/fs/timerfd.c } /* -diff -Nur linux-3.18.12.orig/include/acpi/platform/aclinux.h linux-3.18.12/include/acpi/platform/aclinux.h ---- linux-3.18.12.orig/include/acpi/platform/aclinux.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/acpi/platform/aclinux.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/fs/xfs/xfs_linux.h linux-3.18.14-rt/fs/xfs/xfs_linux.h +--- linux-3.18.14.orig/fs/xfs/xfs_linux.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/fs/xfs/xfs_linux.h 2015-05-31 15:32:47.989635371 -0500 +@@ -119,7 +119,7 @@ + /* + * Feature macros (disable/enable) + */ +-#ifdef CONFIG_SMP ++#if defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_RT_FULL) + #define HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ + #else + #undef HAVE_PERCPU_SB /* per cpu superblock counters are a 2.6 feature */ +diff -Nur linux-3.18.14.orig/include/acpi/platform/aclinux.h linux-3.18.14-rt/include/acpi/platform/aclinux.h +--- linux-3.18.14.orig/include/acpi/platform/aclinux.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/acpi/platform/aclinux.h 2015-05-31 15:32:48.013635371 -0500 @@ -123,6 +123,7 @@ #define acpi_cache_t struct kmem_cache @@ -7244,9 +10884,9 @@ diff -Nur linux-3.18.12.orig/include/acpi/platform/aclinux.h linux-3.18.12/inclu /* * OSL interfaces used by debugger/disassembler */ -diff -Nur linux-3.18.12.orig/include/asm-generic/bug.h linux-3.18.12/include/asm-generic/bug.h ---- linux-3.18.12.orig/include/asm-generic/bug.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/asm-generic/bug.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/asm-generic/bug.h linux-3.18.14-rt/include/asm-generic/bug.h +--- linux-3.18.14.orig/include/asm-generic/bug.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/asm-generic/bug.h 2015-05-31 15:32:48.037635370 -0500 @@ -206,6 +206,20 @@ # define WARN_ON_SMP(x) ({0;}) #endif @@ -7268,9 +10908,9 @@ diff -Nur linux-3.18.12.orig/include/asm-generic/bug.h linux-3.18.12/include/asm #endif /* __ASSEMBLY__ */ #endif -diff -Nur linux-3.18.12.orig/include/linux/blkdev.h linux-3.18.12/include/linux/blkdev.h ---- linux-3.18.12.orig/include/linux/blkdev.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/blkdev.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/blkdev.h linux-3.18.14-rt/include/linux/blkdev.h +--- linux-3.18.14.orig/include/linux/blkdev.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/blkdev.h 2015-05-31 15:32:48.077635370 -0500 @@ -101,6 +101,7 @@ struct list_head queuelist; union { @@ -7288,9 +10928,9 @@ diff -Nur linux-3.18.12.orig/include/linux/blkdev.h linux-3.18.12/include/linux/ struct percpu_ref mq_usage_counter; struct list_head all_q_node; -diff -Nur linux-3.18.12.orig/include/linux/blk-mq.h linux-3.18.12/include/linux/blk-mq.h ---- linux-3.18.12.orig/include/linux/blk-mq.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/blk-mq.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/blk-mq.h linux-3.18.14-rt/include/linux/blk-mq.h +--- linux-3.18.14.orig/include/linux/blk-mq.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/blk-mq.h 2015-05-31 15:32:48.069635370 -0500 @@ -169,6 +169,7 @@ struct blk_mq_hw_ctx *blk_mq_map_queue(struct request_queue *, const int ctx_index); @@ -7299,9 +10939,9 @@ diff -Nur linux-3.18.12.orig/include/linux/blk-mq.h linux-3.18.12/include/linux/ void blk_mq_start_request(struct request *rq); void blk_mq_end_request(struct request *rq, int error); -diff -Nur linux-3.18.12.orig/include/linux/bottom_half.h linux-3.18.12/include/linux/bottom_half.h ---- linux-3.18.12.orig/include/linux/bottom_half.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/bottom_half.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/bottom_half.h linux-3.18.14-rt/include/linux/bottom_half.h +--- linux-3.18.14.orig/include/linux/bottom_half.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/bottom_half.h 2015-05-31 15:32:48.081635370 -0500 @@ -4,6 +4,17 @@ #include <linux/preempt.h> #include <linux/preempt_mask.h> @@ -7327,9 +10967,9 @@ diff -Nur linux-3.18.12.orig/include/linux/bottom_half.h linux-3.18.12/include/l +#endif #endif /* _LINUX_BH_H */ -diff -Nur linux-3.18.12.orig/include/linux/buffer_head.h linux-3.18.12/include/linux/buffer_head.h ---- linux-3.18.12.orig/include/linux/buffer_head.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/buffer_head.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/buffer_head.h linux-3.18.14-rt/include/linux/buffer_head.h +--- linux-3.18.14.orig/include/linux/buffer_head.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/buffer_head.h 2015-05-31 15:32:48.109635370 -0500 @@ -75,8 +75,52 @@ struct address_space *b_assoc_map; /* mapping this buffer is associated with */ @@ -7383,9 +11023,9 @@ diff -Nur linux-3.18.12.orig/include/linux/buffer_head.h linux-3.18.12/include/l /* * macro tricks to expand the set_buffer_foo(), clear_buffer_foo() * and buffer_foo() functions. -diff -Nur linux-3.18.12.orig/include/linux/cgroup.h linux-3.18.12/include/linux/cgroup.h ---- linux-3.18.12.orig/include/linux/cgroup.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/cgroup.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/cgroup.h linux-3.18.14-rt/include/linux/cgroup.h +--- linux-3.18.14.orig/include/linux/cgroup.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/cgroup.h 2015-05-31 15:32:48.117635370 -0500 @@ -22,6 +22,7 @@ #include <linux/seq_file.h> #include <linux/kernfs.h> @@ -7402,9 +11042,9 @@ diff -Nur linux-3.18.12.orig/include/linux/cgroup.h linux-3.18.12/include/linux/ }; /* bits in struct cgroup_subsys_state flags field */ -diff -Nur linux-3.18.12.orig/include/linux/completion.h linux-3.18.12/include/linux/completion.h ---- linux-3.18.12.orig/include/linux/completion.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/completion.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/completion.h linux-3.18.14-rt/include/linux/completion.h +--- linux-3.18.14.orig/include/linux/completion.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/completion.h 2015-05-31 15:32:48.117635370 -0500 @@ -7,8 +7,7 @@ * Atomic wait-for-completion handler data structures. * See kernel/sched/completion.c for details. @@ -7438,9 +11078,9 @@ diff -Nur linux-3.18.12.orig/include/linux/completion.h linux-3.18.12/include/li } /** -diff -Nur linux-3.18.12.orig/include/linux/cpu.h linux-3.18.12/include/linux/cpu.h ---- linux-3.18.12.orig/include/linux/cpu.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/cpu.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/cpu.h linux-3.18.14-rt/include/linux/cpu.h +--- linux-3.18.14.orig/include/linux/cpu.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/cpu.h 2015-05-31 15:32:48.129635370 -0500 @@ -217,6 +217,8 @@ extern void put_online_cpus(void); extern void cpu_hotplug_disable(void); @@ -7459,9 +11099,9 @@ diff -Nur linux-3.18.12.orig/include/linux/cpu.h linux-3.18.12/include/linux/cpu #define hotcpu_notifier(fn, pri) do { (void)(fn); } while (0) #define __hotcpu_notifier(fn, pri) do { (void)(fn); } while (0) /* These aren't inline functions due to a GCC bug. */ -diff -Nur linux-3.18.12.orig/include/linux/delay.h linux-3.18.12/include/linux/delay.h ---- linux-3.18.12.orig/include/linux/delay.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/delay.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/delay.h linux-3.18.14-rt/include/linux/delay.h +--- linux-3.18.14.orig/include/linux/delay.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/delay.h 2015-05-31 15:32:48.129635370 -0500 @@ -52,4 +52,10 @@ msleep(seconds * 1000); } @@ -7473,9 +11113,9 @@ diff -Nur linux-3.18.12.orig/include/linux/delay.h linux-3.18.12/include/linux/d +#endif + #endif /* defined(_LINUX_DELAY_H) */ -diff -Nur linux-3.18.12.orig/include/linux/ftrace_event.h linux-3.18.12/include/linux/ftrace_event.h ---- linux-3.18.12.orig/include/linux/ftrace_event.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/ftrace_event.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/ftrace_event.h linux-3.18.14-rt/include/linux/ftrace_event.h +--- linux-3.18.14.orig/include/linux/ftrace_event.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/ftrace_event.h 2015-05-31 15:32:48.157635370 -0500 @@ -61,6 +61,9 @@ unsigned char flags; unsigned char preempt_count; @@ -7486,9 +11126,9 @@ diff -Nur linux-3.18.12.orig/include/linux/ftrace_event.h linux-3.18.12/include/ }; #define FTRACE_MAX_EVENT \ -diff -Nur linux-3.18.12.orig/include/linux/highmem.h linux-3.18.12/include/linux/highmem.h ---- linux-3.18.12.orig/include/linux/highmem.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/highmem.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/highmem.h linux-3.18.14-rt/include/linux/highmem.h +--- linux-3.18.14.orig/include/linux/highmem.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/highmem.h 2015-05-31 15:32:48.157635370 -0500 @@ -7,6 +7,7 @@ #include <linux/mm.h> #include <linux/uaccess.h> @@ -7553,9 +11193,9 @@ diff -Nur linux-3.18.12.orig/include/linux/highmem.h linux-3.18.12/include/linux #endif } -diff -Nur linux-3.18.12.orig/include/linux/hrtimer.h linux-3.18.12/include/linux/hrtimer.h ---- linux-3.18.12.orig/include/linux/hrtimer.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/hrtimer.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/hrtimer.h linux-3.18.14-rt/include/linux/hrtimer.h +--- linux-3.18.14.orig/include/linux/hrtimer.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/hrtimer.h 2015-05-31 15:32:48.161635369 -0500 @@ -111,6 +111,11 @@ enum hrtimer_restart (*function)(struct hrtimer *); struct hrtimer_clock_base *base; @@ -7600,9 +11240,9 @@ diff -Nur linux-3.18.12.orig/include/linux/hrtimer.h linux-3.18.12/include/linux /* Query timers: */ extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer); extern int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp); -diff -Nur linux-3.18.12.orig/include/linux/idr.h linux-3.18.12/include/linux/idr.h ---- linux-3.18.12.orig/include/linux/idr.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/idr.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/idr.h linux-3.18.14-rt/include/linux/idr.h +--- linux-3.18.14.orig/include/linux/idr.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/idr.h 2015-05-31 15:32:48.161635369 -0500 @@ -95,10 +95,14 @@ * Each idr_preload() should be matched with an invocation of this * function. See idr_preload() for details. @@ -7618,9 +11258,9 @@ diff -Nur linux-3.18.12.orig/include/linux/idr.h linux-3.18.12/include/linux/idr /** * idr_find - return pointer for given id -diff -Nur linux-3.18.12.orig/include/linux/init_task.h linux-3.18.12/include/linux/init_task.h ---- linux-3.18.12.orig/include/linux/init_task.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/init_task.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/init_task.h linux-3.18.14-rt/include/linux/init_task.h +--- linux-3.18.14.orig/include/linux/init_task.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/init_task.h 2015-05-31 15:32:48.177635369 -0500 @@ -147,9 +147,16 @@ # define INIT_PERF_EVENTS(tsk) #endif @@ -7647,9 +11287,9 @@ diff -Nur linux-3.18.12.orig/include/linux/init_task.h linux-3.18.12/include/lin .pids = { \ [PIDTYPE_PID] = INIT_PID_LINK(PIDTYPE_PID), \ [PIDTYPE_PGID] = INIT_PID_LINK(PIDTYPE_PGID), \ -diff -Nur linux-3.18.12.orig/include/linux/interrupt.h linux-3.18.12/include/linux/interrupt.h ---- linux-3.18.12.orig/include/linux/interrupt.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/interrupt.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/interrupt.h linux-3.18.14-rt/include/linux/interrupt.h +--- linux-3.18.14.orig/include/linux/interrupt.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/interrupt.h 2015-05-31 15:32:48.181635369 -0500 @@ -57,6 +57,7 @@ * IRQF_NO_THREAD - Interrupt cannot be threaded * IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device @@ -7816,9 +11456,9 @@ diff -Nur linux-3.18.12.orig/include/linux/interrupt.h linux-3.18.12/include/lin /* * Autoprobing for irqs: * -diff -Nur linux-3.18.12.orig/include/linux/irqdesc.h linux-3.18.12/include/linux/irqdesc.h ---- linux-3.18.12.orig/include/linux/irqdesc.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/irqdesc.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/irqdesc.h linux-3.18.14-rt/include/linux/irqdesc.h +--- linux-3.18.14.orig/include/linux/irqdesc.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/irqdesc.h 2015-05-31 15:32:48.217635369 -0500 @@ -63,6 +63,7 @@ unsigned int irqs_unhandled; atomic_t threads_handled; @@ -7827,9 +11467,9 @@ diff -Nur linux-3.18.12.orig/include/linux/irqdesc.h linux-3.18.12/include/linux raw_spinlock_t lock; struct cpumask *percpu_enabled; #ifdef CONFIG_SMP -diff -Nur linux-3.18.12.orig/include/linux/irqflags.h linux-3.18.12/include/linux/irqflags.h ---- linux-3.18.12.orig/include/linux/irqflags.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/irqflags.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/irqflags.h linux-3.18.14-rt/include/linux/irqflags.h +--- linux-3.18.14.orig/include/linux/irqflags.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/irqflags.h 2015-05-31 15:32:48.233635369 -0500 @@ -25,8 +25,6 @@ # define trace_softirqs_enabled(p) ((p)->softirqs_enabled) # define trace_hardirq_enter() do { current->hardirq_context++; } while (0) @@ -7880,9 +11520,9 @@ diff -Nur linux-3.18.12.orig/include/linux/irqflags.h linux-3.18.12/include/linu +#endif + #endif -diff -Nur linux-3.18.12.orig/include/linux/irq.h linux-3.18.12/include/linux/irq.h ---- linux-3.18.12.orig/include/linux/irq.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/irq.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/irq.h linux-3.18.14-rt/include/linux/irq.h +--- linux-3.18.14.orig/include/linux/irq.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/irq.h 2015-05-31 15:32:48.185635369 -0500 @@ -73,6 +73,7 @@ * IRQ_IS_POLLED - Always polled by another interrupt. Exclude * it from the spurious interrupt detection @@ -7907,9 +11547,9 @@ diff -Nur linux-3.18.12.orig/include/linux/irq.h linux-3.18.12/include/linux/irq #define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING) -diff -Nur linux-3.18.12.orig/include/linux/irq_work.h linux-3.18.12/include/linux/irq_work.h ---- linux-3.18.12.orig/include/linux/irq_work.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/irq_work.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/irq_work.h linux-3.18.14-rt/include/linux/irq_work.h +--- linux-3.18.14.orig/include/linux/irq_work.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/irq_work.h 2015-05-31 15:32:48.217635369 -0500 @@ -16,6 +16,7 @@ #define IRQ_WORK_BUSY 2UL #define IRQ_WORK_FLAGS 3UL @@ -7918,9 +11558,9 @@ diff -Nur linux-3.18.12.orig/include/linux/irq_work.h linux-3.18.12/include/linu struct irq_work { unsigned long flags; -diff -Nur linux-3.18.12.orig/include/linux/jbd_common.h linux-3.18.12/include/linux/jbd_common.h ---- linux-3.18.12.orig/include/linux/jbd_common.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/jbd_common.h 2015-04-26 13:32:22.415684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/jbd_common.h linux-3.18.14-rt/include/linux/jbd_common.h +--- linux-3.18.14.orig/include/linux/jbd_common.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/jbd_common.h 2015-05-31 15:32:48.237635369 -0500 @@ -15,32 +15,56 @@ static inline void jbd_lock_bh_state(struct buffer_head *bh) @@ -7978,9 +11618,9 @@ diff -Nur linux-3.18.12.orig/include/linux/jbd_common.h linux-3.18.12/include/li } #endif -diff -Nur linux-3.18.12.orig/include/linux/jump_label.h linux-3.18.12/include/linux/jump_label.h ---- linux-3.18.12.orig/include/linux/jump_label.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/jump_label.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/jump_label.h linux-3.18.14-rt/include/linux/jump_label.h +--- linux-3.18.14.orig/include/linux/jump_label.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/jump_label.h 2015-05-31 15:32:48.237635369 -0500 @@ -55,7 +55,8 @@ "%s used before call to jump_label_init", \ __func__) @@ -7991,9 +11631,9 @@ diff -Nur linux-3.18.12.orig/include/linux/jump_label.h linux-3.18.12/include/li struct static_key { atomic_t enabled; -diff -Nur linux-3.18.12.orig/include/linux/kdb.h linux-3.18.12/include/linux/kdb.h ---- linux-3.18.12.orig/include/linux/kdb.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/kdb.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/kdb.h linux-3.18.14-rt/include/linux/kdb.h +--- linux-3.18.14.orig/include/linux/kdb.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/kdb.h 2015-05-31 15:32:48.245635369 -0500 @@ -116,7 +116,7 @@ extern __printf(1, 0) int vkdb_printf(const char *fmt, va_list args); extern __printf(1, 2) int kdb_printf(const char *, ...); @@ -8011,9 +11651,9 @@ diff -Nur linux-3.18.12.orig/include/linux/kdb.h linux-3.18.12/include/linux/kdb static inline void kdb_init(int level) {} static inline int kdb_register(char *cmd, kdb_func_t func, char *usage, char *help, short minlen) { return 0; } -diff -Nur linux-3.18.12.orig/include/linux/kernel.h linux-3.18.12/include/linux/kernel.h ---- linux-3.18.12.orig/include/linux/kernel.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/kernel.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/kernel.h linux-3.18.14-rt/include/linux/kernel.h +--- linux-3.18.14.orig/include/linux/kernel.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/kernel.h 2015-05-31 15:32:48.245635369 -0500 @@ -451,6 +451,7 @@ SYSTEM_HALT, SYSTEM_POWER_OFF, @@ -8022,10 +11662,10 @@ diff -Nur linux-3.18.12.orig/include/linux/kernel.h linux-3.18.12/include/linux/ } system_state; #define TAINT_PROPRIETARY_MODULE 0 -diff -Nur linux-3.18.12.orig/include/linux/kvm_host.h linux-3.18.12/include/linux/kvm_host.h ---- linux-3.18.12.orig/include/linux/kvm_host.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/kvm_host.h 2015-04-26 13:32:22.419684003 -0500 -@@ -244,7 +244,7 @@ +diff -Nur linux-3.18.14.orig/include/linux/kvm_host.h linux-3.18.14-rt/include/linux/kvm_host.h +--- linux-3.18.14.orig/include/linux/kvm_host.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/kvm_host.h 2015-05-31 15:32:48.253635368 -0500 +@@ -245,7 +245,7 @@ int fpu_active; int guest_fpu_loaded, guest_xcr0_loaded; @@ -8034,7 +11674,7 @@ diff -Nur linux-3.18.12.orig/include/linux/kvm_host.h linux-3.18.12/include/linu struct pid *pid; int sigset_active; sigset_t sigset; -@@ -687,7 +687,7 @@ +@@ -688,7 +688,7 @@ } #endif @@ -8043,9 +11683,1124 @@ diff -Nur linux-3.18.12.orig/include/linux/kvm_host.h linux-3.18.12/include/linu { #ifdef __KVM_HAVE_ARCH_WQP return vcpu->arch.wqp; -diff -Nur linux-3.18.12.orig/include/linux/lglock.h linux-3.18.12/include/linux/lglock.h ---- linux-3.18.12.orig/include/linux/lglock.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/lglock.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/kvm_host.h.orig linux-3.18.14-rt/include/linux/kvm_host.h.orig +--- linux-3.18.14.orig/include/linux/kvm_host.h.orig 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/include/linux/kvm_host.h.orig 2015-05-20 10:04:50.000000000 -0500 +@@ -0,0 +1,1111 @@ ++#ifndef __KVM_HOST_H ++#define __KVM_HOST_H ++ ++/* ++ * This work is licensed under the terms of the GNU GPL, version 2. See ++ * the COPYING file in the top-level directory. ++ */ ++ ++#include <linux/types.h> ++#include <linux/hardirq.h> ++#include <linux/list.h> ++#include <linux/mutex.h> ++#include <linux/spinlock.h> ++#include <linux/signal.h> ++#include <linux/sched.h> ++#include <linux/bug.h> ++#include <linux/mm.h> ++#include <linux/mmu_notifier.h> ++#include <linux/preempt.h> ++#include <linux/msi.h> ++#include <linux/slab.h> ++#include <linux/rcupdate.h> ++#include <linux/ratelimit.h> ++#include <linux/err.h> ++#include <linux/irqflags.h> ++#include <linux/context_tracking.h> ++#include <asm/signal.h> ++ ++#include <linux/kvm.h> ++#include <linux/kvm_para.h> ++ ++#include <linux/kvm_types.h> ++ ++#include <asm/kvm_host.h> ++ ++#ifndef KVM_MMIO_SIZE ++#define KVM_MMIO_SIZE 8 ++#endif ++ ++/* ++ * The bit 16 ~ bit 31 of kvm_memory_region::flags are internally used ++ * in kvm, other bits are visible for userspace which are defined in ++ * include/linux/kvm_h. ++ */ ++#define KVM_MEMSLOT_INVALID (1UL << 16) ++#define KVM_MEMSLOT_INCOHERENT (1UL << 17) ++ ++/* Two fragments for cross MMIO pages. */ ++#define KVM_MAX_MMIO_FRAGMENTS 2 ++ ++/* ++ * For the normal pfn, the highest 12 bits should be zero, ++ * so we can mask bit 62 ~ bit 52 to indicate the error pfn, ++ * mask bit 63 to indicate the noslot pfn. ++ */ ++#define KVM_PFN_ERR_MASK (0x7ffULL << 52) ++#define KVM_PFN_ERR_NOSLOT_MASK (0xfffULL << 52) ++#define KVM_PFN_NOSLOT (0x1ULL << 63) ++ ++#define KVM_PFN_ERR_FAULT (KVM_PFN_ERR_MASK) ++#define KVM_PFN_ERR_HWPOISON (KVM_PFN_ERR_MASK + 1) ++#define KVM_PFN_ERR_RO_FAULT (KVM_PFN_ERR_MASK + 2) ++ ++/* ++ * error pfns indicate that the gfn is in slot but faild to ++ * translate it to pfn on host. ++ */ ++static inline bool is_error_pfn(pfn_t pfn) ++{ ++ return !!(pfn & KVM_PFN_ERR_MASK); ++} ++ ++/* ++ * error_noslot pfns indicate that the gfn can not be ++ * translated to pfn - it is not in slot or failed to ++ * translate it to pfn. ++ */ ++static inline bool is_error_noslot_pfn(pfn_t pfn) ++{ ++ return !!(pfn & KVM_PFN_ERR_NOSLOT_MASK); ++} ++ ++/* noslot pfn indicates that the gfn is not in slot. */ ++static inline bool is_noslot_pfn(pfn_t pfn) ++{ ++ return pfn == KVM_PFN_NOSLOT; ++} ++ ++/* ++ * architectures with KVM_HVA_ERR_BAD other than PAGE_OFFSET (e.g. s390) ++ * provide own defines and kvm_is_error_hva ++ */ ++#ifndef KVM_HVA_ERR_BAD ++ ++#define KVM_HVA_ERR_BAD (PAGE_OFFSET) ++#define KVM_HVA_ERR_RO_BAD (PAGE_OFFSET + PAGE_SIZE) ++ ++static inline bool kvm_is_error_hva(unsigned long addr) ++{ ++ return addr >= PAGE_OFFSET; ++} ++ ++#endif ++ ++#define KVM_ERR_PTR_BAD_PAGE (ERR_PTR(-ENOENT)) ++ ++static inline bool is_error_page(struct page *page) ++{ ++ return IS_ERR(page); ++} ++ ++/* ++ * vcpu->requests bit members ++ */ ++#define KVM_REQ_TLB_FLUSH 0 ++#define KVM_REQ_MIGRATE_TIMER 1 ++#define KVM_REQ_REPORT_TPR_ACCESS 2 ++#define KVM_REQ_MMU_RELOAD 3 ++#define KVM_REQ_TRIPLE_FAULT 4 ++#define KVM_REQ_PENDING_TIMER 5 ++#define KVM_REQ_UNHALT 6 ++#define KVM_REQ_MMU_SYNC 7 ++#define KVM_REQ_CLOCK_UPDATE 8 ++#define KVM_REQ_KICK 9 ++#define KVM_REQ_DEACTIVATE_FPU 10 ++#define KVM_REQ_EVENT 11 ++#define KVM_REQ_APF_HALT 12 ++#define KVM_REQ_STEAL_UPDATE 13 ++#define KVM_REQ_NMI 14 ++#define KVM_REQ_PMU 15 ++#define KVM_REQ_PMI 16 ++#define KVM_REQ_WATCHDOG 17 ++#define KVM_REQ_MASTERCLOCK_UPDATE 18 ++#define KVM_REQ_MCLOCK_INPROGRESS 19 ++#define KVM_REQ_EPR_EXIT 20 ++#define KVM_REQ_SCAN_IOAPIC 21 ++#define KVM_REQ_GLOBAL_CLOCK_UPDATE 22 ++#define KVM_REQ_ENABLE_IBS 23 ++#define KVM_REQ_DISABLE_IBS 24 ++#define KVM_REQ_APIC_PAGE_RELOAD 25 ++ ++#define KVM_USERSPACE_IRQ_SOURCE_ID 0 ++#define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1 ++ ++extern struct kmem_cache *kvm_vcpu_cache; ++ ++extern spinlock_t kvm_lock; ++extern struct list_head vm_list; ++ ++struct kvm_io_range { ++ gpa_t addr; ++ int len; ++ struct kvm_io_device *dev; ++}; ++ ++#define NR_IOBUS_DEVS 1000 ++ ++struct kvm_io_bus { ++ int dev_count; ++ int ioeventfd_count; ++ struct kvm_io_range range[]; ++}; ++ ++enum kvm_bus { ++ KVM_MMIO_BUS, ++ KVM_PIO_BUS, ++ KVM_VIRTIO_CCW_NOTIFY_BUS, ++ KVM_FAST_MMIO_BUS, ++ KVM_NR_BUSES ++}; ++ ++int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, ++ int len, const void *val); ++int kvm_io_bus_write_cookie(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, ++ int len, const void *val, long cookie); ++int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len, ++ void *val); ++int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, ++ int len, struct kvm_io_device *dev); ++int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, ++ struct kvm_io_device *dev); ++ ++#ifdef CONFIG_KVM_ASYNC_PF ++struct kvm_async_pf { ++ struct work_struct work; ++ struct list_head link; ++ struct list_head queue; ++ struct kvm_vcpu *vcpu; ++ struct mm_struct *mm; ++ gva_t gva; ++ unsigned long addr; ++ struct kvm_arch_async_pf arch; ++ bool wakeup_all; ++}; ++ ++void kvm_clear_async_pf_completion_queue(struct kvm_vcpu *vcpu); ++void kvm_check_async_pf_completion(struct kvm_vcpu *vcpu); ++int kvm_setup_async_pf(struct kvm_vcpu *vcpu, gva_t gva, unsigned long hva, ++ struct kvm_arch_async_pf *arch); ++int kvm_async_pf_wakeup_all(struct kvm_vcpu *vcpu); ++#endif ++ ++/* ++ * Carry out a gup that requires IO. Allow the mm to relinquish the mmap ++ * semaphore if the filemap/swap has to wait on a page lock. pagep == NULL ++ * controls whether we retry the gup one more time to completion in that case. ++ * Typically this is called after a FAULT_FLAG_RETRY_NOWAIT in the main tdp ++ * handler. ++ */ ++int kvm_get_user_page_io(struct task_struct *tsk, struct mm_struct *mm, ++ unsigned long addr, bool write_fault, ++ struct page **pagep); ++ ++enum { ++ OUTSIDE_GUEST_MODE, ++ IN_GUEST_MODE, ++ EXITING_GUEST_MODE, ++ READING_SHADOW_PAGE_TABLES, ++}; ++ ++/* ++ * Sometimes a large or cross-page mmio needs to be broken up into separate ++ * exits for userspace servicing. ++ */ ++struct kvm_mmio_fragment { ++ gpa_t gpa; ++ void *data; ++ unsigned len; ++}; ++ ++struct kvm_vcpu { ++ struct kvm *kvm; ++#ifdef CONFIG_PREEMPT_NOTIFIERS ++ struct preempt_notifier preempt_notifier; ++#endif ++ int cpu; ++ int vcpu_id; ++ int srcu_idx; ++ int mode; ++ unsigned long requests; ++ unsigned long guest_debug; ++ ++ struct mutex mutex; ++ struct kvm_run *run; ++ ++ int fpu_active; ++ int guest_fpu_loaded, guest_xcr0_loaded; ++ wait_queue_head_t wq; ++ struct pid *pid; ++ int sigset_active; ++ sigset_t sigset; ++ struct kvm_vcpu_stat stat; ++ ++#ifdef CONFIG_HAS_IOMEM ++ int mmio_needed; ++ int mmio_read_completed; ++ int mmio_is_write; ++ int mmio_cur_fragment; ++ int mmio_nr_fragments; ++ struct kvm_mmio_fragment mmio_fragments[KVM_MAX_MMIO_FRAGMENTS]; ++#endif ++ ++#ifdef CONFIG_KVM_ASYNC_PF ++ struct { ++ u32 queued; ++ struct list_head queue; ++ struct list_head done; ++ spinlock_t lock; ++ } async_pf; ++#endif ++ ++#ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT ++ /* ++ * Cpu relax intercept or pause loop exit optimization ++ * in_spin_loop: set when a vcpu does a pause loop exit ++ * or cpu relax intercepted. ++ * dy_eligible: indicates whether vcpu is eligible for directed yield. ++ */ ++ struct { ++ bool in_spin_loop; ++ bool dy_eligible; ++ } spin_loop; ++#endif ++ bool preempted; ++ struct kvm_vcpu_arch arch; ++}; ++ ++static inline int kvm_vcpu_exiting_guest_mode(struct kvm_vcpu *vcpu) ++{ ++ return cmpxchg(&vcpu->mode, IN_GUEST_MODE, EXITING_GUEST_MODE); ++} ++ ++/* ++ * Some of the bitops functions do not support too long bitmaps. ++ * This number must be determined not to exceed such limits. ++ */ ++#define KVM_MEM_MAX_NR_PAGES ((1UL << 31) - 1) ++ ++struct kvm_memory_slot { ++ gfn_t base_gfn; ++ unsigned long npages; ++ unsigned long *dirty_bitmap; ++ struct kvm_arch_memory_slot arch; ++ unsigned long userspace_addr; ++ u32 flags; ++ short id; ++}; ++ ++static inline unsigned long kvm_dirty_bitmap_bytes(struct kvm_memory_slot *memslot) ++{ ++ return ALIGN(memslot->npages, BITS_PER_LONG) / 8; ++} ++ ++struct kvm_s390_adapter_int { ++ u64 ind_addr; ++ u64 summary_addr; ++ u64 ind_offset; ++ u32 summary_offset; ++ u32 adapter_id; ++}; ++ ++struct kvm_kernel_irq_routing_entry { ++ u32 gsi; ++ u32 type; ++ int (*set)(struct kvm_kernel_irq_routing_entry *e, ++ struct kvm *kvm, int irq_source_id, int level, ++ bool line_status); ++ union { ++ struct { ++ unsigned irqchip; ++ unsigned pin; ++ } irqchip; ++ struct msi_msg msi; ++ struct kvm_s390_adapter_int adapter; ++ }; ++ struct hlist_node link; ++}; ++ ++#ifndef KVM_PRIVATE_MEM_SLOTS ++#define KVM_PRIVATE_MEM_SLOTS 0 ++#endif ++ ++#ifndef KVM_MEM_SLOTS_NUM ++#define KVM_MEM_SLOTS_NUM (KVM_USER_MEM_SLOTS + KVM_PRIVATE_MEM_SLOTS) ++#endif ++ ++/* ++ * Note: ++ * memslots are not sorted by id anymore, please use id_to_memslot() ++ * to get the memslot by its id. ++ */ ++struct kvm_memslots { ++ u64 generation; ++ struct kvm_memory_slot memslots[KVM_MEM_SLOTS_NUM]; ++ /* The mapping table from slot id to the index in memslots[]. */ ++ short id_to_index[KVM_MEM_SLOTS_NUM]; ++}; ++ ++struct kvm { ++ spinlock_t mmu_lock; ++ struct mutex slots_lock; ++ struct mm_struct *mm; /* userspace tied to this vm */ ++ struct kvm_memslots *memslots; ++ struct srcu_struct srcu; ++ struct srcu_struct irq_srcu; ++#ifdef CONFIG_KVM_APIC_ARCHITECTURE ++ u32 bsp_vcpu_id; ++#endif ++ struct kvm_vcpu *vcpus[KVM_MAX_VCPUS]; ++ atomic_t online_vcpus; ++ int last_boosted_vcpu; ++ struct list_head vm_list; ++ struct mutex lock; ++ struct kvm_io_bus *buses[KVM_NR_BUSES]; ++#ifdef CONFIG_HAVE_KVM_EVENTFD ++ struct { ++ spinlock_t lock; ++ struct list_head items; ++ struct list_head resampler_list; ++ struct mutex resampler_lock; ++ } irqfds; ++ struct list_head ioeventfds; ++#endif ++ struct kvm_vm_stat stat; ++ struct kvm_arch arch; ++ atomic_t users_count; ++#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET ++ struct kvm_coalesced_mmio_ring *coalesced_mmio_ring; ++ spinlock_t ring_lock; ++ struct list_head coalesced_zones; ++#endif ++ ++ struct mutex irq_lock; ++#ifdef CONFIG_HAVE_KVM_IRQCHIP ++ /* ++ * Update side is protected by irq_lock. ++ */ ++ struct kvm_irq_routing_table __rcu *irq_routing; ++ struct hlist_head mask_notifier_list; ++#endif ++#ifdef CONFIG_HAVE_KVM_IRQFD ++ struct hlist_head irq_ack_notifier_list; ++#endif ++ ++#if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER) ++ struct mmu_notifier mmu_notifier; ++ unsigned long mmu_notifier_seq; ++ long mmu_notifier_count; ++#endif ++ long tlbs_dirty; ++ struct list_head devices; ++}; ++ ++#define kvm_err(fmt, ...) \ ++ pr_err("kvm [%i]: " fmt, task_pid_nr(current), ## __VA_ARGS__) ++#define kvm_info(fmt, ...) \ ++ pr_info("kvm [%i]: " fmt, task_pid_nr(current), ## __VA_ARGS__) ++#define kvm_debug(fmt, ...) \ ++ pr_debug("kvm [%i]: " fmt, task_pid_nr(current), ## __VA_ARGS__) ++#define kvm_pr_unimpl(fmt, ...) \ ++ pr_err_ratelimited("kvm [%i]: " fmt, \ ++ task_tgid_nr(current), ## __VA_ARGS__) ++ ++/* The guest did something we don't support. */ ++#define vcpu_unimpl(vcpu, fmt, ...) \ ++ kvm_pr_unimpl("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__) ++ ++static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i) ++{ ++ smp_rmb(); ++ return kvm->vcpus[i]; ++} ++ ++#define kvm_for_each_vcpu(idx, vcpup, kvm) \ ++ for (idx = 0; \ ++ idx < atomic_read(&kvm->online_vcpus) && \ ++ (vcpup = kvm_get_vcpu(kvm, idx)) != NULL; \ ++ idx++) ++ ++#define kvm_for_each_memslot(memslot, slots) \ ++ for (memslot = &slots->memslots[0]; \ ++ memslot < slots->memslots + KVM_MEM_SLOTS_NUM && memslot->npages;\ ++ memslot++) ++ ++int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, unsigned id); ++void kvm_vcpu_uninit(struct kvm_vcpu *vcpu); ++ ++int __must_check vcpu_load(struct kvm_vcpu *vcpu); ++void vcpu_put(struct kvm_vcpu *vcpu); ++ ++#ifdef CONFIG_HAVE_KVM_IRQFD ++int kvm_irqfd_init(void); ++void kvm_irqfd_exit(void); ++#else ++static inline int kvm_irqfd_init(void) ++{ ++ return 0; ++} ++ ++static inline void kvm_irqfd_exit(void) ++{ ++} ++#endif ++int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align, ++ struct module *module); ++void kvm_exit(void); ++ ++void kvm_get_kvm(struct kvm *kvm); ++void kvm_put_kvm(struct kvm *kvm); ++ ++static inline struct kvm_memslots *kvm_memslots(struct kvm *kvm) ++{ ++ return rcu_dereference_check(kvm->memslots, ++ srcu_read_lock_held(&kvm->srcu) ++ || lockdep_is_held(&kvm->slots_lock)); ++} ++ ++static inline struct kvm_memory_slot * ++id_to_memslot(struct kvm_memslots *slots, int id) ++{ ++ int index = slots->id_to_index[id]; ++ struct kvm_memory_slot *slot; ++ ++ slot = &slots->memslots[index]; ++ ++ WARN_ON(slot->id != id); ++ return slot; ++} ++ ++/* ++ * KVM_SET_USER_MEMORY_REGION ioctl allows the following operations: ++ * - create a new memory slot ++ * - delete an existing memory slot ++ * - modify an existing memory slot ++ * -- move it in the guest physical memory space ++ * -- just change its flags ++ * ++ * Since flags can be changed by some of these operations, the following ++ * differentiation is the best we can do for __kvm_set_memory_region(): ++ */ ++enum kvm_mr_change { ++ KVM_MR_CREATE, ++ KVM_MR_DELETE, ++ KVM_MR_MOVE, ++ KVM_MR_FLAGS_ONLY, ++}; ++ ++int kvm_set_memory_region(struct kvm *kvm, ++ struct kvm_userspace_memory_region *mem); ++int __kvm_set_memory_region(struct kvm *kvm, ++ struct kvm_userspace_memory_region *mem); ++void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free, ++ struct kvm_memory_slot *dont); ++int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, ++ unsigned long npages); ++void kvm_arch_memslots_updated(struct kvm *kvm); ++int kvm_arch_prepare_memory_region(struct kvm *kvm, ++ struct kvm_memory_slot *memslot, ++ struct kvm_userspace_memory_region *mem, ++ enum kvm_mr_change change); ++void kvm_arch_commit_memory_region(struct kvm *kvm, ++ struct kvm_userspace_memory_region *mem, ++ const struct kvm_memory_slot *old, ++ enum kvm_mr_change change); ++bool kvm_largepages_enabled(void); ++void kvm_disable_largepages(void); ++/* flush all memory translations */ ++void kvm_arch_flush_shadow_all(struct kvm *kvm); ++/* flush memory translations pointing to 'slot' */ ++void kvm_arch_flush_shadow_memslot(struct kvm *kvm, ++ struct kvm_memory_slot *slot); ++ ++int gfn_to_page_many_atomic(struct kvm *kvm, gfn_t gfn, struct page **pages, ++ int nr_pages); ++ ++struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn); ++unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn); ++unsigned long gfn_to_hva_prot(struct kvm *kvm, gfn_t gfn, bool *writable); ++unsigned long gfn_to_hva_memslot(struct kvm_memory_slot *slot, gfn_t gfn); ++unsigned long gfn_to_hva_memslot_prot(struct kvm_memory_slot *slot, gfn_t gfn, ++ bool *writable); ++void kvm_release_page_clean(struct page *page); ++void kvm_release_page_dirty(struct page *page); ++void kvm_set_page_accessed(struct page *page); ++ ++pfn_t gfn_to_pfn_atomic(struct kvm *kvm, gfn_t gfn); ++pfn_t gfn_to_pfn_async(struct kvm *kvm, gfn_t gfn, bool *async, ++ bool write_fault, bool *writable); ++pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn); ++pfn_t gfn_to_pfn_prot(struct kvm *kvm, gfn_t gfn, bool write_fault, ++ bool *writable); ++pfn_t gfn_to_pfn_memslot(struct kvm_memory_slot *slot, gfn_t gfn); ++pfn_t gfn_to_pfn_memslot_atomic(struct kvm_memory_slot *slot, gfn_t gfn); ++ ++void kvm_release_pfn_clean(pfn_t pfn); ++void kvm_set_pfn_dirty(pfn_t pfn); ++void kvm_set_pfn_accessed(pfn_t pfn); ++void kvm_get_pfn(pfn_t pfn); ++ ++int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset, ++ int len); ++int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data, ++ unsigned long len); ++int kvm_read_guest(struct kvm *kvm, gpa_t gpa, void *data, unsigned long len); ++int kvm_read_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, ++ void *data, unsigned long len); ++int kvm_write_guest_page(struct kvm *kvm, gfn_t gfn, const void *data, ++ int offset, int len); ++int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data, ++ unsigned long len); ++int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, ++ void *data, unsigned long len); ++int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc, ++ gpa_t gpa, unsigned long len); ++int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len); ++int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len); ++struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn); ++int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn); ++unsigned long kvm_host_page_size(struct kvm *kvm, gfn_t gfn); ++void mark_page_dirty(struct kvm *kvm, gfn_t gfn); ++ ++void kvm_vcpu_block(struct kvm_vcpu *vcpu); ++void kvm_vcpu_kick(struct kvm_vcpu *vcpu); ++int kvm_vcpu_yield_to(struct kvm_vcpu *target); ++void kvm_vcpu_on_spin(struct kvm_vcpu *vcpu); ++void kvm_load_guest_fpu(struct kvm_vcpu *vcpu); ++void kvm_put_guest_fpu(struct kvm_vcpu *vcpu); ++ ++void kvm_flush_remote_tlbs(struct kvm *kvm); ++void kvm_reload_remote_mmus(struct kvm *kvm); ++void kvm_make_mclock_inprogress_request(struct kvm *kvm); ++void kvm_make_scan_ioapic_request(struct kvm *kvm); ++bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req); ++ ++long kvm_arch_dev_ioctl(struct file *filp, ++ unsigned int ioctl, unsigned long arg); ++long kvm_arch_vcpu_ioctl(struct file *filp, ++ unsigned int ioctl, unsigned long arg); ++int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf); ++ ++int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext); ++ ++int kvm_get_dirty_log(struct kvm *kvm, ++ struct kvm_dirty_log *log, int *is_dirty); ++int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, ++ struct kvm_dirty_log *log); ++ ++int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level, ++ bool line_status); ++long kvm_arch_vm_ioctl(struct file *filp, ++ unsigned int ioctl, unsigned long arg); ++ ++int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu); ++int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu); ++ ++int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, ++ struct kvm_translation *tr); ++ ++int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs); ++int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs); ++int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, ++ struct kvm_sregs *sregs); ++int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, ++ struct kvm_sregs *sregs); ++int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, ++ struct kvm_mp_state *mp_state); ++int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, ++ struct kvm_mp_state *mp_state); ++int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, ++ struct kvm_guest_debug *dbg); ++int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run); ++ ++int kvm_arch_init(void *opaque); ++void kvm_arch_exit(void); ++ ++int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu); ++void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu); ++ ++void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu); ++ ++void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu); ++void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu); ++void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu); ++struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id); ++int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu); ++int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu); ++void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu); ++ ++int kvm_arch_hardware_enable(void); ++void kvm_arch_hardware_disable(void); ++int kvm_arch_hardware_setup(void); ++void kvm_arch_hardware_unsetup(void); ++void kvm_arch_check_processor_compat(void *rtn); ++int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu); ++int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu); ++ ++void *kvm_kvzalloc(unsigned long size); ++void kvm_kvfree(const void *addr); ++ ++#ifndef __KVM_HAVE_ARCH_VM_ALLOC ++static inline struct kvm *kvm_arch_alloc_vm(void) ++{ ++ return kzalloc(sizeof(struct kvm), GFP_KERNEL); ++} ++ ++static inline void kvm_arch_free_vm(struct kvm *kvm) ++{ ++ kfree(kvm); ++} ++#endif ++ ++#ifdef __KVM_HAVE_ARCH_NONCOHERENT_DMA ++void kvm_arch_register_noncoherent_dma(struct kvm *kvm); ++void kvm_arch_unregister_noncoherent_dma(struct kvm *kvm); ++bool kvm_arch_has_noncoherent_dma(struct kvm *kvm); ++#else ++static inline void kvm_arch_register_noncoherent_dma(struct kvm *kvm) ++{ ++} ++ ++static inline void kvm_arch_unregister_noncoherent_dma(struct kvm *kvm) ++{ ++} ++ ++static inline bool kvm_arch_has_noncoherent_dma(struct kvm *kvm) ++{ ++ return false; ++} ++#endif ++ ++static inline wait_queue_head_t *kvm_arch_vcpu_wq(struct kvm_vcpu *vcpu) ++{ ++#ifdef __KVM_HAVE_ARCH_WQP ++ return vcpu->arch.wqp; ++#else ++ return &vcpu->wq; ++#endif ++} ++ ++int kvm_arch_init_vm(struct kvm *kvm, unsigned long type); ++void kvm_arch_destroy_vm(struct kvm *kvm); ++void kvm_arch_sync_events(struct kvm *kvm); ++ ++int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu); ++void kvm_vcpu_kick(struct kvm_vcpu *vcpu); ++ ++bool kvm_is_reserved_pfn(pfn_t pfn); ++ ++struct kvm_irq_ack_notifier { ++ struct hlist_node link; ++ unsigned gsi; ++ void (*irq_acked)(struct kvm_irq_ack_notifier *kian); ++}; ++ ++struct kvm_assigned_dev_kernel { ++ struct kvm_irq_ack_notifier ack_notifier; ++ struct list_head list; ++ int assigned_dev_id; ++ int host_segnr; ++ int host_busnr; ++ int host_devfn; ++ unsigned int entries_nr; ++ int host_irq; ++ bool host_irq_disabled; ++ bool pci_2_3; ++ struct msix_entry *host_msix_entries; ++ int guest_irq; ++ struct msix_entry *guest_msix_entries; ++ unsigned long irq_requested_type; ++ int irq_source_id; ++ int flags; ++ struct pci_dev *dev; ++ struct kvm *kvm; ++ spinlock_t intx_lock; ++ spinlock_t intx_mask_lock; ++ char irq_name[32]; ++ struct pci_saved_state *pci_saved_state; ++}; ++ ++struct kvm_irq_mask_notifier { ++ void (*func)(struct kvm_irq_mask_notifier *kimn, bool masked); ++ int irq; ++ struct hlist_node link; ++}; ++ ++void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, ++ struct kvm_irq_mask_notifier *kimn); ++void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, ++ struct kvm_irq_mask_notifier *kimn); ++void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin, ++ bool mask); ++ ++int kvm_irq_map_gsi(struct kvm *kvm, ++ struct kvm_kernel_irq_routing_entry *entries, int gsi); ++int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin); ++ ++int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, ++ bool line_status); ++int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level); ++int kvm_set_msi(struct kvm_kernel_irq_routing_entry *irq_entry, struct kvm *kvm, ++ int irq_source_id, int level, bool line_status); ++bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin); ++void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin); ++void kvm_register_irq_ack_notifier(struct kvm *kvm, ++ struct kvm_irq_ack_notifier *kian); ++void kvm_unregister_irq_ack_notifier(struct kvm *kvm, ++ struct kvm_irq_ack_notifier *kian); ++int kvm_request_irq_source_id(struct kvm *kvm); ++void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id); ++ ++#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT ++int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot); ++void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot); ++int kvm_iommu_map_guest(struct kvm *kvm); ++int kvm_iommu_unmap_guest(struct kvm *kvm); ++int kvm_assign_device(struct kvm *kvm, ++ struct kvm_assigned_dev_kernel *assigned_dev); ++int kvm_deassign_device(struct kvm *kvm, ++ struct kvm_assigned_dev_kernel *assigned_dev); ++#else ++static inline int kvm_iommu_map_pages(struct kvm *kvm, ++ struct kvm_memory_slot *slot) ++{ ++ return 0; ++} ++ ++static inline void kvm_iommu_unmap_pages(struct kvm *kvm, ++ struct kvm_memory_slot *slot) ++{ ++} ++ ++static inline int kvm_iommu_unmap_guest(struct kvm *kvm) ++{ ++ return 0; ++} ++#endif ++ ++static inline void kvm_guest_enter(void) ++{ ++ unsigned long flags; ++ ++ BUG_ON(preemptible()); ++ ++ local_irq_save(flags); ++ guest_enter(); ++ local_irq_restore(flags); ++ ++ /* KVM does not hold any references to rcu protected data when it ++ * switches CPU into a guest mode. In fact switching to a guest mode ++ * is very similar to exiting to userspace from rcu point of view. In ++ * addition CPU may stay in a guest mode for quite a long time (up to ++ * one time slice). Lets treat guest mode as quiescent state, just like ++ * we do with user-mode execution. ++ */ ++ rcu_virt_note_context_switch(smp_processor_id()); ++} ++ ++static inline void kvm_guest_exit(void) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ guest_exit(); ++ local_irq_restore(flags); ++} ++ ++/* ++ * search_memslots() and __gfn_to_memslot() are here because they are ++ * used in non-modular code in arch/powerpc/kvm/book3s_hv_rm_mmu.c. ++ * gfn_to_memslot() itself isn't here as an inline because that would ++ * bloat other code too much. ++ */ ++static inline struct kvm_memory_slot * ++search_memslots(struct kvm_memslots *slots, gfn_t gfn) ++{ ++ struct kvm_memory_slot *memslot; ++ ++ kvm_for_each_memslot(memslot, slots) ++ if (gfn >= memslot->base_gfn && ++ gfn < memslot->base_gfn + memslot->npages) ++ return memslot; ++ ++ return NULL; ++} ++ ++static inline struct kvm_memory_slot * ++__gfn_to_memslot(struct kvm_memslots *slots, gfn_t gfn) ++{ ++ return search_memslots(slots, gfn); ++} ++ ++static inline unsigned long ++__gfn_to_hva_memslot(struct kvm_memory_slot *slot, gfn_t gfn) ++{ ++ return slot->userspace_addr + (gfn - slot->base_gfn) * PAGE_SIZE; ++} ++ ++static inline int memslot_id(struct kvm *kvm, gfn_t gfn) ++{ ++ return gfn_to_memslot(kvm, gfn)->id; ++} ++ ++static inline gfn_t ++hva_to_gfn_memslot(unsigned long hva, struct kvm_memory_slot *slot) ++{ ++ gfn_t gfn_offset = (hva - slot->userspace_addr) >> PAGE_SHIFT; ++ ++ return slot->base_gfn + gfn_offset; ++} ++ ++static inline gpa_t gfn_to_gpa(gfn_t gfn) ++{ ++ return (gpa_t)gfn << PAGE_SHIFT; ++} ++ ++static inline gfn_t gpa_to_gfn(gpa_t gpa) ++{ ++ return (gfn_t)(gpa >> PAGE_SHIFT); ++} ++ ++static inline hpa_t pfn_to_hpa(pfn_t pfn) ++{ ++ return (hpa_t)pfn << PAGE_SHIFT; ++} ++ ++static inline bool kvm_is_error_gpa(struct kvm *kvm, gpa_t gpa) ++{ ++ unsigned long hva = gfn_to_hva(kvm, gpa_to_gfn(gpa)); ++ ++ return kvm_is_error_hva(hva); ++} ++ ++static inline void kvm_migrate_timers(struct kvm_vcpu *vcpu) ++{ ++ set_bit(KVM_REQ_MIGRATE_TIMER, &vcpu->requests); ++} ++ ++enum kvm_stat_kind { ++ KVM_STAT_VM, ++ KVM_STAT_VCPU, ++}; ++ ++struct kvm_stats_debugfs_item { ++ const char *name; ++ int offset; ++ enum kvm_stat_kind kind; ++ struct dentry *dentry; ++}; ++extern struct kvm_stats_debugfs_item debugfs_entries[]; ++extern struct dentry *kvm_debugfs_dir; ++ ++#if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER) ++static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq) ++{ ++ if (unlikely(kvm->mmu_notifier_count)) ++ return 1; ++ /* ++ * Ensure the read of mmu_notifier_count happens before the read ++ * of mmu_notifier_seq. This interacts with the smp_wmb() in ++ * mmu_notifier_invalidate_range_end to make sure that the caller ++ * either sees the old (non-zero) value of mmu_notifier_count or ++ * the new (incremented) value of mmu_notifier_seq. ++ * PowerPC Book3s HV KVM calls this under a per-page lock ++ * rather than under kvm->mmu_lock, for scalability, so ++ * can't rely on kvm->mmu_lock to keep things ordered. ++ */ ++ smp_rmb(); ++ if (kvm->mmu_notifier_seq != mmu_seq) ++ return 1; ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING ++ ++#ifdef CONFIG_S390 ++#define KVM_MAX_IRQ_ROUTES 4096 //FIXME: we can have more than that... ++#else ++#define KVM_MAX_IRQ_ROUTES 1024 ++#endif ++ ++int kvm_setup_default_irq_routing(struct kvm *kvm); ++int kvm_set_irq_routing(struct kvm *kvm, ++ const struct kvm_irq_routing_entry *entries, ++ unsigned nr, ++ unsigned flags); ++int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e, ++ const struct kvm_irq_routing_entry *ue); ++void kvm_free_irq_routing(struct kvm *kvm); ++ ++#else ++ ++static inline void kvm_free_irq_routing(struct kvm *kvm) {} ++ ++#endif ++ ++int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi); ++ ++#ifdef CONFIG_HAVE_KVM_EVENTFD ++ ++void kvm_eventfd_init(struct kvm *kvm); ++int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args); ++ ++#ifdef CONFIG_HAVE_KVM_IRQFD ++int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args); ++void kvm_irqfd_release(struct kvm *kvm); ++void kvm_irq_routing_update(struct kvm *); ++#else ++static inline int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args) ++{ ++ return -EINVAL; ++} ++ ++static inline void kvm_irqfd_release(struct kvm *kvm) {} ++#endif ++ ++#else ++ ++static inline void kvm_eventfd_init(struct kvm *kvm) {} ++ ++static inline int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args) ++{ ++ return -EINVAL; ++} ++ ++static inline void kvm_irqfd_release(struct kvm *kvm) {} ++ ++#ifdef CONFIG_HAVE_KVM_IRQCHIP ++static inline void kvm_irq_routing_update(struct kvm *kvm) ++{ ++} ++#endif ++ ++static inline int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args) ++{ ++ return -ENOSYS; ++} ++ ++#endif /* CONFIG_HAVE_KVM_EVENTFD */ ++ ++#ifdef CONFIG_KVM_APIC_ARCHITECTURE ++static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu) ++{ ++ return vcpu->kvm->bsp_vcpu_id == vcpu->vcpu_id; ++} ++ ++bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu); ++ ++#else ++ ++static inline bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) { return true; } ++ ++#endif ++ ++#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT ++ ++long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl, ++ unsigned long arg); ++ ++void kvm_free_all_assigned_devices(struct kvm *kvm); ++ ++#else ++ ++static inline long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl, ++ unsigned long arg) ++{ ++ return -ENOTTY; ++} ++ ++static inline void kvm_free_all_assigned_devices(struct kvm *kvm) {} ++ ++#endif ++ ++static inline void kvm_make_request(int req, struct kvm_vcpu *vcpu) ++{ ++ set_bit(req, &vcpu->requests); ++} ++ ++static inline bool kvm_check_request(int req, struct kvm_vcpu *vcpu) ++{ ++ if (test_bit(req, &vcpu->requests)) { ++ clear_bit(req, &vcpu->requests); ++ return true; ++ } else { ++ return false; ++ } ++} ++ ++extern bool kvm_rebooting; ++ ++struct kvm_device { ++ struct kvm_device_ops *ops; ++ struct kvm *kvm; ++ void *private; ++ struct list_head vm_node; ++}; ++ ++/* create, destroy, and name are mandatory */ ++struct kvm_device_ops { ++ const char *name; ++ int (*create)(struct kvm_device *dev, u32 type); ++ ++ /* ++ * Destroy is responsible for freeing dev. ++ * ++ * Destroy may be called before or after destructors are called ++ * on emulated I/O regions, depending on whether a reference is ++ * held by a vcpu or other kvm component that gets destroyed ++ * after the emulated I/O. ++ */ ++ void (*destroy)(struct kvm_device *dev); ++ ++ int (*set_attr)(struct kvm_device *dev, struct kvm_device_attr *attr); ++ int (*get_attr)(struct kvm_device *dev, struct kvm_device_attr *attr); ++ int (*has_attr)(struct kvm_device *dev, struct kvm_device_attr *attr); ++ long (*ioctl)(struct kvm_device *dev, unsigned int ioctl, ++ unsigned long arg); ++}; ++ ++void kvm_device_get(struct kvm_device *dev); ++void kvm_device_put(struct kvm_device *dev); ++struct kvm_device *kvm_device_from_filp(struct file *filp); ++int kvm_register_device_ops(struct kvm_device_ops *ops, u32 type); ++void kvm_unregister_device_ops(u32 type); ++ ++extern struct kvm_device_ops kvm_mpic_ops; ++extern struct kvm_device_ops kvm_xics_ops; ++ ++#ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT ++ ++static inline void kvm_vcpu_set_in_spin_loop(struct kvm_vcpu *vcpu, bool val) ++{ ++ vcpu->spin_loop.in_spin_loop = val; ++} ++static inline void kvm_vcpu_set_dy_eligible(struct kvm_vcpu *vcpu, bool val) ++{ ++ vcpu->spin_loop.dy_eligible = val; ++} ++ ++#else /* !CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT */ ++ ++static inline void kvm_vcpu_set_in_spin_loop(struct kvm_vcpu *vcpu, bool val) ++{ ++} ++ ++static inline void kvm_vcpu_set_dy_eligible(struct kvm_vcpu *vcpu, bool val) ++{ ++} ++#endif /* CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT */ ++#endif ++ +diff -Nur linux-3.18.14.orig/include/linux/lglock.h linux-3.18.14-rt/include/linux/lglock.h +--- linux-3.18.14.orig/include/linux/lglock.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/lglock.h 2015-05-31 15:32:48.261635369 -0500 @@ -34,22 +34,39 @@ #endif @@ -8101,9 +12856,9 @@ diff -Nur linux-3.18.12.orig/include/linux/lglock.h linux-3.18.12/include/linux/ #else /* When !CONFIG_SMP, map lglock to spinlock */ #define lglock spinlock -diff -Nur linux-3.18.12.orig/include/linux/list_bl.h linux-3.18.12/include/linux/list_bl.h ---- linux-3.18.12.orig/include/linux/list_bl.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/list_bl.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/list_bl.h linux-3.18.14-rt/include/linux/list_bl.h +--- linux-3.18.14.orig/include/linux/list_bl.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/list_bl.h 2015-05-31 15:32:48.265635369 -0500 @@ -2,6 +2,7 @@ #define _LINUX_LIST_BL_H @@ -8164,9 +12919,9 @@ diff -Nur linux-3.18.12.orig/include/linux/list_bl.h linux-3.18.12/include/linux } static inline bool hlist_bl_is_locked(struct hlist_bl_head *b) -diff -Nur linux-3.18.12.orig/include/linux/locallock.h linux-3.18.12/include/linux/locallock.h ---- linux-3.18.12.orig/include/linux/locallock.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/include/linux/locallock.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/locallock.h linux-3.18.14-rt/include/linux/locallock.h +--- linux-3.18.14.orig/include/linux/locallock.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/include/linux/locallock.h 2015-05-31 15:32:48.273635368 -0500 @@ -0,0 +1,270 @@ +#ifndef _LINUX_LOCALLOCK_H +#define _LINUX_LOCALLOCK_H @@ -8438,9 +13193,9 @@ diff -Nur linux-3.18.12.orig/include/linux/locallock.h linux-3.18.12/include/lin +#endif + +#endif -diff -Nur linux-3.18.12.orig/include/linux/mm_types.h linux-3.18.12/include/linux/mm_types.h ---- linux-3.18.12.orig/include/linux/mm_types.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/mm_types.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/mm_types.h linux-3.18.14-rt/include/linux/mm_types.h +--- linux-3.18.14.orig/include/linux/mm_types.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/mm_types.h 2015-05-31 15:32:48.273635368 -0500 @@ -11,6 +11,7 @@ #include <linux/completion.h> #include <linux/cpumask.h> @@ -8459,9 +13214,9 @@ diff -Nur linux-3.18.12.orig/include/linux/mm_types.h linux-3.18.12/include/linu }; static inline void mm_init_cpumask(struct mm_struct *mm) -diff -Nur linux-3.18.12.orig/include/linux/mutex.h linux-3.18.12/include/linux/mutex.h ---- linux-3.18.12.orig/include/linux/mutex.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/mutex.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/mutex.h linux-3.18.14-rt/include/linux/mutex.h +--- linux-3.18.14.orig/include/linux/mutex.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/mutex.h 2015-05-31 15:32:48.273635368 -0500 @@ -19,6 +19,17 @@ #include <asm/processor.h> #include <linux/osq_lock.h> @@ -8503,9 +13258,9 @@ diff -Nur linux-3.18.12.orig/include/linux/mutex.h linux-3.18.12/include/linux/m extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock); #endif /* __LINUX_MUTEX_H */ -diff -Nur linux-3.18.12.orig/include/linux/mutex_rt.h linux-3.18.12/include/linux/mutex_rt.h ---- linux-3.18.12.orig/include/linux/mutex_rt.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/include/linux/mutex_rt.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/mutex_rt.h linux-3.18.14-rt/include/linux/mutex_rt.h +--- linux-3.18.14.orig/include/linux/mutex_rt.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/include/linux/mutex_rt.h 2015-05-31 15:32:48.273635368 -0500 @@ -0,0 +1,84 @@ +#ifndef __LINUX_MUTEX_RT_H +#define __LINUX_MUTEX_RT_H @@ -8591,10 +13346,10 @@ diff -Nur linux-3.18.12.orig/include/linux/mutex_rt.h linux-3.18.12/include/linu +} while (0) + +#endif -diff -Nur linux-3.18.12.orig/include/linux/netdevice.h linux-3.18.12/include/linux/netdevice.h ---- linux-3.18.12.orig/include/linux/netdevice.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/netdevice.h 2015-04-26 13:32:22.419684003 -0500 -@@ -2345,6 +2345,7 @@ +diff -Nur linux-3.18.14.orig/include/linux/netdevice.h linux-3.18.14-rt/include/linux/netdevice.h +--- linux-3.18.14.orig/include/linux/netdevice.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/netdevice.h 2015-05-31 15:32:48.305635368 -0500 +@@ -2351,6 +2351,7 @@ unsigned int dropped; struct sk_buff_head input_pkt_queue; struct napi_struct backlog; @@ -8602,9 +13357,9 @@ diff -Nur linux-3.18.12.orig/include/linux/netdevice.h linux-3.18.12/include/lin #ifdef CONFIG_NET_FLOW_LIMIT struct sd_flow_limit __rcu *flow_limit; -diff -Nur linux-3.18.12.orig/include/linux/netfilter/x_tables.h linux-3.18.12/include/linux/netfilter/x_tables.h ---- linux-3.18.12.orig/include/linux/netfilter/x_tables.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/netfilter/x_tables.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/netfilter/x_tables.h linux-3.18.14-rt/include/linux/netfilter/x_tables.h +--- linux-3.18.14.orig/include/linux/netfilter/x_tables.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/netfilter/x_tables.h 2015-05-31 15:32:48.305635368 -0500 @@ -3,6 +3,7 @@ @@ -8640,9 +13395,9 @@ diff -Nur linux-3.18.12.orig/include/linux/netfilter/x_tables.h linux-3.18.12/in } /* -diff -Nur linux-3.18.12.orig/include/linux/notifier.h linux-3.18.12/include/linux/notifier.h ---- linux-3.18.12.orig/include/linux/notifier.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/notifier.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/notifier.h linux-3.18.14-rt/include/linux/notifier.h +--- linux-3.18.14.orig/include/linux/notifier.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/notifier.h 2015-05-31 15:32:48.305635368 -0500 @@ -6,7 +6,7 @@ * * Alan Cox <Alan.Cox@linux.org> @@ -8722,9 +13477,9 @@ diff -Nur linux-3.18.12.orig/include/linux/notifier.h linux-3.18.12/include/linu /* CPU notfiers are defined in include/linux/cpu.h. */ /* netdevice notifiers are defined in include/linux/netdevice.h */ -diff -Nur linux-3.18.12.orig/include/linux/percpu.h linux-3.18.12/include/linux/percpu.h ---- linux-3.18.12.orig/include/linux/percpu.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/percpu.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/percpu.h linux-3.18.14-rt/include/linux/percpu.h +--- linux-3.18.14.orig/include/linux/percpu.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/percpu.h 2015-05-31 15:32:48.305635368 -0500 @@ -23,6 +23,35 @@ PERCPU_MODULE_RESERVE) #endif @@ -8761,9 +13516,9 @@ diff -Nur linux-3.18.12.orig/include/linux/percpu.h linux-3.18.12/include/linux/ /* minimum unit size, also is the maximum supported allocation size */ #define PCPU_MIN_UNIT_SIZE PFN_ALIGN(32 << 10) -diff -Nur linux-3.18.12.orig/include/linux/pid.h linux-3.18.12/include/linux/pid.h ---- linux-3.18.12.orig/include/linux/pid.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/pid.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/pid.h linux-3.18.14-rt/include/linux/pid.h +--- linux-3.18.14.orig/include/linux/pid.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/pid.h 2015-05-31 15:32:48.341635368 -0500 @@ -2,6 +2,7 @@ #define _LINUX_PID_H @@ -8772,9 +13527,9 @@ diff -Nur linux-3.18.12.orig/include/linux/pid.h linux-3.18.12/include/linux/pid enum pid_type { -diff -Nur linux-3.18.12.orig/include/linux/preempt.h linux-3.18.12/include/linux/preempt.h ---- linux-3.18.12.orig/include/linux/preempt.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/preempt.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/preempt.h linux-3.18.14-rt/include/linux/preempt.h +--- linux-3.18.14.orig/include/linux/preempt.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/preempt.h 2015-05-31 15:32:48.341635368 -0500 @@ -33,6 +33,20 @@ #define preempt_count_inc() preempt_count_add(1) #define preempt_count_dec() preempt_count_sub(1) @@ -8878,9 +13633,9 @@ diff -Nur linux-3.18.12.orig/include/linux/preempt.h linux-3.18.12/include/linux #ifdef CONFIG_PREEMPT_NOTIFIERS struct preempt_notifier; -diff -Nur linux-3.18.12.orig/include/linux/preempt_mask.h linux-3.18.12/include/linux/preempt_mask.h ---- linux-3.18.12.orig/include/linux/preempt_mask.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/preempt_mask.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/preempt_mask.h linux-3.18.14-rt/include/linux/preempt_mask.h +--- linux-3.18.14.orig/include/linux/preempt_mask.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/preempt_mask.h 2015-05-31 15:32:48.341635368 -0500 @@ -44,16 +44,26 @@ #define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT) #define NMI_OFFSET (1UL << NMI_SHIFT) @@ -8918,9 +13673,9 @@ diff -Nur linux-3.18.12.orig/include/linux/preempt_mask.h linux-3.18.12/include/ /* * Are we in NMI context? -diff -Nur linux-3.18.12.orig/include/linux/printk.h linux-3.18.12/include/linux/printk.h ---- linux-3.18.12.orig/include/linux/printk.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/printk.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/printk.h linux-3.18.14-rt/include/linux/printk.h +--- linux-3.18.14.orig/include/linux/printk.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/printk.h 2015-05-31 15:32:48.341635368 -0500 @@ -119,9 +119,11 @@ extern asmlinkage __printf(1, 2) void early_printk(const char *fmt, ...); @@ -8941,9 +13696,9 @@ diff -Nur linux-3.18.12.orig/include/linux/printk.h linux-3.18.12/include/linux/ extern int printk_delay_msec; extern int dmesg_restrict; extern int kptr_restrict; -diff -Nur linux-3.18.12.orig/include/linux/radix-tree.h linux-3.18.12/include/linux/radix-tree.h ---- linux-3.18.12.orig/include/linux/radix-tree.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/radix-tree.h 2015-04-26 13:32:22.419684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/radix-tree.h linux-3.18.14-rt/include/linux/radix-tree.h +--- linux-3.18.14.orig/include/linux/radix-tree.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/radix-tree.h 2015-05-31 15:32:48.341635368 -0500 @@ -277,8 +277,13 @@ unsigned int radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results, unsigned long *indices, @@ -8967,9 +13722,9 @@ diff -Nur linux-3.18.12.orig/include/linux/radix-tree.h linux-3.18.12/include/li } /** -diff -Nur linux-3.18.12.orig/include/linux/random.h linux-3.18.12/include/linux/random.h ---- linux-3.18.12.orig/include/linux/random.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/random.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/random.h linux-3.18.14-rt/include/linux/random.h +--- linux-3.18.14.orig/include/linux/random.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/random.h 2015-05-31 15:32:48.341635368 -0500 @@ -11,7 +11,7 @@ extern void add_device_randomness(const void *, unsigned int); extern void add_input_randomness(unsigned int type, unsigned int code, @@ -8979,9 +13734,9 @@ diff -Nur linux-3.18.12.orig/include/linux/random.h linux-3.18.12/include/linux/ extern void get_random_bytes(void *buf, int nbytes); extern void get_random_bytes_arch(void *buf, int nbytes); -diff -Nur linux-3.18.12.orig/include/linux/rcupdate.h linux-3.18.12/include/linux/rcupdate.h ---- linux-3.18.12.orig/include/linux/rcupdate.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/rcupdate.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/rcupdate.h linux-3.18.14-rt/include/linux/rcupdate.h +--- linux-3.18.14.orig/include/linux/rcupdate.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/rcupdate.h 2015-05-31 15:32:48.341635368 -0500 @@ -147,6 +147,9 @@ #endif /* #else #ifdef CONFIG_PREEMPT_RCU */ @@ -9066,9 +13821,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rcupdate.h linux-3.18.12/include/linu local_bh_enable(); } -diff -Nur linux-3.18.12.orig/include/linux/rcutree.h linux-3.18.12/include/linux/rcutree.h ---- linux-3.18.12.orig/include/linux/rcutree.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/rcutree.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/rcutree.h linux-3.18.14-rt/include/linux/rcutree.h +--- linux-3.18.14.orig/include/linux/rcutree.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/rcutree.h 2015-05-31 15:32:48.361635367 -0500 @@ -46,7 +46,11 @@ rcu_note_context_switch(cpu); } @@ -9119,9 +13874,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rcutree.h linux-3.18.12/include/linux +#endif + #endif /* __LINUX_RCUTREE_H */ -diff -Nur linux-3.18.12.orig/include/linux/rtmutex.h linux-3.18.12/include/linux/rtmutex.h ---- linux-3.18.12.orig/include/linux/rtmutex.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/rtmutex.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/rtmutex.h linux-3.18.14-rt/include/linux/rtmutex.h +--- linux-3.18.14.orig/include/linux/rtmutex.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/rtmutex.h 2015-05-31 15:32:48.377635367 -0500 @@ -14,10 +14,14 @@ #include <linux/linkage.h> @@ -9195,9 +13950,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rtmutex.h linux-3.18.12/include/linux extern int rt_mutex_timed_lock(struct rt_mutex *lock, struct hrtimer_sleeper *timeout); -diff -Nur linux-3.18.12.orig/include/linux/rwlock_rt.h linux-3.18.12/include/linux/rwlock_rt.h ---- linux-3.18.12.orig/include/linux/rwlock_rt.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/include/linux/rwlock_rt.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/rwlock_rt.h linux-3.18.14-rt/include/linux/rwlock_rt.h +--- linux-3.18.14.orig/include/linux/rwlock_rt.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/include/linux/rwlock_rt.h 2015-05-31 15:32:48.377635367 -0500 @@ -0,0 +1,99 @@ +#ifndef __LINUX_RWLOCK_RT_H +#define __LINUX_RWLOCK_RT_H @@ -9298,9 +14053,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rwlock_rt.h linux-3.18.12/include/lin + } while (0) + +#endif -diff -Nur linux-3.18.12.orig/include/linux/rwlock_types.h linux-3.18.12/include/linux/rwlock_types.h ---- linux-3.18.12.orig/include/linux/rwlock_types.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/rwlock_types.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/rwlock_types.h linux-3.18.14-rt/include/linux/rwlock_types.h +--- linux-3.18.14.orig/include/linux/rwlock_types.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/rwlock_types.h 2015-05-31 15:32:48.377635367 -0500 @@ -1,6 +1,10 @@ #ifndef __LINUX_RWLOCK_TYPES_H #define __LINUX_RWLOCK_TYPES_H @@ -9321,9 +14076,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rwlock_types.h linux-3.18.12/include/ + rwlock_t name __cacheline_aligned_in_smp = __RW_LOCK_UNLOCKED(name) #endif /* __LINUX_RWLOCK_TYPES_H */ -diff -Nur linux-3.18.12.orig/include/linux/rwlock_types_rt.h linux-3.18.12/include/linux/rwlock_types_rt.h ---- linux-3.18.12.orig/include/linux/rwlock_types_rt.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/include/linux/rwlock_types_rt.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/rwlock_types_rt.h linux-3.18.14-rt/include/linux/rwlock_types_rt.h +--- linux-3.18.14.orig/include/linux/rwlock_types_rt.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/include/linux/rwlock_types_rt.h 2015-05-31 15:32:48.377635367 -0500 @@ -0,0 +1,33 @@ +#ifndef __LINUX_RWLOCK_TYPES_RT_H +#define __LINUX_RWLOCK_TYPES_RT_H @@ -9358,9 +14113,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rwlock_types_rt.h linux-3.18.12/inclu + rwlock_t name __cacheline_aligned_in_smp = __RW_LOCK_UNLOCKED(name) + +#endif -diff -Nur linux-3.18.12.orig/include/linux/rwsem.h linux-3.18.12/include/linux/rwsem.h ---- linux-3.18.12.orig/include/linux/rwsem.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/rwsem.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/rwsem.h linux-3.18.14-rt/include/linux/rwsem.h +--- linux-3.18.14.orig/include/linux/rwsem.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/rwsem.h 2015-05-31 15:32:48.377635367 -0500 @@ -18,6 +18,10 @@ #include <linux/osq_lock.h> #endif @@ -9379,9 +14134,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rwsem.h linux-3.18.12/include/linux/r +#endif /* !PREEMPT_RT_FULL */ + #endif /* _LINUX_RWSEM_H */ -diff -Nur linux-3.18.12.orig/include/linux/rwsem_rt.h linux-3.18.12/include/linux/rwsem_rt.h ---- linux-3.18.12.orig/include/linux/rwsem_rt.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/include/linux/rwsem_rt.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/rwsem_rt.h linux-3.18.14-rt/include/linux/rwsem_rt.h +--- linux-3.18.14.orig/include/linux/rwsem_rt.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/include/linux/rwsem_rt.h 2015-05-31 15:32:48.377635367 -0500 @@ -0,0 +1,134 @@ +#ifndef _LINUX_RWSEM_RT_H +#define _LINUX_RWSEM_RT_H @@ -9517,9 +14272,9 @@ diff -Nur linux-3.18.12.orig/include/linux/rwsem_rt.h linux-3.18.12/include/linu +} +#endif +#endif -diff -Nur linux-3.18.12.orig/include/linux/sched.h linux-3.18.12/include/linux/sched.h ---- linux-3.18.12.orig/include/linux/sched.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/sched.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/sched.h linux-3.18.14-rt/include/linux/sched.h +--- linux-3.18.14.orig/include/linux/sched.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/sched.h 2015-05-31 15:32:48.381635367 -0500 @@ -26,6 +26,7 @@ #include <linux/nodemask.h> #include <linux/mm_types.h> @@ -9903,9 +14658,9 @@ diff -Nur linux-3.18.12.orig/include/linux/sched.h linux-3.18.12/include/linux/s extern long sched_setaffinity(pid_t pid, const struct cpumask *new_mask); extern long sched_getaffinity(pid_t pid, struct cpumask *mask); -diff -Nur linux-3.18.12.orig/include/linux/seqlock.h linux-3.18.12/include/linux/seqlock.h ---- linux-3.18.12.orig/include/linux/seqlock.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/seqlock.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/seqlock.h linux-3.18.14-rt/include/linux/seqlock.h +--- linux-3.18.14.orig/include/linux/seqlock.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/seqlock.h 2015-05-31 15:32:48.381635367 -0500 @@ -219,20 +219,30 @@ return __read_seqcount_retry(s, start); } @@ -10035,9 +14790,9 @@ diff -Nur linux-3.18.12.orig/include/linux/seqlock.h linux-3.18.12/include/linux spin_unlock_irqrestore(&sl->lock, flags); } -diff -Nur linux-3.18.12.orig/include/linux/signal.h linux-3.18.12/include/linux/signal.h ---- linux-3.18.12.orig/include/linux/signal.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/signal.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/signal.h linux-3.18.14-rt/include/linux/signal.h +--- linux-3.18.14.orig/include/linux/signal.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/signal.h 2015-05-31 15:32:48.381635367 -0500 @@ -218,6 +218,7 @@ } @@ -10046,9 +14801,9 @@ diff -Nur linux-3.18.12.orig/include/linux/signal.h linux-3.18.12/include/linux/ /* Test if 'sig' is valid signal. Use this instead of testing _NSIG directly */ static inline int valid_signal(unsigned long sig) -diff -Nur linux-3.18.12.orig/include/linux/skbuff.h linux-3.18.12/include/linux/skbuff.h ---- linux-3.18.12.orig/include/linux/skbuff.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/skbuff.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/skbuff.h linux-3.18.14-rt/include/linux/skbuff.h +--- linux-3.18.14.orig/include/linux/skbuff.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/skbuff.h 2015-05-31 15:32:48.405635367 -0500 @@ -172,6 +172,7 @@ __u32 qlen; @@ -10057,7 +14812,7 @@ diff -Nur linux-3.18.12.orig/include/linux/skbuff.h linux-3.18.12/include/linux/ }; struct sk_buff; -@@ -1327,6 +1328,12 @@ +@@ -1328,6 +1329,12 @@ __skb_queue_head_init(list); } @@ -10070,9 +14825,3377 @@ diff -Nur linux-3.18.12.orig/include/linux/skbuff.h linux-3.18.12/include/linux/ static inline void skb_queue_head_init_class(struct sk_buff_head *list, struct lock_class_key *class) { -diff -Nur linux-3.18.12.orig/include/linux/smp.h linux-3.18.12/include/linux/smp.h ---- linux-3.18.12.orig/include/linux/smp.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/smp.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/skbuff.h.orig linux-3.18.14-rt/include/linux/skbuff.h.orig +--- linux-3.18.14.orig/include/linux/skbuff.h.orig 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/include/linux/skbuff.h.orig 2015-05-20 10:04:50.000000000 -0500 +@@ -0,0 +1,3364 @@ ++/* ++ * Definitions for the 'struct sk_buff' memory handlers. ++ * ++ * Authors: ++ * Alan Cox, <gw4pts@gw4pts.ampr.org> ++ * Florian La Roche, <rzsfl@rz.uni-sb.de> ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. ++ */ ++ ++#ifndef _LINUX_SKBUFF_H ++#define _LINUX_SKBUFF_H ++ ++#include <linux/kernel.h> ++#include <linux/kmemcheck.h> ++#include <linux/compiler.h> ++#include <linux/time.h> ++#include <linux/bug.h> ++#include <linux/cache.h> ++ ++#include <linux/atomic.h> ++#include <asm/types.h> ++#include <linux/spinlock.h> ++#include <linux/net.h> ++#include <linux/textsearch.h> ++#include <net/checksum.h> ++#include <linux/rcupdate.h> ++#include <linux/hrtimer.h> ++#include <linux/dma-mapping.h> ++#include <linux/netdev_features.h> ++#include <linux/sched.h> ++#include <net/flow_keys.h> ++ ++/* A. Checksumming of received packets by device. ++ * ++ * CHECKSUM_NONE: ++ * ++ * Device failed to checksum this packet e.g. due to lack of capabilities. ++ * The packet contains full (though not verified) checksum in packet but ++ * not in skb->csum. Thus, skb->csum is undefined in this case. ++ * ++ * CHECKSUM_UNNECESSARY: ++ * ++ * The hardware you're dealing with doesn't calculate the full checksum ++ * (as in CHECKSUM_COMPLETE), but it does parse headers and verify checksums ++ * for specific protocols. For such packets it will set CHECKSUM_UNNECESSARY ++ * if their checksums are okay. skb->csum is still undefined in this case ++ * though. It is a bad option, but, unfortunately, nowadays most vendors do ++ * this. Apparently with the secret goal to sell you new devices, when you ++ * will add new protocol to your host, f.e. IPv6 8) ++ * ++ * CHECKSUM_UNNECESSARY is applicable to following protocols: ++ * TCP: IPv6 and IPv4. ++ * UDP: IPv4 and IPv6. A device may apply CHECKSUM_UNNECESSARY to a ++ * zero UDP checksum for either IPv4 or IPv6, the networking stack ++ * may perform further validation in this case. ++ * GRE: only if the checksum is present in the header. ++ * SCTP: indicates the CRC in SCTP header has been validated. ++ * ++ * skb->csum_level indicates the number of consecutive checksums found in ++ * the packet minus one that have been verified as CHECKSUM_UNNECESSARY. ++ * For instance if a device receives an IPv6->UDP->GRE->IPv4->TCP packet ++ * and a device is able to verify the checksums for UDP (possibly zero), ++ * GRE (checksum flag is set), and TCP-- skb->csum_level would be set to ++ * two. If the device were only able to verify the UDP checksum and not ++ * GRE, either because it doesn't support GRE checksum of because GRE ++ * checksum is bad, skb->csum_level would be set to zero (TCP checksum is ++ * not considered in this case). ++ * ++ * CHECKSUM_COMPLETE: ++ * ++ * This is the most generic way. The device supplied checksum of the _whole_ ++ * packet as seen by netif_rx() and fills out in skb->csum. Meaning, the ++ * hardware doesn't need to parse L3/L4 headers to implement this. ++ * ++ * Note: Even if device supports only some protocols, but is able to produce ++ * skb->csum, it MUST use CHECKSUM_COMPLETE, not CHECKSUM_UNNECESSARY. ++ * ++ * CHECKSUM_PARTIAL: ++ * ++ * This is identical to the case for output below. This may occur on a packet ++ * received directly from another Linux OS, e.g., a virtualized Linux kernel ++ * on the same host. The packet can be treated in the same way as ++ * CHECKSUM_UNNECESSARY, except that on output (i.e., forwarding) the ++ * checksum must be filled in by the OS or the hardware. ++ * ++ * B. Checksumming on output. ++ * ++ * CHECKSUM_NONE: ++ * ++ * The skb was already checksummed by the protocol, or a checksum is not ++ * required. ++ * ++ * CHECKSUM_PARTIAL: ++ * ++ * The device is required to checksum the packet as seen by hard_start_xmit() ++ * from skb->csum_start up to the end, and to record/write the checksum at ++ * offset skb->csum_start + skb->csum_offset. ++ * ++ * The device must show its capabilities in dev->features, set up at device ++ * setup time, e.g. netdev_features.h: ++ * ++ * NETIF_F_HW_CSUM - It's a clever device, it's able to checksum everything. ++ * NETIF_F_IP_CSUM - Device is dumb, it's able to checksum only TCP/UDP over ++ * IPv4. Sigh. Vendors like this way for an unknown reason. ++ * Though, see comment above about CHECKSUM_UNNECESSARY. 8) ++ * NETIF_F_IPV6_CSUM - About as dumb as the last one but does IPv6 instead. ++ * NETIF_F_... - Well, you get the picture. ++ * ++ * CHECKSUM_UNNECESSARY: ++ * ++ * Normally, the device will do per protocol specific checksumming. Protocol ++ * implementations that do not want the NIC to perform the checksum ++ * calculation should use this flag in their outgoing skbs. ++ * ++ * NETIF_F_FCOE_CRC - This indicates that the device can do FCoE FC CRC ++ * offload. Correspondingly, the FCoE protocol driver ++ * stack should use CHECKSUM_UNNECESSARY. ++ * ++ * Any questions? No questions, good. --ANK ++ */ ++ ++/* Don't change this without changing skb_csum_unnecessary! */ ++#define CHECKSUM_NONE 0 ++#define CHECKSUM_UNNECESSARY 1 ++#define CHECKSUM_COMPLETE 2 ++#define CHECKSUM_PARTIAL 3 ++ ++/* Maximum value in skb->csum_level */ ++#define SKB_MAX_CSUM_LEVEL 3 ++ ++#define SKB_DATA_ALIGN(X) ALIGN(X, SMP_CACHE_BYTES) ++#define SKB_WITH_OVERHEAD(X) \ ++ ((X) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) ++#define SKB_MAX_ORDER(X, ORDER) \ ++ SKB_WITH_OVERHEAD((PAGE_SIZE << (ORDER)) - (X)) ++#define SKB_MAX_HEAD(X) (SKB_MAX_ORDER((X), 0)) ++#define SKB_MAX_ALLOC (SKB_MAX_ORDER(0, 2)) ++ ++/* return minimum truesize of one skb containing X bytes of data */ ++#define SKB_TRUESIZE(X) ((X) + \ ++ SKB_DATA_ALIGN(sizeof(struct sk_buff)) + \ ++ SKB_DATA_ALIGN(sizeof(struct skb_shared_info))) ++ ++struct net_device; ++struct scatterlist; ++struct pipe_inode_info; ++ ++#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) ++struct nf_conntrack { ++ atomic_t use; ++}; ++#endif ++ ++#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) ++struct nf_bridge_info { ++ atomic_t use; ++ unsigned int mask; ++ struct net_device *physindev; ++ struct net_device *physoutdev; ++ unsigned long data[32 / sizeof(unsigned long)]; ++}; ++#endif ++ ++struct sk_buff_head { ++ /* These two members must be first. */ ++ struct sk_buff *next; ++ struct sk_buff *prev; ++ ++ __u32 qlen; ++ spinlock_t lock; ++}; ++ ++struct sk_buff; ++ ++/* To allow 64K frame to be packed as single skb without frag_list we ++ * require 64K/PAGE_SIZE pages plus 1 additional page to allow for ++ * buffers which do not start on a page boundary. ++ * ++ * Since GRO uses frags we allocate at least 16 regardless of page ++ * size. ++ */ ++#if (65536/PAGE_SIZE + 1) < 16 ++#define MAX_SKB_FRAGS 16UL ++#else ++#define MAX_SKB_FRAGS (65536/PAGE_SIZE + 1) ++#endif ++ ++typedef struct skb_frag_struct skb_frag_t; ++ ++struct skb_frag_struct { ++ struct { ++ struct page *p; ++ } page; ++#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536) ++ __u32 page_offset; ++ __u32 size; ++#else ++ __u16 page_offset; ++ __u16 size; ++#endif ++}; ++ ++static inline unsigned int skb_frag_size(const skb_frag_t *frag) ++{ ++ return frag->size; ++} ++ ++static inline void skb_frag_size_set(skb_frag_t *frag, unsigned int size) ++{ ++ frag->size = size; ++} ++ ++static inline void skb_frag_size_add(skb_frag_t *frag, int delta) ++{ ++ frag->size += delta; ++} ++ ++static inline void skb_frag_size_sub(skb_frag_t *frag, int delta) ++{ ++ frag->size -= delta; ++} ++ ++#define HAVE_HW_TIME_STAMP ++ ++/** ++ * struct skb_shared_hwtstamps - hardware time stamps ++ * @hwtstamp: hardware time stamp transformed into duration ++ * since arbitrary point in time ++ * ++ * Software time stamps generated by ktime_get_real() are stored in ++ * skb->tstamp. ++ * ++ * hwtstamps can only be compared against other hwtstamps from ++ * the same device. ++ * ++ * This structure is attached to packets as part of the ++ * &skb_shared_info. Use skb_hwtstamps() to get a pointer. ++ */ ++struct skb_shared_hwtstamps { ++ ktime_t hwtstamp; ++}; ++ ++/* Definitions for tx_flags in struct skb_shared_info */ ++enum { ++ /* generate hardware time stamp */ ++ SKBTX_HW_TSTAMP = 1 << 0, ++ ++ /* generate software time stamp when queueing packet to NIC */ ++ SKBTX_SW_TSTAMP = 1 << 1, ++ ++ /* device driver is going to provide hardware time stamp */ ++ SKBTX_IN_PROGRESS = 1 << 2, ++ ++ /* device driver supports TX zero-copy buffers */ ++ SKBTX_DEV_ZEROCOPY = 1 << 3, ++ ++ /* generate wifi status information (where possible) */ ++ SKBTX_WIFI_STATUS = 1 << 4, ++ ++ /* This indicates at least one fragment might be overwritten ++ * (as in vmsplice(), sendfile() ...) ++ * If we need to compute a TX checksum, we'll need to copy ++ * all frags to avoid possible bad checksum ++ */ ++ SKBTX_SHARED_FRAG = 1 << 5, ++ ++ /* generate software time stamp when entering packet scheduling */ ++ SKBTX_SCHED_TSTAMP = 1 << 6, ++ ++ /* generate software timestamp on peer data acknowledgment */ ++ SKBTX_ACK_TSTAMP = 1 << 7, ++}; ++ ++#define SKBTX_ANY_SW_TSTAMP (SKBTX_SW_TSTAMP | \ ++ SKBTX_SCHED_TSTAMP | \ ++ SKBTX_ACK_TSTAMP) ++#define SKBTX_ANY_TSTAMP (SKBTX_HW_TSTAMP | SKBTX_ANY_SW_TSTAMP) ++ ++/* ++ * The callback notifies userspace to release buffers when skb DMA is done in ++ * lower device, the skb last reference should be 0 when calling this. ++ * The zerocopy_success argument is true if zero copy transmit occurred, ++ * false on data copy or out of memory error caused by data copy attempt. ++ * The ctx field is used to track device context. ++ * The desc field is used to track userspace buffer index. ++ */ ++struct ubuf_info { ++ void (*callback)(struct ubuf_info *, bool zerocopy_success); ++ void *ctx; ++ unsigned long desc; ++}; ++ ++/* This data is invariant across clones and lives at ++ * the end of the header data, ie. at skb->end. ++ */ ++struct skb_shared_info { ++ unsigned char nr_frags; ++ __u8 tx_flags; ++ unsigned short gso_size; ++ /* Warning: this field is not always filled in (UFO)! */ ++ unsigned short gso_segs; ++ unsigned short gso_type; ++ struct sk_buff *frag_list; ++ struct skb_shared_hwtstamps hwtstamps; ++ u32 tskey; ++ __be32 ip6_frag_id; ++ ++ /* ++ * Warning : all fields before dataref are cleared in __alloc_skb() ++ */ ++ atomic_t dataref; ++ ++ /* Intermediate layers must ensure that destructor_arg ++ * remains valid until skb destructor */ ++ void * destructor_arg; ++ ++ /* must be last field, see pskb_expand_head() */ ++ skb_frag_t frags[MAX_SKB_FRAGS]; ++}; ++ ++/* We divide dataref into two halves. The higher 16 bits hold references ++ * to the payload part of skb->data. The lower 16 bits hold references to ++ * the entire skb->data. A clone of a headerless skb holds the length of ++ * the header in skb->hdr_len. ++ * ++ * All users must obey the rule that the skb->data reference count must be ++ * greater than or equal to the payload reference count. ++ * ++ * Holding a reference to the payload part means that the user does not ++ * care about modifications to the header part of skb->data. ++ */ ++#define SKB_DATAREF_SHIFT 16 ++#define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1) ++ ++ ++enum { ++ SKB_FCLONE_UNAVAILABLE, /* skb has no fclone (from head_cache) */ ++ SKB_FCLONE_ORIG, /* orig skb (from fclone_cache) */ ++ SKB_FCLONE_CLONE, /* companion fclone skb (from fclone_cache) */ ++ SKB_FCLONE_FREE, /* this companion fclone skb is available */ ++}; ++ ++enum { ++ SKB_GSO_TCPV4 = 1 << 0, ++ SKB_GSO_UDP = 1 << 1, ++ ++ /* This indicates the skb is from an untrusted source. */ ++ SKB_GSO_DODGY = 1 << 2, ++ ++ /* This indicates the tcp segment has CWR set. */ ++ SKB_GSO_TCP_ECN = 1 << 3, ++ ++ SKB_GSO_TCPV6 = 1 << 4, ++ ++ SKB_GSO_FCOE = 1 << 5, ++ ++ SKB_GSO_GRE = 1 << 6, ++ ++ SKB_GSO_GRE_CSUM = 1 << 7, ++ ++ SKB_GSO_IPIP = 1 << 8, ++ ++ SKB_GSO_SIT = 1 << 9, ++ ++ SKB_GSO_UDP_TUNNEL = 1 << 10, ++ ++ SKB_GSO_UDP_TUNNEL_CSUM = 1 << 11, ++ ++ SKB_GSO_MPLS = 1 << 12, ++ ++}; ++ ++#if BITS_PER_LONG > 32 ++#define NET_SKBUFF_DATA_USES_OFFSET 1 ++#endif ++ ++#ifdef NET_SKBUFF_DATA_USES_OFFSET ++typedef unsigned int sk_buff_data_t; ++#else ++typedef unsigned char *sk_buff_data_t; ++#endif ++ ++/** ++ * struct skb_mstamp - multi resolution time stamps ++ * @stamp_us: timestamp in us resolution ++ * @stamp_jiffies: timestamp in jiffies ++ */ ++struct skb_mstamp { ++ union { ++ u64 v64; ++ struct { ++ u32 stamp_us; ++ u32 stamp_jiffies; ++ }; ++ }; ++}; ++ ++/** ++ * skb_mstamp_get - get current timestamp ++ * @cl: place to store timestamps ++ */ ++static inline void skb_mstamp_get(struct skb_mstamp *cl) ++{ ++ u64 val = local_clock(); ++ ++ do_div(val, NSEC_PER_USEC); ++ cl->stamp_us = (u32)val; ++ cl->stamp_jiffies = (u32)jiffies; ++} ++ ++/** ++ * skb_mstamp_delta - compute the difference in usec between two skb_mstamp ++ * @t1: pointer to newest sample ++ * @t0: pointer to oldest sample ++ */ ++static inline u32 skb_mstamp_us_delta(const struct skb_mstamp *t1, ++ const struct skb_mstamp *t0) ++{ ++ s32 delta_us = t1->stamp_us - t0->stamp_us; ++ u32 delta_jiffies = t1->stamp_jiffies - t0->stamp_jiffies; ++ ++ /* If delta_us is negative, this might be because interval is too big, ++ * or local_clock() drift is too big : fallback using jiffies. ++ */ ++ if (delta_us <= 0 || ++ delta_jiffies >= (INT_MAX / (USEC_PER_SEC / HZ))) ++ ++ delta_us = jiffies_to_usecs(delta_jiffies); ++ ++ return delta_us; ++} ++ ++ ++/** ++ * struct sk_buff - socket buffer ++ * @next: Next buffer in list ++ * @prev: Previous buffer in list ++ * @tstamp: Time we arrived/left ++ * @sk: Socket we are owned by ++ * @dev: Device we arrived on/are leaving by ++ * @cb: Control buffer. Free for use by every layer. Put private vars here ++ * @_skb_refdst: destination entry (with norefcount bit) ++ * @sp: the security path, used for xfrm ++ * @len: Length of actual data ++ * @data_len: Data length ++ * @mac_len: Length of link layer header ++ * @hdr_len: writable header length of cloned skb ++ * @csum: Checksum (must include start/offset pair) ++ * @csum_start: Offset from skb->head where checksumming should start ++ * @csum_offset: Offset from csum_start where checksum should be stored ++ * @priority: Packet queueing priority ++ * @ignore_df: allow local fragmentation ++ * @cloned: Head may be cloned (check refcnt to be sure) ++ * @ip_summed: Driver fed us an IP checksum ++ * @nohdr: Payload reference only, must not modify header ++ * @nfctinfo: Relationship of this skb to the connection ++ * @pkt_type: Packet class ++ * @fclone: skbuff clone status ++ * @ipvs_property: skbuff is owned by ipvs ++ * @peeked: this packet has been seen already, so stats have been ++ * done for it, don't do them again ++ * @nf_trace: netfilter packet trace flag ++ * @protocol: Packet protocol from driver ++ * @destructor: Destruct function ++ * @nfct: Associated connection, if any ++ * @nf_bridge: Saved data about a bridged frame - see br_netfilter.c ++ * @skb_iif: ifindex of device we arrived on ++ * @tc_index: Traffic control index ++ * @tc_verd: traffic control verdict ++ * @hash: the packet hash ++ * @queue_mapping: Queue mapping for multiqueue devices ++ * @xmit_more: More SKBs are pending for this queue ++ * @ndisc_nodetype: router type (from link layer) ++ * @ooo_okay: allow the mapping of a socket to a queue to be changed ++ * @l4_hash: indicate hash is a canonical 4-tuple hash over transport ++ * ports. ++ * @sw_hash: indicates hash was computed in software stack ++ * @wifi_acked_valid: wifi_acked was set ++ * @wifi_acked: whether frame was acked on wifi or not ++ * @no_fcs: Request NIC to treat last 4 bytes as Ethernet FCS ++ * @napi_id: id of the NAPI struct this skb came from ++ * @secmark: security marking ++ * @mark: Generic packet mark ++ * @dropcount: total number of sk_receive_queue overflows ++ * @vlan_proto: vlan encapsulation protocol ++ * @vlan_tci: vlan tag control information ++ * @inner_protocol: Protocol (encapsulation) ++ * @inner_transport_header: Inner transport layer header (encapsulation) ++ * @inner_network_header: Network layer header (encapsulation) ++ * @inner_mac_header: Link layer header (encapsulation) ++ * @transport_header: Transport layer header ++ * @network_header: Network layer header ++ * @mac_header: Link layer header ++ * @tail: Tail pointer ++ * @end: End pointer ++ * @head: Head of buffer ++ * @data: Data head pointer ++ * @truesize: Buffer size ++ * @users: User count - see {datagram,tcp}.c ++ */ ++ ++struct sk_buff { ++ /* These two members must be first. */ ++ struct sk_buff *next; ++ struct sk_buff *prev; ++ ++ union { ++ ktime_t tstamp; ++ struct skb_mstamp skb_mstamp; ++ }; ++ ++ struct sock *sk; ++ struct net_device *dev; ++ ++ /* ++ * This is the control buffer. It is free to use for every ++ * layer. Please put your private variables there. If you ++ * want to keep them across layers you have to do a skb_clone() ++ * first. This is owned by whoever has the skb queued ATM. ++ */ ++ char cb[48] __aligned(8); ++ ++ unsigned long _skb_refdst; ++ void (*destructor)(struct sk_buff *skb); ++#ifdef CONFIG_XFRM ++ struct sec_path *sp; ++#endif ++#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) ++ struct nf_conntrack *nfct; ++#endif ++#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) ++ struct nf_bridge_info *nf_bridge; ++#endif ++ unsigned int len, ++ data_len; ++ __u16 mac_len, ++ hdr_len; ++ ++ /* Following fields are _not_ copied in __copy_skb_header() ++ * Note that queue_mapping is here mostly to fill a hole. ++ */ ++ kmemcheck_bitfield_begin(flags1); ++ __u16 queue_mapping; ++ __u8 cloned:1, ++ nohdr:1, ++ fclone:2, ++ peeked:1, ++ head_frag:1, ++ xmit_more:1; ++ /* one bit hole */ ++ kmemcheck_bitfield_end(flags1); ++ ++ /* fields enclosed in headers_start/headers_end are copied ++ * using a single memcpy() in __copy_skb_header() ++ */ ++ /* private: */ ++ __u32 headers_start[0]; ++ /* public: */ ++ ++/* if you move pkt_type around you also must adapt those constants */ ++#ifdef __BIG_ENDIAN_BITFIELD ++#define PKT_TYPE_MAX (7 << 5) ++#else ++#define PKT_TYPE_MAX 7 ++#endif ++#define PKT_TYPE_OFFSET() offsetof(struct sk_buff, __pkt_type_offset) ++ ++ __u8 __pkt_type_offset[0]; ++ __u8 pkt_type:3; ++ __u8 pfmemalloc:1; ++ __u8 ignore_df:1; ++ __u8 nfctinfo:3; ++ ++ __u8 nf_trace:1; ++ __u8 ip_summed:2; ++ __u8 ooo_okay:1; ++ __u8 l4_hash:1; ++ __u8 sw_hash:1; ++ __u8 wifi_acked_valid:1; ++ __u8 wifi_acked:1; ++ ++ __u8 no_fcs:1; ++ /* Indicates the inner headers are valid in the skbuff. */ ++ __u8 encapsulation:1; ++ __u8 encap_hdr_csum:1; ++ __u8 csum_valid:1; ++ __u8 csum_complete_sw:1; ++ __u8 csum_level:2; ++ __u8 csum_bad:1; ++ ++#ifdef CONFIG_IPV6_NDISC_NODETYPE ++ __u8 ndisc_nodetype:2; ++#endif ++ __u8 ipvs_property:1; ++ __u8 inner_protocol_type:1; ++ /* 4 or 6 bit hole */ ++ ++#ifdef CONFIG_NET_SCHED ++ __u16 tc_index; /* traffic control index */ ++#ifdef CONFIG_NET_CLS_ACT ++ __u16 tc_verd; /* traffic control verdict */ ++#endif ++#endif ++ ++ union { ++ __wsum csum; ++ struct { ++ __u16 csum_start; ++ __u16 csum_offset; ++ }; ++ }; ++ __u32 priority; ++ int skb_iif; ++ __u32 hash; ++ __be16 vlan_proto; ++ __u16 vlan_tci; ++#ifdef CONFIG_NET_RX_BUSY_POLL ++ unsigned int napi_id; ++#endif ++#ifdef CONFIG_NETWORK_SECMARK ++ __u32 secmark; ++#endif ++ union { ++ __u32 mark; ++ __u32 dropcount; ++ __u32 reserved_tailroom; ++ }; ++ ++ union { ++ __be16 inner_protocol; ++ __u8 inner_ipproto; ++ }; ++ ++ __u16 inner_transport_header; ++ __u16 inner_network_header; ++ __u16 inner_mac_header; ++ ++ __be16 protocol; ++ __u16 transport_header; ++ __u16 network_header; ++ __u16 mac_header; ++ ++ /* private: */ ++ __u32 headers_end[0]; ++ /* public: */ ++ ++ /* These elements must be at the end, see alloc_skb() for details. */ ++ sk_buff_data_t tail; ++ sk_buff_data_t end; ++ unsigned char *head, ++ *data; ++ unsigned int truesize; ++ atomic_t users; ++}; ++ ++#ifdef __KERNEL__ ++/* ++ * Handling routines are only of interest to the kernel ++ */ ++#include <linux/slab.h> ++ ++ ++#define SKB_ALLOC_FCLONE 0x01 ++#define SKB_ALLOC_RX 0x02 ++ ++/* Returns true if the skb was allocated from PFMEMALLOC reserves */ ++static inline bool skb_pfmemalloc(const struct sk_buff *skb) ++{ ++ return unlikely(skb->pfmemalloc); ++} ++ ++/* ++ * skb might have a dst pointer attached, refcounted or not. ++ * _skb_refdst low order bit is set if refcount was _not_ taken ++ */ ++#define SKB_DST_NOREF 1UL ++#define SKB_DST_PTRMASK ~(SKB_DST_NOREF) ++ ++/** ++ * skb_dst - returns skb dst_entry ++ * @skb: buffer ++ * ++ * Returns skb dst_entry, regardless of reference taken or not. ++ */ ++static inline struct dst_entry *skb_dst(const struct sk_buff *skb) ++{ ++ /* If refdst was not refcounted, check we still are in a ++ * rcu_read_lock section ++ */ ++ WARN_ON((skb->_skb_refdst & SKB_DST_NOREF) && ++ !rcu_read_lock_held() && ++ !rcu_read_lock_bh_held()); ++ return (struct dst_entry *)(skb->_skb_refdst & SKB_DST_PTRMASK); ++} ++ ++/** ++ * skb_dst_set - sets skb dst ++ * @skb: buffer ++ * @dst: dst entry ++ * ++ * Sets skb dst, assuming a reference was taken on dst and should ++ * be released by skb_dst_drop() ++ */ ++static inline void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst) ++{ ++ skb->_skb_refdst = (unsigned long)dst; ++} ++ ++void __skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst, ++ bool force); ++ ++/** ++ * skb_dst_set_noref - sets skb dst, hopefully, without taking reference ++ * @skb: buffer ++ * @dst: dst entry ++ * ++ * Sets skb dst, assuming a reference was not taken on dst. ++ * If dst entry is cached, we do not take reference and dst_release ++ * will be avoided by refdst_drop. If dst entry is not cached, we take ++ * reference, so that last dst_release can destroy the dst immediately. ++ */ ++static inline void skb_dst_set_noref(struct sk_buff *skb, struct dst_entry *dst) ++{ ++ __skb_dst_set_noref(skb, dst, false); ++} ++ ++/** ++ * skb_dst_set_noref_force - sets skb dst, without taking reference ++ * @skb: buffer ++ * @dst: dst entry ++ * ++ * Sets skb dst, assuming a reference was not taken on dst. ++ * No reference is taken and no dst_release will be called. While for ++ * cached dsts deferred reclaim is a basic feature, for entries that are ++ * not cached it is caller's job to guarantee that last dst_release for ++ * provided dst happens when nobody uses it, eg. after a RCU grace period. ++ */ ++static inline void skb_dst_set_noref_force(struct sk_buff *skb, ++ struct dst_entry *dst) ++{ ++ __skb_dst_set_noref(skb, dst, true); ++} ++ ++/** ++ * skb_dst_is_noref - Test if skb dst isn't refcounted ++ * @skb: buffer ++ */ ++static inline bool skb_dst_is_noref(const struct sk_buff *skb) ++{ ++ return (skb->_skb_refdst & SKB_DST_NOREF) && skb_dst(skb); ++} ++ ++static inline struct rtable *skb_rtable(const struct sk_buff *skb) ++{ ++ return (struct rtable *)skb_dst(skb); ++} ++ ++void kfree_skb(struct sk_buff *skb); ++void kfree_skb_list(struct sk_buff *segs); ++void skb_tx_error(struct sk_buff *skb); ++void consume_skb(struct sk_buff *skb); ++void __kfree_skb(struct sk_buff *skb); ++extern struct kmem_cache *skbuff_head_cache; ++ ++void kfree_skb_partial(struct sk_buff *skb, bool head_stolen); ++bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, ++ bool *fragstolen, int *delta_truesize); ++ ++struct sk_buff *__alloc_skb(unsigned int size, gfp_t priority, int flags, ++ int node); ++struct sk_buff *__build_skb(void *data, unsigned int frag_size); ++struct sk_buff *build_skb(void *data, unsigned int frag_size); ++static inline struct sk_buff *alloc_skb(unsigned int size, ++ gfp_t priority) ++{ ++ return __alloc_skb(size, priority, 0, NUMA_NO_NODE); ++} ++ ++struct sk_buff *alloc_skb_with_frags(unsigned long header_len, ++ unsigned long data_len, ++ int max_page_order, ++ int *errcode, ++ gfp_t gfp_mask); ++ ++/* Layout of fast clones : [skb1][skb2][fclone_ref] */ ++struct sk_buff_fclones { ++ struct sk_buff skb1; ++ ++ struct sk_buff skb2; ++ ++ atomic_t fclone_ref; ++}; ++ ++/** ++ * skb_fclone_busy - check if fclone is busy ++ * @skb: buffer ++ * ++ * Returns true is skb is a fast clone, and its clone is not freed. ++ * Some drivers call skb_orphan() in their ndo_start_xmit(), ++ * so we also check that this didnt happen. ++ */ ++static inline bool skb_fclone_busy(const struct sock *sk, ++ const struct sk_buff *skb) ++{ ++ const struct sk_buff_fclones *fclones; ++ ++ fclones = container_of(skb, struct sk_buff_fclones, skb1); ++ ++ return skb->fclone == SKB_FCLONE_ORIG && ++ fclones->skb2.fclone == SKB_FCLONE_CLONE && ++ fclones->skb2.sk == sk; ++} ++ ++static inline struct sk_buff *alloc_skb_fclone(unsigned int size, ++ gfp_t priority) ++{ ++ return __alloc_skb(size, priority, SKB_ALLOC_FCLONE, NUMA_NO_NODE); ++} ++ ++struct sk_buff *__alloc_skb_head(gfp_t priority, int node); ++static inline struct sk_buff *alloc_skb_head(gfp_t priority) ++{ ++ return __alloc_skb_head(priority, -1); ++} ++ ++struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src); ++int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask); ++struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t priority); ++struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t priority); ++struct sk_buff *__pskb_copy_fclone(struct sk_buff *skb, int headroom, ++ gfp_t gfp_mask, bool fclone); ++static inline struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom, ++ gfp_t gfp_mask) ++{ ++ return __pskb_copy_fclone(skb, headroom, gfp_mask, false); ++} ++ ++int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, gfp_t gfp_mask); ++struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, ++ unsigned int headroom); ++struct sk_buff *skb_copy_expand(const struct sk_buff *skb, int newheadroom, ++ int newtailroom, gfp_t priority); ++int skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg, ++ int offset, int len); ++int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, ++ int len); ++int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer); ++int skb_pad(struct sk_buff *skb, int pad); ++#define dev_kfree_skb(a) consume_skb(a) ++ ++int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, ++ int getfrag(void *from, char *to, int offset, ++ int len, int odd, struct sk_buff *skb), ++ void *from, int length); ++ ++struct skb_seq_state { ++ __u32 lower_offset; ++ __u32 upper_offset; ++ __u32 frag_idx; ++ __u32 stepped_offset; ++ struct sk_buff *root_skb; ++ struct sk_buff *cur_skb; ++ __u8 *frag_data; ++}; ++ ++void skb_prepare_seq_read(struct sk_buff *skb, unsigned int from, ++ unsigned int to, struct skb_seq_state *st); ++unsigned int skb_seq_read(unsigned int consumed, const u8 **data, ++ struct skb_seq_state *st); ++void skb_abort_seq_read(struct skb_seq_state *st); ++ ++unsigned int skb_find_text(struct sk_buff *skb, unsigned int from, ++ unsigned int to, struct ts_config *config, ++ struct ts_state *state); ++ ++/* ++ * Packet hash types specify the type of hash in skb_set_hash. ++ * ++ * Hash types refer to the protocol layer addresses which are used to ++ * construct a packet's hash. The hashes are used to differentiate or identify ++ * flows of the protocol layer for the hash type. Hash types are either ++ * layer-2 (L2), layer-3 (L3), or layer-4 (L4). ++ * ++ * Properties of hashes: ++ * ++ * 1) Two packets in different flows have different hash values ++ * 2) Two packets in the same flow should have the same hash value ++ * ++ * A hash at a higher layer is considered to be more specific. A driver should ++ * set the most specific hash possible. ++ * ++ * A driver cannot indicate a more specific hash than the layer at which a hash ++ * was computed. For instance an L3 hash cannot be set as an L4 hash. ++ * ++ * A driver may indicate a hash level which is less specific than the ++ * actual layer the hash was computed on. For instance, a hash computed ++ * at L4 may be considered an L3 hash. This should only be done if the ++ * driver can't unambiguously determine that the HW computed the hash at ++ * the higher layer. Note that the "should" in the second property above ++ * permits this. ++ */ ++enum pkt_hash_types { ++ PKT_HASH_TYPE_NONE, /* Undefined type */ ++ PKT_HASH_TYPE_L2, /* Input: src_MAC, dest_MAC */ ++ PKT_HASH_TYPE_L3, /* Input: src_IP, dst_IP */ ++ PKT_HASH_TYPE_L4, /* Input: src_IP, dst_IP, src_port, dst_port */ ++}; ++ ++static inline void ++skb_set_hash(struct sk_buff *skb, __u32 hash, enum pkt_hash_types type) ++{ ++ skb->l4_hash = (type == PKT_HASH_TYPE_L4); ++ skb->sw_hash = 0; ++ skb->hash = hash; ++} ++ ++void __skb_get_hash(struct sk_buff *skb); ++static inline __u32 skb_get_hash(struct sk_buff *skb) ++{ ++ if (!skb->l4_hash && !skb->sw_hash) ++ __skb_get_hash(skb); ++ ++ return skb->hash; ++} ++ ++static inline __u32 skb_get_hash_raw(const struct sk_buff *skb) ++{ ++ return skb->hash; ++} ++ ++static inline void skb_clear_hash(struct sk_buff *skb) ++{ ++ skb->hash = 0; ++ skb->sw_hash = 0; ++ skb->l4_hash = 0; ++} ++ ++static inline void skb_clear_hash_if_not_l4(struct sk_buff *skb) ++{ ++ if (!skb->l4_hash) ++ skb_clear_hash(skb); ++} ++ ++static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from) ++{ ++ to->hash = from->hash; ++ to->sw_hash = from->sw_hash; ++ to->l4_hash = from->l4_hash; ++}; ++ ++#ifdef NET_SKBUFF_DATA_USES_OFFSET ++static inline unsigned char *skb_end_pointer(const struct sk_buff *skb) ++{ ++ return skb->head + skb->end; ++} ++ ++static inline unsigned int skb_end_offset(const struct sk_buff *skb) ++{ ++ return skb->end; ++} ++#else ++static inline unsigned char *skb_end_pointer(const struct sk_buff *skb) ++{ ++ return skb->end; ++} ++ ++static inline unsigned int skb_end_offset(const struct sk_buff *skb) ++{ ++ return skb->end - skb->head; ++} ++#endif ++ ++/* Internal */ ++#define skb_shinfo(SKB) ((struct skb_shared_info *)(skb_end_pointer(SKB))) ++ ++static inline struct skb_shared_hwtstamps *skb_hwtstamps(struct sk_buff *skb) ++{ ++ return &skb_shinfo(skb)->hwtstamps; ++} ++ ++/** ++ * skb_queue_empty - check if a queue is empty ++ * @list: queue head ++ * ++ * Returns true if the queue is empty, false otherwise. ++ */ ++static inline int skb_queue_empty(const struct sk_buff_head *list) ++{ ++ return list->next == (const struct sk_buff *) list; ++} ++ ++/** ++ * skb_queue_is_last - check if skb is the last entry in the queue ++ * @list: queue head ++ * @skb: buffer ++ * ++ * Returns true if @skb is the last buffer on the list. ++ */ ++static inline bool skb_queue_is_last(const struct sk_buff_head *list, ++ const struct sk_buff *skb) ++{ ++ return skb->next == (const struct sk_buff *) list; ++} ++ ++/** ++ * skb_queue_is_first - check if skb is the first entry in the queue ++ * @list: queue head ++ * @skb: buffer ++ * ++ * Returns true if @skb is the first buffer on the list. ++ */ ++static inline bool skb_queue_is_first(const struct sk_buff_head *list, ++ const struct sk_buff *skb) ++{ ++ return skb->prev == (const struct sk_buff *) list; ++} ++ ++/** ++ * skb_queue_next - return the next packet in the queue ++ * @list: queue head ++ * @skb: current buffer ++ * ++ * Return the next packet in @list after @skb. It is only valid to ++ * call this if skb_queue_is_last() evaluates to false. ++ */ ++static inline struct sk_buff *skb_queue_next(const struct sk_buff_head *list, ++ const struct sk_buff *skb) ++{ ++ /* This BUG_ON may seem severe, but if we just return then we ++ * are going to dereference garbage. ++ */ ++ BUG_ON(skb_queue_is_last(list, skb)); ++ return skb->next; ++} ++ ++/** ++ * skb_queue_prev - return the prev packet in the queue ++ * @list: queue head ++ * @skb: current buffer ++ * ++ * Return the prev packet in @list before @skb. It is only valid to ++ * call this if skb_queue_is_first() evaluates to false. ++ */ ++static inline struct sk_buff *skb_queue_prev(const struct sk_buff_head *list, ++ const struct sk_buff *skb) ++{ ++ /* This BUG_ON may seem severe, but if we just return then we ++ * are going to dereference garbage. ++ */ ++ BUG_ON(skb_queue_is_first(list, skb)); ++ return skb->prev; ++} ++ ++/** ++ * skb_get - reference buffer ++ * @skb: buffer to reference ++ * ++ * Makes another reference to a socket buffer and returns a pointer ++ * to the buffer. ++ */ ++static inline struct sk_buff *skb_get(struct sk_buff *skb) ++{ ++ atomic_inc(&skb->users); ++ return skb; ++} ++ ++/* ++ * If users == 1, we are the only owner and are can avoid redundant ++ * atomic change. ++ */ ++ ++/** ++ * skb_cloned - is the buffer a clone ++ * @skb: buffer to check ++ * ++ * Returns true if the buffer was generated with skb_clone() and is ++ * one of multiple shared copies of the buffer. Cloned buffers are ++ * shared data so must not be written to under normal circumstances. ++ */ ++static inline int skb_cloned(const struct sk_buff *skb) ++{ ++ return skb->cloned && ++ (atomic_read(&skb_shinfo(skb)->dataref) & SKB_DATAREF_MASK) != 1; ++} ++ ++static inline int skb_unclone(struct sk_buff *skb, gfp_t pri) ++{ ++ might_sleep_if(pri & __GFP_WAIT); ++ ++ if (skb_cloned(skb)) ++ return pskb_expand_head(skb, 0, 0, pri); ++ ++ return 0; ++} ++ ++/** ++ * skb_header_cloned - is the header a clone ++ * @skb: buffer to check ++ * ++ * Returns true if modifying the header part of the buffer requires ++ * the data to be copied. ++ */ ++static inline int skb_header_cloned(const struct sk_buff *skb) ++{ ++ int dataref; ++ ++ if (!skb->cloned) ++ return 0; ++ ++ dataref = atomic_read(&skb_shinfo(skb)->dataref); ++ dataref = (dataref & SKB_DATAREF_MASK) - (dataref >> SKB_DATAREF_SHIFT); ++ return dataref != 1; ++} ++ ++/** ++ * skb_header_release - release reference to header ++ * @skb: buffer to operate on ++ * ++ * Drop a reference to the header part of the buffer. This is done ++ * by acquiring a payload reference. You must not read from the header ++ * part of skb->data after this. ++ * Note : Check if you can use __skb_header_release() instead. ++ */ ++static inline void skb_header_release(struct sk_buff *skb) ++{ ++ BUG_ON(skb->nohdr); ++ skb->nohdr = 1; ++ atomic_add(1 << SKB_DATAREF_SHIFT, &skb_shinfo(skb)->dataref); ++} ++ ++/** ++ * __skb_header_release - release reference to header ++ * @skb: buffer to operate on ++ * ++ * Variant of skb_header_release() assuming skb is private to caller. ++ * We can avoid one atomic operation. ++ */ ++static inline void __skb_header_release(struct sk_buff *skb) ++{ ++ skb->nohdr = 1; ++ atomic_set(&skb_shinfo(skb)->dataref, 1 + (1 << SKB_DATAREF_SHIFT)); ++} ++ ++ ++/** ++ * skb_shared - is the buffer shared ++ * @skb: buffer to check ++ * ++ * Returns true if more than one person has a reference to this ++ * buffer. ++ */ ++static inline int skb_shared(const struct sk_buff *skb) ++{ ++ return atomic_read(&skb->users) != 1; ++} ++ ++/** ++ * skb_share_check - check if buffer is shared and if so clone it ++ * @skb: buffer to check ++ * @pri: priority for memory allocation ++ * ++ * If the buffer is shared the buffer is cloned and the old copy ++ * drops a reference. A new clone with a single reference is returned. ++ * If the buffer is not shared the original buffer is returned. When ++ * being called from interrupt status or with spinlocks held pri must ++ * be GFP_ATOMIC. ++ * ++ * NULL is returned on a memory allocation failure. ++ */ ++static inline struct sk_buff *skb_share_check(struct sk_buff *skb, gfp_t pri) ++{ ++ might_sleep_if(pri & __GFP_WAIT); ++ if (skb_shared(skb)) { ++ struct sk_buff *nskb = skb_clone(skb, pri); ++ ++ if (likely(nskb)) ++ consume_skb(skb); ++ else ++ kfree_skb(skb); ++ skb = nskb; ++ } ++ return skb; ++} ++ ++/* ++ * Copy shared buffers into a new sk_buff. We effectively do COW on ++ * packets to handle cases where we have a local reader and forward ++ * and a couple of other messy ones. The normal one is tcpdumping ++ * a packet thats being forwarded. ++ */ ++ ++/** ++ * skb_unshare - make a copy of a shared buffer ++ * @skb: buffer to check ++ * @pri: priority for memory allocation ++ * ++ * If the socket buffer is a clone then this function creates a new ++ * copy of the data, drops a reference count on the old copy and returns ++ * the new copy with the reference count at 1. If the buffer is not a clone ++ * the original buffer is returned. When called with a spinlock held or ++ * from interrupt state @pri must be %GFP_ATOMIC ++ * ++ * %NULL is returned on a memory allocation failure. ++ */ ++static inline struct sk_buff *skb_unshare(struct sk_buff *skb, ++ gfp_t pri) ++{ ++ might_sleep_if(pri & __GFP_WAIT); ++ if (skb_cloned(skb)) { ++ struct sk_buff *nskb = skb_copy(skb, pri); ++ ++ /* Free our shared copy */ ++ if (likely(nskb)) ++ consume_skb(skb); ++ else ++ kfree_skb(skb); ++ skb = nskb; ++ } ++ return skb; ++} ++ ++/** ++ * skb_peek - peek at the head of an &sk_buff_head ++ * @list_: list to peek at ++ * ++ * Peek an &sk_buff. Unlike most other operations you _MUST_ ++ * be careful with this one. A peek leaves the buffer on the ++ * list and someone else may run off with it. You must hold ++ * the appropriate locks or have a private queue to do this. ++ * ++ * Returns %NULL for an empty list or a pointer to the head element. ++ * The reference count is not incremented and the reference is therefore ++ * volatile. Use with caution. ++ */ ++static inline struct sk_buff *skb_peek(const struct sk_buff_head *list_) ++{ ++ struct sk_buff *skb = list_->next; ++ ++ if (skb == (struct sk_buff *)list_) ++ skb = NULL; ++ return skb; ++} ++ ++/** ++ * skb_peek_next - peek skb following the given one from a queue ++ * @skb: skb to start from ++ * @list_: list to peek at ++ * ++ * Returns %NULL when the end of the list is met or a pointer to the ++ * next element. The reference count is not incremented and the ++ * reference is therefore volatile. Use with caution. ++ */ ++static inline struct sk_buff *skb_peek_next(struct sk_buff *skb, ++ const struct sk_buff_head *list_) ++{ ++ struct sk_buff *next = skb->next; ++ ++ if (next == (struct sk_buff *)list_) ++ next = NULL; ++ return next; ++} ++ ++/** ++ * skb_peek_tail - peek at the tail of an &sk_buff_head ++ * @list_: list to peek at ++ * ++ * Peek an &sk_buff. Unlike most other operations you _MUST_ ++ * be careful with this one. A peek leaves the buffer on the ++ * list and someone else may run off with it. You must hold ++ * the appropriate locks or have a private queue to do this. ++ * ++ * Returns %NULL for an empty list or a pointer to the tail element. ++ * The reference count is not incremented and the reference is therefore ++ * volatile. Use with caution. ++ */ ++static inline struct sk_buff *skb_peek_tail(const struct sk_buff_head *list_) ++{ ++ struct sk_buff *skb = list_->prev; ++ ++ if (skb == (struct sk_buff *)list_) ++ skb = NULL; ++ return skb; ++ ++} ++ ++/** ++ * skb_queue_len - get queue length ++ * @list_: list to measure ++ * ++ * Return the length of an &sk_buff queue. ++ */ ++static inline __u32 skb_queue_len(const struct sk_buff_head *list_) ++{ ++ return list_->qlen; ++} ++ ++/** ++ * __skb_queue_head_init - initialize non-spinlock portions of sk_buff_head ++ * @list: queue to initialize ++ * ++ * This initializes only the list and queue length aspects of ++ * an sk_buff_head object. This allows to initialize the list ++ * aspects of an sk_buff_head without reinitializing things like ++ * the spinlock. It can also be used for on-stack sk_buff_head ++ * objects where the spinlock is known to not be used. ++ */ ++static inline void __skb_queue_head_init(struct sk_buff_head *list) ++{ ++ list->prev = list->next = (struct sk_buff *)list; ++ list->qlen = 0; ++} ++ ++/* ++ * This function creates a split out lock class for each invocation; ++ * this is needed for now since a whole lot of users of the skb-queue ++ * infrastructure in drivers have different locking usage (in hardirq) ++ * than the networking core (in softirq only). In the long run either the ++ * network layer or drivers should need annotation to consolidate the ++ * main types of usage into 3 classes. ++ */ ++static inline void skb_queue_head_init(struct sk_buff_head *list) ++{ ++ spin_lock_init(&list->lock); ++ __skb_queue_head_init(list); ++} ++ ++static inline void skb_queue_head_init_class(struct sk_buff_head *list, ++ struct lock_class_key *class) ++{ ++ skb_queue_head_init(list); ++ lockdep_set_class(&list->lock, class); ++} ++ ++/* ++ * Insert an sk_buff on a list. ++ * ++ * The "__skb_xxxx()" functions are the non-atomic ones that ++ * can only be called with interrupts disabled. ++ */ ++void skb_insert(struct sk_buff *old, struct sk_buff *newsk, ++ struct sk_buff_head *list); ++static inline void __skb_insert(struct sk_buff *newsk, ++ struct sk_buff *prev, struct sk_buff *next, ++ struct sk_buff_head *list) ++{ ++ newsk->next = next; ++ newsk->prev = prev; ++ next->prev = prev->next = newsk; ++ list->qlen++; ++} ++ ++static inline void __skb_queue_splice(const struct sk_buff_head *list, ++ struct sk_buff *prev, ++ struct sk_buff *next) ++{ ++ struct sk_buff *first = list->next; ++ struct sk_buff *last = list->prev; ++ ++ first->prev = prev; ++ prev->next = first; ++ ++ last->next = next; ++ next->prev = last; ++} ++ ++/** ++ * skb_queue_splice - join two skb lists, this is designed for stacks ++ * @list: the new list to add ++ * @head: the place to add it in the first list ++ */ ++static inline void skb_queue_splice(const struct sk_buff_head *list, ++ struct sk_buff_head *head) ++{ ++ if (!skb_queue_empty(list)) { ++ __skb_queue_splice(list, (struct sk_buff *) head, head->next); ++ head->qlen += list->qlen; ++ } ++} ++ ++/** ++ * skb_queue_splice_init - join two skb lists and reinitialise the emptied list ++ * @list: the new list to add ++ * @head: the place to add it in the first list ++ * ++ * The list at @list is reinitialised ++ */ ++static inline void skb_queue_splice_init(struct sk_buff_head *list, ++ struct sk_buff_head *head) ++{ ++ if (!skb_queue_empty(list)) { ++ __skb_queue_splice(list, (struct sk_buff *) head, head->next); ++ head->qlen += list->qlen; ++ __skb_queue_head_init(list); ++ } ++} ++ ++/** ++ * skb_queue_splice_tail - join two skb lists, each list being a queue ++ * @list: the new list to add ++ * @head: the place to add it in the first list ++ */ ++static inline void skb_queue_splice_tail(const struct sk_buff_head *list, ++ struct sk_buff_head *head) ++{ ++ if (!skb_queue_empty(list)) { ++ __skb_queue_splice(list, head->prev, (struct sk_buff *) head); ++ head->qlen += list->qlen; ++ } ++} ++ ++/** ++ * skb_queue_splice_tail_init - join two skb lists and reinitialise the emptied list ++ * @list: the new list to add ++ * @head: the place to add it in the first list ++ * ++ * Each of the lists is a queue. ++ * The list at @list is reinitialised ++ */ ++static inline void skb_queue_splice_tail_init(struct sk_buff_head *list, ++ struct sk_buff_head *head) ++{ ++ if (!skb_queue_empty(list)) { ++ __skb_queue_splice(list, head->prev, (struct sk_buff *) head); ++ head->qlen += list->qlen; ++ __skb_queue_head_init(list); ++ } ++} ++ ++/** ++ * __skb_queue_after - queue a buffer at the list head ++ * @list: list to use ++ * @prev: place after this buffer ++ * @newsk: buffer to queue ++ * ++ * Queue a buffer int the middle of a list. This function takes no locks ++ * and you must therefore hold required locks before calling it. ++ * ++ * A buffer cannot be placed on two lists at the same time. ++ */ ++static inline void __skb_queue_after(struct sk_buff_head *list, ++ struct sk_buff *prev, ++ struct sk_buff *newsk) ++{ ++ __skb_insert(newsk, prev, prev->next, list); ++} ++ ++void skb_append(struct sk_buff *old, struct sk_buff *newsk, ++ struct sk_buff_head *list); ++ ++static inline void __skb_queue_before(struct sk_buff_head *list, ++ struct sk_buff *next, ++ struct sk_buff *newsk) ++{ ++ __skb_insert(newsk, next->prev, next, list); ++} ++ ++/** ++ * __skb_queue_head - queue a buffer at the list head ++ * @list: list to use ++ * @newsk: buffer to queue ++ * ++ * Queue a buffer at the start of a list. This function takes no locks ++ * and you must therefore hold required locks before calling it. ++ * ++ * A buffer cannot be placed on two lists at the same time. ++ */ ++void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk); ++static inline void __skb_queue_head(struct sk_buff_head *list, ++ struct sk_buff *newsk) ++{ ++ __skb_queue_after(list, (struct sk_buff *)list, newsk); ++} ++ ++/** ++ * __skb_queue_tail - queue a buffer at the list tail ++ * @list: list to use ++ * @newsk: buffer to queue ++ * ++ * Queue a buffer at the end of a list. This function takes no locks ++ * and you must therefore hold required locks before calling it. ++ * ++ * A buffer cannot be placed on two lists at the same time. ++ */ ++void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk); ++static inline void __skb_queue_tail(struct sk_buff_head *list, ++ struct sk_buff *newsk) ++{ ++ __skb_queue_before(list, (struct sk_buff *)list, newsk); ++} ++ ++/* ++ * remove sk_buff from list. _Must_ be called atomically, and with ++ * the list known.. ++ */ ++void skb_unlink(struct sk_buff *skb, struct sk_buff_head *list); ++static inline void __skb_unlink(struct sk_buff *skb, struct sk_buff_head *list) ++{ ++ struct sk_buff *next, *prev; ++ ++ list->qlen--; ++ next = skb->next; ++ prev = skb->prev; ++ skb->next = skb->prev = NULL; ++ next->prev = prev; ++ prev->next = next; ++} ++ ++/** ++ * __skb_dequeue - remove from the head of the queue ++ * @list: list to dequeue from ++ * ++ * Remove the head of the list. This function does not take any locks ++ * so must be used with appropriate locks held only. The head item is ++ * returned or %NULL if the list is empty. ++ */ ++struct sk_buff *skb_dequeue(struct sk_buff_head *list); ++static inline struct sk_buff *__skb_dequeue(struct sk_buff_head *list) ++{ ++ struct sk_buff *skb = skb_peek(list); ++ if (skb) ++ __skb_unlink(skb, list); ++ return skb; ++} ++ ++/** ++ * __skb_dequeue_tail - remove from the tail of the queue ++ * @list: list to dequeue from ++ * ++ * Remove the tail of the list. This function does not take any locks ++ * so must be used with appropriate locks held only. The tail item is ++ * returned or %NULL if the list is empty. ++ */ ++struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list); ++static inline struct sk_buff *__skb_dequeue_tail(struct sk_buff_head *list) ++{ ++ struct sk_buff *skb = skb_peek_tail(list); ++ if (skb) ++ __skb_unlink(skb, list); ++ return skb; ++} ++ ++ ++static inline bool skb_is_nonlinear(const struct sk_buff *skb) ++{ ++ return skb->data_len; ++} ++ ++static inline unsigned int skb_headlen(const struct sk_buff *skb) ++{ ++ return skb->len - skb->data_len; ++} ++ ++static inline int skb_pagelen(const struct sk_buff *skb) ++{ ++ int i, len = 0; ++ ++ for (i = (int)skb_shinfo(skb)->nr_frags - 1; i >= 0; i--) ++ len += skb_frag_size(&skb_shinfo(skb)->frags[i]); ++ return len + skb_headlen(skb); ++} ++ ++/** ++ * __skb_fill_page_desc - initialise a paged fragment in an skb ++ * @skb: buffer containing fragment to be initialised ++ * @i: paged fragment index to initialise ++ * @page: the page to use for this fragment ++ * @off: the offset to the data with @page ++ * @size: the length of the data ++ * ++ * Initialises the @i'th fragment of @skb to point to &size bytes at ++ * offset @off within @page. ++ * ++ * Does not take any additional reference on the fragment. ++ */ ++static inline void __skb_fill_page_desc(struct sk_buff *skb, int i, ++ struct page *page, int off, int size) ++{ ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ ++ /* ++ * Propagate page->pfmemalloc to the skb if we can. The problem is ++ * that not all callers have unique ownership of the page. If ++ * pfmemalloc is set, we check the mapping as a mapping implies ++ * page->index is set (index and pfmemalloc share space). ++ * If it's a valid mapping, we cannot use page->pfmemalloc but we ++ * do not lose pfmemalloc information as the pages would not be ++ * allocated using __GFP_MEMALLOC. ++ */ ++ frag->page.p = page; ++ frag->page_offset = off; ++ skb_frag_size_set(frag, size); ++ ++ page = compound_head(page); ++ if (page->pfmemalloc && !page->mapping) ++ skb->pfmemalloc = true; ++} ++ ++/** ++ * skb_fill_page_desc - initialise a paged fragment in an skb ++ * @skb: buffer containing fragment to be initialised ++ * @i: paged fragment index to initialise ++ * @page: the page to use for this fragment ++ * @off: the offset to the data with @page ++ * @size: the length of the data ++ * ++ * As per __skb_fill_page_desc() -- initialises the @i'th fragment of ++ * @skb to point to @size bytes at offset @off within @page. In ++ * addition updates @skb such that @i is the last fragment. ++ * ++ * Does not take any additional reference on the fragment. ++ */ ++static inline void skb_fill_page_desc(struct sk_buff *skb, int i, ++ struct page *page, int off, int size) ++{ ++ __skb_fill_page_desc(skb, i, page, off, size); ++ skb_shinfo(skb)->nr_frags = i + 1; ++} ++ ++void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, ++ int size, unsigned int truesize); ++ ++void skb_coalesce_rx_frag(struct sk_buff *skb, int i, int size, ++ unsigned int truesize); ++ ++#define SKB_PAGE_ASSERT(skb) BUG_ON(skb_shinfo(skb)->nr_frags) ++#define SKB_FRAG_ASSERT(skb) BUG_ON(skb_has_frag_list(skb)) ++#define SKB_LINEAR_ASSERT(skb) BUG_ON(skb_is_nonlinear(skb)) ++ ++#ifdef NET_SKBUFF_DATA_USES_OFFSET ++static inline unsigned char *skb_tail_pointer(const struct sk_buff *skb) ++{ ++ return skb->head + skb->tail; ++} ++ ++static inline void skb_reset_tail_pointer(struct sk_buff *skb) ++{ ++ skb->tail = skb->data - skb->head; ++} ++ ++static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset) ++{ ++ skb_reset_tail_pointer(skb); ++ skb->tail += offset; ++} ++ ++#else /* NET_SKBUFF_DATA_USES_OFFSET */ ++static inline unsigned char *skb_tail_pointer(const struct sk_buff *skb) ++{ ++ return skb->tail; ++} ++ ++static inline void skb_reset_tail_pointer(struct sk_buff *skb) ++{ ++ skb->tail = skb->data; ++} ++ ++static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset) ++{ ++ skb->tail = skb->data + offset; ++} ++ ++#endif /* NET_SKBUFF_DATA_USES_OFFSET */ ++ ++/* ++ * Add data to an sk_buff ++ */ ++unsigned char *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len); ++unsigned char *skb_put(struct sk_buff *skb, unsigned int len); ++static inline unsigned char *__skb_put(struct sk_buff *skb, unsigned int len) ++{ ++ unsigned char *tmp = skb_tail_pointer(skb); ++ SKB_LINEAR_ASSERT(skb); ++ skb->tail += len; ++ skb->len += len; ++ return tmp; ++} ++ ++unsigned char *skb_push(struct sk_buff *skb, unsigned int len); ++static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len) ++{ ++ skb->data -= len; ++ skb->len += len; ++ return skb->data; ++} ++ ++unsigned char *skb_pull(struct sk_buff *skb, unsigned int len); ++static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) ++{ ++ skb->len -= len; ++ BUG_ON(skb->len < skb->data_len); ++ return skb->data += len; ++} ++ ++static inline unsigned char *skb_pull_inline(struct sk_buff *skb, unsigned int len) ++{ ++ return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len); ++} ++ ++unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta); ++ ++static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len) ++{ ++ if (len > skb_headlen(skb) && ++ !__pskb_pull_tail(skb, len - skb_headlen(skb))) ++ return NULL; ++ skb->len -= len; ++ return skb->data += len; ++} ++ ++static inline unsigned char *pskb_pull(struct sk_buff *skb, unsigned int len) ++{ ++ return unlikely(len > skb->len) ? NULL : __pskb_pull(skb, len); ++} ++ ++static inline int pskb_may_pull(struct sk_buff *skb, unsigned int len) ++{ ++ if (likely(len <= skb_headlen(skb))) ++ return 1; ++ if (unlikely(len > skb->len)) ++ return 0; ++ return __pskb_pull_tail(skb, len - skb_headlen(skb)) != NULL; ++} ++ ++/** ++ * skb_headroom - bytes at buffer head ++ * @skb: buffer to check ++ * ++ * Return the number of bytes of free space at the head of an &sk_buff. ++ */ ++static inline unsigned int skb_headroom(const struct sk_buff *skb) ++{ ++ return skb->data - skb->head; ++} ++ ++/** ++ * skb_tailroom - bytes at buffer end ++ * @skb: buffer to check ++ * ++ * Return the number of bytes of free space at the tail of an sk_buff ++ */ ++static inline int skb_tailroom(const struct sk_buff *skb) ++{ ++ return skb_is_nonlinear(skb) ? 0 : skb->end - skb->tail; ++} ++ ++/** ++ * skb_availroom - bytes at buffer end ++ * @skb: buffer to check ++ * ++ * Return the number of bytes of free space at the tail of an sk_buff ++ * allocated by sk_stream_alloc() ++ */ ++static inline int skb_availroom(const struct sk_buff *skb) ++{ ++ if (skb_is_nonlinear(skb)) ++ return 0; ++ ++ return skb->end - skb->tail - skb->reserved_tailroom; ++} ++ ++/** ++ * skb_reserve - adjust headroom ++ * @skb: buffer to alter ++ * @len: bytes to move ++ * ++ * Increase the headroom of an empty &sk_buff by reducing the tail ++ * room. This is only allowed for an empty buffer. ++ */ ++static inline void skb_reserve(struct sk_buff *skb, int len) ++{ ++ skb->data += len; ++ skb->tail += len; ++} ++ ++#define ENCAP_TYPE_ETHER 0 ++#define ENCAP_TYPE_IPPROTO 1 ++ ++static inline void skb_set_inner_protocol(struct sk_buff *skb, ++ __be16 protocol) ++{ ++ skb->inner_protocol = protocol; ++ skb->inner_protocol_type = ENCAP_TYPE_ETHER; ++} ++ ++static inline void skb_set_inner_ipproto(struct sk_buff *skb, ++ __u8 ipproto) ++{ ++ skb->inner_ipproto = ipproto; ++ skb->inner_protocol_type = ENCAP_TYPE_IPPROTO; ++} ++ ++static inline void skb_reset_inner_headers(struct sk_buff *skb) ++{ ++ skb->inner_mac_header = skb->mac_header; ++ skb->inner_network_header = skb->network_header; ++ skb->inner_transport_header = skb->transport_header; ++} ++ ++static inline void skb_reset_mac_len(struct sk_buff *skb) ++{ ++ skb->mac_len = skb->network_header - skb->mac_header; ++} ++ ++static inline unsigned char *skb_inner_transport_header(const struct sk_buff ++ *skb) ++{ ++ return skb->head + skb->inner_transport_header; ++} ++ ++static inline void skb_reset_inner_transport_header(struct sk_buff *skb) ++{ ++ skb->inner_transport_header = skb->data - skb->head; ++} ++ ++static inline void skb_set_inner_transport_header(struct sk_buff *skb, ++ const int offset) ++{ ++ skb_reset_inner_transport_header(skb); ++ skb->inner_transport_header += offset; ++} ++ ++static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb) ++{ ++ return skb->head + skb->inner_network_header; ++} ++ ++static inline void skb_reset_inner_network_header(struct sk_buff *skb) ++{ ++ skb->inner_network_header = skb->data - skb->head; ++} ++ ++static inline void skb_set_inner_network_header(struct sk_buff *skb, ++ const int offset) ++{ ++ skb_reset_inner_network_header(skb); ++ skb->inner_network_header += offset; ++} ++ ++static inline unsigned char *skb_inner_mac_header(const struct sk_buff *skb) ++{ ++ return skb->head + skb->inner_mac_header; ++} ++ ++static inline void skb_reset_inner_mac_header(struct sk_buff *skb) ++{ ++ skb->inner_mac_header = skb->data - skb->head; ++} ++ ++static inline void skb_set_inner_mac_header(struct sk_buff *skb, ++ const int offset) ++{ ++ skb_reset_inner_mac_header(skb); ++ skb->inner_mac_header += offset; ++} ++static inline bool skb_transport_header_was_set(const struct sk_buff *skb) ++{ ++ return skb->transport_header != (typeof(skb->transport_header))~0U; ++} ++ ++static inline unsigned char *skb_transport_header(const struct sk_buff *skb) ++{ ++ return skb->head + skb->transport_header; ++} ++ ++static inline void skb_reset_transport_header(struct sk_buff *skb) ++{ ++ skb->transport_header = skb->data - skb->head; ++} ++ ++static inline void skb_set_transport_header(struct sk_buff *skb, ++ const int offset) ++{ ++ skb_reset_transport_header(skb); ++ skb->transport_header += offset; ++} ++ ++static inline unsigned char *skb_network_header(const struct sk_buff *skb) ++{ ++ return skb->head + skb->network_header; ++} ++ ++static inline void skb_reset_network_header(struct sk_buff *skb) ++{ ++ skb->network_header = skb->data - skb->head; ++} ++ ++static inline void skb_set_network_header(struct sk_buff *skb, const int offset) ++{ ++ skb_reset_network_header(skb); ++ skb->network_header += offset; ++} ++ ++static inline unsigned char *skb_mac_header(const struct sk_buff *skb) ++{ ++ return skb->head + skb->mac_header; ++} ++ ++static inline int skb_mac_header_was_set(const struct sk_buff *skb) ++{ ++ return skb->mac_header != (typeof(skb->mac_header))~0U; ++} ++ ++static inline void skb_reset_mac_header(struct sk_buff *skb) ++{ ++ skb->mac_header = skb->data - skb->head; ++} ++ ++static inline void skb_set_mac_header(struct sk_buff *skb, const int offset) ++{ ++ skb_reset_mac_header(skb); ++ skb->mac_header += offset; ++} ++ ++static inline void skb_pop_mac_header(struct sk_buff *skb) ++{ ++ skb->mac_header = skb->network_header; ++} ++ ++static inline void skb_probe_transport_header(struct sk_buff *skb, ++ const int offset_hint) ++{ ++ struct flow_keys keys; ++ ++ if (skb_transport_header_was_set(skb)) ++ return; ++ else if (skb_flow_dissect(skb, &keys)) ++ skb_set_transport_header(skb, keys.thoff); ++ else ++ skb_set_transport_header(skb, offset_hint); ++} ++ ++static inline void skb_mac_header_rebuild(struct sk_buff *skb) ++{ ++ if (skb_mac_header_was_set(skb)) { ++ const unsigned char *old_mac = skb_mac_header(skb); ++ ++ skb_set_mac_header(skb, -skb->mac_len); ++ memmove(skb_mac_header(skb), old_mac, skb->mac_len); ++ } ++} ++ ++static inline int skb_checksum_start_offset(const struct sk_buff *skb) ++{ ++ return skb->csum_start - skb_headroom(skb); ++} ++ ++static inline int skb_transport_offset(const struct sk_buff *skb) ++{ ++ return skb_transport_header(skb) - skb->data; ++} ++ ++static inline u32 skb_network_header_len(const struct sk_buff *skb) ++{ ++ return skb->transport_header - skb->network_header; ++} ++ ++static inline u32 skb_inner_network_header_len(const struct sk_buff *skb) ++{ ++ return skb->inner_transport_header - skb->inner_network_header; ++} ++ ++static inline int skb_network_offset(const struct sk_buff *skb) ++{ ++ return skb_network_header(skb) - skb->data; ++} ++ ++static inline int skb_inner_network_offset(const struct sk_buff *skb) ++{ ++ return skb_inner_network_header(skb) - skb->data; ++} ++ ++static inline int pskb_network_may_pull(struct sk_buff *skb, unsigned int len) ++{ ++ return pskb_may_pull(skb, skb_network_offset(skb) + len); ++} ++ ++/* ++ * CPUs often take a performance hit when accessing unaligned memory ++ * locations. The actual performance hit varies, it can be small if the ++ * hardware handles it or large if we have to take an exception and fix it ++ * in software. ++ * ++ * Since an ethernet header is 14 bytes network drivers often end up with ++ * the IP header at an unaligned offset. The IP header can be aligned by ++ * shifting the start of the packet by 2 bytes. Drivers should do this ++ * with: ++ * ++ * skb_reserve(skb, NET_IP_ALIGN); ++ * ++ * The downside to this alignment of the IP header is that the DMA is now ++ * unaligned. On some architectures the cost of an unaligned DMA is high ++ * and this cost outweighs the gains made by aligning the IP header. ++ * ++ * Since this trade off varies between architectures, we allow NET_IP_ALIGN ++ * to be overridden. ++ */ ++#ifndef NET_IP_ALIGN ++#define NET_IP_ALIGN 2 ++#endif ++ ++/* ++ * The networking layer reserves some headroom in skb data (via ++ * dev_alloc_skb). This is used to avoid having to reallocate skb data when ++ * the header has to grow. In the default case, if the header has to grow ++ * 32 bytes or less we avoid the reallocation. ++ * ++ * Unfortunately this headroom changes the DMA alignment of the resulting ++ * network packet. As for NET_IP_ALIGN, this unaligned DMA is expensive ++ * on some architectures. An architecture can override this value, ++ * perhaps setting it to a cacheline in size (since that will maintain ++ * cacheline alignment of the DMA). It must be a power of 2. ++ * ++ * Various parts of the networking layer expect at least 32 bytes of ++ * headroom, you should not reduce this. ++ * ++ * Using max(32, L1_CACHE_BYTES) makes sense (especially with RPS) ++ * to reduce average number of cache lines per packet. ++ * get_rps_cpus() for example only access one 64 bytes aligned block : ++ * NET_IP_ALIGN(2) + ethernet_header(14) + IP_header(20/40) + ports(8) ++ */ ++#ifndef NET_SKB_PAD ++#define NET_SKB_PAD max(32, L1_CACHE_BYTES) ++#endif ++ ++int ___pskb_trim(struct sk_buff *skb, unsigned int len); ++ ++static inline void __skb_trim(struct sk_buff *skb, unsigned int len) ++{ ++ if (unlikely(skb_is_nonlinear(skb))) { ++ WARN_ON(1); ++ return; ++ } ++ skb->len = len; ++ skb_set_tail_pointer(skb, len); ++} ++ ++void skb_trim(struct sk_buff *skb, unsigned int len); ++ ++static inline int __pskb_trim(struct sk_buff *skb, unsigned int len) ++{ ++ if (skb->data_len) ++ return ___pskb_trim(skb, len); ++ __skb_trim(skb, len); ++ return 0; ++} ++ ++static inline int pskb_trim(struct sk_buff *skb, unsigned int len) ++{ ++ return (len < skb->len) ? __pskb_trim(skb, len) : 0; ++} ++ ++/** ++ * pskb_trim_unique - remove end from a paged unique (not cloned) buffer ++ * @skb: buffer to alter ++ * @len: new length ++ * ++ * This is identical to pskb_trim except that the caller knows that ++ * the skb is not cloned so we should never get an error due to out- ++ * of-memory. ++ */ ++static inline void pskb_trim_unique(struct sk_buff *skb, unsigned int len) ++{ ++ int err = pskb_trim(skb, len); ++ BUG_ON(err); ++} ++ ++/** ++ * skb_orphan - orphan a buffer ++ * @skb: buffer to orphan ++ * ++ * If a buffer currently has an owner then we call the owner's ++ * destructor function and make the @skb unowned. The buffer continues ++ * to exist but is no longer charged to its former owner. ++ */ ++static inline void skb_orphan(struct sk_buff *skb) ++{ ++ if (skb->destructor) { ++ skb->destructor(skb); ++ skb->destructor = NULL; ++ skb->sk = NULL; ++ } else { ++ BUG_ON(skb->sk); ++ } ++} ++ ++/** ++ * skb_orphan_frags - orphan the frags contained in a buffer ++ * @skb: buffer to orphan frags from ++ * @gfp_mask: allocation mask for replacement pages ++ * ++ * For each frag in the SKB which needs a destructor (i.e. has an ++ * owner) create a copy of that frag and release the original ++ * page by calling the destructor. ++ */ ++static inline int skb_orphan_frags(struct sk_buff *skb, gfp_t gfp_mask) ++{ ++ if (likely(!(skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY))) ++ return 0; ++ return skb_copy_ubufs(skb, gfp_mask); ++} ++ ++/** ++ * __skb_queue_purge - empty a list ++ * @list: list to empty ++ * ++ * Delete all buffers on an &sk_buff list. Each buffer is removed from ++ * the list and one reference dropped. This function does not take the ++ * list lock and the caller must hold the relevant locks to use it. ++ */ ++void skb_queue_purge(struct sk_buff_head *list); ++static inline void __skb_queue_purge(struct sk_buff_head *list) ++{ ++ struct sk_buff *skb; ++ while ((skb = __skb_dequeue(list)) != NULL) ++ kfree_skb(skb); ++} ++ ++#define NETDEV_FRAG_PAGE_MAX_ORDER get_order(32768) ++#define NETDEV_FRAG_PAGE_MAX_SIZE (PAGE_SIZE << NETDEV_FRAG_PAGE_MAX_ORDER) ++#define NETDEV_PAGECNT_MAX_BIAS NETDEV_FRAG_PAGE_MAX_SIZE ++ ++void *netdev_alloc_frag(unsigned int fragsz); ++ ++struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int length, ++ gfp_t gfp_mask); ++ ++/** ++ * netdev_alloc_skb - allocate an skbuff for rx on a specific device ++ * @dev: network device to receive on ++ * @length: length to allocate ++ * ++ * Allocate a new &sk_buff and assign it a usage count of one. The ++ * buffer has unspecified headroom built in. Users should allocate ++ * the headroom they think they need without accounting for the ++ * built in space. The built in space is used for optimisations. ++ * ++ * %NULL is returned if there is no free memory. Although this function ++ * allocates memory it can be called from an interrupt. ++ */ ++static inline struct sk_buff *netdev_alloc_skb(struct net_device *dev, ++ unsigned int length) ++{ ++ return __netdev_alloc_skb(dev, length, GFP_ATOMIC); ++} ++ ++/* legacy helper around __netdev_alloc_skb() */ ++static inline struct sk_buff *__dev_alloc_skb(unsigned int length, ++ gfp_t gfp_mask) ++{ ++ return __netdev_alloc_skb(NULL, length, gfp_mask); ++} ++ ++/* legacy helper around netdev_alloc_skb() */ ++static inline struct sk_buff *dev_alloc_skb(unsigned int length) ++{ ++ return netdev_alloc_skb(NULL, length); ++} ++ ++ ++static inline struct sk_buff *__netdev_alloc_skb_ip_align(struct net_device *dev, ++ unsigned int length, gfp_t gfp) ++{ ++ struct sk_buff *skb = __netdev_alloc_skb(dev, length + NET_IP_ALIGN, gfp); ++ ++ if (NET_IP_ALIGN && skb) ++ skb_reserve(skb, NET_IP_ALIGN); ++ return skb; ++} ++ ++static inline struct sk_buff *netdev_alloc_skb_ip_align(struct net_device *dev, ++ unsigned int length) ++{ ++ return __netdev_alloc_skb_ip_align(dev, length, GFP_ATOMIC); ++} ++ ++/** ++ * __skb_alloc_pages - allocate pages for ps-rx on a skb and preserve pfmemalloc data ++ * @gfp_mask: alloc_pages_node mask. Set __GFP_NOMEMALLOC if not for network packet RX ++ * @skb: skb to set pfmemalloc on if __GFP_MEMALLOC is used ++ * @order: size of the allocation ++ * ++ * Allocate a new page. ++ * ++ * %NULL is returned if there is no free memory. ++*/ ++static inline struct page *__skb_alloc_pages(gfp_t gfp_mask, ++ struct sk_buff *skb, ++ unsigned int order) ++{ ++ struct page *page; ++ ++ gfp_mask |= __GFP_COLD; ++ ++ if (!(gfp_mask & __GFP_NOMEMALLOC)) ++ gfp_mask |= __GFP_MEMALLOC; ++ ++ page = alloc_pages_node(NUMA_NO_NODE, gfp_mask, order); ++ if (skb && page && page->pfmemalloc) ++ skb->pfmemalloc = true; ++ ++ return page; ++} ++ ++/** ++ * __skb_alloc_page - allocate a page for ps-rx for a given skb and preserve pfmemalloc data ++ * @gfp_mask: alloc_pages_node mask. Set __GFP_NOMEMALLOC if not for network packet RX ++ * @skb: skb to set pfmemalloc on if __GFP_MEMALLOC is used ++ * ++ * Allocate a new page. ++ * ++ * %NULL is returned if there is no free memory. ++ */ ++static inline struct page *__skb_alloc_page(gfp_t gfp_mask, ++ struct sk_buff *skb) ++{ ++ return __skb_alloc_pages(gfp_mask, skb, 0); ++} ++ ++/** ++ * skb_propagate_pfmemalloc - Propagate pfmemalloc if skb is allocated after RX page ++ * @page: The page that was allocated from skb_alloc_page ++ * @skb: The skb that may need pfmemalloc set ++ */ ++static inline void skb_propagate_pfmemalloc(struct page *page, ++ struct sk_buff *skb) ++{ ++ if (page && page->pfmemalloc) ++ skb->pfmemalloc = true; ++} ++ ++/** ++ * skb_frag_page - retrieve the page referred to by a paged fragment ++ * @frag: the paged fragment ++ * ++ * Returns the &struct page associated with @frag. ++ */ ++static inline struct page *skb_frag_page(const skb_frag_t *frag) ++{ ++ return frag->page.p; ++} ++ ++/** ++ * __skb_frag_ref - take an addition reference on a paged fragment. ++ * @frag: the paged fragment ++ * ++ * Takes an additional reference on the paged fragment @frag. ++ */ ++static inline void __skb_frag_ref(skb_frag_t *frag) ++{ ++ get_page(skb_frag_page(frag)); ++} ++ ++/** ++ * skb_frag_ref - take an addition reference on a paged fragment of an skb. ++ * @skb: the buffer ++ * @f: the fragment offset. ++ * ++ * Takes an additional reference on the @f'th paged fragment of @skb. ++ */ ++static inline void skb_frag_ref(struct sk_buff *skb, int f) ++{ ++ __skb_frag_ref(&skb_shinfo(skb)->frags[f]); ++} ++ ++/** ++ * __skb_frag_unref - release a reference on a paged fragment. ++ * @frag: the paged fragment ++ * ++ * Releases a reference on the paged fragment @frag. ++ */ ++static inline void __skb_frag_unref(skb_frag_t *frag) ++{ ++ put_page(skb_frag_page(frag)); ++} ++ ++/** ++ * skb_frag_unref - release a reference on a paged fragment of an skb. ++ * @skb: the buffer ++ * @f: the fragment offset ++ * ++ * Releases a reference on the @f'th paged fragment of @skb. ++ */ ++static inline void skb_frag_unref(struct sk_buff *skb, int f) ++{ ++ __skb_frag_unref(&skb_shinfo(skb)->frags[f]); ++} ++ ++/** ++ * skb_frag_address - gets the address of the data contained in a paged fragment ++ * @frag: the paged fragment buffer ++ * ++ * Returns the address of the data within @frag. The page must already ++ * be mapped. ++ */ ++static inline void *skb_frag_address(const skb_frag_t *frag) ++{ ++ return page_address(skb_frag_page(frag)) + frag->page_offset; ++} ++ ++/** ++ * skb_frag_address_safe - gets the address of the data contained in a paged fragment ++ * @frag: the paged fragment buffer ++ * ++ * Returns the address of the data within @frag. Checks that the page ++ * is mapped and returns %NULL otherwise. ++ */ ++static inline void *skb_frag_address_safe(const skb_frag_t *frag) ++{ ++ void *ptr = page_address(skb_frag_page(frag)); ++ if (unlikely(!ptr)) ++ return NULL; ++ ++ return ptr + frag->page_offset; ++} ++ ++/** ++ * __skb_frag_set_page - sets the page contained in a paged fragment ++ * @frag: the paged fragment ++ * @page: the page to set ++ * ++ * Sets the fragment @frag to contain @page. ++ */ ++static inline void __skb_frag_set_page(skb_frag_t *frag, struct page *page) ++{ ++ frag->page.p = page; ++} ++ ++/** ++ * skb_frag_set_page - sets the page contained in a paged fragment of an skb ++ * @skb: the buffer ++ * @f: the fragment offset ++ * @page: the page to set ++ * ++ * Sets the @f'th fragment of @skb to contain @page. ++ */ ++static inline void skb_frag_set_page(struct sk_buff *skb, int f, ++ struct page *page) ++{ ++ __skb_frag_set_page(&skb_shinfo(skb)->frags[f], page); ++} ++ ++bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio); ++ ++/** ++ * skb_frag_dma_map - maps a paged fragment via the DMA API ++ * @dev: the device to map the fragment to ++ * @frag: the paged fragment to map ++ * @offset: the offset within the fragment (starting at the ++ * fragment's own offset) ++ * @size: the number of bytes to map ++ * @dir: the direction of the mapping (%PCI_DMA_*) ++ * ++ * Maps the page associated with @frag to @device. ++ */ ++static inline dma_addr_t skb_frag_dma_map(struct device *dev, ++ const skb_frag_t *frag, ++ size_t offset, size_t size, ++ enum dma_data_direction dir) ++{ ++ return dma_map_page(dev, skb_frag_page(frag), ++ frag->page_offset + offset, size, dir); ++} ++ ++static inline struct sk_buff *pskb_copy(struct sk_buff *skb, ++ gfp_t gfp_mask) ++{ ++ return __pskb_copy(skb, skb_headroom(skb), gfp_mask); ++} ++ ++ ++static inline struct sk_buff *pskb_copy_for_clone(struct sk_buff *skb, ++ gfp_t gfp_mask) ++{ ++ return __pskb_copy_fclone(skb, skb_headroom(skb), gfp_mask, true); ++} ++ ++ ++/** ++ * skb_clone_writable - is the header of a clone writable ++ * @skb: buffer to check ++ * @len: length up to which to write ++ * ++ * Returns true if modifying the header part of the cloned buffer ++ * does not requires the data to be copied. ++ */ ++static inline int skb_clone_writable(const struct sk_buff *skb, unsigned int len) ++{ ++ return !skb_header_cloned(skb) && ++ skb_headroom(skb) + len <= skb->hdr_len; ++} ++ ++static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom, ++ int cloned) ++{ ++ int delta = 0; ++ ++ if (headroom > skb_headroom(skb)) ++ delta = headroom - skb_headroom(skb); ++ ++ if (delta || cloned) ++ return pskb_expand_head(skb, ALIGN(delta, NET_SKB_PAD), 0, ++ GFP_ATOMIC); ++ return 0; ++} ++ ++/** ++ * skb_cow - copy header of skb when it is required ++ * @skb: buffer to cow ++ * @headroom: needed headroom ++ * ++ * If the skb passed lacks sufficient headroom or its data part ++ * is shared, data is reallocated. If reallocation fails, an error ++ * is returned and original skb is not changed. ++ * ++ * The result is skb with writable area skb->head...skb->tail ++ * and at least @headroom of space at head. ++ */ ++static inline int skb_cow(struct sk_buff *skb, unsigned int headroom) ++{ ++ return __skb_cow(skb, headroom, skb_cloned(skb)); ++} ++ ++/** ++ * skb_cow_head - skb_cow but only making the head writable ++ * @skb: buffer to cow ++ * @headroom: needed headroom ++ * ++ * This function is identical to skb_cow except that we replace the ++ * skb_cloned check by skb_header_cloned. It should be used when ++ * you only need to push on some header and do not need to modify ++ * the data. ++ */ ++static inline int skb_cow_head(struct sk_buff *skb, unsigned int headroom) ++{ ++ return __skb_cow(skb, headroom, skb_header_cloned(skb)); ++} ++ ++/** ++ * skb_padto - pad an skbuff up to a minimal size ++ * @skb: buffer to pad ++ * @len: minimal length ++ * ++ * Pads up a buffer to ensure the trailing bytes exist and are ++ * blanked. If the buffer already contains sufficient data it ++ * is untouched. Otherwise it is extended. Returns zero on ++ * success. The skb is freed on error. ++ */ ++ ++static inline int skb_padto(struct sk_buff *skb, unsigned int len) ++{ ++ unsigned int size = skb->len; ++ if (likely(size >= len)) ++ return 0; ++ return skb_pad(skb, len - size); ++} ++ ++static inline int skb_add_data(struct sk_buff *skb, ++ char __user *from, int copy) ++{ ++ const int off = skb->len; ++ ++ if (skb->ip_summed == CHECKSUM_NONE) { ++ int err = 0; ++ __wsum csum = csum_and_copy_from_user(from, skb_put(skb, copy), ++ copy, 0, &err); ++ if (!err) { ++ skb->csum = csum_block_add(skb->csum, csum, off); ++ return 0; ++ } ++ } else if (!copy_from_user(skb_put(skb, copy), from, copy)) ++ return 0; ++ ++ __skb_trim(skb, off); ++ return -EFAULT; ++} ++ ++static inline bool skb_can_coalesce(struct sk_buff *skb, int i, ++ const struct page *page, int off) ++{ ++ if (i) { ++ const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1]; ++ ++ return page == skb_frag_page(frag) && ++ off == frag->page_offset + skb_frag_size(frag); ++ } ++ return false; ++} ++ ++static inline int __skb_linearize(struct sk_buff *skb) ++{ ++ return __pskb_pull_tail(skb, skb->data_len) ? 0 : -ENOMEM; ++} ++ ++/** ++ * skb_linearize - convert paged skb to linear one ++ * @skb: buffer to linarize ++ * ++ * If there is no free memory -ENOMEM is returned, otherwise zero ++ * is returned and the old skb data released. ++ */ ++static inline int skb_linearize(struct sk_buff *skb) ++{ ++ return skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0; ++} ++ ++/** ++ * skb_has_shared_frag - can any frag be overwritten ++ * @skb: buffer to test ++ * ++ * Return true if the skb has at least one frag that might be modified ++ * by an external entity (as in vmsplice()/sendfile()) ++ */ ++static inline bool skb_has_shared_frag(const struct sk_buff *skb) ++{ ++ return skb_is_nonlinear(skb) && ++ skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG; ++} ++ ++/** ++ * skb_linearize_cow - make sure skb is linear and writable ++ * @skb: buffer to process ++ * ++ * If there is no free memory -ENOMEM is returned, otherwise zero ++ * is returned and the old skb data released. ++ */ ++static inline int skb_linearize_cow(struct sk_buff *skb) ++{ ++ return skb_is_nonlinear(skb) || skb_cloned(skb) ? ++ __skb_linearize(skb) : 0; ++} ++ ++/** ++ * skb_postpull_rcsum - update checksum for received skb after pull ++ * @skb: buffer to update ++ * @start: start of data before pull ++ * @len: length of data pulled ++ * ++ * After doing a pull on a received packet, you need to call this to ++ * update the CHECKSUM_COMPLETE checksum, or set ip_summed to ++ * CHECKSUM_NONE so that it can be recomputed from scratch. ++ */ ++ ++static inline void skb_postpull_rcsum(struct sk_buff *skb, ++ const void *start, unsigned int len) ++{ ++ if (skb->ip_summed == CHECKSUM_COMPLETE) ++ skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0)); ++} ++ ++unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len); ++ ++/** ++ * pskb_trim_rcsum - trim received skb and update checksum ++ * @skb: buffer to trim ++ * @len: new length ++ * ++ * This is exactly the same as pskb_trim except that it ensures the ++ * checksum of received packets are still valid after the operation. ++ */ ++ ++static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len) ++{ ++ if (likely(len >= skb->len)) ++ return 0; ++ if (skb->ip_summed == CHECKSUM_COMPLETE) ++ skb->ip_summed = CHECKSUM_NONE; ++ return __pskb_trim(skb, len); ++} ++ ++#define skb_queue_walk(queue, skb) \ ++ for (skb = (queue)->next; \ ++ skb != (struct sk_buff *)(queue); \ ++ skb = skb->next) ++ ++#define skb_queue_walk_safe(queue, skb, tmp) \ ++ for (skb = (queue)->next, tmp = skb->next; \ ++ skb != (struct sk_buff *)(queue); \ ++ skb = tmp, tmp = skb->next) ++ ++#define skb_queue_walk_from(queue, skb) \ ++ for (; skb != (struct sk_buff *)(queue); \ ++ skb = skb->next) ++ ++#define skb_queue_walk_from_safe(queue, skb, tmp) \ ++ for (tmp = skb->next; \ ++ skb != (struct sk_buff *)(queue); \ ++ skb = tmp, tmp = skb->next) ++ ++#define skb_queue_reverse_walk(queue, skb) \ ++ for (skb = (queue)->prev; \ ++ skb != (struct sk_buff *)(queue); \ ++ skb = skb->prev) ++ ++#define skb_queue_reverse_walk_safe(queue, skb, tmp) \ ++ for (skb = (queue)->prev, tmp = skb->prev; \ ++ skb != (struct sk_buff *)(queue); \ ++ skb = tmp, tmp = skb->prev) ++ ++#define skb_queue_reverse_walk_from_safe(queue, skb, tmp) \ ++ for (tmp = skb->prev; \ ++ skb != (struct sk_buff *)(queue); \ ++ skb = tmp, tmp = skb->prev) ++ ++static inline bool skb_has_frag_list(const struct sk_buff *skb) ++{ ++ return skb_shinfo(skb)->frag_list != NULL; ++} ++ ++static inline void skb_frag_list_init(struct sk_buff *skb) ++{ ++ skb_shinfo(skb)->frag_list = NULL; ++} ++ ++static inline void skb_frag_add_head(struct sk_buff *skb, struct sk_buff *frag) ++{ ++ frag->next = skb_shinfo(skb)->frag_list; ++ skb_shinfo(skb)->frag_list = frag; ++} ++ ++#define skb_walk_frags(skb, iter) \ ++ for (iter = skb_shinfo(skb)->frag_list; iter; iter = iter->next) ++ ++struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags, ++ int *peeked, int *off, int *err); ++struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, ++ int *err); ++unsigned int datagram_poll(struct file *file, struct socket *sock, ++ struct poll_table_struct *wait); ++int skb_copy_datagram_iovec(const struct sk_buff *from, int offset, ++ struct iovec *to, int size); ++int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb, int hlen, ++ struct iovec *iov); ++int skb_copy_datagram_from_iovec(struct sk_buff *skb, int offset, ++ const struct iovec *from, int from_offset, ++ int len); ++int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *frm, ++ int offset, size_t count); ++int skb_copy_datagram_const_iovec(const struct sk_buff *from, int offset, ++ const struct iovec *to, int to_offset, ++ int size); ++void skb_free_datagram(struct sock *sk, struct sk_buff *skb); ++void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb); ++int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags); ++int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len); ++int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len); ++__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to, ++ int len, __wsum csum); ++int skb_splice_bits(struct sk_buff *skb, unsigned int offset, ++ struct pipe_inode_info *pipe, unsigned int len, ++ unsigned int flags); ++void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to); ++unsigned int skb_zerocopy_headlen(const struct sk_buff *from); ++int skb_zerocopy(struct sk_buff *to, struct sk_buff *from, ++ int len, int hlen); ++void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len); ++int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen); ++void skb_scrub_packet(struct sk_buff *skb, bool xnet); ++unsigned int skb_gso_transport_seglen(const struct sk_buff *skb); ++struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features); ++struct sk_buff *skb_vlan_untag(struct sk_buff *skb); ++ ++struct skb_checksum_ops { ++ __wsum (*update)(const void *mem, int len, __wsum wsum); ++ __wsum (*combine)(__wsum csum, __wsum csum2, int offset, int len); ++}; ++ ++__wsum __skb_checksum(const struct sk_buff *skb, int offset, int len, ++ __wsum csum, const struct skb_checksum_ops *ops); ++__wsum skb_checksum(const struct sk_buff *skb, int offset, int len, ++ __wsum csum); ++ ++static inline void *__skb_header_pointer(const struct sk_buff *skb, int offset, ++ int len, void *data, int hlen, void *buffer) ++{ ++ if (hlen - offset >= len) ++ return data + offset; ++ ++ if (!skb || ++ skb_copy_bits(skb, offset, buffer, len) < 0) ++ return NULL; ++ ++ return buffer; ++} ++ ++static inline void *skb_header_pointer(const struct sk_buff *skb, int offset, ++ int len, void *buffer) ++{ ++ return __skb_header_pointer(skb, offset, len, skb->data, ++ skb_headlen(skb), buffer); ++} ++ ++/** ++ * skb_needs_linearize - check if we need to linearize a given skb ++ * depending on the given device features. ++ * @skb: socket buffer to check ++ * @features: net device features ++ * ++ * Returns true if either: ++ * 1. skb has frag_list and the device doesn't support FRAGLIST, or ++ * 2. skb is fragmented and the device does not support SG. ++ */ ++static inline bool skb_needs_linearize(struct sk_buff *skb, ++ netdev_features_t features) ++{ ++ return skb_is_nonlinear(skb) && ++ ((skb_has_frag_list(skb) && !(features & NETIF_F_FRAGLIST)) || ++ (skb_shinfo(skb)->nr_frags && !(features & NETIF_F_SG))); ++} ++ ++static inline void skb_copy_from_linear_data(const struct sk_buff *skb, ++ void *to, ++ const unsigned int len) ++{ ++ memcpy(to, skb->data, len); ++} ++ ++static inline void skb_copy_from_linear_data_offset(const struct sk_buff *skb, ++ const int offset, void *to, ++ const unsigned int len) ++{ ++ memcpy(to, skb->data + offset, len); ++} ++ ++static inline void skb_copy_to_linear_data(struct sk_buff *skb, ++ const void *from, ++ const unsigned int len) ++{ ++ memcpy(skb->data, from, len); ++} ++ ++static inline void skb_copy_to_linear_data_offset(struct sk_buff *skb, ++ const int offset, ++ const void *from, ++ const unsigned int len) ++{ ++ memcpy(skb->data + offset, from, len); ++} ++ ++void skb_init(void); ++ ++static inline ktime_t skb_get_ktime(const struct sk_buff *skb) ++{ ++ return skb->tstamp; ++} ++ ++/** ++ * skb_get_timestamp - get timestamp from a skb ++ * @skb: skb to get stamp from ++ * @stamp: pointer to struct timeval to store stamp in ++ * ++ * Timestamps are stored in the skb as offsets to a base timestamp. ++ * This function converts the offset back to a struct timeval and stores ++ * it in stamp. ++ */ ++static inline void skb_get_timestamp(const struct sk_buff *skb, ++ struct timeval *stamp) ++{ ++ *stamp = ktime_to_timeval(skb->tstamp); ++} ++ ++static inline void skb_get_timestampns(const struct sk_buff *skb, ++ struct timespec *stamp) ++{ ++ *stamp = ktime_to_timespec(skb->tstamp); ++} ++ ++static inline void __net_timestamp(struct sk_buff *skb) ++{ ++ skb->tstamp = ktime_get_real(); ++} ++ ++static inline ktime_t net_timedelta(ktime_t t) ++{ ++ return ktime_sub(ktime_get_real(), t); ++} ++ ++static inline ktime_t net_invalid_timestamp(void) ++{ ++ return ktime_set(0, 0); ++} ++ ++struct sk_buff *skb_clone_sk(struct sk_buff *skb); ++ ++#ifdef CONFIG_NETWORK_PHY_TIMESTAMPING ++ ++void skb_clone_tx_timestamp(struct sk_buff *skb); ++bool skb_defer_rx_timestamp(struct sk_buff *skb); ++ ++#else /* CONFIG_NETWORK_PHY_TIMESTAMPING */ ++ ++static inline void skb_clone_tx_timestamp(struct sk_buff *skb) ++{ ++} ++ ++static inline bool skb_defer_rx_timestamp(struct sk_buff *skb) ++{ ++ return false; ++} ++ ++#endif /* !CONFIG_NETWORK_PHY_TIMESTAMPING */ ++ ++/** ++ * skb_complete_tx_timestamp() - deliver cloned skb with tx timestamps ++ * ++ * PHY drivers may accept clones of transmitted packets for ++ * timestamping via their phy_driver.txtstamp method. These drivers ++ * must call this function to return the skb back to the stack, with ++ * or without a timestamp. ++ * ++ * @skb: clone of the the original outgoing packet ++ * @hwtstamps: hardware time stamps, may be NULL if not available ++ * ++ */ ++void skb_complete_tx_timestamp(struct sk_buff *skb, ++ struct skb_shared_hwtstamps *hwtstamps); ++ ++void __skb_tstamp_tx(struct sk_buff *orig_skb, ++ struct skb_shared_hwtstamps *hwtstamps, ++ struct sock *sk, int tstype); ++ ++/** ++ * skb_tstamp_tx - queue clone of skb with send time stamps ++ * @orig_skb: the original outgoing packet ++ * @hwtstamps: hardware time stamps, may be NULL if not available ++ * ++ * If the skb has a socket associated, then this function clones the ++ * skb (thus sharing the actual data and optional structures), stores ++ * the optional hardware time stamping information (if non NULL) or ++ * generates a software time stamp (otherwise), then queues the clone ++ * to the error queue of the socket. Errors are silently ignored. ++ */ ++void skb_tstamp_tx(struct sk_buff *orig_skb, ++ struct skb_shared_hwtstamps *hwtstamps); ++ ++static inline void sw_tx_timestamp(struct sk_buff *skb) ++{ ++ if (skb_shinfo(skb)->tx_flags & SKBTX_SW_TSTAMP && ++ !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) ++ skb_tstamp_tx(skb, NULL); ++} ++ ++/** ++ * skb_tx_timestamp() - Driver hook for transmit timestamping ++ * ++ * Ethernet MAC Drivers should call this function in their hard_xmit() ++ * function immediately before giving the sk_buff to the MAC hardware. ++ * ++ * Specifically, one should make absolutely sure that this function is ++ * called before TX completion of this packet can trigger. Otherwise ++ * the packet could potentially already be freed. ++ * ++ * @skb: A socket buffer. ++ */ ++static inline void skb_tx_timestamp(struct sk_buff *skb) ++{ ++ skb_clone_tx_timestamp(skb); ++ sw_tx_timestamp(skb); ++} ++ ++/** ++ * skb_complete_wifi_ack - deliver skb with wifi status ++ * ++ * @skb: the original outgoing packet ++ * @acked: ack status ++ * ++ */ ++void skb_complete_wifi_ack(struct sk_buff *skb, bool acked); ++ ++__sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len); ++__sum16 __skb_checksum_complete(struct sk_buff *skb); ++ ++static inline int skb_csum_unnecessary(const struct sk_buff *skb) ++{ ++ return ((skb->ip_summed & CHECKSUM_UNNECESSARY) || skb->csum_valid); ++} ++ ++/** ++ * skb_checksum_complete - Calculate checksum of an entire packet ++ * @skb: packet to process ++ * ++ * This function calculates the checksum over the entire packet plus ++ * the value of skb->csum. The latter can be used to supply the ++ * checksum of a pseudo header as used by TCP/UDP. It returns the ++ * checksum. ++ * ++ * For protocols that contain complete checksums such as ICMP/TCP/UDP, ++ * this function can be used to verify that checksum on received ++ * packets. In that case the function should return zero if the ++ * checksum is correct. In particular, this function will return zero ++ * if skb->ip_summed is CHECKSUM_UNNECESSARY which indicates that the ++ * hardware has already verified the correctness of the checksum. ++ */ ++static inline __sum16 skb_checksum_complete(struct sk_buff *skb) ++{ ++ return skb_csum_unnecessary(skb) ? ++ 0 : __skb_checksum_complete(skb); ++} ++ ++static inline void __skb_decr_checksum_unnecessary(struct sk_buff *skb) ++{ ++ if (skb->ip_summed == CHECKSUM_UNNECESSARY) { ++ if (skb->csum_level == 0) ++ skb->ip_summed = CHECKSUM_NONE; ++ else ++ skb->csum_level--; ++ } ++} ++ ++static inline void __skb_incr_checksum_unnecessary(struct sk_buff *skb) ++{ ++ if (skb->ip_summed == CHECKSUM_UNNECESSARY) { ++ if (skb->csum_level < SKB_MAX_CSUM_LEVEL) ++ skb->csum_level++; ++ } else if (skb->ip_summed == CHECKSUM_NONE) { ++ skb->ip_summed = CHECKSUM_UNNECESSARY; ++ skb->csum_level = 0; ++ } ++} ++ ++static inline void __skb_mark_checksum_bad(struct sk_buff *skb) ++{ ++ /* Mark current checksum as bad (typically called from GRO ++ * path). In the case that ip_summed is CHECKSUM_NONE ++ * this must be the first checksum encountered in the packet. ++ * When ip_summed is CHECKSUM_UNNECESSARY, this is the first ++ * checksum after the last one validated. For UDP, a zero ++ * checksum can not be marked as bad. ++ */ ++ ++ if (skb->ip_summed == CHECKSUM_NONE || ++ skb->ip_summed == CHECKSUM_UNNECESSARY) ++ skb->csum_bad = 1; ++} ++ ++/* Check if we need to perform checksum complete validation. ++ * ++ * Returns true if checksum complete is needed, false otherwise ++ * (either checksum is unnecessary or zero checksum is allowed). ++ */ ++static inline bool __skb_checksum_validate_needed(struct sk_buff *skb, ++ bool zero_okay, ++ __sum16 check) ++{ ++ if (skb_csum_unnecessary(skb) || (zero_okay && !check)) { ++ skb->csum_valid = 1; ++ __skb_decr_checksum_unnecessary(skb); ++ return false; ++ } ++ ++ return true; ++} ++ ++/* For small packets <= CHECKSUM_BREAK peform checksum complete directly ++ * in checksum_init. ++ */ ++#define CHECKSUM_BREAK 76 ++ ++/* Unset checksum-complete ++ * ++ * Unset checksum complete can be done when packet is being modified ++ * (uncompressed for instance) and checksum-complete value is ++ * invalidated. ++ */ ++static inline void skb_checksum_complete_unset(struct sk_buff *skb) ++{ ++ if (skb->ip_summed == CHECKSUM_COMPLETE) ++ skb->ip_summed = CHECKSUM_NONE; ++} ++ ++/* Validate (init) checksum based on checksum complete. ++ * ++ * Return values: ++ * 0: checksum is validated or try to in skb_checksum_complete. In the latter ++ * case the ip_summed will not be CHECKSUM_UNNECESSARY and the pseudo ++ * checksum is stored in skb->csum for use in __skb_checksum_complete ++ * non-zero: value of invalid checksum ++ * ++ */ ++static inline __sum16 __skb_checksum_validate_complete(struct sk_buff *skb, ++ bool complete, ++ __wsum psum) ++{ ++ if (skb->ip_summed == CHECKSUM_COMPLETE) { ++ if (!csum_fold(csum_add(psum, skb->csum))) { ++ skb->csum_valid = 1; ++ return 0; ++ } ++ } else if (skb->csum_bad) { ++ /* ip_summed == CHECKSUM_NONE in this case */ ++ return 1; ++ } ++ ++ skb->csum = psum; ++ ++ if (complete || skb->len <= CHECKSUM_BREAK) { ++ __sum16 csum; ++ ++ csum = __skb_checksum_complete(skb); ++ skb->csum_valid = !csum; ++ return csum; ++ } ++ ++ return 0; ++} ++ ++static inline __wsum null_compute_pseudo(struct sk_buff *skb, int proto) ++{ ++ return 0; ++} ++ ++/* Perform checksum validate (init). Note that this is a macro since we only ++ * want to calculate the pseudo header which is an input function if necessary. ++ * First we try to validate without any computation (checksum unnecessary) and ++ * then calculate based on checksum complete calling the function to compute ++ * pseudo header. ++ * ++ * Return values: ++ * 0: checksum is validated or try to in skb_checksum_complete ++ * non-zero: value of invalid checksum ++ */ ++#define __skb_checksum_validate(skb, proto, complete, \ ++ zero_okay, check, compute_pseudo) \ ++({ \ ++ __sum16 __ret = 0; \ ++ skb->csum_valid = 0; \ ++ if (__skb_checksum_validate_needed(skb, zero_okay, check)) \ ++ __ret = __skb_checksum_validate_complete(skb, \ ++ complete, compute_pseudo(skb, proto)); \ ++ __ret; \ ++}) ++ ++#define skb_checksum_init(skb, proto, compute_pseudo) \ ++ __skb_checksum_validate(skb, proto, false, false, 0, compute_pseudo) ++ ++#define skb_checksum_init_zero_check(skb, proto, check, compute_pseudo) \ ++ __skb_checksum_validate(skb, proto, false, true, check, compute_pseudo) ++ ++#define skb_checksum_validate(skb, proto, compute_pseudo) \ ++ __skb_checksum_validate(skb, proto, true, false, 0, compute_pseudo) ++ ++#define skb_checksum_validate_zero_check(skb, proto, check, \ ++ compute_pseudo) \ ++ __skb_checksum_validate_(skb, proto, true, true, check, compute_pseudo) ++ ++#define skb_checksum_simple_validate(skb) \ ++ __skb_checksum_validate(skb, 0, true, false, 0, null_compute_pseudo) ++ ++static inline bool __skb_checksum_convert_check(struct sk_buff *skb) ++{ ++ return (skb->ip_summed == CHECKSUM_NONE && ++ skb->csum_valid && !skb->csum_bad); ++} ++ ++static inline void __skb_checksum_convert(struct sk_buff *skb, ++ __sum16 check, __wsum pseudo) ++{ ++ skb->csum = ~pseudo; ++ skb->ip_summed = CHECKSUM_COMPLETE; ++} ++ ++#define skb_checksum_try_convert(skb, proto, check, compute_pseudo) \ ++do { \ ++ if (__skb_checksum_convert_check(skb)) \ ++ __skb_checksum_convert(skb, check, \ ++ compute_pseudo(skb, proto)); \ ++} while (0) ++ ++#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) ++void nf_conntrack_destroy(struct nf_conntrack *nfct); ++static inline void nf_conntrack_put(struct nf_conntrack *nfct) ++{ ++ if (nfct && atomic_dec_and_test(&nfct->use)) ++ nf_conntrack_destroy(nfct); ++} ++static inline void nf_conntrack_get(struct nf_conntrack *nfct) ++{ ++ if (nfct) ++ atomic_inc(&nfct->use); ++} ++#endif ++#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) ++static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) ++{ ++ if (nf_bridge && atomic_dec_and_test(&nf_bridge->use)) ++ kfree(nf_bridge); ++} ++static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge) ++{ ++ if (nf_bridge) ++ atomic_inc(&nf_bridge->use); ++} ++#endif /* CONFIG_BRIDGE_NETFILTER */ ++static inline void nf_reset(struct sk_buff *skb) ++{ ++#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) ++ nf_conntrack_put(skb->nfct); ++ skb->nfct = NULL; ++#endif ++#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) ++ nf_bridge_put(skb->nf_bridge); ++ skb->nf_bridge = NULL; ++#endif ++} ++ ++static inline void nf_reset_trace(struct sk_buff *skb) ++{ ++#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES) ++ skb->nf_trace = 0; ++#endif ++} ++ ++/* Note: This doesn't put any conntrack and bridge info in dst. */ ++static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src, ++ bool copy) ++{ ++#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) ++ dst->nfct = src->nfct; ++ nf_conntrack_get(src->nfct); ++ if (copy) ++ dst->nfctinfo = src->nfctinfo; ++#endif ++#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) ++ dst->nf_bridge = src->nf_bridge; ++ nf_bridge_get(src->nf_bridge); ++#endif ++#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) || defined(CONFIG_NF_TABLES) ++ if (copy) ++ dst->nf_trace = src->nf_trace; ++#endif ++} ++ ++static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src) ++{ ++#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) ++ nf_conntrack_put(dst->nfct); ++#endif ++#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) ++ nf_bridge_put(dst->nf_bridge); ++#endif ++ __nf_copy(dst, src, true); ++} ++ ++#ifdef CONFIG_NETWORK_SECMARK ++static inline void skb_copy_secmark(struct sk_buff *to, const struct sk_buff *from) ++{ ++ to->secmark = from->secmark; ++} ++ ++static inline void skb_init_secmark(struct sk_buff *skb) ++{ ++ skb->secmark = 0; ++} ++#else ++static inline void skb_copy_secmark(struct sk_buff *to, const struct sk_buff *from) ++{ } ++ ++static inline void skb_init_secmark(struct sk_buff *skb) ++{ } ++#endif ++ ++static inline bool skb_irq_freeable(const struct sk_buff *skb) ++{ ++ return !skb->destructor && ++#if IS_ENABLED(CONFIG_XFRM) ++ !skb->sp && ++#endif ++#if IS_ENABLED(CONFIG_NF_CONNTRACK) ++ !skb->nfct && ++#endif ++ !skb->_skb_refdst && ++ !skb_has_frag_list(skb); ++} ++ ++static inline void skb_set_queue_mapping(struct sk_buff *skb, u16 queue_mapping) ++{ ++ skb->queue_mapping = queue_mapping; ++} ++ ++static inline u16 skb_get_queue_mapping(const struct sk_buff *skb) ++{ ++ return skb->queue_mapping; ++} ++ ++static inline void skb_copy_queue_mapping(struct sk_buff *to, const struct sk_buff *from) ++{ ++ to->queue_mapping = from->queue_mapping; ++} ++ ++static inline void skb_record_rx_queue(struct sk_buff *skb, u16 rx_queue) ++{ ++ skb->queue_mapping = rx_queue + 1; ++} ++ ++static inline u16 skb_get_rx_queue(const struct sk_buff *skb) ++{ ++ return skb->queue_mapping - 1; ++} ++ ++static inline bool skb_rx_queue_recorded(const struct sk_buff *skb) ++{ ++ return skb->queue_mapping != 0; ++} ++ ++u16 __skb_tx_hash(const struct net_device *dev, struct sk_buff *skb, ++ unsigned int num_tx_queues); ++ ++static inline struct sec_path *skb_sec_path(struct sk_buff *skb) ++{ ++#ifdef CONFIG_XFRM ++ return skb->sp; ++#else ++ return NULL; ++#endif ++} ++ ++/* Keeps track of mac header offset relative to skb->head. ++ * It is useful for TSO of Tunneling protocol. e.g. GRE. ++ * For non-tunnel skb it points to skb_mac_header() and for ++ * tunnel skb it points to outer mac header. ++ * Keeps track of level of encapsulation of network headers. ++ */ ++struct skb_gso_cb { ++ int mac_offset; ++ int encap_level; ++ __u16 csum_start; ++}; ++#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)(skb)->cb) ++ ++static inline int skb_tnl_header_len(const struct sk_buff *inner_skb) ++{ ++ return (skb_mac_header(inner_skb) - inner_skb->head) - ++ SKB_GSO_CB(inner_skb)->mac_offset; ++} ++ ++static inline int gso_pskb_expand_head(struct sk_buff *skb, int extra) ++{ ++ int new_headroom, headroom; ++ int ret; ++ ++ headroom = skb_headroom(skb); ++ ret = pskb_expand_head(skb, extra, 0, GFP_ATOMIC); ++ if (ret) ++ return ret; ++ ++ new_headroom = skb_headroom(skb); ++ SKB_GSO_CB(skb)->mac_offset += (new_headroom - headroom); ++ return 0; ++} ++ ++/* Compute the checksum for a gso segment. First compute the checksum value ++ * from the start of transport header to SKB_GSO_CB(skb)->csum_start, and ++ * then add in skb->csum (checksum from csum_start to end of packet). ++ * skb->csum and csum_start are then updated to reflect the checksum of the ++ * resultant packet starting from the transport header-- the resultant checksum ++ * is in the res argument (i.e. normally zero or ~ of checksum of a pseudo ++ * header. ++ */ ++static inline __sum16 gso_make_checksum(struct sk_buff *skb, __wsum res) ++{ ++ int plen = SKB_GSO_CB(skb)->csum_start - skb_headroom(skb) - ++ skb_transport_offset(skb); ++ __u16 csum; ++ ++ csum = csum_fold(csum_partial(skb_transport_header(skb), ++ plen, skb->csum)); ++ skb->csum = res; ++ SKB_GSO_CB(skb)->csum_start -= plen; ++ ++ return csum; ++} ++ ++static inline bool skb_is_gso(const struct sk_buff *skb) ++{ ++ return skb_shinfo(skb)->gso_size; ++} ++ ++/* Note: Should be called only if skb_is_gso(skb) is true */ ++static inline bool skb_is_gso_v6(const struct sk_buff *skb) ++{ ++ return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6; ++} ++ ++void __skb_warn_lro_forwarding(const struct sk_buff *skb); ++ ++static inline bool skb_warn_if_lro(const struct sk_buff *skb) ++{ ++ /* LRO sets gso_size but not gso_type, whereas if GSO is really ++ * wanted then gso_type will be set. */ ++ const struct skb_shared_info *shinfo = skb_shinfo(skb); ++ ++ if (skb_is_nonlinear(skb) && shinfo->gso_size != 0 && ++ unlikely(shinfo->gso_type == 0)) { ++ __skb_warn_lro_forwarding(skb); ++ return true; ++ } ++ return false; ++} ++ ++static inline void skb_forward_csum(struct sk_buff *skb) ++{ ++ /* Unfortunately we don't support this one. Any brave souls? */ ++ if (skb->ip_summed == CHECKSUM_COMPLETE) ++ skb->ip_summed = CHECKSUM_NONE; ++} ++ ++/** ++ * skb_checksum_none_assert - make sure skb ip_summed is CHECKSUM_NONE ++ * @skb: skb to check ++ * ++ * fresh skbs have their ip_summed set to CHECKSUM_NONE. ++ * Instead of forcing ip_summed to CHECKSUM_NONE, we can ++ * use this helper, to document places where we make this assertion. ++ */ ++static inline void skb_checksum_none_assert(const struct sk_buff *skb) ++{ ++#ifdef DEBUG ++ BUG_ON(skb->ip_summed != CHECKSUM_NONE); ++#endif ++} ++ ++bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off); ++ ++int skb_checksum_setup(struct sk_buff *skb, bool recalculate); ++ ++u32 skb_get_poff(const struct sk_buff *skb); ++u32 __skb_get_poff(const struct sk_buff *skb, void *data, ++ const struct flow_keys *keys, int hlen); ++ ++/** ++ * skb_head_is_locked - Determine if the skb->head is locked down ++ * @skb: skb to check ++ * ++ * The head on skbs build around a head frag can be removed if they are ++ * not cloned. This function returns true if the skb head is locked down ++ * due to either being allocated via kmalloc, or by being a clone with ++ * multiple references to the head. ++ */ ++static inline bool skb_head_is_locked(const struct sk_buff *skb) ++{ ++ return !skb->head_frag || skb_cloned(skb); ++} ++ ++/** ++ * skb_gso_network_seglen - Return length of individual segments of a gso packet ++ * ++ * @skb: GSO skb ++ * ++ * skb_gso_network_seglen is used to determine the real size of the ++ * individual segments, including Layer3 (IP, IPv6) and L4 headers (TCP/UDP). ++ * ++ * The MAC/L2 header is not accounted for. ++ */ ++static inline unsigned int skb_gso_network_seglen(const struct sk_buff *skb) ++{ ++ unsigned int hdr_len = skb_transport_header(skb) - ++ skb_network_header(skb); ++ return hdr_len + skb_gso_transport_seglen(skb); ++} ++#endif /* __KERNEL__ */ ++#endif /* _LINUX_SKBUFF_H */ +diff -Nur linux-3.18.14.orig/include/linux/smp.h linux-3.18.14-rt/include/linux/smp.h +--- linux-3.18.14.orig/include/linux/smp.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/smp.h 2015-05-31 15:32:48.405635367 -0500 @@ -178,6 +178,9 @@ #define get_cpu() ({ preempt_disable(); smp_processor_id(); }) #define put_cpu() preempt_enable() @@ -10083,9 +18206,9 @@ diff -Nur linux-3.18.12.orig/include/linux/smp.h linux-3.18.12/include/linux/smp /* * Callback to arch code if there's nosmp or maxcpus=0 on the * boot command line: -diff -Nur linux-3.18.12.orig/include/linux/spinlock_api_smp.h linux-3.18.12/include/linux/spinlock_api_smp.h ---- linux-3.18.12.orig/include/linux/spinlock_api_smp.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/spinlock_api_smp.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/spinlock_api_smp.h linux-3.18.14-rt/include/linux/spinlock_api_smp.h +--- linux-3.18.14.orig/include/linux/spinlock_api_smp.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/spinlock_api_smp.h 2015-05-31 15:32:48.409635367 -0500 @@ -187,6 +187,8 @@ return 0; } @@ -10096,9 +18219,9 @@ diff -Nur linux-3.18.12.orig/include/linux/spinlock_api_smp.h linux-3.18.12/incl +#endif #endif /* __LINUX_SPINLOCK_API_SMP_H */ -diff -Nur linux-3.18.12.orig/include/linux/spinlock.h linux-3.18.12/include/linux/spinlock.h ---- linux-3.18.12.orig/include/linux/spinlock.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/spinlock.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/spinlock.h linux-3.18.14-rt/include/linux/spinlock.h +--- linux-3.18.14.orig/include/linux/spinlock.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/spinlock.h 2015-05-31 15:32:48.405635367 -0500 @@ -278,7 +278,11 @@ #define raw_spin_can_lock(lock) (!raw_spin_is_locked(lock)) @@ -10130,9 +18253,9 @@ diff -Nur linux-3.18.12.orig/include/linux/spinlock.h linux-3.18.12/include/linu +#endif /* !PREEMPT_RT_FULL */ + #endif /* __LINUX_SPINLOCK_H */ -diff -Nur linux-3.18.12.orig/include/linux/spinlock_rt.h linux-3.18.12/include/linux/spinlock_rt.h ---- linux-3.18.12.orig/include/linux/spinlock_rt.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/include/linux/spinlock_rt.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/spinlock_rt.h linux-3.18.14-rt/include/linux/spinlock_rt.h +--- linux-3.18.14.orig/include/linux/spinlock_rt.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/include/linux/spinlock_rt.h 2015-05-31 15:32:48.413635367 -0500 @@ -0,0 +1,167 @@ +#ifndef __LINUX_SPINLOCK_RT_H +#define __LINUX_SPINLOCK_RT_H @@ -10301,9 +18424,9 @@ diff -Nur linux-3.18.12.orig/include/linux/spinlock_rt.h linux-3.18.12/include/l + atomic_dec_and_spin_lock(atomic, lock) + +#endif -diff -Nur linux-3.18.12.orig/include/linux/spinlock_types.h linux-3.18.12/include/linux/spinlock_types.h ---- linux-3.18.12.orig/include/linux/spinlock_types.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/spinlock_types.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/spinlock_types.h linux-3.18.14-rt/include/linux/spinlock_types.h +--- linux-3.18.14.orig/include/linux/spinlock_types.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/spinlock_types.h 2015-05-31 15:32:48.413635367 -0500 @@ -9,80 +9,15 @@ * Released under the General Public License (GPL). */ @@ -10392,9 +18515,9 @@ diff -Nur linux-3.18.12.orig/include/linux/spinlock_types.h linux-3.18.12/includ -#include <linux/rwlock_types.h> - #endif /* __LINUX_SPINLOCK_TYPES_H */ -diff -Nur linux-3.18.12.orig/include/linux/spinlock_types_nort.h linux-3.18.12/include/linux/spinlock_types_nort.h ---- linux-3.18.12.orig/include/linux/spinlock_types_nort.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/include/linux/spinlock_types_nort.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/spinlock_types_nort.h linux-3.18.14-rt/include/linux/spinlock_types_nort.h +--- linux-3.18.14.orig/include/linux/spinlock_types_nort.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/include/linux/spinlock_types_nort.h 2015-05-31 15:32:48.413635367 -0500 @@ -0,0 +1,33 @@ +#ifndef __LINUX_SPINLOCK_TYPES_NORT_H +#define __LINUX_SPINLOCK_TYPES_NORT_H @@ -10429,9 +18552,9 @@ diff -Nur linux-3.18.12.orig/include/linux/spinlock_types_nort.h linux-3.18.12/i +#define DEFINE_SPINLOCK(x) spinlock_t x = __SPIN_LOCK_UNLOCKED(x) + +#endif -diff -Nur linux-3.18.12.orig/include/linux/spinlock_types_raw.h linux-3.18.12/include/linux/spinlock_types_raw.h ---- linux-3.18.12.orig/include/linux/spinlock_types_raw.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/include/linux/spinlock_types_raw.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/spinlock_types_raw.h linux-3.18.14-rt/include/linux/spinlock_types_raw.h +--- linux-3.18.14.orig/include/linux/spinlock_types_raw.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/include/linux/spinlock_types_raw.h 2015-05-31 15:32:48.413635367 -0500 @@ -0,0 +1,56 @@ +#ifndef __LINUX_SPINLOCK_TYPES_RAW_H +#define __LINUX_SPINLOCK_TYPES_RAW_H @@ -10489,9 +18612,9 @@ diff -Nur linux-3.18.12.orig/include/linux/spinlock_types_raw.h linux-3.18.12/in +#define DEFINE_RAW_SPINLOCK(x) raw_spinlock_t x = __RAW_SPIN_LOCK_UNLOCKED(x) + +#endif -diff -Nur linux-3.18.12.orig/include/linux/spinlock_types_rt.h linux-3.18.12/include/linux/spinlock_types_rt.h ---- linux-3.18.12.orig/include/linux/spinlock_types_rt.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/include/linux/spinlock_types_rt.h 2015-04-26 13:32:22.423684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/spinlock_types_rt.h linux-3.18.14-rt/include/linux/spinlock_types_rt.h +--- linux-3.18.14.orig/include/linux/spinlock_types_rt.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/include/linux/spinlock_types_rt.h 2015-05-31 15:32:48.413635367 -0500 @@ -0,0 +1,51 @@ +#ifndef __LINUX_SPINLOCK_TYPES_RT_H +#define __LINUX_SPINLOCK_TYPES_RT_H @@ -10544,9 +18667,9 @@ diff -Nur linux-3.18.12.orig/include/linux/spinlock_types_rt.h linux-3.18.12/inc + spinlock_t name __cacheline_aligned_in_smp = __SPIN_LOCK_UNLOCKED(name) + +#endif -diff -Nur linux-3.18.12.orig/include/linux/srcu.h linux-3.18.12/include/linux/srcu.h ---- linux-3.18.12.orig/include/linux/srcu.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/srcu.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/srcu.h linux-3.18.14-rt/include/linux/srcu.h +--- linux-3.18.14.orig/include/linux/srcu.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/srcu.h 2015-05-31 15:32:48.445635367 -0500 @@ -84,10 +84,10 @@ void process_srcu(struct work_struct *work); @@ -10575,9 +18698,9 @@ diff -Nur linux-3.18.12.orig/include/linux/srcu.h linux-3.18.12/include/linux/sr /** * call_srcu() - Queue a callback for invocation after an SRCU grace period -diff -Nur linux-3.18.12.orig/include/linux/swap.h linux-3.18.12/include/linux/swap.h ---- linux-3.18.12.orig/include/linux/swap.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/swap.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/swap.h linux-3.18.14-rt/include/linux/swap.h +--- linux-3.18.14.orig/include/linux/swap.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/swap.h 2015-05-31 15:32:48.449635367 -0500 @@ -11,6 +11,7 @@ #include <linux/fs.h> #include <linux/atomic.h> @@ -10596,9 +18719,9 @@ diff -Nur linux-3.18.12.orig/include/linux/swap.h linux-3.18.12/include/linux/sw static inline unsigned int workingset_node_pages(struct radix_tree_node *node) { -diff -Nur linux-3.18.12.orig/include/linux/sysctl.h linux-3.18.12/include/linux/sysctl.h ---- linux-3.18.12.orig/include/linux/sysctl.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/sysctl.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/sysctl.h linux-3.18.14-rt/include/linux/sysctl.h +--- linux-3.18.14.orig/include/linux/sysctl.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/sysctl.h 2015-05-31 15:32:48.449635367 -0500 @@ -25,6 +25,7 @@ #include <linux/rcupdate.h> #include <linux/wait.h> @@ -10607,9 +18730,9 @@ diff -Nur linux-3.18.12.orig/include/linux/sysctl.h linux-3.18.12/include/linux/ #include <uapi/linux/sysctl.h> /* For the /proc/sys support */ -diff -Nur linux-3.18.12.orig/include/linux/thread_info.h linux-3.18.12/include/linux/thread_info.h ---- linux-3.18.12.orig/include/linux/thread_info.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/thread_info.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/thread_info.h linux-3.18.14-rt/include/linux/thread_info.h +--- linux-3.18.14.orig/include/linux/thread_info.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/thread_info.h 2015-05-31 15:32:48.449635367 -0500 @@ -102,7 +102,17 @@ #define test_thread_flag(flag) \ test_ti_thread_flag(current_thread_info(), flag) @@ -10629,9 +18752,9 @@ diff -Nur linux-3.18.12.orig/include/linux/thread_info.h linux-3.18.12/include/l #if defined TIF_RESTORE_SIGMASK && !defined HAVE_SET_RESTORE_SIGMASK /* -diff -Nur linux-3.18.12.orig/include/linux/timer.h linux-3.18.12/include/linux/timer.h ---- linux-3.18.12.orig/include/linux/timer.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/timer.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/timer.h linux-3.18.14-rt/include/linux/timer.h +--- linux-3.18.14.orig/include/linux/timer.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/timer.h 2015-05-31 15:32:48.449635367 -0500 @@ -241,7 +241,7 @@ extern int try_to_del_timer_sync(struct timer_list *timer); @@ -10641,9 +18764,9 @@ diff -Nur linux-3.18.12.orig/include/linux/timer.h linux-3.18.12/include/linux/t extern int del_timer_sync(struct timer_list *timer); #else # define del_timer_sync(t) del_timer(t) -diff -Nur linux-3.18.12.orig/include/linux/uaccess.h linux-3.18.12/include/linux/uaccess.h ---- linux-3.18.12.orig/include/linux/uaccess.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/uaccess.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/uaccess.h linux-3.18.14-rt/include/linux/uaccess.h +--- linux-3.18.14.orig/include/linux/uaccess.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/uaccess.h 2015-05-31 15:32:48.449635367 -0500 @@ -6,14 +6,9 @@ /* @@ -10704,9 +18827,9 @@ diff -Nur linux-3.18.12.orig/include/linux/uaccess.h linux-3.18.12/include/linux set_fs(old_fs); \ ret; \ }) -diff -Nur linux-3.18.12.orig/include/linux/uprobes.h linux-3.18.12/include/linux/uprobes.h ---- linux-3.18.12.orig/include/linux/uprobes.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/uprobes.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/uprobes.h linux-3.18.14-rt/include/linux/uprobes.h +--- linux-3.18.14.orig/include/linux/uprobes.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/uprobes.h 2015-05-31 15:32:48.481635367 -0500 @@ -27,6 +27,7 @@ #include <linux/errno.h> #include <linux/rbtree.h> @@ -10715,9 +18838,9 @@ diff -Nur linux-3.18.12.orig/include/linux/uprobes.h linux-3.18.12/include/linux struct vm_area_struct; struct mm_struct; -diff -Nur linux-3.18.12.orig/include/linux/vmstat.h linux-3.18.12/include/linux/vmstat.h ---- linux-3.18.12.orig/include/linux/vmstat.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/vmstat.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/vmstat.h linux-3.18.14-rt/include/linux/vmstat.h +--- linux-3.18.14.orig/include/linux/vmstat.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/vmstat.h 2015-05-31 15:32:48.481635367 -0500 @@ -33,7 +33,9 @@ */ static inline void __count_vm_event(enum vm_event_item item) @@ -10738,9 +18861,9 @@ diff -Nur linux-3.18.12.orig/include/linux/vmstat.h linux-3.18.12/include/linux/ } static inline void count_vm_events(enum vm_event_item item, long delta) -diff -Nur linux-3.18.12.orig/include/linux/wait.h linux-3.18.12/include/linux/wait.h ---- linux-3.18.12.orig/include/linux/wait.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/linux/wait.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/wait.h linux-3.18.14-rt/include/linux/wait.h +--- linux-3.18.14.orig/include/linux/wait.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/linux/wait.h 2015-05-31 15:32:48.481635367 -0500 @@ -8,6 +8,7 @@ #include <linux/spinlock.h> #include <asm/current.h> @@ -10749,9 +18872,9 @@ diff -Nur linux-3.18.12.orig/include/linux/wait.h linux-3.18.12/include/linux/wa typedef struct __wait_queue wait_queue_t; typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key); -diff -Nur linux-3.18.12.orig/include/linux/wait-simple.h linux-3.18.12/include/linux/wait-simple.h ---- linux-3.18.12.orig/include/linux/wait-simple.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/include/linux/wait-simple.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/wait-simple.h linux-3.18.14-rt/include/linux/wait-simple.h +--- linux-3.18.14.orig/include/linux/wait-simple.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/include/linux/wait-simple.h 2015-05-31 15:32:48.481635367 -0500 @@ -0,0 +1,207 @@ +#ifndef _LINUX_WAIT_SIMPLE_H +#define _LINUX_WAIT_SIMPLE_H @@ -10960,9 +19083,9 @@ diff -Nur linux-3.18.12.orig/include/linux/wait-simple.h linux-3.18.12/include/l +}) + +#endif -diff -Nur linux-3.18.12.orig/include/linux/work-simple.h linux-3.18.12/include/linux/work-simple.h ---- linux-3.18.12.orig/include/linux/work-simple.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/include/linux/work-simple.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/linux/work-simple.h linux-3.18.14-rt/include/linux/work-simple.h +--- linux-3.18.14.orig/include/linux/work-simple.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/include/linux/work-simple.h 2015-05-31 15:32:48.481635367 -0500 @@ -0,0 +1,24 @@ +#ifndef _LINUX_SWORK_H +#define _LINUX_SWORK_H @@ -10988,9 +19111,9 @@ diff -Nur linux-3.18.12.orig/include/linux/work-simple.h linux-3.18.12/include/l +void swork_put(void); + +#endif /* _LINUX_SWORK_H */ -diff -Nur linux-3.18.12.orig/include/net/dst.h linux-3.18.12/include/net/dst.h ---- linux-3.18.12.orig/include/net/dst.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/net/dst.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/net/dst.h linux-3.18.14-rt/include/net/dst.h +--- linux-3.18.14.orig/include/net/dst.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/net/dst.h 2015-05-31 15:32:48.497635366 -0500 @@ -403,7 +403,7 @@ static inline int dst_neigh_output(struct dst_entry *dst, struct neighbour *n, struct sk_buff *skb) @@ -11000,9 +19123,9 @@ diff -Nur linux-3.18.12.orig/include/net/dst.h linux-3.18.12/include/net/dst.h if (dst->pending_confirm) { unsigned long now = jiffies; -diff -Nur linux-3.18.12.orig/include/net/neighbour.h linux-3.18.12/include/net/neighbour.h ---- linux-3.18.12.orig/include/net/neighbour.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/net/neighbour.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/net/neighbour.h linux-3.18.14-rt/include/net/neighbour.h +--- linux-3.18.14.orig/include/net/neighbour.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/net/neighbour.h 2015-05-31 15:32:48.521635366 -0500 @@ -387,7 +387,7 @@ } #endif @@ -11021,9 +19144,9 @@ diff -Nur linux-3.18.12.orig/include/net/neighbour.h linux-3.18.12/include/net/n const struct net_device *dev) { unsigned int seq; -diff -Nur linux-3.18.12.orig/include/net/netns/ipv4.h linux-3.18.12/include/net/netns/ipv4.h ---- linux-3.18.12.orig/include/net/netns/ipv4.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/include/net/netns/ipv4.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/net/netns/ipv4.h linux-3.18.14-rt/include/net/netns/ipv4.h +--- linux-3.18.14.orig/include/net/netns/ipv4.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/include/net/netns/ipv4.h 2015-05-31 15:32:48.521635366 -0500 @@ -67,6 +67,7 @@ int sysctl_icmp_echo_ignore_all; @@ -11032,9 +19155,9 @@ diff -Nur linux-3.18.12.orig/include/net/netns/ipv4.h linux-3.18.12/include/net/ int sysctl_icmp_ignore_bogus_error_responses; int sysctl_icmp_ratelimit; int sysctl_icmp_ratemask; -diff -Nur linux-3.18.12.orig/include/trace/events/hist.h linux-3.18.12/include/trace/events/hist.h ---- linux-3.18.12.orig/include/trace/events/hist.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/include/trace/events/hist.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/trace/events/hist.h linux-3.18.14-rt/include/trace/events/hist.h +--- linux-3.18.14.orig/include/trace/events/hist.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/include/trace/events/hist.h 2015-05-31 15:32:48.521635366 -0500 @@ -0,0 +1,72 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM hist @@ -11108,9 +19231,9 @@ diff -Nur linux-3.18.12.orig/include/trace/events/hist.h linux-3.18.12/include/t + +/* This part must be outside protection */ +#include <trace/define_trace.h> -diff -Nur linux-3.18.12.orig/include/trace/events/latency_hist.h linux-3.18.12/include/trace/events/latency_hist.h ---- linux-3.18.12.orig/include/trace/events/latency_hist.h 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/include/trace/events/latency_hist.h 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/include/trace/events/latency_hist.h linux-3.18.14-rt/include/trace/events/latency_hist.h +--- linux-3.18.14.orig/include/trace/events/latency_hist.h 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/include/trace/events/latency_hist.h 2015-05-31 15:32:48.521635366 -0500 @@ -0,0 +1,29 @@ +#ifndef _LATENCY_HIST_H +#define _LATENCY_HIST_H @@ -11141,9 +19264,9 @@ diff -Nur linux-3.18.12.orig/include/trace/events/latency_hist.h linux-3.18.12/i +} + +#endif /* _LATENCY_HIST_H */ -diff -Nur linux-3.18.12.orig/init/Kconfig linux-3.18.12/init/Kconfig ---- linux-3.18.12.orig/init/Kconfig 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/init/Kconfig 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/init/Kconfig linux-3.18.14-rt/init/Kconfig +--- linux-3.18.14.orig/init/Kconfig 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/init/Kconfig 2015-05-31 15:32:48.525635366 -0500 @@ -635,7 +635,7 @@ config RCU_FAST_NO_HZ @@ -11186,9 +19309,9 @@ diff -Nur linux-3.18.12.orig/init/Kconfig linux-3.18.12/init/Kconfig help SLOB replaces the stock allocator with a drastically simpler allocator. SLOB is generally more space efficient but -diff -Nur linux-3.18.12.orig/init/main.c linux-3.18.12/init/main.c ---- linux-3.18.12.orig/init/main.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/init/main.c 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/init/main.c linux-3.18.14-rt/init/main.c +--- linux-3.18.14.orig/init/main.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/init/main.c 2015-05-31 15:32:48.545635366 -0500 @@ -533,6 +533,7 @@ setup_command_line(command_line); setup_nr_cpu_ids(); @@ -11197,18 +19320,18 @@ diff -Nur linux-3.18.12.orig/init/main.c linux-3.18.12/init/main.c smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */ build_all_zonelists(NULL, NULL); -diff -Nur linux-3.18.12.orig/init/Makefile linux-3.18.12/init/Makefile ---- linux-3.18.12.orig/init/Makefile 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/init/Makefile 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/init/Makefile linux-3.18.14-rt/init/Makefile +--- linux-3.18.14.orig/init/Makefile 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/init/Makefile 2015-05-31 15:32:48.525635366 -0500 @@ -33,4 +33,4 @@ include/generated/compile.h: FORCE @$($(quiet)chk_compile.h) $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkcompile_h $@ \ - "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CC) $(KBUILD_CFLAGS)" + "$(UTS_MACHINE)" "$(CONFIG_SMP)" "$(CONFIG_PREEMPT)" "$(CONFIG_PREEMPT_RT_FULL)" "$(CC) $(KBUILD_CFLAGS)" -diff -Nur linux-3.18.12.orig/ipc/mqueue.c linux-3.18.12/ipc/mqueue.c ---- linux-3.18.12.orig/ipc/mqueue.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/ipc/mqueue.c 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/ipc/mqueue.c linux-3.18.14-rt/ipc/mqueue.c +--- linux-3.18.14.orig/ipc/mqueue.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/ipc/mqueue.c 2015-05-31 15:32:48.557635366 -0500 @@ -923,12 +923,17 @@ struct msg_msg *message, struct ext_wait_queue *receiver) @@ -11253,9 +19376,9 @@ diff -Nur linux-3.18.12.orig/ipc/mqueue.c linux-3.18.12/ipc/mqueue.c } SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr, -diff -Nur linux-3.18.12.orig/ipc/msg.c linux-3.18.12/ipc/msg.c ---- linux-3.18.12.orig/ipc/msg.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/ipc/msg.c 2015-04-26 13:32:22.427684003 -0500 +diff -Nur linux-3.18.14.orig/ipc/msg.c linux-3.18.14-rt/ipc/msg.c +--- linux-3.18.14.orig/ipc/msg.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/ipc/msg.c 2015-05-31 15:32:48.577635366 -0500 @@ -188,6 +188,12 @@ struct msg_receiver *msr, *t; @@ -11305,9 +19428,9 @@ diff -Nur linux-3.18.12.orig/ipc/msg.c linux-3.18.12/ipc/msg.c return 0; } -diff -Nur linux-3.18.12.orig/ipc/sem.c linux-3.18.12/ipc/sem.c ---- linux-3.18.12.orig/ipc/sem.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/ipc/sem.c 2015-04-26 13:32:22.431684003 -0500 +diff -Nur linux-3.18.14.orig/ipc/sem.c linux-3.18.14-rt/ipc/sem.c +--- linux-3.18.14.orig/ipc/sem.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/ipc/sem.c 2015-05-31 15:32:48.577635366 -0500 @@ -673,6 +673,13 @@ static void wake_up_sem_queue_prepare(struct list_head *pt, struct sem_queue *q, int error) @@ -11346,9 +19469,9 @@ diff -Nur linux-3.18.12.orig/ipc/sem.c linux-3.18.12/ipc/sem.c } static void unlink_queue(struct sem_array *sma, struct sem_queue *q) -diff -Nur linux-3.18.12.orig/kernel/cgroup.c linux-3.18.12/kernel/cgroup.c ---- linux-3.18.12.orig/kernel/cgroup.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/cgroup.c 2015-04-26 13:32:22.431684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/cgroup.c linux-3.18.14-rt/kernel/cgroup.c +--- linux-3.18.14.orig/kernel/cgroup.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/cgroup.c 2015-05-31 15:32:48.597635365 -0500 @@ -4355,10 +4355,10 @@ queue_work(cgroup_destroy_wq, &css->destroy_work); } @@ -11381,9 +19504,9 @@ diff -Nur linux-3.18.12.orig/kernel/cgroup.c linux-3.18.12/kernel/cgroup.c /* * Used to destroy pidlists and separate to serve as flush domain. -diff -Nur linux-3.18.12.orig/kernel/cpu.c linux-3.18.12/kernel/cpu.c ---- linux-3.18.12.orig/kernel/cpu.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/cpu.c 2015-04-26 13:32:22.431684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/cpu.c linux-3.18.14-rt/kernel/cpu.c +--- linux-3.18.14.orig/kernel/cpu.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/cpu.c 2015-05-31 15:32:48.601635365 -0500 @@ -86,6 +86,290 @@ #define cpuhp_lock_acquire() lock_map_acquire(&cpu_hotplug.dep_map) #define cpuhp_lock_release() lock_map_release(&cpu_hotplug.dep_map) @@ -11763,9 +19886,9 @@ diff -Nur linux-3.18.12.orig/kernel/cpu.c linux-3.18.12/kernel/cpu.c return err; } -diff -Nur linux-3.18.12.orig/kernel/debug/kdb/kdb_io.c linux-3.18.12/kernel/debug/kdb/kdb_io.c ---- linux-3.18.12.orig/kernel/debug/kdb/kdb_io.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/debug/kdb/kdb_io.c 2015-04-26 13:32:22.431684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/debug/kdb/kdb_io.c linux-3.18.14-rt/kernel/debug/kdb/kdb_io.c +--- linux-3.18.14.orig/kernel/debug/kdb/kdb_io.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/debug/kdb/kdb_io.c 2015-05-31 15:32:48.605635366 -0500 @@ -554,7 +554,6 @@ int linecount; int colcount; @@ -11803,9 +19926,9 @@ diff -Nur linux-3.18.12.orig/kernel/debug/kdb/kdb_io.c linux-3.18.12/kernel/debu return r; } -diff -Nur linux-3.18.12.orig/kernel/events/core.c linux-3.18.12/kernel/events/core.c ---- linux-3.18.12.orig/kernel/events/core.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/events/core.c 2015-04-26 13:32:22.431684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/events/core.c linux-3.18.14-rt/kernel/events/core.c +--- linux-3.18.14.orig/kernel/events/core.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/events/core.c 2015-05-31 15:32:48.637635365 -0500 @@ -6346,6 +6346,7 @@ hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); @@ -11814,8352 +19937,9 @@ diff -Nur linux-3.18.12.orig/kernel/events/core.c linux-3.18.12/kernel/events/co /* * Since hrtimers have a fixed rate, we can do a static freq->period -diff -Nur linux-3.18.12.orig/kernel/events/core.c.orig linux-3.18.12/kernel/events/core.c.orig ---- linux-3.18.12.orig/kernel/events/core.c.orig 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/kernel/events/core.c.orig 2015-04-20 14:48:02.000000000 -0500 -@@ -0,0 +1,8339 @@ -+/* -+ * Performance events core code: -+ * -+ * Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de> -+ * Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar -+ * Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com> -+ * Copyright © 2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com> -+ * -+ * For licensing details see kernel-base/COPYING -+ */ -+ -+#include <linux/fs.h> -+#include <linux/mm.h> -+#include <linux/cpu.h> -+#include <linux/smp.h> -+#include <linux/idr.h> -+#include <linux/file.h> -+#include <linux/poll.h> -+#include <linux/slab.h> -+#include <linux/hash.h> -+#include <linux/tick.h> -+#include <linux/sysfs.h> -+#include <linux/dcache.h> -+#include <linux/percpu.h> -+#include <linux/ptrace.h> -+#include <linux/reboot.h> -+#include <linux/vmstat.h> -+#include <linux/device.h> -+#include <linux/export.h> -+#include <linux/vmalloc.h> -+#include <linux/hardirq.h> -+#include <linux/rculist.h> -+#include <linux/uaccess.h> -+#include <linux/syscalls.h> -+#include <linux/anon_inodes.h> -+#include <linux/kernel_stat.h> -+#include <linux/perf_event.h> -+#include <linux/ftrace_event.h> -+#include <linux/hw_breakpoint.h> -+#include <linux/mm_types.h> -+#include <linux/cgroup.h> -+#include <linux/module.h> -+#include <linux/mman.h> -+#include <linux/compat.h> -+ -+#include "internal.h" -+ -+#include <asm/irq_regs.h> -+ -+static struct workqueue_struct *perf_wq; -+ -+struct remote_function_call { -+ struct task_struct *p; -+ int (*func)(void *info); -+ void *info; -+ int ret; -+}; -+ -+static void remote_function(void *data) -+{ -+ struct remote_function_call *tfc = data; -+ struct task_struct *p = tfc->p; -+ -+ if (p) { -+ tfc->ret = -EAGAIN; -+ if (task_cpu(p) != smp_processor_id() || !task_curr(p)) -+ return; -+ } -+ -+ tfc->ret = tfc->func(tfc->info); -+} -+ -+/** -+ * task_function_call - call a function on the cpu on which a task runs -+ * @p: the task to evaluate -+ * @func: the function to be called -+ * @info: the function call argument -+ * -+ * Calls the function @func when the task is currently running. This might -+ * be on the current CPU, which just calls the function directly -+ * -+ * returns: @func return value, or -+ * -ESRCH - when the process isn't running -+ * -EAGAIN - when the process moved away -+ */ -+static int -+task_function_call(struct task_struct *p, int (*func) (void *info), void *info) -+{ -+ struct remote_function_call data = { -+ .p = p, -+ .func = func, -+ .info = info, -+ .ret = -ESRCH, /* No such (running) process */ -+ }; -+ -+ if (task_curr(p)) -+ smp_call_function_single(task_cpu(p), remote_function, &data, 1); -+ -+ return data.ret; -+} -+ -+/** -+ * cpu_function_call - call a function on the cpu -+ * @func: the function to be called -+ * @info: the function call argument -+ * -+ * Calls the function @func on the remote cpu. -+ * -+ * returns: @func return value or -ENXIO when the cpu is offline -+ */ -+static int cpu_function_call(int cpu, int (*func) (void *info), void *info) -+{ -+ struct remote_function_call data = { -+ .p = NULL, -+ .func = func, -+ .info = info, -+ .ret = -ENXIO, /* No such CPU */ -+ }; -+ -+ smp_call_function_single(cpu, remote_function, &data, 1); -+ -+ return data.ret; -+} -+ -+#define EVENT_OWNER_KERNEL ((void *) -1) -+ -+static bool is_kernel_event(struct perf_event *event) -+{ -+ return event->owner == EVENT_OWNER_KERNEL; -+} -+ -+#define PERF_FLAG_ALL (PERF_FLAG_FD_NO_GROUP |\ -+ PERF_FLAG_FD_OUTPUT |\ -+ PERF_FLAG_PID_CGROUP |\ -+ PERF_FLAG_FD_CLOEXEC) -+ -+/* -+ * branch priv levels that need permission checks -+ */ -+#define PERF_SAMPLE_BRANCH_PERM_PLM \ -+ (PERF_SAMPLE_BRANCH_KERNEL |\ -+ PERF_SAMPLE_BRANCH_HV) -+ -+enum event_type_t { -+ EVENT_FLEXIBLE = 0x1, -+ EVENT_PINNED = 0x2, -+ EVENT_ALL = EVENT_FLEXIBLE | EVENT_PINNED, -+}; -+ -+/* -+ * perf_sched_events : >0 events exist -+ * perf_cgroup_events: >0 per-cpu cgroup events exist on this cpu -+ */ -+struct static_key_deferred perf_sched_events __read_mostly; -+static DEFINE_PER_CPU(atomic_t, perf_cgroup_events); -+static DEFINE_PER_CPU(atomic_t, perf_branch_stack_events); -+ -+static atomic_t nr_mmap_events __read_mostly; -+static atomic_t nr_comm_events __read_mostly; -+static atomic_t nr_task_events __read_mostly; -+static atomic_t nr_freq_events __read_mostly; -+ -+static LIST_HEAD(pmus); -+static DEFINE_MUTEX(pmus_lock); -+static struct srcu_struct pmus_srcu; -+ -+/* -+ * perf event paranoia level: -+ * -1 - not paranoid at all -+ * 0 - disallow raw tracepoint access for unpriv -+ * 1 - disallow cpu events for unpriv -+ * 2 - disallow kernel profiling for unpriv -+ */ -+int sysctl_perf_event_paranoid __read_mostly = 1; -+ -+/* Minimum for 512 kiB + 1 user control page */ -+int sysctl_perf_event_mlock __read_mostly = 512 + (PAGE_SIZE / 1024); /* 'free' kiB per user */ -+ -+/* -+ * max perf event sample rate -+ */ -+#define DEFAULT_MAX_SAMPLE_RATE 100000 -+#define DEFAULT_SAMPLE_PERIOD_NS (NSEC_PER_SEC / DEFAULT_MAX_SAMPLE_RATE) -+#define DEFAULT_CPU_TIME_MAX_PERCENT 25 -+ -+int sysctl_perf_event_sample_rate __read_mostly = DEFAULT_MAX_SAMPLE_RATE; -+ -+static int max_samples_per_tick __read_mostly = DIV_ROUND_UP(DEFAULT_MAX_SAMPLE_RATE, HZ); -+static int perf_sample_period_ns __read_mostly = DEFAULT_SAMPLE_PERIOD_NS; -+ -+static int perf_sample_allowed_ns __read_mostly = -+ DEFAULT_SAMPLE_PERIOD_NS * DEFAULT_CPU_TIME_MAX_PERCENT / 100; -+ -+void update_perf_cpu_limits(void) -+{ -+ u64 tmp = perf_sample_period_ns; -+ -+ tmp *= sysctl_perf_cpu_time_max_percent; -+ do_div(tmp, 100); -+ ACCESS_ONCE(perf_sample_allowed_ns) = tmp; -+} -+ -+static int perf_rotate_context(struct perf_cpu_context *cpuctx); -+ -+int perf_proc_update_handler(struct ctl_table *table, int write, -+ void __user *buffer, size_t *lenp, -+ loff_t *ppos) -+{ -+ int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); -+ -+ if (ret || !write) -+ return ret; -+ -+ max_samples_per_tick = DIV_ROUND_UP(sysctl_perf_event_sample_rate, HZ); -+ perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate; -+ update_perf_cpu_limits(); -+ -+ return 0; -+} -+ -+int sysctl_perf_cpu_time_max_percent __read_mostly = DEFAULT_CPU_TIME_MAX_PERCENT; -+ -+int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write, -+ void __user *buffer, size_t *lenp, -+ loff_t *ppos) -+{ -+ int ret = proc_dointvec(table, write, buffer, lenp, ppos); -+ -+ if (ret || !write) -+ return ret; -+ -+ update_perf_cpu_limits(); -+ -+ return 0; -+} -+ -+/* -+ * perf samples are done in some very critical code paths (NMIs). -+ * If they take too much CPU time, the system can lock up and not -+ * get any real work done. This will drop the sample rate when -+ * we detect that events are taking too long. -+ */ -+#define NR_ACCUMULATED_SAMPLES 128 -+static DEFINE_PER_CPU(u64, running_sample_length); -+ -+static void perf_duration_warn(struct irq_work *w) -+{ -+ u64 allowed_ns = ACCESS_ONCE(perf_sample_allowed_ns); -+ u64 avg_local_sample_len; -+ u64 local_samples_len; -+ -+ local_samples_len = __this_cpu_read(running_sample_length); -+ avg_local_sample_len = local_samples_len/NR_ACCUMULATED_SAMPLES; -+ -+ printk_ratelimited(KERN_WARNING -+ "perf interrupt took too long (%lld > %lld), lowering " -+ "kernel.perf_event_max_sample_rate to %d\n", -+ avg_local_sample_len, allowed_ns >> 1, -+ sysctl_perf_event_sample_rate); -+} -+ -+static DEFINE_IRQ_WORK(perf_duration_work, perf_duration_warn); -+ -+void perf_sample_event_took(u64 sample_len_ns) -+{ -+ u64 allowed_ns = ACCESS_ONCE(perf_sample_allowed_ns); -+ u64 avg_local_sample_len; -+ u64 local_samples_len; -+ -+ if (allowed_ns == 0) -+ return; -+ -+ /* decay the counter by 1 average sample */ -+ local_samples_len = __this_cpu_read(running_sample_length); -+ local_samples_len -= local_samples_len/NR_ACCUMULATED_SAMPLES; -+ local_samples_len += sample_len_ns; -+ __this_cpu_write(running_sample_length, local_samples_len); -+ -+ /* -+ * note: this will be biased artifically low until we have -+ * seen NR_ACCUMULATED_SAMPLES. Doing it this way keeps us -+ * from having to maintain a count. -+ */ -+ avg_local_sample_len = local_samples_len/NR_ACCUMULATED_SAMPLES; -+ -+ if (avg_local_sample_len <= allowed_ns) -+ return; -+ -+ if (max_samples_per_tick <= 1) -+ return; -+ -+ max_samples_per_tick = DIV_ROUND_UP(max_samples_per_tick, 2); -+ sysctl_perf_event_sample_rate = max_samples_per_tick * HZ; -+ perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate; -+ -+ update_perf_cpu_limits(); -+ -+ if (!irq_work_queue(&perf_duration_work)) { -+ early_printk("perf interrupt took too long (%lld > %lld), lowering " -+ "kernel.perf_event_max_sample_rate to %d\n", -+ avg_local_sample_len, allowed_ns >> 1, -+ sysctl_perf_event_sample_rate); -+ } -+} -+ -+static atomic64_t perf_event_id; -+ -+static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx, -+ enum event_type_t event_type); -+ -+static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx, -+ enum event_type_t event_type, -+ struct task_struct *task); -+ -+static void update_context_time(struct perf_event_context *ctx); -+static u64 perf_event_time(struct perf_event *event); -+ -+void __weak perf_event_print_debug(void) { } -+ -+extern __weak const char *perf_pmu_name(void) -+{ -+ return "pmu"; -+} -+ -+static inline u64 perf_clock(void) -+{ -+ return local_clock(); -+} -+ -+static inline struct perf_cpu_context * -+__get_cpu_context(struct perf_event_context *ctx) -+{ -+ return this_cpu_ptr(ctx->pmu->pmu_cpu_context); -+} -+ -+static void perf_ctx_lock(struct perf_cpu_context *cpuctx, -+ struct perf_event_context *ctx) -+{ -+ raw_spin_lock(&cpuctx->ctx.lock); -+ if (ctx) -+ raw_spin_lock(&ctx->lock); -+} -+ -+static void perf_ctx_unlock(struct perf_cpu_context *cpuctx, -+ struct perf_event_context *ctx) -+{ -+ if (ctx) -+ raw_spin_unlock(&ctx->lock); -+ raw_spin_unlock(&cpuctx->ctx.lock); -+} -+ -+#ifdef CONFIG_CGROUP_PERF -+ -+/* -+ * perf_cgroup_info keeps track of time_enabled for a cgroup. -+ * This is a per-cpu dynamically allocated data structure. -+ */ -+struct perf_cgroup_info { -+ u64 time; -+ u64 timestamp; -+}; -+ -+struct perf_cgroup { -+ struct cgroup_subsys_state css; -+ struct perf_cgroup_info __percpu *info; -+}; -+ -+/* -+ * Must ensure cgroup is pinned (css_get) before calling -+ * this function. In other words, we cannot call this function -+ * if there is no cgroup event for the current CPU context. -+ */ -+static inline struct perf_cgroup * -+perf_cgroup_from_task(struct task_struct *task) -+{ -+ return container_of(task_css(task, perf_event_cgrp_id), -+ struct perf_cgroup, css); -+} -+ -+static inline bool -+perf_cgroup_match(struct perf_event *event) -+{ -+ struct perf_event_context *ctx = event->ctx; -+ struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); -+ -+ /* @event doesn't care about cgroup */ -+ if (!event->cgrp) -+ return true; -+ -+ /* wants specific cgroup scope but @cpuctx isn't associated with any */ -+ if (!cpuctx->cgrp) -+ return false; -+ -+ /* -+ * Cgroup scoping is recursive. An event enabled for a cgroup is -+ * also enabled for all its descendant cgroups. If @cpuctx's -+ * cgroup is a descendant of @event's (the test covers identity -+ * case), it's a match. -+ */ -+ return cgroup_is_descendant(cpuctx->cgrp->css.cgroup, -+ event->cgrp->css.cgroup); -+} -+ -+static inline void perf_detach_cgroup(struct perf_event *event) -+{ -+ css_put(&event->cgrp->css); -+ event->cgrp = NULL; -+} -+ -+static inline int is_cgroup_event(struct perf_event *event) -+{ -+ return event->cgrp != NULL; -+} -+ -+static inline u64 perf_cgroup_event_time(struct perf_event *event) -+{ -+ struct perf_cgroup_info *t; -+ -+ t = per_cpu_ptr(event->cgrp->info, event->cpu); -+ return t->time; -+} -+ -+static inline void __update_cgrp_time(struct perf_cgroup *cgrp) -+{ -+ struct perf_cgroup_info *info; -+ u64 now; -+ -+ now = perf_clock(); -+ -+ info = this_cpu_ptr(cgrp->info); -+ -+ info->time += now - info->timestamp; -+ info->timestamp = now; -+} -+ -+static inline void update_cgrp_time_from_cpuctx(struct perf_cpu_context *cpuctx) -+{ -+ struct perf_cgroup *cgrp_out = cpuctx->cgrp; -+ if (cgrp_out) -+ __update_cgrp_time(cgrp_out); -+} -+ -+static inline void update_cgrp_time_from_event(struct perf_event *event) -+{ -+ struct perf_cgroup *cgrp; -+ -+ /* -+ * ensure we access cgroup data only when needed and -+ * when we know the cgroup is pinned (css_get) -+ */ -+ if (!is_cgroup_event(event)) -+ return; -+ -+ cgrp = perf_cgroup_from_task(current); -+ /* -+ * Do not update time when cgroup is not active -+ */ -+ if (cgrp == event->cgrp) -+ __update_cgrp_time(event->cgrp); -+} -+ -+static inline void -+perf_cgroup_set_timestamp(struct task_struct *task, -+ struct perf_event_context *ctx) -+{ -+ struct perf_cgroup *cgrp; -+ struct perf_cgroup_info *info; -+ -+ /* -+ * ctx->lock held by caller -+ * ensure we do not access cgroup data -+ * unless we have the cgroup pinned (css_get) -+ */ -+ if (!task || !ctx->nr_cgroups) -+ return; -+ -+ cgrp = perf_cgroup_from_task(task); -+ info = this_cpu_ptr(cgrp->info); -+ info->timestamp = ctx->timestamp; -+} -+ -+#define PERF_CGROUP_SWOUT 0x1 /* cgroup switch out every event */ -+#define PERF_CGROUP_SWIN 0x2 /* cgroup switch in events based on task */ -+ -+/* -+ * reschedule events based on the cgroup constraint of task. -+ * -+ * mode SWOUT : schedule out everything -+ * mode SWIN : schedule in based on cgroup for next -+ */ -+void perf_cgroup_switch(struct task_struct *task, int mode) -+{ -+ struct perf_cpu_context *cpuctx; -+ struct pmu *pmu; -+ unsigned long flags; -+ -+ /* -+ * disable interrupts to avoid geting nr_cgroup -+ * changes via __perf_event_disable(). Also -+ * avoids preemption. -+ */ -+ local_irq_save(flags); -+ -+ /* -+ * we reschedule only in the presence of cgroup -+ * constrained events. -+ */ -+ rcu_read_lock(); -+ -+ list_for_each_entry_rcu(pmu, &pmus, entry) { -+ cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); -+ if (cpuctx->unique_pmu != pmu) -+ continue; /* ensure we process each cpuctx once */ -+ -+ /* -+ * perf_cgroup_events says at least one -+ * context on this CPU has cgroup events. -+ * -+ * ctx->nr_cgroups reports the number of cgroup -+ * events for a context. -+ */ -+ if (cpuctx->ctx.nr_cgroups > 0) { -+ perf_ctx_lock(cpuctx, cpuctx->task_ctx); -+ perf_pmu_disable(cpuctx->ctx.pmu); -+ -+ if (mode & PERF_CGROUP_SWOUT) { -+ cpu_ctx_sched_out(cpuctx, EVENT_ALL); -+ /* -+ * must not be done before ctxswout due -+ * to event_filter_match() in event_sched_out() -+ */ -+ cpuctx->cgrp = NULL; -+ } -+ -+ if (mode & PERF_CGROUP_SWIN) { -+ WARN_ON_ONCE(cpuctx->cgrp); -+ /* -+ * set cgrp before ctxsw in to allow -+ * event_filter_match() to not have to pass -+ * task around -+ */ -+ cpuctx->cgrp = perf_cgroup_from_task(task); -+ cpu_ctx_sched_in(cpuctx, EVENT_ALL, task); -+ } -+ perf_pmu_enable(cpuctx->ctx.pmu); -+ perf_ctx_unlock(cpuctx, cpuctx->task_ctx); -+ } -+ } -+ -+ rcu_read_unlock(); -+ -+ local_irq_restore(flags); -+} -+ -+static inline void perf_cgroup_sched_out(struct task_struct *task, -+ struct task_struct *next) -+{ -+ struct perf_cgroup *cgrp1; -+ struct perf_cgroup *cgrp2 = NULL; -+ -+ /* -+ * we come here when we know perf_cgroup_events > 0 -+ */ -+ cgrp1 = perf_cgroup_from_task(task); -+ -+ /* -+ * next is NULL when called from perf_event_enable_on_exec() -+ * that will systematically cause a cgroup_switch() -+ */ -+ if (next) -+ cgrp2 = perf_cgroup_from_task(next); -+ -+ /* -+ * only schedule out current cgroup events if we know -+ * that we are switching to a different cgroup. Otherwise, -+ * do no touch the cgroup events. -+ */ -+ if (cgrp1 != cgrp2) -+ perf_cgroup_switch(task, PERF_CGROUP_SWOUT); -+} -+ -+static inline void perf_cgroup_sched_in(struct task_struct *prev, -+ struct task_struct *task) -+{ -+ struct perf_cgroup *cgrp1; -+ struct perf_cgroup *cgrp2 = NULL; -+ -+ /* -+ * we come here when we know perf_cgroup_events > 0 -+ */ -+ cgrp1 = perf_cgroup_from_task(task); -+ -+ /* prev can never be NULL */ -+ cgrp2 = perf_cgroup_from_task(prev); -+ -+ /* -+ * only need to schedule in cgroup events if we are changing -+ * cgroup during ctxsw. Cgroup events were not scheduled -+ * out of ctxsw out if that was not the case. -+ */ -+ if (cgrp1 != cgrp2) -+ perf_cgroup_switch(task, PERF_CGROUP_SWIN); -+} -+ -+static inline int perf_cgroup_connect(int fd, struct perf_event *event, -+ struct perf_event_attr *attr, -+ struct perf_event *group_leader) -+{ -+ struct perf_cgroup *cgrp; -+ struct cgroup_subsys_state *css; -+ struct fd f = fdget(fd); -+ int ret = 0; -+ -+ if (!f.file) -+ return -EBADF; -+ -+ css = css_tryget_online_from_dir(f.file->f_dentry, -+ &perf_event_cgrp_subsys); -+ if (IS_ERR(css)) { -+ ret = PTR_ERR(css); -+ goto out; -+ } -+ -+ cgrp = container_of(css, struct perf_cgroup, css); -+ event->cgrp = cgrp; -+ -+ /* -+ * all events in a group must monitor -+ * the same cgroup because a task belongs -+ * to only one perf cgroup at a time -+ */ -+ if (group_leader && group_leader->cgrp != cgrp) { -+ perf_detach_cgroup(event); -+ ret = -EINVAL; -+ } -+out: -+ fdput(f); -+ return ret; -+} -+ -+static inline void -+perf_cgroup_set_shadow_time(struct perf_event *event, u64 now) -+{ -+ struct perf_cgroup_info *t; -+ t = per_cpu_ptr(event->cgrp->info, event->cpu); -+ event->shadow_ctx_time = now - t->timestamp; -+} -+ -+static inline void -+perf_cgroup_defer_enabled(struct perf_event *event) -+{ -+ /* -+ * when the current task's perf cgroup does not match -+ * the event's, we need to remember to call the -+ * perf_mark_enable() function the first time a task with -+ * a matching perf cgroup is scheduled in. -+ */ -+ if (is_cgroup_event(event) && !perf_cgroup_match(event)) -+ event->cgrp_defer_enabled = 1; -+} -+ -+static inline void -+perf_cgroup_mark_enabled(struct perf_event *event, -+ struct perf_event_context *ctx) -+{ -+ struct perf_event *sub; -+ u64 tstamp = perf_event_time(event); -+ -+ if (!event->cgrp_defer_enabled) -+ return; -+ -+ event->cgrp_defer_enabled = 0; -+ -+ event->tstamp_enabled = tstamp - event->total_time_enabled; -+ list_for_each_entry(sub, &event->sibling_list, group_entry) { -+ if (sub->state >= PERF_EVENT_STATE_INACTIVE) { -+ sub->tstamp_enabled = tstamp - sub->total_time_enabled; -+ sub->cgrp_defer_enabled = 0; -+ } -+ } -+} -+#else /* !CONFIG_CGROUP_PERF */ -+ -+static inline bool -+perf_cgroup_match(struct perf_event *event) -+{ -+ return true; -+} -+ -+static inline void perf_detach_cgroup(struct perf_event *event) -+{} -+ -+static inline int is_cgroup_event(struct perf_event *event) -+{ -+ return 0; -+} -+ -+static inline u64 perf_cgroup_event_cgrp_time(struct perf_event *event) -+{ -+ return 0; -+} -+ -+static inline void update_cgrp_time_from_event(struct perf_event *event) -+{ -+} -+ -+static inline void update_cgrp_time_from_cpuctx(struct perf_cpu_context *cpuctx) -+{ -+} -+ -+static inline void perf_cgroup_sched_out(struct task_struct *task, -+ struct task_struct *next) -+{ -+} -+ -+static inline void perf_cgroup_sched_in(struct task_struct *prev, -+ struct task_struct *task) -+{ -+} -+ -+static inline int perf_cgroup_connect(pid_t pid, struct perf_event *event, -+ struct perf_event_attr *attr, -+ struct perf_event *group_leader) -+{ -+ return -EINVAL; -+} -+ -+static inline void -+perf_cgroup_set_timestamp(struct task_struct *task, -+ struct perf_event_context *ctx) -+{ -+} -+ -+void -+perf_cgroup_switch(struct task_struct *task, struct task_struct *next) -+{ -+} -+ -+static inline void -+perf_cgroup_set_shadow_time(struct perf_event *event, u64 now) -+{ -+} -+ -+static inline u64 perf_cgroup_event_time(struct perf_event *event) -+{ -+ return 0; -+} -+ -+static inline void -+perf_cgroup_defer_enabled(struct perf_event *event) -+{ -+} -+ -+static inline void -+perf_cgroup_mark_enabled(struct perf_event *event, -+ struct perf_event_context *ctx) -+{ -+} -+#endif -+ -+/* -+ * set default to be dependent on timer tick just -+ * like original code -+ */ -+#define PERF_CPU_HRTIMER (1000 / HZ) -+/* -+ * function must be called with interrupts disbled -+ */ -+static enum hrtimer_restart perf_cpu_hrtimer_handler(struct hrtimer *hr) -+{ -+ struct perf_cpu_context *cpuctx; -+ enum hrtimer_restart ret = HRTIMER_NORESTART; -+ int rotations = 0; -+ -+ WARN_ON(!irqs_disabled()); -+ -+ cpuctx = container_of(hr, struct perf_cpu_context, hrtimer); -+ -+ rotations = perf_rotate_context(cpuctx); -+ -+ /* -+ * arm timer if needed -+ */ -+ if (rotations) { -+ hrtimer_forward_now(hr, cpuctx->hrtimer_interval); -+ ret = HRTIMER_RESTART; -+ } -+ -+ return ret; -+} -+ -+/* CPU is going down */ -+void perf_cpu_hrtimer_cancel(int cpu) -+{ -+ struct perf_cpu_context *cpuctx; -+ struct pmu *pmu; -+ unsigned long flags; -+ -+ if (WARN_ON(cpu != smp_processor_id())) -+ return; -+ -+ local_irq_save(flags); -+ -+ rcu_read_lock(); -+ -+ list_for_each_entry_rcu(pmu, &pmus, entry) { -+ cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); -+ -+ if (pmu->task_ctx_nr == perf_sw_context) -+ continue; -+ -+ hrtimer_cancel(&cpuctx->hrtimer); -+ } -+ -+ rcu_read_unlock(); -+ -+ local_irq_restore(flags); -+} -+ -+static void __perf_cpu_hrtimer_init(struct perf_cpu_context *cpuctx, int cpu) -+{ -+ struct hrtimer *hr = &cpuctx->hrtimer; -+ struct pmu *pmu = cpuctx->ctx.pmu; -+ int timer; -+ -+ /* no multiplexing needed for SW PMU */ -+ if (pmu->task_ctx_nr == perf_sw_context) -+ return; -+ -+ /* -+ * check default is sane, if not set then force to -+ * default interval (1/tick) -+ */ -+ timer = pmu->hrtimer_interval_ms; -+ if (timer < 1) -+ timer = pmu->hrtimer_interval_ms = PERF_CPU_HRTIMER; -+ -+ cpuctx->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * timer); -+ -+ hrtimer_init(hr, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED); -+ hr->function = perf_cpu_hrtimer_handler; -+} -+ -+static void perf_cpu_hrtimer_restart(struct perf_cpu_context *cpuctx) -+{ -+ struct hrtimer *hr = &cpuctx->hrtimer; -+ struct pmu *pmu = cpuctx->ctx.pmu; -+ -+ /* not for SW PMU */ -+ if (pmu->task_ctx_nr == perf_sw_context) -+ return; -+ -+ if (hrtimer_active(hr)) -+ return; -+ -+ if (!hrtimer_callback_running(hr)) -+ __hrtimer_start_range_ns(hr, cpuctx->hrtimer_interval, -+ 0, HRTIMER_MODE_REL_PINNED, 0); -+} -+ -+void perf_pmu_disable(struct pmu *pmu) -+{ -+ int *count = this_cpu_ptr(pmu->pmu_disable_count); -+ if (!(*count)++) -+ pmu->pmu_disable(pmu); -+} -+ -+void perf_pmu_enable(struct pmu *pmu) -+{ -+ int *count = this_cpu_ptr(pmu->pmu_disable_count); -+ if (!--(*count)) -+ pmu->pmu_enable(pmu); -+} -+ -+static DEFINE_PER_CPU(struct list_head, rotation_list); -+ -+/* -+ * perf_pmu_rotate_start() and perf_rotate_context() are fully serialized -+ * because they're strictly cpu affine and rotate_start is called with IRQs -+ * disabled, while rotate_context is called from IRQ context. -+ */ -+static void perf_pmu_rotate_start(struct pmu *pmu) -+{ -+ struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); -+ struct list_head *head = this_cpu_ptr(&rotation_list); -+ -+ WARN_ON(!irqs_disabled()); -+ -+ if (list_empty(&cpuctx->rotation_list)) -+ list_add(&cpuctx->rotation_list, head); -+} -+ -+static void get_ctx(struct perf_event_context *ctx) -+{ -+ WARN_ON(!atomic_inc_not_zero(&ctx->refcount)); -+} -+ -+static void put_ctx(struct perf_event_context *ctx) -+{ -+ if (atomic_dec_and_test(&ctx->refcount)) { -+ if (ctx->parent_ctx) -+ put_ctx(ctx->parent_ctx); -+ if (ctx->task) -+ put_task_struct(ctx->task); -+ kfree_rcu(ctx, rcu_head); -+ } -+} -+ -+/* -+ * This must be done under the ctx->lock, such as to serialize against -+ * context_equiv(), therefore we cannot call put_ctx() since that might end up -+ * calling scheduler related locks and ctx->lock nests inside those. -+ */ -+static __must_check struct perf_event_context * -+unclone_ctx(struct perf_event_context *ctx) -+{ -+ struct perf_event_context *parent_ctx = ctx->parent_ctx; -+ -+ lockdep_assert_held(&ctx->lock); -+ -+ if (parent_ctx) -+ ctx->parent_ctx = NULL; -+ ctx->generation++; -+ -+ return parent_ctx; -+} -+ -+static u32 perf_event_pid(struct perf_event *event, struct task_struct *p) -+{ -+ /* -+ * only top level events have the pid namespace they were created in -+ */ -+ if (event->parent) -+ event = event->parent; -+ -+ return task_tgid_nr_ns(p, event->ns); -+} -+ -+static u32 perf_event_tid(struct perf_event *event, struct task_struct *p) -+{ -+ /* -+ * only top level events have the pid namespace they were created in -+ */ -+ if (event->parent) -+ event = event->parent; -+ -+ return task_pid_nr_ns(p, event->ns); -+} -+ -+/* -+ * If we inherit events we want to return the parent event id -+ * to userspace. -+ */ -+static u64 primary_event_id(struct perf_event *event) -+{ -+ u64 id = event->id; -+ -+ if (event->parent) -+ id = event->parent->id; -+ -+ return id; -+} -+ -+/* -+ * Get the perf_event_context for a task and lock it. -+ * This has to cope with with the fact that until it is locked, -+ * the context could get moved to another task. -+ */ -+static struct perf_event_context * -+perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags) -+{ -+ struct perf_event_context *ctx; -+ -+retry: -+ /* -+ * One of the few rules of preemptible RCU is that one cannot do -+ * rcu_read_unlock() while holding a scheduler (or nested) lock when -+ * part of the read side critical section was preemptible -- see -+ * rcu_read_unlock_special(). -+ * -+ * Since ctx->lock nests under rq->lock we must ensure the entire read -+ * side critical section is non-preemptible. -+ */ -+ preempt_disable(); -+ rcu_read_lock(); -+ ctx = rcu_dereference(task->perf_event_ctxp[ctxn]); -+ if (ctx) { -+ /* -+ * If this context is a clone of another, it might -+ * get swapped for another underneath us by -+ * perf_event_task_sched_out, though the -+ * rcu_read_lock() protects us from any context -+ * getting freed. Lock the context and check if it -+ * got swapped before we could get the lock, and retry -+ * if so. If we locked the right context, then it -+ * can't get swapped on us any more. -+ */ -+ raw_spin_lock_irqsave(&ctx->lock, *flags); -+ if (ctx != rcu_dereference(task->perf_event_ctxp[ctxn])) { -+ raw_spin_unlock_irqrestore(&ctx->lock, *flags); -+ rcu_read_unlock(); -+ preempt_enable(); -+ goto retry; -+ } -+ -+ if (!atomic_inc_not_zero(&ctx->refcount)) { -+ raw_spin_unlock_irqrestore(&ctx->lock, *flags); -+ ctx = NULL; -+ } -+ } -+ rcu_read_unlock(); -+ preempt_enable(); -+ return ctx; -+} -+ -+/* -+ * Get the context for a task and increment its pin_count so it -+ * can't get swapped to another task. This also increments its -+ * reference count so that the context can't get freed. -+ */ -+static struct perf_event_context * -+perf_pin_task_context(struct task_struct *task, int ctxn) -+{ -+ struct perf_event_context *ctx; -+ unsigned long flags; -+ -+ ctx = perf_lock_task_context(task, ctxn, &flags); -+ if (ctx) { -+ ++ctx->pin_count; -+ raw_spin_unlock_irqrestore(&ctx->lock, flags); -+ } -+ return ctx; -+} -+ -+static void perf_unpin_context(struct perf_event_context *ctx) -+{ -+ unsigned long flags; -+ -+ raw_spin_lock_irqsave(&ctx->lock, flags); -+ --ctx->pin_count; -+ raw_spin_unlock_irqrestore(&ctx->lock, flags); -+} -+ -+/* -+ * Update the record of the current time in a context. -+ */ -+static void update_context_time(struct perf_event_context *ctx) -+{ -+ u64 now = perf_clock(); -+ -+ ctx->time += now - ctx->timestamp; -+ ctx->timestamp = now; -+} -+ -+static u64 perf_event_time(struct perf_event *event) -+{ -+ struct perf_event_context *ctx = event->ctx; -+ -+ if (is_cgroup_event(event)) -+ return perf_cgroup_event_time(event); -+ -+ return ctx ? ctx->time : 0; -+} -+ -+/* -+ * Update the total_time_enabled and total_time_running fields for a event. -+ * The caller of this function needs to hold the ctx->lock. -+ */ -+static void update_event_times(struct perf_event *event) -+{ -+ struct perf_event_context *ctx = event->ctx; -+ u64 run_end; -+ -+ if (event->state < PERF_EVENT_STATE_INACTIVE || -+ event->group_leader->state < PERF_EVENT_STATE_INACTIVE) -+ return; -+ /* -+ * in cgroup mode, time_enabled represents -+ * the time the event was enabled AND active -+ * tasks were in the monitored cgroup. This is -+ * independent of the activity of the context as -+ * there may be a mix of cgroup and non-cgroup events. -+ * -+ * That is why we treat cgroup events differently -+ * here. -+ */ -+ if (is_cgroup_event(event)) -+ run_end = perf_cgroup_event_time(event); -+ else if (ctx->is_active) -+ run_end = ctx->time; -+ else -+ run_end = event->tstamp_stopped; -+ -+ event->total_time_enabled = run_end - event->tstamp_enabled; -+ -+ if (event->state == PERF_EVENT_STATE_INACTIVE) -+ run_end = event->tstamp_stopped; -+ else -+ run_end = perf_event_time(event); -+ -+ event->total_time_running = run_end - event->tstamp_running; -+ -+} -+ -+/* -+ * Update total_time_enabled and total_time_running for all events in a group. -+ */ -+static void update_group_times(struct perf_event *leader) -+{ -+ struct perf_event *event; -+ -+ update_event_times(leader); -+ list_for_each_entry(event, &leader->sibling_list, group_entry) -+ update_event_times(event); -+} -+ -+static struct list_head * -+ctx_group_list(struct perf_event *event, struct perf_event_context *ctx) -+{ -+ if (event->attr.pinned) -+ return &ctx->pinned_groups; -+ else -+ return &ctx->flexible_groups; -+} -+ -+/* -+ * Add a event from the lists for its context. -+ * Must be called with ctx->mutex and ctx->lock held. -+ */ -+static void -+list_add_event(struct perf_event *event, struct perf_event_context *ctx) -+{ -+ WARN_ON_ONCE(event->attach_state & PERF_ATTACH_CONTEXT); -+ event->attach_state |= PERF_ATTACH_CONTEXT; -+ -+ /* -+ * If we're a stand alone event or group leader, we go to the context -+ * list, group events are kept attached to the group so that -+ * perf_group_detach can, at all times, locate all siblings. -+ */ -+ if (event->group_leader == event) { -+ struct list_head *list; -+ -+ if (is_software_event(event)) -+ event->group_flags |= PERF_GROUP_SOFTWARE; -+ -+ list = ctx_group_list(event, ctx); -+ list_add_tail(&event->group_entry, list); -+ } -+ -+ if (is_cgroup_event(event)) -+ ctx->nr_cgroups++; -+ -+ if (has_branch_stack(event)) -+ ctx->nr_branch_stack++; -+ -+ list_add_rcu(&event->event_entry, &ctx->event_list); -+ if (!ctx->nr_events) -+ perf_pmu_rotate_start(ctx->pmu); -+ ctx->nr_events++; -+ if (event->attr.inherit_stat) -+ ctx->nr_stat++; -+ -+ ctx->generation++; -+} -+ -+/* -+ * Initialize event state based on the perf_event_attr::disabled. -+ */ -+static inline void perf_event__state_init(struct perf_event *event) -+{ -+ event->state = event->attr.disabled ? PERF_EVENT_STATE_OFF : -+ PERF_EVENT_STATE_INACTIVE; -+} -+ -+/* -+ * Called at perf_event creation and when events are attached/detached from a -+ * group. -+ */ -+static void perf_event__read_size(struct perf_event *event) -+{ -+ int entry = sizeof(u64); /* value */ -+ int size = 0; -+ int nr = 1; -+ -+ if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) -+ size += sizeof(u64); -+ -+ if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) -+ size += sizeof(u64); -+ -+ if (event->attr.read_format & PERF_FORMAT_ID) -+ entry += sizeof(u64); -+ -+ if (event->attr.read_format & PERF_FORMAT_GROUP) { -+ nr += event->group_leader->nr_siblings; -+ size += sizeof(u64); -+ } -+ -+ size += entry * nr; -+ event->read_size = size; -+} -+ -+static void perf_event__header_size(struct perf_event *event) -+{ -+ struct perf_sample_data *data; -+ u64 sample_type = event->attr.sample_type; -+ u16 size = 0; -+ -+ perf_event__read_size(event); -+ -+ if (sample_type & PERF_SAMPLE_IP) -+ size += sizeof(data->ip); -+ -+ if (sample_type & PERF_SAMPLE_ADDR) -+ size += sizeof(data->addr); -+ -+ if (sample_type & PERF_SAMPLE_PERIOD) -+ size += sizeof(data->period); -+ -+ if (sample_type & PERF_SAMPLE_WEIGHT) -+ size += sizeof(data->weight); -+ -+ if (sample_type & PERF_SAMPLE_READ) -+ size += event->read_size; -+ -+ if (sample_type & PERF_SAMPLE_DATA_SRC) -+ size += sizeof(data->data_src.val); -+ -+ if (sample_type & PERF_SAMPLE_TRANSACTION) -+ size += sizeof(data->txn); -+ -+ event->header_size = size; -+} -+ -+static void perf_event__id_header_size(struct perf_event *event) -+{ -+ struct perf_sample_data *data; -+ u64 sample_type = event->attr.sample_type; -+ u16 size = 0; -+ -+ if (sample_type & PERF_SAMPLE_TID) -+ size += sizeof(data->tid_entry); -+ -+ if (sample_type & PERF_SAMPLE_TIME) -+ size += sizeof(data->time); -+ -+ if (sample_type & PERF_SAMPLE_IDENTIFIER) -+ size += sizeof(data->id); -+ -+ if (sample_type & PERF_SAMPLE_ID) -+ size += sizeof(data->id); -+ -+ if (sample_type & PERF_SAMPLE_STREAM_ID) -+ size += sizeof(data->stream_id); -+ -+ if (sample_type & PERF_SAMPLE_CPU) -+ size += sizeof(data->cpu_entry); -+ -+ event->id_header_size = size; -+} -+ -+static void perf_group_attach(struct perf_event *event) -+{ -+ struct perf_event *group_leader = event->group_leader, *pos; -+ -+ /* -+ * We can have double attach due to group movement in perf_event_open. -+ */ -+ if (event->attach_state & PERF_ATTACH_GROUP) -+ return; -+ -+ event->attach_state |= PERF_ATTACH_GROUP; -+ -+ if (group_leader == event) -+ return; -+ -+ if (group_leader->group_flags & PERF_GROUP_SOFTWARE && -+ !is_software_event(event)) -+ group_leader->group_flags &= ~PERF_GROUP_SOFTWARE; -+ -+ list_add_tail(&event->group_entry, &group_leader->sibling_list); -+ group_leader->nr_siblings++; -+ -+ perf_event__header_size(group_leader); -+ -+ list_for_each_entry(pos, &group_leader->sibling_list, group_entry) -+ perf_event__header_size(pos); -+} -+ -+/* -+ * Remove a event from the lists for its context. -+ * Must be called with ctx->mutex and ctx->lock held. -+ */ -+static void -+list_del_event(struct perf_event *event, struct perf_event_context *ctx) -+{ -+ struct perf_cpu_context *cpuctx; -+ /* -+ * We can have double detach due to exit/hot-unplug + close. -+ */ -+ if (!(event->attach_state & PERF_ATTACH_CONTEXT)) -+ return; -+ -+ event->attach_state &= ~PERF_ATTACH_CONTEXT; -+ -+ if (is_cgroup_event(event)) { -+ ctx->nr_cgroups--; -+ cpuctx = __get_cpu_context(ctx); -+ /* -+ * if there are no more cgroup events -+ * then cler cgrp to avoid stale pointer -+ * in update_cgrp_time_from_cpuctx() -+ */ -+ if (!ctx->nr_cgroups) -+ cpuctx->cgrp = NULL; -+ } -+ -+ if (has_branch_stack(event)) -+ ctx->nr_branch_stack--; -+ -+ ctx->nr_events--; -+ if (event->attr.inherit_stat) -+ ctx->nr_stat--; -+ -+ list_del_rcu(&event->event_entry); -+ -+ if (event->group_leader == event) -+ list_del_init(&event->group_entry); -+ -+ update_group_times(event); -+ -+ /* -+ * If event was in error state, then keep it -+ * that way, otherwise bogus counts will be -+ * returned on read(). The only way to get out -+ * of error state is by explicit re-enabling -+ * of the event -+ */ -+ if (event->state > PERF_EVENT_STATE_OFF) -+ event->state = PERF_EVENT_STATE_OFF; -+ -+ ctx->generation++; -+} -+ -+static void perf_group_detach(struct perf_event *event) -+{ -+ struct perf_event *sibling, *tmp; -+ struct list_head *list = NULL; -+ -+ /* -+ * We can have double detach due to exit/hot-unplug + close. -+ */ -+ if (!(event->attach_state & PERF_ATTACH_GROUP)) -+ return; -+ -+ event->attach_state &= ~PERF_ATTACH_GROUP; -+ -+ /* -+ * If this is a sibling, remove it from its group. -+ */ -+ if (event->group_leader != event) { -+ list_del_init(&event->group_entry); -+ event->group_leader->nr_siblings--; -+ goto out; -+ } -+ -+ if (!list_empty(&event->group_entry)) -+ list = &event->group_entry; -+ -+ /* -+ * If this was a group event with sibling events then -+ * upgrade the siblings to singleton events by adding them -+ * to whatever list we are on. -+ */ -+ list_for_each_entry_safe(sibling, tmp, &event->sibling_list, group_entry) { -+ if (list) -+ list_move_tail(&sibling->group_entry, list); -+ sibling->group_leader = sibling; -+ -+ /* Inherit group flags from the previous leader */ -+ sibling->group_flags = event->group_flags; -+ } -+ -+out: -+ perf_event__header_size(event->group_leader); -+ -+ list_for_each_entry(tmp, &event->group_leader->sibling_list, group_entry) -+ perf_event__header_size(tmp); -+} -+ -+/* -+ * User event without the task. -+ */ -+static bool is_orphaned_event(struct perf_event *event) -+{ -+ return event && !is_kernel_event(event) && !event->owner; -+} -+ -+/* -+ * Event has a parent but parent's task finished and it's -+ * alive only because of children holding refference. -+ */ -+static bool is_orphaned_child(struct perf_event *event) -+{ -+ return is_orphaned_event(event->parent); -+} -+ -+static void orphans_remove_work(struct work_struct *work); -+ -+static void schedule_orphans_remove(struct perf_event_context *ctx) -+{ -+ if (!ctx->task || ctx->orphans_remove_sched || !perf_wq) -+ return; -+ -+ if (queue_delayed_work(perf_wq, &ctx->orphans_remove, 1)) { -+ get_ctx(ctx); -+ ctx->orphans_remove_sched = true; -+ } -+} -+ -+static int __init perf_workqueue_init(void) -+{ -+ perf_wq = create_singlethread_workqueue("perf"); -+ WARN(!perf_wq, "failed to create perf workqueue\n"); -+ return perf_wq ? 0 : -1; -+} -+ -+core_initcall(perf_workqueue_init); -+ -+static inline int -+event_filter_match(struct perf_event *event) -+{ -+ return (event->cpu == -1 || event->cpu == smp_processor_id()) -+ && perf_cgroup_match(event); -+} -+ -+static void -+event_sched_out(struct perf_event *event, -+ struct perf_cpu_context *cpuctx, -+ struct perf_event_context *ctx) -+{ -+ u64 tstamp = perf_event_time(event); -+ u64 delta; -+ /* -+ * An event which could not be activated because of -+ * filter mismatch still needs to have its timings -+ * maintained, otherwise bogus information is return -+ * via read() for time_enabled, time_running: -+ */ -+ if (event->state == PERF_EVENT_STATE_INACTIVE -+ && !event_filter_match(event)) { -+ delta = tstamp - event->tstamp_stopped; -+ event->tstamp_running += delta; -+ event->tstamp_stopped = tstamp; -+ } -+ -+ if (event->state != PERF_EVENT_STATE_ACTIVE) -+ return; -+ -+ perf_pmu_disable(event->pmu); -+ -+ event->state = PERF_EVENT_STATE_INACTIVE; -+ if (event->pending_disable) { -+ event->pending_disable = 0; -+ event->state = PERF_EVENT_STATE_OFF; -+ } -+ event->tstamp_stopped = tstamp; -+ event->pmu->del(event, 0); -+ event->oncpu = -1; -+ -+ if (!is_software_event(event)) -+ cpuctx->active_oncpu--; -+ ctx->nr_active--; -+ if (event->attr.freq && event->attr.sample_freq) -+ ctx->nr_freq--; -+ if (event->attr.exclusive || !cpuctx->active_oncpu) -+ cpuctx->exclusive = 0; -+ -+ if (is_orphaned_child(event)) -+ schedule_orphans_remove(ctx); -+ -+ perf_pmu_enable(event->pmu); -+} -+ -+static void -+group_sched_out(struct perf_event *group_event, -+ struct perf_cpu_context *cpuctx, -+ struct perf_event_context *ctx) -+{ -+ struct perf_event *event; -+ int state = group_event->state; -+ -+ event_sched_out(group_event, cpuctx, ctx); -+ -+ /* -+ * Schedule out siblings (if any): -+ */ -+ list_for_each_entry(event, &group_event->sibling_list, group_entry) -+ event_sched_out(event, cpuctx, ctx); -+ -+ if (state == PERF_EVENT_STATE_ACTIVE && group_event->attr.exclusive) -+ cpuctx->exclusive = 0; -+} -+ -+struct remove_event { -+ struct perf_event *event; -+ bool detach_group; -+}; -+ -+/* -+ * Cross CPU call to remove a performance event -+ * -+ * We disable the event on the hardware level first. After that we -+ * remove it from the context list. -+ */ -+static int __perf_remove_from_context(void *info) -+{ -+ struct remove_event *re = info; -+ struct perf_event *event = re->event; -+ struct perf_event_context *ctx = event->ctx; -+ struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); -+ -+ raw_spin_lock(&ctx->lock); -+ event_sched_out(event, cpuctx, ctx); -+ if (re->detach_group) -+ perf_group_detach(event); -+ list_del_event(event, ctx); -+ if (!ctx->nr_events && cpuctx->task_ctx == ctx) { -+ ctx->is_active = 0; -+ cpuctx->task_ctx = NULL; -+ } -+ raw_spin_unlock(&ctx->lock); -+ -+ return 0; -+} -+ -+ -+/* -+ * Remove the event from a task's (or a CPU's) list of events. -+ * -+ * CPU events are removed with a smp call. For task events we only -+ * call when the task is on a CPU. -+ * -+ * If event->ctx is a cloned context, callers must make sure that -+ * every task struct that event->ctx->task could possibly point to -+ * remains valid. This is OK when called from perf_release since -+ * that only calls us on the top-level context, which can't be a clone. -+ * When called from perf_event_exit_task, it's OK because the -+ * context has been detached from its task. -+ */ -+static void perf_remove_from_context(struct perf_event *event, bool detach_group) -+{ -+ struct perf_event_context *ctx = event->ctx; -+ struct task_struct *task = ctx->task; -+ struct remove_event re = { -+ .event = event, -+ .detach_group = detach_group, -+ }; -+ -+ lockdep_assert_held(&ctx->mutex); -+ -+ if (!task) { -+ /* -+ * Per cpu events are removed via an smp call. The removal can -+ * fail if the CPU is currently offline, but in that case we -+ * already called __perf_remove_from_context from -+ * perf_event_exit_cpu. -+ */ -+ cpu_function_call(event->cpu, __perf_remove_from_context, &re); -+ return; -+ } -+ -+retry: -+ if (!task_function_call(task, __perf_remove_from_context, &re)) -+ return; -+ -+ raw_spin_lock_irq(&ctx->lock); -+ /* -+ * If we failed to find a running task, but find the context active now -+ * that we've acquired the ctx->lock, retry. -+ */ -+ if (ctx->is_active) { -+ raw_spin_unlock_irq(&ctx->lock); -+ /* -+ * Reload the task pointer, it might have been changed by -+ * a concurrent perf_event_context_sched_out(). -+ */ -+ task = ctx->task; -+ goto retry; -+ } -+ -+ /* -+ * Since the task isn't running, its safe to remove the event, us -+ * holding the ctx->lock ensures the task won't get scheduled in. -+ */ -+ if (detach_group) -+ perf_group_detach(event); -+ list_del_event(event, ctx); -+ raw_spin_unlock_irq(&ctx->lock); -+} -+ -+/* -+ * Cross CPU call to disable a performance event -+ */ -+int __perf_event_disable(void *info) -+{ -+ struct perf_event *event = info; -+ struct perf_event_context *ctx = event->ctx; -+ struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); -+ -+ /* -+ * If this is a per-task event, need to check whether this -+ * event's task is the current task on this cpu. -+ * -+ * Can trigger due to concurrent perf_event_context_sched_out() -+ * flipping contexts around. -+ */ -+ if (ctx->task && cpuctx->task_ctx != ctx) -+ return -EINVAL; -+ -+ raw_spin_lock(&ctx->lock); -+ -+ /* -+ * If the event is on, turn it off. -+ * If it is in error state, leave it in error state. -+ */ -+ if (event->state >= PERF_EVENT_STATE_INACTIVE) { -+ update_context_time(ctx); -+ update_cgrp_time_from_event(event); -+ update_group_times(event); -+ if (event == event->group_leader) -+ group_sched_out(event, cpuctx, ctx); -+ else -+ event_sched_out(event, cpuctx, ctx); -+ event->state = PERF_EVENT_STATE_OFF; -+ } -+ -+ raw_spin_unlock(&ctx->lock); -+ -+ return 0; -+} -+ -+/* -+ * Disable a event. -+ * -+ * If event->ctx is a cloned context, callers must make sure that -+ * every task struct that event->ctx->task could possibly point to -+ * remains valid. This condition is satisifed when called through -+ * perf_event_for_each_child or perf_event_for_each because they -+ * hold the top-level event's child_mutex, so any descendant that -+ * goes to exit will block in sync_child_event. -+ * When called from perf_pending_event it's OK because event->ctx -+ * is the current context on this CPU and preemption is disabled, -+ * hence we can't get into perf_event_task_sched_out for this context. -+ */ -+void perf_event_disable(struct perf_event *event) -+{ -+ struct perf_event_context *ctx = event->ctx; -+ struct task_struct *task = ctx->task; -+ -+ if (!task) { -+ /* -+ * Disable the event on the cpu that it's on -+ */ -+ cpu_function_call(event->cpu, __perf_event_disable, event); -+ return; -+ } -+ -+retry: -+ if (!task_function_call(task, __perf_event_disable, event)) -+ return; -+ -+ raw_spin_lock_irq(&ctx->lock); -+ /* -+ * If the event is still active, we need to retry the cross-call. -+ */ -+ if (event->state == PERF_EVENT_STATE_ACTIVE) { -+ raw_spin_unlock_irq(&ctx->lock); -+ /* -+ * Reload the task pointer, it might have been changed by -+ * a concurrent perf_event_context_sched_out(). -+ */ -+ task = ctx->task; -+ goto retry; -+ } -+ -+ /* -+ * Since we have the lock this context can't be scheduled -+ * in, so we can change the state safely. -+ */ -+ if (event->state == PERF_EVENT_STATE_INACTIVE) { -+ update_group_times(event); -+ event->state = PERF_EVENT_STATE_OFF; -+ } -+ raw_spin_unlock_irq(&ctx->lock); -+} -+EXPORT_SYMBOL_GPL(perf_event_disable); -+ -+static void perf_set_shadow_time(struct perf_event *event, -+ struct perf_event_context *ctx, -+ u64 tstamp) -+{ -+ /* -+ * use the correct time source for the time snapshot -+ * -+ * We could get by without this by leveraging the -+ * fact that to get to this function, the caller -+ * has most likely already called update_context_time() -+ * and update_cgrp_time_xx() and thus both timestamp -+ * are identical (or very close). Given that tstamp is, -+ * already adjusted for cgroup, we could say that: -+ * tstamp - ctx->timestamp -+ * is equivalent to -+ * tstamp - cgrp->timestamp. -+ * -+ * Then, in perf_output_read(), the calculation would -+ * work with no changes because: -+ * - event is guaranteed scheduled in -+ * - no scheduled out in between -+ * - thus the timestamp would be the same -+ * -+ * But this is a bit hairy. -+ * -+ * So instead, we have an explicit cgroup call to remain -+ * within the time time source all along. We believe it -+ * is cleaner and simpler to understand. -+ */ -+ if (is_cgroup_event(event)) -+ perf_cgroup_set_shadow_time(event, tstamp); -+ else -+ event->shadow_ctx_time = tstamp - ctx->timestamp; -+} -+ -+#define MAX_INTERRUPTS (~0ULL) -+ -+static void perf_log_throttle(struct perf_event *event, int enable); -+ -+static int -+event_sched_in(struct perf_event *event, -+ struct perf_cpu_context *cpuctx, -+ struct perf_event_context *ctx) -+{ -+ u64 tstamp = perf_event_time(event); -+ int ret = 0; -+ -+ lockdep_assert_held(&ctx->lock); -+ -+ if (event->state <= PERF_EVENT_STATE_OFF) -+ return 0; -+ -+ event->state = PERF_EVENT_STATE_ACTIVE; -+ event->oncpu = smp_processor_id(); -+ -+ /* -+ * Unthrottle events, since we scheduled we might have missed several -+ * ticks already, also for a heavily scheduling task there is little -+ * guarantee it'll get a tick in a timely manner. -+ */ -+ if (unlikely(event->hw.interrupts == MAX_INTERRUPTS)) { -+ perf_log_throttle(event, 1); -+ event->hw.interrupts = 0; -+ } -+ -+ /* -+ * The new state must be visible before we turn it on in the hardware: -+ */ -+ smp_wmb(); -+ -+ perf_pmu_disable(event->pmu); -+ -+ if (event->pmu->add(event, PERF_EF_START)) { -+ event->state = PERF_EVENT_STATE_INACTIVE; -+ event->oncpu = -1; -+ ret = -EAGAIN; -+ goto out; -+ } -+ -+ event->tstamp_running += tstamp - event->tstamp_stopped; -+ -+ perf_set_shadow_time(event, ctx, tstamp); -+ -+ if (!is_software_event(event)) -+ cpuctx->active_oncpu++; -+ ctx->nr_active++; -+ if (event->attr.freq && event->attr.sample_freq) -+ ctx->nr_freq++; -+ -+ if (event->attr.exclusive) -+ cpuctx->exclusive = 1; -+ -+ if (is_orphaned_child(event)) -+ schedule_orphans_remove(ctx); -+ -+out: -+ perf_pmu_enable(event->pmu); -+ -+ return ret; -+} -+ -+static int -+group_sched_in(struct perf_event *group_event, -+ struct perf_cpu_context *cpuctx, -+ struct perf_event_context *ctx) -+{ -+ struct perf_event *event, *partial_group = NULL; -+ struct pmu *pmu = ctx->pmu; -+ u64 now = ctx->time; -+ bool simulate = false; -+ -+ if (group_event->state == PERF_EVENT_STATE_OFF) -+ return 0; -+ -+ pmu->start_txn(pmu); -+ -+ if (event_sched_in(group_event, cpuctx, ctx)) { -+ pmu->cancel_txn(pmu); -+ perf_cpu_hrtimer_restart(cpuctx); -+ return -EAGAIN; -+ } -+ -+ /* -+ * Schedule in siblings as one group (if any): -+ */ -+ list_for_each_entry(event, &group_event->sibling_list, group_entry) { -+ if (event_sched_in(event, cpuctx, ctx)) { -+ partial_group = event; -+ goto group_error; -+ } -+ } -+ -+ if (!pmu->commit_txn(pmu)) -+ return 0; -+ -+group_error: -+ /* -+ * Groups can be scheduled in as one unit only, so undo any -+ * partial group before returning: -+ * The events up to the failed event are scheduled out normally, -+ * tstamp_stopped will be updated. -+ * -+ * The failed events and the remaining siblings need to have -+ * their timings updated as if they had gone thru event_sched_in() -+ * and event_sched_out(). This is required to get consistent timings -+ * across the group. This also takes care of the case where the group -+ * could never be scheduled by ensuring tstamp_stopped is set to mark -+ * the time the event was actually stopped, such that time delta -+ * calculation in update_event_times() is correct. -+ */ -+ list_for_each_entry(event, &group_event->sibling_list, group_entry) { -+ if (event == partial_group) -+ simulate = true; -+ -+ if (simulate) { -+ event->tstamp_running += now - event->tstamp_stopped; -+ event->tstamp_stopped = now; -+ } else { -+ event_sched_out(event, cpuctx, ctx); -+ } -+ } -+ event_sched_out(group_event, cpuctx, ctx); -+ -+ pmu->cancel_txn(pmu); -+ -+ perf_cpu_hrtimer_restart(cpuctx); -+ -+ return -EAGAIN; -+} -+ -+/* -+ * Work out whether we can put this event group on the CPU now. -+ */ -+static int group_can_go_on(struct perf_event *event, -+ struct perf_cpu_context *cpuctx, -+ int can_add_hw) -+{ -+ /* -+ * Groups consisting entirely of software events can always go on. -+ */ -+ if (event->group_flags & PERF_GROUP_SOFTWARE) -+ return 1; -+ /* -+ * If an exclusive group is already on, no other hardware -+ * events can go on. -+ */ -+ if (cpuctx->exclusive) -+ return 0; -+ /* -+ * If this group is exclusive and there are already -+ * events on the CPU, it can't go on. -+ */ -+ if (event->attr.exclusive && cpuctx->active_oncpu) -+ return 0; -+ /* -+ * Otherwise, try to add it if all previous groups were able -+ * to go on. -+ */ -+ return can_add_hw; -+} -+ -+static void add_event_to_ctx(struct perf_event *event, -+ struct perf_event_context *ctx) -+{ -+ u64 tstamp = perf_event_time(event); -+ -+ list_add_event(event, ctx); -+ perf_group_attach(event); -+ event->tstamp_enabled = tstamp; -+ event->tstamp_running = tstamp; -+ event->tstamp_stopped = tstamp; -+} -+ -+static void task_ctx_sched_out(struct perf_event_context *ctx); -+static void -+ctx_sched_in(struct perf_event_context *ctx, -+ struct perf_cpu_context *cpuctx, -+ enum event_type_t event_type, -+ struct task_struct *task); -+ -+static void perf_event_sched_in(struct perf_cpu_context *cpuctx, -+ struct perf_event_context *ctx, -+ struct task_struct *task) -+{ -+ cpu_ctx_sched_in(cpuctx, EVENT_PINNED, task); -+ if (ctx) -+ ctx_sched_in(ctx, cpuctx, EVENT_PINNED, task); -+ cpu_ctx_sched_in(cpuctx, EVENT_FLEXIBLE, task); -+ if (ctx) -+ ctx_sched_in(ctx, cpuctx, EVENT_FLEXIBLE, task); -+} -+ -+/* -+ * Cross CPU call to install and enable a performance event -+ * -+ * Must be called with ctx->mutex held -+ */ -+static int __perf_install_in_context(void *info) -+{ -+ struct perf_event *event = info; -+ struct perf_event_context *ctx = event->ctx; -+ struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); -+ struct perf_event_context *task_ctx = cpuctx->task_ctx; -+ struct task_struct *task = current; -+ -+ perf_ctx_lock(cpuctx, task_ctx); -+ perf_pmu_disable(cpuctx->ctx.pmu); -+ -+ /* -+ * If there was an active task_ctx schedule it out. -+ */ -+ if (task_ctx) -+ task_ctx_sched_out(task_ctx); -+ -+ /* -+ * If the context we're installing events in is not the -+ * active task_ctx, flip them. -+ */ -+ if (ctx->task && task_ctx != ctx) { -+ if (task_ctx) -+ raw_spin_unlock(&task_ctx->lock); -+ raw_spin_lock(&ctx->lock); -+ task_ctx = ctx; -+ } -+ -+ if (task_ctx) { -+ cpuctx->task_ctx = task_ctx; -+ task = task_ctx->task; -+ } -+ -+ cpu_ctx_sched_out(cpuctx, EVENT_ALL); -+ -+ update_context_time(ctx); -+ /* -+ * update cgrp time only if current cgrp -+ * matches event->cgrp. Must be done before -+ * calling add_event_to_ctx() -+ */ -+ update_cgrp_time_from_event(event); -+ -+ add_event_to_ctx(event, ctx); -+ -+ /* -+ * Schedule everything back in -+ */ -+ perf_event_sched_in(cpuctx, task_ctx, task); -+ -+ perf_pmu_enable(cpuctx->ctx.pmu); -+ perf_ctx_unlock(cpuctx, task_ctx); -+ -+ return 0; -+} -+ -+/* -+ * Attach a performance event to a context -+ * -+ * First we add the event to the list with the hardware enable bit -+ * in event->hw_config cleared. -+ * -+ * If the event is attached to a task which is on a CPU we use a smp -+ * call to enable it in the task context. The task might have been -+ * scheduled away, but we check this in the smp call again. -+ */ -+static void -+perf_install_in_context(struct perf_event_context *ctx, -+ struct perf_event *event, -+ int cpu) -+{ -+ struct task_struct *task = ctx->task; -+ -+ lockdep_assert_held(&ctx->mutex); -+ -+ event->ctx = ctx; -+ if (event->cpu != -1) -+ event->cpu = cpu; -+ -+ if (!task) { -+ /* -+ * Per cpu events are installed via an smp call and -+ * the install is always successful. -+ */ -+ cpu_function_call(cpu, __perf_install_in_context, event); -+ return; -+ } -+ -+retry: -+ if (!task_function_call(task, __perf_install_in_context, event)) -+ return; -+ -+ raw_spin_lock_irq(&ctx->lock); -+ /* -+ * If we failed to find a running task, but find the context active now -+ * that we've acquired the ctx->lock, retry. -+ */ -+ if (ctx->is_active) { -+ raw_spin_unlock_irq(&ctx->lock); -+ /* -+ * Reload the task pointer, it might have been changed by -+ * a concurrent perf_event_context_sched_out(). -+ */ -+ task = ctx->task; -+ goto retry; -+ } -+ -+ /* -+ * Since the task isn't running, its safe to add the event, us holding -+ * the ctx->lock ensures the task won't get scheduled in. -+ */ -+ add_event_to_ctx(event, ctx); -+ raw_spin_unlock_irq(&ctx->lock); -+} -+ -+/* -+ * Put a event into inactive state and update time fields. -+ * Enabling the leader of a group effectively enables all -+ * the group members that aren't explicitly disabled, so we -+ * have to update their ->tstamp_enabled also. -+ * Note: this works for group members as well as group leaders -+ * since the non-leader members' sibling_lists will be empty. -+ */ -+static void __perf_event_mark_enabled(struct perf_event *event) -+{ -+ struct perf_event *sub; -+ u64 tstamp = perf_event_time(event); -+ -+ event->state = PERF_EVENT_STATE_INACTIVE; -+ event->tstamp_enabled = tstamp - event->total_time_enabled; -+ list_for_each_entry(sub, &event->sibling_list, group_entry) { -+ if (sub->state >= PERF_EVENT_STATE_INACTIVE) -+ sub->tstamp_enabled = tstamp - sub->total_time_enabled; -+ } -+} -+ -+/* -+ * Cross CPU call to enable a performance event -+ */ -+static int __perf_event_enable(void *info) -+{ -+ struct perf_event *event = info; -+ struct perf_event_context *ctx = event->ctx; -+ struct perf_event *leader = event->group_leader; -+ struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); -+ int err; -+ -+ /* -+ * There's a time window between 'ctx->is_active' check -+ * in perf_event_enable function and this place having: -+ * - IRQs on -+ * - ctx->lock unlocked -+ * -+ * where the task could be killed and 'ctx' deactivated -+ * by perf_event_exit_task. -+ */ -+ if (!ctx->is_active) -+ return -EINVAL; -+ -+ raw_spin_lock(&ctx->lock); -+ update_context_time(ctx); -+ -+ if (event->state >= PERF_EVENT_STATE_INACTIVE) -+ goto unlock; -+ -+ /* -+ * set current task's cgroup time reference point -+ */ -+ perf_cgroup_set_timestamp(current, ctx); -+ -+ __perf_event_mark_enabled(event); -+ -+ if (!event_filter_match(event)) { -+ if (is_cgroup_event(event)) -+ perf_cgroup_defer_enabled(event); -+ goto unlock; -+ } -+ -+ /* -+ * If the event is in a group and isn't the group leader, -+ * then don't put it on unless the group is on. -+ */ -+ if (leader != event && leader->state != PERF_EVENT_STATE_ACTIVE) -+ goto unlock; -+ -+ if (!group_can_go_on(event, cpuctx, 1)) { -+ err = -EEXIST; -+ } else { -+ if (event == leader) -+ err = group_sched_in(event, cpuctx, ctx); -+ else -+ err = event_sched_in(event, cpuctx, ctx); -+ } -+ -+ if (err) { -+ /* -+ * If this event can't go on and it's part of a -+ * group, then the whole group has to come off. -+ */ -+ if (leader != event) { -+ group_sched_out(leader, cpuctx, ctx); -+ perf_cpu_hrtimer_restart(cpuctx); -+ } -+ if (leader->attr.pinned) { -+ update_group_times(leader); -+ leader->state = PERF_EVENT_STATE_ERROR; -+ } -+ } -+ -+unlock: -+ raw_spin_unlock(&ctx->lock); -+ -+ return 0; -+} -+ -+/* -+ * Enable a event. -+ * -+ * If event->ctx is a cloned context, callers must make sure that -+ * every task struct that event->ctx->task could possibly point to -+ * remains valid. This condition is satisfied when called through -+ * perf_event_for_each_child or perf_event_for_each as described -+ * for perf_event_disable. -+ */ -+void perf_event_enable(struct perf_event *event) -+{ -+ struct perf_event_context *ctx = event->ctx; -+ struct task_struct *task = ctx->task; -+ -+ if (!task) { -+ /* -+ * Enable the event on the cpu that it's on -+ */ -+ cpu_function_call(event->cpu, __perf_event_enable, event); -+ return; -+ } -+ -+ raw_spin_lock_irq(&ctx->lock); -+ if (event->state >= PERF_EVENT_STATE_INACTIVE) -+ goto out; -+ -+ /* -+ * If the event is in error state, clear that first. -+ * That way, if we see the event in error state below, we -+ * know that it has gone back into error state, as distinct -+ * from the task having been scheduled away before the -+ * cross-call arrived. -+ */ -+ if (event->state == PERF_EVENT_STATE_ERROR) -+ event->state = PERF_EVENT_STATE_OFF; -+ -+retry: -+ if (!ctx->is_active) { -+ __perf_event_mark_enabled(event); -+ goto out; -+ } -+ -+ raw_spin_unlock_irq(&ctx->lock); -+ -+ if (!task_function_call(task, __perf_event_enable, event)) -+ return; -+ -+ raw_spin_lock_irq(&ctx->lock); -+ -+ /* -+ * If the context is active and the event is still off, -+ * we need to retry the cross-call. -+ */ -+ if (ctx->is_active && event->state == PERF_EVENT_STATE_OFF) { -+ /* -+ * task could have been flipped by a concurrent -+ * perf_event_context_sched_out() -+ */ -+ task = ctx->task; -+ goto retry; -+ } -+ -+out: -+ raw_spin_unlock_irq(&ctx->lock); -+} -+EXPORT_SYMBOL_GPL(perf_event_enable); -+ -+int perf_event_refresh(struct perf_event *event, int refresh) -+{ -+ /* -+ * not supported on inherited events -+ */ -+ if (event->attr.inherit || !is_sampling_event(event)) -+ return -EINVAL; -+ -+ atomic_add(refresh, &event->event_limit); -+ perf_event_enable(event); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(perf_event_refresh); -+ -+static void ctx_sched_out(struct perf_event_context *ctx, -+ struct perf_cpu_context *cpuctx, -+ enum event_type_t event_type) -+{ -+ struct perf_event *event; -+ int is_active = ctx->is_active; -+ -+ ctx->is_active &= ~event_type; -+ if (likely(!ctx->nr_events)) -+ return; -+ -+ update_context_time(ctx); -+ update_cgrp_time_from_cpuctx(cpuctx); -+ if (!ctx->nr_active) -+ return; -+ -+ perf_pmu_disable(ctx->pmu); -+ if ((is_active & EVENT_PINNED) && (event_type & EVENT_PINNED)) { -+ list_for_each_entry(event, &ctx->pinned_groups, group_entry) -+ group_sched_out(event, cpuctx, ctx); -+ } -+ -+ if ((is_active & EVENT_FLEXIBLE) && (event_type & EVENT_FLEXIBLE)) { -+ list_for_each_entry(event, &ctx->flexible_groups, group_entry) -+ group_sched_out(event, cpuctx, ctx); -+ } -+ perf_pmu_enable(ctx->pmu); -+} -+ -+/* -+ * Test whether two contexts are equivalent, i.e. whether they have both been -+ * cloned from the same version of the same context. -+ * -+ * Equivalence is measured using a generation number in the context that is -+ * incremented on each modification to it; see unclone_ctx(), list_add_event() -+ * and list_del_event(). -+ */ -+static int context_equiv(struct perf_event_context *ctx1, -+ struct perf_event_context *ctx2) -+{ -+ lockdep_assert_held(&ctx1->lock); -+ lockdep_assert_held(&ctx2->lock); -+ -+ /* Pinning disables the swap optimization */ -+ if (ctx1->pin_count || ctx2->pin_count) -+ return 0; -+ -+ /* If ctx1 is the parent of ctx2 */ -+ if (ctx1 == ctx2->parent_ctx && ctx1->generation == ctx2->parent_gen) -+ return 1; -+ -+ /* If ctx2 is the parent of ctx1 */ -+ if (ctx1->parent_ctx == ctx2 && ctx1->parent_gen == ctx2->generation) -+ return 1; -+ -+ /* -+ * If ctx1 and ctx2 have the same parent; we flatten the parent -+ * hierarchy, see perf_event_init_context(). -+ */ -+ if (ctx1->parent_ctx && ctx1->parent_ctx == ctx2->parent_ctx && -+ ctx1->parent_gen == ctx2->parent_gen) -+ return 1; -+ -+ /* Unmatched */ -+ return 0; -+} -+ -+static void __perf_event_sync_stat(struct perf_event *event, -+ struct perf_event *next_event) -+{ -+ u64 value; -+ -+ if (!event->attr.inherit_stat) -+ return; -+ -+ /* -+ * Update the event value, we cannot use perf_event_read() -+ * because we're in the middle of a context switch and have IRQs -+ * disabled, which upsets smp_call_function_single(), however -+ * we know the event must be on the current CPU, therefore we -+ * don't need to use it. -+ */ -+ switch (event->state) { -+ case PERF_EVENT_STATE_ACTIVE: -+ event->pmu->read(event); -+ /* fall-through */ -+ -+ case PERF_EVENT_STATE_INACTIVE: -+ update_event_times(event); -+ break; -+ -+ default: -+ break; -+ } -+ -+ /* -+ * In order to keep per-task stats reliable we need to flip the event -+ * values when we flip the contexts. -+ */ -+ value = local64_read(&next_event->count); -+ value = local64_xchg(&event->count, value); -+ local64_set(&next_event->count, value); -+ -+ swap(event->total_time_enabled, next_event->total_time_enabled); -+ swap(event->total_time_running, next_event->total_time_running); -+ -+ /* -+ * Since we swizzled the values, update the user visible data too. -+ */ -+ perf_event_update_userpage(event); -+ perf_event_update_userpage(next_event); -+} -+ -+static void perf_event_sync_stat(struct perf_event_context *ctx, -+ struct perf_event_context *next_ctx) -+{ -+ struct perf_event *event, *next_event; -+ -+ if (!ctx->nr_stat) -+ return; -+ -+ update_context_time(ctx); -+ -+ event = list_first_entry(&ctx->event_list, -+ struct perf_event, event_entry); -+ -+ next_event = list_first_entry(&next_ctx->event_list, -+ struct perf_event, event_entry); -+ -+ while (&event->event_entry != &ctx->event_list && -+ &next_event->event_entry != &next_ctx->event_list) { -+ -+ __perf_event_sync_stat(event, next_event); -+ -+ event = list_next_entry(event, event_entry); -+ next_event = list_next_entry(next_event, event_entry); -+ } -+} -+ -+static void perf_event_context_sched_out(struct task_struct *task, int ctxn, -+ struct task_struct *next) -+{ -+ struct perf_event_context *ctx = task->perf_event_ctxp[ctxn]; -+ struct perf_event_context *next_ctx; -+ struct perf_event_context *parent, *next_parent; -+ struct perf_cpu_context *cpuctx; -+ int do_switch = 1; -+ -+ if (likely(!ctx)) -+ return; -+ -+ cpuctx = __get_cpu_context(ctx); -+ if (!cpuctx->task_ctx) -+ return; -+ -+ rcu_read_lock(); -+ next_ctx = next->perf_event_ctxp[ctxn]; -+ if (!next_ctx) -+ goto unlock; -+ -+ parent = rcu_dereference(ctx->parent_ctx); -+ next_parent = rcu_dereference(next_ctx->parent_ctx); -+ -+ /* If neither context have a parent context; they cannot be clones. */ -+ if (!parent && !next_parent) -+ goto unlock; -+ -+ if (next_parent == ctx || next_ctx == parent || next_parent == parent) { -+ /* -+ * Looks like the two contexts are clones, so we might be -+ * able to optimize the context switch. We lock both -+ * contexts and check that they are clones under the -+ * lock (including re-checking that neither has been -+ * uncloned in the meantime). It doesn't matter which -+ * order we take the locks because no other cpu could -+ * be trying to lock both of these tasks. -+ */ -+ raw_spin_lock(&ctx->lock); -+ raw_spin_lock_nested(&next_ctx->lock, SINGLE_DEPTH_NESTING); -+ if (context_equiv(ctx, next_ctx)) { -+ /* -+ * XXX do we need a memory barrier of sorts -+ * wrt to rcu_dereference() of perf_event_ctxp -+ */ -+ task->perf_event_ctxp[ctxn] = next_ctx; -+ next->perf_event_ctxp[ctxn] = ctx; -+ ctx->task = next; -+ next_ctx->task = task; -+ do_switch = 0; -+ -+ perf_event_sync_stat(ctx, next_ctx); -+ } -+ raw_spin_unlock(&next_ctx->lock); -+ raw_spin_unlock(&ctx->lock); -+ } -+unlock: -+ rcu_read_unlock(); -+ -+ if (do_switch) { -+ raw_spin_lock(&ctx->lock); -+ ctx_sched_out(ctx, cpuctx, EVENT_ALL); -+ cpuctx->task_ctx = NULL; -+ raw_spin_unlock(&ctx->lock); -+ } -+} -+ -+#define for_each_task_context_nr(ctxn) \ -+ for ((ctxn) = 0; (ctxn) < perf_nr_task_contexts; (ctxn)++) -+ -+/* -+ * Called from scheduler to remove the events of the current task, -+ * with interrupts disabled. -+ * -+ * We stop each event and update the event value in event->count. -+ * -+ * This does not protect us against NMI, but disable() -+ * sets the disabled bit in the control field of event _before_ -+ * accessing the event control register. If a NMI hits, then it will -+ * not restart the event. -+ */ -+void __perf_event_task_sched_out(struct task_struct *task, -+ struct task_struct *next) -+{ -+ int ctxn; -+ -+ for_each_task_context_nr(ctxn) -+ perf_event_context_sched_out(task, ctxn, next); -+ -+ /* -+ * if cgroup events exist on this CPU, then we need -+ * to check if we have to switch out PMU state. -+ * cgroup event are system-wide mode only -+ */ -+ if (atomic_read(this_cpu_ptr(&perf_cgroup_events))) -+ perf_cgroup_sched_out(task, next); -+} -+ -+static void task_ctx_sched_out(struct perf_event_context *ctx) -+{ -+ struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); -+ -+ if (!cpuctx->task_ctx) -+ return; -+ -+ if (WARN_ON_ONCE(ctx != cpuctx->task_ctx)) -+ return; -+ -+ ctx_sched_out(ctx, cpuctx, EVENT_ALL); -+ cpuctx->task_ctx = NULL; -+} -+ -+/* -+ * Called with IRQs disabled -+ */ -+static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx, -+ enum event_type_t event_type) -+{ -+ ctx_sched_out(&cpuctx->ctx, cpuctx, event_type); -+} -+ -+static void -+ctx_pinned_sched_in(struct perf_event_context *ctx, -+ struct perf_cpu_context *cpuctx) -+{ -+ struct perf_event *event; -+ -+ list_for_each_entry(event, &ctx->pinned_groups, group_entry) { -+ if (event->state <= PERF_EVENT_STATE_OFF) -+ continue; -+ if (!event_filter_match(event)) -+ continue; -+ -+ /* may need to reset tstamp_enabled */ -+ if (is_cgroup_event(event)) -+ perf_cgroup_mark_enabled(event, ctx); -+ -+ if (group_can_go_on(event, cpuctx, 1)) -+ group_sched_in(event, cpuctx, ctx); -+ -+ /* -+ * If this pinned group hasn't been scheduled, -+ * put it in error state. -+ */ -+ if (event->state == PERF_EVENT_STATE_INACTIVE) { -+ update_group_times(event); -+ event->state = PERF_EVENT_STATE_ERROR; -+ } -+ } -+} -+ -+static void -+ctx_flexible_sched_in(struct perf_event_context *ctx, -+ struct perf_cpu_context *cpuctx) -+{ -+ struct perf_event *event; -+ int can_add_hw = 1; -+ -+ list_for_each_entry(event, &ctx->flexible_groups, group_entry) { -+ /* Ignore events in OFF or ERROR state */ -+ if (event->state <= PERF_EVENT_STATE_OFF) -+ continue; -+ /* -+ * Listen to the 'cpu' scheduling filter constraint -+ * of events: -+ */ -+ if (!event_filter_match(event)) -+ continue; -+ -+ /* may need to reset tstamp_enabled */ -+ if (is_cgroup_event(event)) -+ perf_cgroup_mark_enabled(event, ctx); -+ -+ if (group_can_go_on(event, cpuctx, can_add_hw)) { -+ if (group_sched_in(event, cpuctx, ctx)) -+ can_add_hw = 0; -+ } -+ } -+} -+ -+static void -+ctx_sched_in(struct perf_event_context *ctx, -+ struct perf_cpu_context *cpuctx, -+ enum event_type_t event_type, -+ struct task_struct *task) -+{ -+ u64 now; -+ int is_active = ctx->is_active; -+ -+ ctx->is_active |= event_type; -+ if (likely(!ctx->nr_events)) -+ return; -+ -+ now = perf_clock(); -+ ctx->timestamp = now; -+ perf_cgroup_set_timestamp(task, ctx); -+ /* -+ * First go through the list and put on any pinned groups -+ * in order to give them the best chance of going on. -+ */ -+ if (!(is_active & EVENT_PINNED) && (event_type & EVENT_PINNED)) -+ ctx_pinned_sched_in(ctx, cpuctx); -+ -+ /* Then walk through the lower prio flexible groups */ -+ if (!(is_active & EVENT_FLEXIBLE) && (event_type & EVENT_FLEXIBLE)) -+ ctx_flexible_sched_in(ctx, cpuctx); -+} -+ -+static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx, -+ enum event_type_t event_type, -+ struct task_struct *task) -+{ -+ struct perf_event_context *ctx = &cpuctx->ctx; -+ -+ ctx_sched_in(ctx, cpuctx, event_type, task); -+} -+ -+static void perf_event_context_sched_in(struct perf_event_context *ctx, -+ struct task_struct *task) -+{ -+ struct perf_cpu_context *cpuctx; -+ -+ cpuctx = __get_cpu_context(ctx); -+ if (cpuctx->task_ctx == ctx) -+ return; -+ -+ perf_ctx_lock(cpuctx, ctx); -+ perf_pmu_disable(ctx->pmu); -+ /* -+ * We want to keep the following priority order: -+ * cpu pinned (that don't need to move), task pinned, -+ * cpu flexible, task flexible. -+ */ -+ cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE); -+ -+ if (ctx->nr_events) -+ cpuctx->task_ctx = ctx; -+ -+ perf_event_sched_in(cpuctx, cpuctx->task_ctx, task); -+ -+ perf_pmu_enable(ctx->pmu); -+ perf_ctx_unlock(cpuctx, ctx); -+ -+ /* -+ * Since these rotations are per-cpu, we need to ensure the -+ * cpu-context we got scheduled on is actually rotating. -+ */ -+ perf_pmu_rotate_start(ctx->pmu); -+} -+ -+/* -+ * When sampling the branck stack in system-wide, it may be necessary -+ * to flush the stack on context switch. This happens when the branch -+ * stack does not tag its entries with the pid of the current task. -+ * Otherwise it becomes impossible to associate a branch entry with a -+ * task. This ambiguity is more likely to appear when the branch stack -+ * supports priv level filtering and the user sets it to monitor only -+ * at the user level (which could be a useful measurement in system-wide -+ * mode). In that case, the risk is high of having a branch stack with -+ * branch from multiple tasks. Flushing may mean dropping the existing -+ * entries or stashing them somewhere in the PMU specific code layer. -+ * -+ * This function provides the context switch callback to the lower code -+ * layer. It is invoked ONLY when there is at least one system-wide context -+ * with at least one active event using taken branch sampling. -+ */ -+static void perf_branch_stack_sched_in(struct task_struct *prev, -+ struct task_struct *task) -+{ -+ struct perf_cpu_context *cpuctx; -+ struct pmu *pmu; -+ unsigned long flags; -+ -+ /* no need to flush branch stack if not changing task */ -+ if (prev == task) -+ return; -+ -+ local_irq_save(flags); -+ -+ rcu_read_lock(); -+ -+ list_for_each_entry_rcu(pmu, &pmus, entry) { -+ cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); -+ -+ /* -+ * check if the context has at least one -+ * event using PERF_SAMPLE_BRANCH_STACK -+ */ -+ if (cpuctx->ctx.nr_branch_stack > 0 -+ && pmu->flush_branch_stack) { -+ -+ perf_ctx_lock(cpuctx, cpuctx->task_ctx); -+ -+ perf_pmu_disable(pmu); -+ -+ pmu->flush_branch_stack(); -+ -+ perf_pmu_enable(pmu); -+ -+ perf_ctx_unlock(cpuctx, cpuctx->task_ctx); -+ } -+ } -+ -+ rcu_read_unlock(); -+ -+ local_irq_restore(flags); -+} -+ -+/* -+ * Called from scheduler to add the events of the current task -+ * with interrupts disabled. -+ * -+ * We restore the event value and then enable it. -+ * -+ * This does not protect us against NMI, but enable() -+ * sets the enabled bit in the control field of event _before_ -+ * accessing the event control register. If a NMI hits, then it will -+ * keep the event running. -+ */ -+void __perf_event_task_sched_in(struct task_struct *prev, -+ struct task_struct *task) -+{ -+ struct perf_event_context *ctx; -+ int ctxn; -+ -+ for_each_task_context_nr(ctxn) { -+ ctx = task->perf_event_ctxp[ctxn]; -+ if (likely(!ctx)) -+ continue; -+ -+ perf_event_context_sched_in(ctx, task); -+ } -+ /* -+ * if cgroup events exist on this CPU, then we need -+ * to check if we have to switch in PMU state. -+ * cgroup event are system-wide mode only -+ */ -+ if (atomic_read(this_cpu_ptr(&perf_cgroup_events))) -+ perf_cgroup_sched_in(prev, task); -+ -+ /* check for system-wide branch_stack events */ -+ if (atomic_read(this_cpu_ptr(&perf_branch_stack_events))) -+ perf_branch_stack_sched_in(prev, task); -+} -+ -+static u64 perf_calculate_period(struct perf_event *event, u64 nsec, u64 count) -+{ -+ u64 frequency = event->attr.sample_freq; -+ u64 sec = NSEC_PER_SEC; -+ u64 divisor, dividend; -+ -+ int count_fls, nsec_fls, frequency_fls, sec_fls; -+ -+ count_fls = fls64(count); -+ nsec_fls = fls64(nsec); -+ frequency_fls = fls64(frequency); -+ sec_fls = 30; -+ -+ /* -+ * We got @count in @nsec, with a target of sample_freq HZ -+ * the target period becomes: -+ * -+ * @count * 10^9 -+ * period = ------------------- -+ * @nsec * sample_freq -+ * -+ */ -+ -+ /* -+ * Reduce accuracy by one bit such that @a and @b converge -+ * to a similar magnitude. -+ */ -+#define REDUCE_FLS(a, b) \ -+do { \ -+ if (a##_fls > b##_fls) { \ -+ a >>= 1; \ -+ a##_fls--; \ -+ } else { \ -+ b >>= 1; \ -+ b##_fls--; \ -+ } \ -+} while (0) -+ -+ /* -+ * Reduce accuracy until either term fits in a u64, then proceed with -+ * the other, so that finally we can do a u64/u64 division. -+ */ -+ while (count_fls + sec_fls > 64 && nsec_fls + frequency_fls > 64) { -+ REDUCE_FLS(nsec, frequency); -+ REDUCE_FLS(sec, count); -+ } -+ -+ if (count_fls + sec_fls > 64) { -+ divisor = nsec * frequency; -+ -+ while (count_fls + sec_fls > 64) { -+ REDUCE_FLS(count, sec); -+ divisor >>= 1; -+ } -+ -+ dividend = count * sec; -+ } else { -+ dividend = count * sec; -+ -+ while (nsec_fls + frequency_fls > 64) { -+ REDUCE_FLS(nsec, frequency); -+ dividend >>= 1; -+ } -+ -+ divisor = nsec * frequency; -+ } -+ -+ if (!divisor) -+ return dividend; -+ -+ return div64_u64(dividend, divisor); -+} -+ -+static DEFINE_PER_CPU(int, perf_throttled_count); -+static DEFINE_PER_CPU(u64, perf_throttled_seq); -+ -+static void perf_adjust_period(struct perf_event *event, u64 nsec, u64 count, bool disable) -+{ -+ struct hw_perf_event *hwc = &event->hw; -+ s64 period, sample_period; -+ s64 delta; -+ -+ period = perf_calculate_period(event, nsec, count); -+ -+ delta = (s64)(period - hwc->sample_period); -+ delta = (delta + 7) / 8; /* low pass filter */ -+ -+ sample_period = hwc->sample_period + delta; -+ -+ if (!sample_period) -+ sample_period = 1; -+ -+ hwc->sample_period = sample_period; -+ -+ if (local64_read(&hwc->period_left) > 8*sample_period) { -+ if (disable) -+ event->pmu->stop(event, PERF_EF_UPDATE); -+ -+ local64_set(&hwc->period_left, 0); -+ -+ if (disable) -+ event->pmu->start(event, PERF_EF_RELOAD); -+ } -+} -+ -+/* -+ * combine freq adjustment with unthrottling to avoid two passes over the -+ * events. At the same time, make sure, having freq events does not change -+ * the rate of unthrottling as that would introduce bias. -+ */ -+static void perf_adjust_freq_unthr_context(struct perf_event_context *ctx, -+ int needs_unthr) -+{ -+ struct perf_event *event; -+ struct hw_perf_event *hwc; -+ u64 now, period = TICK_NSEC; -+ s64 delta; -+ -+ /* -+ * only need to iterate over all events iff: -+ * - context have events in frequency mode (needs freq adjust) -+ * - there are events to unthrottle on this cpu -+ */ -+ if (!(ctx->nr_freq || needs_unthr)) -+ return; -+ -+ raw_spin_lock(&ctx->lock); -+ perf_pmu_disable(ctx->pmu); -+ -+ list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { -+ if (event->state != PERF_EVENT_STATE_ACTIVE) -+ continue; -+ -+ if (!event_filter_match(event)) -+ continue; -+ -+ perf_pmu_disable(event->pmu); -+ -+ hwc = &event->hw; -+ -+ if (hwc->interrupts == MAX_INTERRUPTS) { -+ hwc->interrupts = 0; -+ perf_log_throttle(event, 1); -+ event->pmu->start(event, 0); -+ } -+ -+ if (!event->attr.freq || !event->attr.sample_freq) -+ goto next; -+ -+ /* -+ * stop the event and update event->count -+ */ -+ event->pmu->stop(event, PERF_EF_UPDATE); -+ -+ now = local64_read(&event->count); -+ delta = now - hwc->freq_count_stamp; -+ hwc->freq_count_stamp = now; -+ -+ /* -+ * restart the event -+ * reload only if value has changed -+ * we have stopped the event so tell that -+ * to perf_adjust_period() to avoid stopping it -+ * twice. -+ */ -+ if (delta > 0) -+ perf_adjust_period(event, period, delta, false); -+ -+ event->pmu->start(event, delta > 0 ? PERF_EF_RELOAD : 0); -+ next: -+ perf_pmu_enable(event->pmu); -+ } -+ -+ perf_pmu_enable(ctx->pmu); -+ raw_spin_unlock(&ctx->lock); -+} -+ -+/* -+ * Round-robin a context's events: -+ */ -+static void rotate_ctx(struct perf_event_context *ctx) -+{ -+ /* -+ * Rotate the first entry last of non-pinned groups. Rotation might be -+ * disabled by the inheritance code. -+ */ -+ if (!ctx->rotate_disable) -+ list_rotate_left(&ctx->flexible_groups); -+} -+ -+/* -+ * perf_pmu_rotate_start() and perf_rotate_context() are fully serialized -+ * because they're strictly cpu affine and rotate_start is called with IRQs -+ * disabled, while rotate_context is called from IRQ context. -+ */ -+static int perf_rotate_context(struct perf_cpu_context *cpuctx) -+{ -+ struct perf_event_context *ctx = NULL; -+ int rotate = 0, remove = 1; -+ -+ if (cpuctx->ctx.nr_events) { -+ remove = 0; -+ if (cpuctx->ctx.nr_events != cpuctx->ctx.nr_active) -+ rotate = 1; -+ } -+ -+ ctx = cpuctx->task_ctx; -+ if (ctx && ctx->nr_events) { -+ remove = 0; -+ if (ctx->nr_events != ctx->nr_active) -+ rotate = 1; -+ } -+ -+ if (!rotate) -+ goto done; -+ -+ perf_ctx_lock(cpuctx, cpuctx->task_ctx); -+ perf_pmu_disable(cpuctx->ctx.pmu); -+ -+ cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE); -+ if (ctx) -+ ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE); -+ -+ rotate_ctx(&cpuctx->ctx); -+ if (ctx) -+ rotate_ctx(ctx); -+ -+ perf_event_sched_in(cpuctx, ctx, current); -+ -+ perf_pmu_enable(cpuctx->ctx.pmu); -+ perf_ctx_unlock(cpuctx, cpuctx->task_ctx); -+done: -+ if (remove) -+ list_del_init(&cpuctx->rotation_list); -+ -+ return rotate; -+} -+ -+#ifdef CONFIG_NO_HZ_FULL -+bool perf_event_can_stop_tick(void) -+{ -+ if (atomic_read(&nr_freq_events) || -+ __this_cpu_read(perf_throttled_count)) -+ return false; -+ else -+ return true; -+} -+#endif -+ -+void perf_event_task_tick(void) -+{ -+ struct list_head *head = this_cpu_ptr(&rotation_list); -+ struct perf_cpu_context *cpuctx, *tmp; -+ struct perf_event_context *ctx; -+ int throttled; -+ -+ WARN_ON(!irqs_disabled()); -+ -+ __this_cpu_inc(perf_throttled_seq); -+ throttled = __this_cpu_xchg(perf_throttled_count, 0); -+ -+ list_for_each_entry_safe(cpuctx, tmp, head, rotation_list) { -+ ctx = &cpuctx->ctx; -+ perf_adjust_freq_unthr_context(ctx, throttled); -+ -+ ctx = cpuctx->task_ctx; -+ if (ctx) -+ perf_adjust_freq_unthr_context(ctx, throttled); -+ } -+} -+ -+static int event_enable_on_exec(struct perf_event *event, -+ struct perf_event_context *ctx) -+{ -+ if (!event->attr.enable_on_exec) -+ return 0; -+ -+ event->attr.enable_on_exec = 0; -+ if (event->state >= PERF_EVENT_STATE_INACTIVE) -+ return 0; -+ -+ __perf_event_mark_enabled(event); -+ -+ return 1; -+} -+ -+/* -+ * Enable all of a task's events that have been marked enable-on-exec. -+ * This expects task == current. -+ */ -+static void perf_event_enable_on_exec(struct perf_event_context *ctx) -+{ -+ struct perf_event_context *clone_ctx = NULL; -+ struct perf_event *event; -+ unsigned long flags; -+ int enabled = 0; -+ int ret; -+ -+ local_irq_save(flags); -+ if (!ctx || !ctx->nr_events) -+ goto out; -+ -+ /* -+ * We must ctxsw out cgroup events to avoid conflict -+ * when invoking perf_task_event_sched_in() later on -+ * in this function. Otherwise we end up trying to -+ * ctxswin cgroup events which are already scheduled -+ * in. -+ */ -+ perf_cgroup_sched_out(current, NULL); -+ -+ raw_spin_lock(&ctx->lock); -+ task_ctx_sched_out(ctx); -+ -+ list_for_each_entry(event, &ctx->event_list, event_entry) { -+ ret = event_enable_on_exec(event, ctx); -+ if (ret) -+ enabled = 1; -+ } -+ -+ /* -+ * Unclone this context if we enabled any event. -+ */ -+ if (enabled) -+ clone_ctx = unclone_ctx(ctx); -+ -+ raw_spin_unlock(&ctx->lock); -+ -+ /* -+ * Also calls ctxswin for cgroup events, if any: -+ */ -+ perf_event_context_sched_in(ctx, ctx->task); -+out: -+ local_irq_restore(flags); -+ -+ if (clone_ctx) -+ put_ctx(clone_ctx); -+} -+ -+void perf_event_exec(void) -+{ -+ struct perf_event_context *ctx; -+ int ctxn; -+ -+ rcu_read_lock(); -+ for_each_task_context_nr(ctxn) { -+ ctx = current->perf_event_ctxp[ctxn]; -+ if (!ctx) -+ continue; -+ -+ perf_event_enable_on_exec(ctx); -+ } -+ rcu_read_unlock(); -+} -+ -+/* -+ * Cross CPU call to read the hardware event -+ */ -+static void __perf_event_read(void *info) -+{ -+ struct perf_event *event = info; -+ struct perf_event_context *ctx = event->ctx; -+ struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); -+ -+ /* -+ * If this is a task context, we need to check whether it is -+ * the current task context of this cpu. If not it has been -+ * scheduled out before the smp call arrived. In that case -+ * event->count would have been updated to a recent sample -+ * when the event was scheduled out. -+ */ -+ if (ctx->task && cpuctx->task_ctx != ctx) -+ return; -+ -+ raw_spin_lock(&ctx->lock); -+ if (ctx->is_active) { -+ update_context_time(ctx); -+ update_cgrp_time_from_event(event); -+ } -+ update_event_times(event); -+ if (event->state == PERF_EVENT_STATE_ACTIVE) -+ event->pmu->read(event); -+ raw_spin_unlock(&ctx->lock); -+} -+ -+static inline u64 perf_event_count(struct perf_event *event) -+{ -+ return local64_read(&event->count) + atomic64_read(&event->child_count); -+} -+ -+static u64 perf_event_read(struct perf_event *event) -+{ -+ /* -+ * If event is enabled and currently active on a CPU, update the -+ * value in the event structure: -+ */ -+ if (event->state == PERF_EVENT_STATE_ACTIVE) { -+ smp_call_function_single(event->oncpu, -+ __perf_event_read, event, 1); -+ } else if (event->state == PERF_EVENT_STATE_INACTIVE) { -+ struct perf_event_context *ctx = event->ctx; -+ unsigned long flags; -+ -+ raw_spin_lock_irqsave(&ctx->lock, flags); -+ /* -+ * may read while context is not active -+ * (e.g., thread is blocked), in that case -+ * we cannot update context time -+ */ -+ if (ctx->is_active) { -+ update_context_time(ctx); -+ update_cgrp_time_from_event(event); -+ } -+ update_event_times(event); -+ raw_spin_unlock_irqrestore(&ctx->lock, flags); -+ } -+ -+ return perf_event_count(event); -+} -+ -+/* -+ * Initialize the perf_event context in a task_struct: -+ */ -+static void __perf_event_init_context(struct perf_event_context *ctx) -+{ -+ raw_spin_lock_init(&ctx->lock); -+ mutex_init(&ctx->mutex); -+ INIT_LIST_HEAD(&ctx->pinned_groups); -+ INIT_LIST_HEAD(&ctx->flexible_groups); -+ INIT_LIST_HEAD(&ctx->event_list); -+ atomic_set(&ctx->refcount, 1); -+ INIT_DELAYED_WORK(&ctx->orphans_remove, orphans_remove_work); -+} -+ -+static struct perf_event_context * -+alloc_perf_context(struct pmu *pmu, struct task_struct *task) -+{ -+ struct perf_event_context *ctx; -+ -+ ctx = kzalloc(sizeof(struct perf_event_context), GFP_KERNEL); -+ if (!ctx) -+ return NULL; -+ -+ __perf_event_init_context(ctx); -+ if (task) { -+ ctx->task = task; -+ get_task_struct(task); -+ } -+ ctx->pmu = pmu; -+ -+ return ctx; -+} -+ -+static struct task_struct * -+find_lively_task_by_vpid(pid_t vpid) -+{ -+ struct task_struct *task; -+ int err; -+ -+ rcu_read_lock(); -+ if (!vpid) -+ task = current; -+ else -+ task = find_task_by_vpid(vpid); -+ if (task) -+ get_task_struct(task); -+ rcu_read_unlock(); -+ -+ if (!task) -+ return ERR_PTR(-ESRCH); -+ -+ /* Reuse ptrace permission checks for now. */ -+ err = -EACCES; -+ if (!ptrace_may_access(task, PTRACE_MODE_READ)) -+ goto errout; -+ -+ return task; -+errout: -+ put_task_struct(task); -+ return ERR_PTR(err); -+ -+} -+ -+/* -+ * Returns a matching context with refcount and pincount. -+ */ -+static struct perf_event_context * -+find_get_context(struct pmu *pmu, struct task_struct *task, int cpu) -+{ -+ struct perf_event_context *ctx, *clone_ctx = NULL; -+ struct perf_cpu_context *cpuctx; -+ unsigned long flags; -+ int ctxn, err; -+ -+ if (!task) { -+ /* Must be root to operate on a CPU event: */ -+ if (perf_paranoid_cpu() && !capable(CAP_SYS_ADMIN)) -+ return ERR_PTR(-EACCES); -+ -+ /* -+ * We could be clever and allow to attach a event to an -+ * offline CPU and activate it when the CPU comes up, but -+ * that's for later. -+ */ -+ if (!cpu_online(cpu)) -+ return ERR_PTR(-ENODEV); -+ -+ cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); -+ ctx = &cpuctx->ctx; -+ get_ctx(ctx); -+ ++ctx->pin_count; -+ -+ return ctx; -+ } -+ -+ err = -EINVAL; -+ ctxn = pmu->task_ctx_nr; -+ if (ctxn < 0) -+ goto errout; -+ -+retry: -+ ctx = perf_lock_task_context(task, ctxn, &flags); -+ if (ctx) { -+ clone_ctx = unclone_ctx(ctx); -+ ++ctx->pin_count; -+ raw_spin_unlock_irqrestore(&ctx->lock, flags); -+ -+ if (clone_ctx) -+ put_ctx(clone_ctx); -+ } else { -+ ctx = alloc_perf_context(pmu, task); -+ err = -ENOMEM; -+ if (!ctx) -+ goto errout; -+ -+ err = 0; -+ mutex_lock(&task->perf_event_mutex); -+ /* -+ * If it has already passed perf_event_exit_task(). -+ * we must see PF_EXITING, it takes this mutex too. -+ */ -+ if (task->flags & PF_EXITING) -+ err = -ESRCH; -+ else if (task->perf_event_ctxp[ctxn]) -+ err = -EAGAIN; -+ else { -+ get_ctx(ctx); -+ ++ctx->pin_count; -+ rcu_assign_pointer(task->perf_event_ctxp[ctxn], ctx); -+ } -+ mutex_unlock(&task->perf_event_mutex); -+ -+ if (unlikely(err)) { -+ put_ctx(ctx); -+ -+ if (err == -EAGAIN) -+ goto retry; -+ goto errout; -+ } -+ } -+ -+ return ctx; -+ -+errout: -+ return ERR_PTR(err); -+} -+ -+static void perf_event_free_filter(struct perf_event *event); -+ -+static void free_event_rcu(struct rcu_head *head) -+{ -+ struct perf_event *event; -+ -+ event = container_of(head, struct perf_event, rcu_head); -+ if (event->ns) -+ put_pid_ns(event->ns); -+ perf_event_free_filter(event); -+ kfree(event); -+} -+ -+static void ring_buffer_put(struct ring_buffer *rb); -+static void ring_buffer_attach(struct perf_event *event, -+ struct ring_buffer *rb); -+ -+static void unaccount_event_cpu(struct perf_event *event, int cpu) -+{ -+ if (event->parent) -+ return; -+ -+ if (has_branch_stack(event)) { -+ if (!(event->attach_state & PERF_ATTACH_TASK)) -+ atomic_dec(&per_cpu(perf_branch_stack_events, cpu)); -+ } -+ if (is_cgroup_event(event)) -+ atomic_dec(&per_cpu(perf_cgroup_events, cpu)); -+} -+ -+static void unaccount_event(struct perf_event *event) -+{ -+ if (event->parent) -+ return; -+ -+ if (event->attach_state & PERF_ATTACH_TASK) -+ static_key_slow_dec_deferred(&perf_sched_events); -+ if (event->attr.mmap || event->attr.mmap_data) -+ atomic_dec(&nr_mmap_events); -+ if (event->attr.comm) -+ atomic_dec(&nr_comm_events); -+ if (event->attr.task) -+ atomic_dec(&nr_task_events); -+ if (event->attr.freq) -+ atomic_dec(&nr_freq_events); -+ if (is_cgroup_event(event)) -+ static_key_slow_dec_deferred(&perf_sched_events); -+ if (has_branch_stack(event)) -+ static_key_slow_dec_deferred(&perf_sched_events); -+ -+ unaccount_event_cpu(event, event->cpu); -+} -+ -+static void __free_event(struct perf_event *event) -+{ -+ if (!event->parent) { -+ if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) -+ put_callchain_buffers(); -+ } -+ -+ if (event->destroy) -+ event->destroy(event); -+ -+ if (event->ctx) -+ put_ctx(event->ctx); -+ -+ if (event->pmu) -+ module_put(event->pmu->module); -+ -+ call_rcu(&event->rcu_head, free_event_rcu); -+} -+ -+static void _free_event(struct perf_event *event) -+{ -+ irq_work_sync(&event->pending); -+ -+ unaccount_event(event); -+ -+ if (event->rb) { -+ /* -+ * Can happen when we close an event with re-directed output. -+ * -+ * Since we have a 0 refcount, perf_mmap_close() will skip -+ * over us; possibly making our ring_buffer_put() the last. -+ */ -+ mutex_lock(&event->mmap_mutex); -+ ring_buffer_attach(event, NULL); -+ mutex_unlock(&event->mmap_mutex); -+ } -+ -+ if (is_cgroup_event(event)) -+ perf_detach_cgroup(event); -+ -+ __free_event(event); -+} -+ -+/* -+ * Used to free events which have a known refcount of 1, such as in error paths -+ * where the event isn't exposed yet and inherited events. -+ */ -+static void free_event(struct perf_event *event) -+{ -+ if (WARN(atomic_long_cmpxchg(&event->refcount, 1, 0) != 1, -+ "unexpected event refcount: %ld; ptr=%p\n", -+ atomic_long_read(&event->refcount), event)) { -+ /* leak to avoid use-after-free */ -+ return; -+ } -+ -+ _free_event(event); -+} -+ -+/* -+ * Remove user event from the owner task. -+ */ -+static void perf_remove_from_owner(struct perf_event *event) -+{ -+ struct task_struct *owner; -+ -+ rcu_read_lock(); -+ owner = ACCESS_ONCE(event->owner); -+ /* -+ * Matches the smp_wmb() in perf_event_exit_task(). If we observe -+ * !owner it means the list deletion is complete and we can indeed -+ * free this event, otherwise we need to serialize on -+ * owner->perf_event_mutex. -+ */ -+ smp_read_barrier_depends(); -+ if (owner) { -+ /* -+ * Since delayed_put_task_struct() also drops the last -+ * task reference we can safely take a new reference -+ * while holding the rcu_read_lock(). -+ */ -+ get_task_struct(owner); -+ } -+ rcu_read_unlock(); -+ -+ if (owner) { -+ mutex_lock(&owner->perf_event_mutex); -+ /* -+ * We have to re-check the event->owner field, if it is cleared -+ * we raced with perf_event_exit_task(), acquiring the mutex -+ * ensured they're done, and we can proceed with freeing the -+ * event. -+ */ -+ if (event->owner) -+ list_del_init(&event->owner_entry); -+ mutex_unlock(&owner->perf_event_mutex); -+ put_task_struct(owner); -+ } -+} -+ -+/* -+ * Called when the last reference to the file is gone. -+ */ -+static void put_event(struct perf_event *event) -+{ -+ struct perf_event_context *ctx = event->ctx; -+ -+ if (!atomic_long_dec_and_test(&event->refcount)) -+ return; -+ -+ if (!is_kernel_event(event)) -+ perf_remove_from_owner(event); -+ -+ WARN_ON_ONCE(ctx->parent_ctx); -+ /* -+ * There are two ways this annotation is useful: -+ * -+ * 1) there is a lock recursion from perf_event_exit_task -+ * see the comment there. -+ * -+ * 2) there is a lock-inversion with mmap_sem through -+ * perf_event_read_group(), which takes faults while -+ * holding ctx->mutex, however this is called after -+ * the last filedesc died, so there is no possibility -+ * to trigger the AB-BA case. -+ */ -+ mutex_lock_nested(&ctx->mutex, SINGLE_DEPTH_NESTING); -+ perf_remove_from_context(event, true); -+ mutex_unlock(&ctx->mutex); -+ -+ _free_event(event); -+} -+ -+int perf_event_release_kernel(struct perf_event *event) -+{ -+ put_event(event); -+ return 0; -+} -+EXPORT_SYMBOL_GPL(perf_event_release_kernel); -+ -+static int perf_release(struct inode *inode, struct file *file) -+{ -+ put_event(file->private_data); -+ return 0; -+} -+ -+/* -+ * Remove all orphanes events from the context. -+ */ -+static void orphans_remove_work(struct work_struct *work) -+{ -+ struct perf_event_context *ctx; -+ struct perf_event *event, *tmp; -+ -+ ctx = container_of(work, struct perf_event_context, -+ orphans_remove.work); -+ -+ mutex_lock(&ctx->mutex); -+ list_for_each_entry_safe(event, tmp, &ctx->event_list, event_entry) { -+ struct perf_event *parent_event = event->parent; -+ -+ if (!is_orphaned_child(event)) -+ continue; -+ -+ perf_remove_from_context(event, true); -+ -+ mutex_lock(&parent_event->child_mutex); -+ list_del_init(&event->child_list); -+ mutex_unlock(&parent_event->child_mutex); -+ -+ free_event(event); -+ put_event(parent_event); -+ } -+ -+ raw_spin_lock_irq(&ctx->lock); -+ ctx->orphans_remove_sched = false; -+ raw_spin_unlock_irq(&ctx->lock); -+ mutex_unlock(&ctx->mutex); -+ -+ put_ctx(ctx); -+} -+ -+u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running) -+{ -+ struct perf_event *child; -+ u64 total = 0; -+ -+ *enabled = 0; -+ *running = 0; -+ -+ mutex_lock(&event->child_mutex); -+ total += perf_event_read(event); -+ *enabled += event->total_time_enabled + -+ atomic64_read(&event->child_total_time_enabled); -+ *running += event->total_time_running + -+ atomic64_read(&event->child_total_time_running); -+ -+ list_for_each_entry(child, &event->child_list, child_list) { -+ total += perf_event_read(child); -+ *enabled += child->total_time_enabled; -+ *running += child->total_time_running; -+ } -+ mutex_unlock(&event->child_mutex); -+ -+ return total; -+} -+EXPORT_SYMBOL_GPL(perf_event_read_value); -+ -+static int perf_event_read_group(struct perf_event *event, -+ u64 read_format, char __user *buf) -+{ -+ struct perf_event *leader = event->group_leader, *sub; -+ int n = 0, size = 0, ret = -EFAULT; -+ struct perf_event_context *ctx = leader->ctx; -+ u64 values[5]; -+ u64 count, enabled, running; -+ -+ mutex_lock(&ctx->mutex); -+ count = perf_event_read_value(leader, &enabled, &running); -+ -+ values[n++] = 1 + leader->nr_siblings; -+ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) -+ values[n++] = enabled; -+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) -+ values[n++] = running; -+ values[n++] = count; -+ if (read_format & PERF_FORMAT_ID) -+ values[n++] = primary_event_id(leader); -+ -+ size = n * sizeof(u64); -+ -+ if (copy_to_user(buf, values, size)) -+ goto unlock; -+ -+ ret = size; -+ -+ list_for_each_entry(sub, &leader->sibling_list, group_entry) { -+ n = 0; -+ -+ values[n++] = perf_event_read_value(sub, &enabled, &running); -+ if (read_format & PERF_FORMAT_ID) -+ values[n++] = primary_event_id(sub); -+ -+ size = n * sizeof(u64); -+ -+ if (copy_to_user(buf + ret, values, size)) { -+ ret = -EFAULT; -+ goto unlock; -+ } -+ -+ ret += size; -+ } -+unlock: -+ mutex_unlock(&ctx->mutex); -+ -+ return ret; -+} -+ -+static int perf_event_read_one(struct perf_event *event, -+ u64 read_format, char __user *buf) -+{ -+ u64 enabled, running; -+ u64 values[4]; -+ int n = 0; -+ -+ values[n++] = perf_event_read_value(event, &enabled, &running); -+ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) -+ values[n++] = enabled; -+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) -+ values[n++] = running; -+ if (read_format & PERF_FORMAT_ID) -+ values[n++] = primary_event_id(event); -+ -+ if (copy_to_user(buf, values, n * sizeof(u64))) -+ return -EFAULT; -+ -+ return n * sizeof(u64); -+} -+ -+static bool is_event_hup(struct perf_event *event) -+{ -+ bool no_children; -+ -+ if (event->state != PERF_EVENT_STATE_EXIT) -+ return false; -+ -+ mutex_lock(&event->child_mutex); -+ no_children = list_empty(&event->child_list); -+ mutex_unlock(&event->child_mutex); -+ return no_children; -+} -+ -+/* -+ * Read the performance event - simple non blocking version for now -+ */ -+static ssize_t -+perf_read_hw(struct perf_event *event, char __user *buf, size_t count) -+{ -+ u64 read_format = event->attr.read_format; -+ int ret; -+ -+ /* -+ * Return end-of-file for a read on a event that is in -+ * error state (i.e. because it was pinned but it couldn't be -+ * scheduled on to the CPU at some point). -+ */ -+ if (event->state == PERF_EVENT_STATE_ERROR) -+ return 0; -+ -+ if (count < event->read_size) -+ return -ENOSPC; -+ -+ WARN_ON_ONCE(event->ctx->parent_ctx); -+ if (read_format & PERF_FORMAT_GROUP) -+ ret = perf_event_read_group(event, read_format, buf); -+ else -+ ret = perf_event_read_one(event, read_format, buf); -+ -+ return ret; -+} -+ -+static ssize_t -+perf_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) -+{ -+ struct perf_event *event = file->private_data; -+ -+ return perf_read_hw(event, buf, count); -+} -+ -+static unsigned int perf_poll(struct file *file, poll_table *wait) -+{ -+ struct perf_event *event = file->private_data; -+ struct ring_buffer *rb; -+ unsigned int events = POLLHUP; -+ -+ poll_wait(file, &event->waitq, wait); -+ -+ if (is_event_hup(event)) -+ return events; -+ -+ /* -+ * Pin the event->rb by taking event->mmap_mutex; otherwise -+ * perf_event_set_output() can swizzle our rb and make us miss wakeups. -+ */ -+ mutex_lock(&event->mmap_mutex); -+ rb = event->rb; -+ if (rb) -+ events = atomic_xchg(&rb->poll, 0); -+ mutex_unlock(&event->mmap_mutex); -+ return events; -+} -+ -+static void perf_event_reset(struct perf_event *event) -+{ -+ (void)perf_event_read(event); -+ local64_set(&event->count, 0); -+ perf_event_update_userpage(event); -+} -+ -+/* -+ * Holding the top-level event's child_mutex means that any -+ * descendant process that has inherited this event will block -+ * in sync_child_event if it goes to exit, thus satisfying the -+ * task existence requirements of perf_event_enable/disable. -+ */ -+static void perf_event_for_each_child(struct perf_event *event, -+ void (*func)(struct perf_event *)) -+{ -+ struct perf_event *child; -+ -+ WARN_ON_ONCE(event->ctx->parent_ctx); -+ mutex_lock(&event->child_mutex); -+ func(event); -+ list_for_each_entry(child, &event->child_list, child_list) -+ func(child); -+ mutex_unlock(&event->child_mutex); -+} -+ -+static void perf_event_for_each(struct perf_event *event, -+ void (*func)(struct perf_event *)) -+{ -+ struct perf_event_context *ctx = event->ctx; -+ struct perf_event *sibling; -+ -+ WARN_ON_ONCE(ctx->parent_ctx); -+ mutex_lock(&ctx->mutex); -+ event = event->group_leader; -+ -+ perf_event_for_each_child(event, func); -+ list_for_each_entry(sibling, &event->sibling_list, group_entry) -+ perf_event_for_each_child(sibling, func); -+ mutex_unlock(&ctx->mutex); -+} -+ -+static int perf_event_period(struct perf_event *event, u64 __user *arg) -+{ -+ struct perf_event_context *ctx = event->ctx; -+ int ret = 0, active; -+ u64 value; -+ -+ if (!is_sampling_event(event)) -+ return -EINVAL; -+ -+ if (copy_from_user(&value, arg, sizeof(value))) -+ return -EFAULT; -+ -+ if (!value) -+ return -EINVAL; -+ -+ raw_spin_lock_irq(&ctx->lock); -+ if (event->attr.freq) { -+ if (value > sysctl_perf_event_sample_rate) { -+ ret = -EINVAL; -+ goto unlock; -+ } -+ -+ event->attr.sample_freq = value; -+ } else { -+ event->attr.sample_period = value; -+ event->hw.sample_period = value; -+ } -+ -+ active = (event->state == PERF_EVENT_STATE_ACTIVE); -+ if (active) { -+ perf_pmu_disable(ctx->pmu); -+ event->pmu->stop(event, PERF_EF_UPDATE); -+ } -+ -+ local64_set(&event->hw.period_left, 0); -+ -+ if (active) { -+ event->pmu->start(event, PERF_EF_RELOAD); -+ perf_pmu_enable(ctx->pmu); -+ } -+ -+unlock: -+ raw_spin_unlock_irq(&ctx->lock); -+ -+ return ret; -+} -+ -+static const struct file_operations perf_fops; -+ -+static inline int perf_fget_light(int fd, struct fd *p) -+{ -+ struct fd f = fdget(fd); -+ if (!f.file) -+ return -EBADF; -+ -+ if (f.file->f_op != &perf_fops) { -+ fdput(f); -+ return -EBADF; -+ } -+ *p = f; -+ return 0; -+} -+ -+static int perf_event_set_output(struct perf_event *event, -+ struct perf_event *output_event); -+static int perf_event_set_filter(struct perf_event *event, void __user *arg); -+ -+static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -+{ -+ struct perf_event *event = file->private_data; -+ void (*func)(struct perf_event *); -+ u32 flags = arg; -+ -+ switch (cmd) { -+ case PERF_EVENT_IOC_ENABLE: -+ func = perf_event_enable; -+ break; -+ case PERF_EVENT_IOC_DISABLE: -+ func = perf_event_disable; -+ break; -+ case PERF_EVENT_IOC_RESET: -+ func = perf_event_reset; -+ break; -+ -+ case PERF_EVENT_IOC_REFRESH: -+ return perf_event_refresh(event, arg); -+ -+ case PERF_EVENT_IOC_PERIOD: -+ return perf_event_period(event, (u64 __user *)arg); -+ -+ case PERF_EVENT_IOC_ID: -+ { -+ u64 id = primary_event_id(event); -+ -+ if (copy_to_user((void __user *)arg, &id, sizeof(id))) -+ return -EFAULT; -+ return 0; -+ } -+ -+ case PERF_EVENT_IOC_SET_OUTPUT: -+ { -+ int ret; -+ if (arg != -1) { -+ struct perf_event *output_event; -+ struct fd output; -+ ret = perf_fget_light(arg, &output); -+ if (ret) -+ return ret; -+ output_event = output.file->private_data; -+ ret = perf_event_set_output(event, output_event); -+ fdput(output); -+ } else { -+ ret = perf_event_set_output(event, NULL); -+ } -+ return ret; -+ } -+ -+ case PERF_EVENT_IOC_SET_FILTER: -+ return perf_event_set_filter(event, (void __user *)arg); -+ -+ default: -+ return -ENOTTY; -+ } -+ -+ if (flags & PERF_IOC_FLAG_GROUP) -+ perf_event_for_each(event, func); -+ else -+ perf_event_for_each_child(event, func); -+ -+ return 0; -+} -+ -+#ifdef CONFIG_COMPAT -+static long perf_compat_ioctl(struct file *file, unsigned int cmd, -+ unsigned long arg) -+{ -+ switch (_IOC_NR(cmd)) { -+ case _IOC_NR(PERF_EVENT_IOC_SET_FILTER): -+ case _IOC_NR(PERF_EVENT_IOC_ID): -+ /* Fix up pointer size (usually 4 -> 8 in 32-on-64-bit case */ -+ if (_IOC_SIZE(cmd) == sizeof(compat_uptr_t)) { -+ cmd &= ~IOCSIZE_MASK; -+ cmd |= sizeof(void *) << IOCSIZE_SHIFT; -+ } -+ break; -+ } -+ return perf_ioctl(file, cmd, arg); -+} -+#else -+# define perf_compat_ioctl NULL -+#endif -+ -+int perf_event_task_enable(void) -+{ -+ struct perf_event *event; -+ -+ mutex_lock(¤t->perf_event_mutex); -+ list_for_each_entry(event, ¤t->perf_event_list, owner_entry) -+ perf_event_for_each_child(event, perf_event_enable); -+ mutex_unlock(¤t->perf_event_mutex); -+ -+ return 0; -+} -+ -+int perf_event_task_disable(void) -+{ -+ struct perf_event *event; -+ -+ mutex_lock(¤t->perf_event_mutex); -+ list_for_each_entry(event, ¤t->perf_event_list, owner_entry) -+ perf_event_for_each_child(event, perf_event_disable); -+ mutex_unlock(¤t->perf_event_mutex); -+ -+ return 0; -+} -+ -+static int perf_event_index(struct perf_event *event) -+{ -+ if (event->hw.state & PERF_HES_STOPPED) -+ return 0; -+ -+ if (event->state != PERF_EVENT_STATE_ACTIVE) -+ return 0; -+ -+ return event->pmu->event_idx(event); -+} -+ -+static void calc_timer_values(struct perf_event *event, -+ u64 *now, -+ u64 *enabled, -+ u64 *running) -+{ -+ u64 ctx_time; -+ -+ *now = perf_clock(); -+ ctx_time = event->shadow_ctx_time + *now; -+ *enabled = ctx_time - event->tstamp_enabled; -+ *running = ctx_time - event->tstamp_running; -+} -+ -+static void perf_event_init_userpage(struct perf_event *event) -+{ -+ struct perf_event_mmap_page *userpg; -+ struct ring_buffer *rb; -+ -+ rcu_read_lock(); -+ rb = rcu_dereference(event->rb); -+ if (!rb) -+ goto unlock; -+ -+ userpg = rb->user_page; -+ -+ /* Allow new userspace to detect that bit 0 is deprecated */ -+ userpg->cap_bit0_is_deprecated = 1; -+ userpg->size = offsetof(struct perf_event_mmap_page, __reserved); -+ -+unlock: -+ rcu_read_unlock(); -+} -+ -+void __weak arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now) -+{ -+} -+ -+/* -+ * Callers need to ensure there can be no nesting of this function, otherwise -+ * the seqlock logic goes bad. We can not serialize this because the arch -+ * code calls this from NMI context. -+ */ -+void perf_event_update_userpage(struct perf_event *event) -+{ -+ struct perf_event_mmap_page *userpg; -+ struct ring_buffer *rb; -+ u64 enabled, running, now; -+ -+ rcu_read_lock(); -+ rb = rcu_dereference(event->rb); -+ if (!rb) -+ goto unlock; -+ -+ /* -+ * compute total_time_enabled, total_time_running -+ * based on snapshot values taken when the event -+ * was last scheduled in. -+ * -+ * we cannot simply called update_context_time() -+ * because of locking issue as we can be called in -+ * NMI context -+ */ -+ calc_timer_values(event, &now, &enabled, &running); -+ -+ userpg = rb->user_page; -+ /* -+ * Disable preemption so as to not let the corresponding user-space -+ * spin too long if we get preempted. -+ */ -+ preempt_disable(); -+ ++userpg->lock; -+ barrier(); -+ userpg->index = perf_event_index(event); -+ userpg->offset = perf_event_count(event); -+ if (userpg->index) -+ userpg->offset -= local64_read(&event->hw.prev_count); -+ -+ userpg->time_enabled = enabled + -+ atomic64_read(&event->child_total_time_enabled); -+ -+ userpg->time_running = running + -+ atomic64_read(&event->child_total_time_running); -+ -+ arch_perf_update_userpage(userpg, now); -+ -+ barrier(); -+ ++userpg->lock; -+ preempt_enable(); -+unlock: -+ rcu_read_unlock(); -+} -+ -+static int perf_mmap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) -+{ -+ struct perf_event *event = vma->vm_file->private_data; -+ struct ring_buffer *rb; -+ int ret = VM_FAULT_SIGBUS; -+ -+ if (vmf->flags & FAULT_FLAG_MKWRITE) { -+ if (vmf->pgoff == 0) -+ ret = 0; -+ return ret; -+ } -+ -+ rcu_read_lock(); -+ rb = rcu_dereference(event->rb); -+ if (!rb) -+ goto unlock; -+ -+ if (vmf->pgoff && (vmf->flags & FAULT_FLAG_WRITE)) -+ goto unlock; -+ -+ vmf->page = perf_mmap_to_page(rb, vmf->pgoff); -+ if (!vmf->page) -+ goto unlock; -+ -+ get_page(vmf->page); -+ vmf->page->mapping = vma->vm_file->f_mapping; -+ vmf->page->index = vmf->pgoff; -+ -+ ret = 0; -+unlock: -+ rcu_read_unlock(); -+ -+ return ret; -+} -+ -+static void ring_buffer_attach(struct perf_event *event, -+ struct ring_buffer *rb) -+{ -+ struct ring_buffer *old_rb = NULL; -+ unsigned long flags; -+ -+ if (event->rb) { -+ /* -+ * Should be impossible, we set this when removing -+ * event->rb_entry and wait/clear when adding event->rb_entry. -+ */ -+ WARN_ON_ONCE(event->rcu_pending); -+ -+ old_rb = event->rb; -+ event->rcu_batches = get_state_synchronize_rcu(); -+ event->rcu_pending = 1; -+ -+ spin_lock_irqsave(&old_rb->event_lock, flags); -+ list_del_rcu(&event->rb_entry); -+ spin_unlock_irqrestore(&old_rb->event_lock, flags); -+ } -+ -+ if (event->rcu_pending && rb) { -+ cond_synchronize_rcu(event->rcu_batches); -+ event->rcu_pending = 0; -+ } -+ -+ if (rb) { -+ spin_lock_irqsave(&rb->event_lock, flags); -+ list_add_rcu(&event->rb_entry, &rb->event_list); -+ spin_unlock_irqrestore(&rb->event_lock, flags); -+ } -+ -+ rcu_assign_pointer(event->rb, rb); -+ -+ if (old_rb) { -+ ring_buffer_put(old_rb); -+ /* -+ * Since we detached before setting the new rb, so that we -+ * could attach the new rb, we could have missed a wakeup. -+ * Provide it now. -+ */ -+ wake_up_all(&event->waitq); -+ } -+} -+ -+static void ring_buffer_wakeup(struct perf_event *event) -+{ -+ struct ring_buffer *rb; -+ -+ rcu_read_lock(); -+ rb = rcu_dereference(event->rb); -+ if (rb) { -+ list_for_each_entry_rcu(event, &rb->event_list, rb_entry) -+ wake_up_all(&event->waitq); -+ } -+ rcu_read_unlock(); -+} -+ -+static void rb_free_rcu(struct rcu_head *rcu_head) -+{ -+ struct ring_buffer *rb; -+ -+ rb = container_of(rcu_head, struct ring_buffer, rcu_head); -+ rb_free(rb); -+} -+ -+static struct ring_buffer *ring_buffer_get(struct perf_event *event) -+{ -+ struct ring_buffer *rb; -+ -+ rcu_read_lock(); -+ rb = rcu_dereference(event->rb); -+ if (rb) { -+ if (!atomic_inc_not_zero(&rb->refcount)) -+ rb = NULL; -+ } -+ rcu_read_unlock(); -+ -+ return rb; -+} -+ -+static void ring_buffer_put(struct ring_buffer *rb) -+{ -+ if (!atomic_dec_and_test(&rb->refcount)) -+ return; -+ -+ WARN_ON_ONCE(!list_empty(&rb->event_list)); -+ -+ call_rcu(&rb->rcu_head, rb_free_rcu); -+} -+ -+static void perf_mmap_open(struct vm_area_struct *vma) -+{ -+ struct perf_event *event = vma->vm_file->private_data; -+ -+ atomic_inc(&event->mmap_count); -+ atomic_inc(&event->rb->mmap_count); -+} -+ -+/* -+ * A buffer can be mmap()ed multiple times; either directly through the same -+ * event, or through other events by use of perf_event_set_output(). -+ * -+ * In order to undo the VM accounting done by perf_mmap() we need to destroy -+ * the buffer here, where we still have a VM context. This means we need -+ * to detach all events redirecting to us. -+ */ -+static void perf_mmap_close(struct vm_area_struct *vma) -+{ -+ struct perf_event *event = vma->vm_file->private_data; -+ -+ struct ring_buffer *rb = ring_buffer_get(event); -+ struct user_struct *mmap_user = rb->mmap_user; -+ int mmap_locked = rb->mmap_locked; -+ unsigned long size = perf_data_size(rb); -+ -+ atomic_dec(&rb->mmap_count); -+ -+ if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) -+ goto out_put; -+ -+ ring_buffer_attach(event, NULL); -+ mutex_unlock(&event->mmap_mutex); -+ -+ /* If there's still other mmap()s of this buffer, we're done. */ -+ if (atomic_read(&rb->mmap_count)) -+ goto out_put; -+ -+ /* -+ * No other mmap()s, detach from all other events that might redirect -+ * into the now unreachable buffer. Somewhat complicated by the -+ * fact that rb::event_lock otherwise nests inside mmap_mutex. -+ */ -+again: -+ rcu_read_lock(); -+ list_for_each_entry_rcu(event, &rb->event_list, rb_entry) { -+ if (!atomic_long_inc_not_zero(&event->refcount)) { -+ /* -+ * This event is en-route to free_event() which will -+ * detach it and remove it from the list. -+ */ -+ continue; -+ } -+ rcu_read_unlock(); -+ -+ mutex_lock(&event->mmap_mutex); -+ /* -+ * Check we didn't race with perf_event_set_output() which can -+ * swizzle the rb from under us while we were waiting to -+ * acquire mmap_mutex. -+ * -+ * If we find a different rb; ignore this event, a next -+ * iteration will no longer find it on the list. We have to -+ * still restart the iteration to make sure we're not now -+ * iterating the wrong list. -+ */ -+ if (event->rb == rb) -+ ring_buffer_attach(event, NULL); -+ -+ mutex_unlock(&event->mmap_mutex); -+ put_event(event); -+ -+ /* -+ * Restart the iteration; either we're on the wrong list or -+ * destroyed its integrity by doing a deletion. -+ */ -+ goto again; -+ } -+ rcu_read_unlock(); -+ -+ /* -+ * It could be there's still a few 0-ref events on the list; they'll -+ * get cleaned up by free_event() -- they'll also still have their -+ * ref on the rb and will free it whenever they are done with it. -+ * -+ * Aside from that, this buffer is 'fully' detached and unmapped, -+ * undo the VM accounting. -+ */ -+ -+ atomic_long_sub((size >> PAGE_SHIFT) + 1, &mmap_user->locked_vm); -+ vma->vm_mm->pinned_vm -= mmap_locked; -+ free_uid(mmap_user); -+ -+out_put: -+ ring_buffer_put(rb); /* could be last */ -+} -+ -+static const struct vm_operations_struct perf_mmap_vmops = { -+ .open = perf_mmap_open, -+ .close = perf_mmap_close, -+ .fault = perf_mmap_fault, -+ .page_mkwrite = perf_mmap_fault, -+}; -+ -+static int perf_mmap(struct file *file, struct vm_area_struct *vma) -+{ -+ struct perf_event *event = file->private_data; -+ unsigned long user_locked, user_lock_limit; -+ struct user_struct *user = current_user(); -+ unsigned long locked, lock_limit; -+ struct ring_buffer *rb; -+ unsigned long vma_size; -+ unsigned long nr_pages; -+ long user_extra, extra; -+ int ret = 0, flags = 0; -+ -+ /* -+ * Don't allow mmap() of inherited per-task counters. This would -+ * create a performance issue due to all children writing to the -+ * same rb. -+ */ -+ if (event->cpu == -1 && event->attr.inherit) -+ return -EINVAL; -+ -+ if (!(vma->vm_flags & VM_SHARED)) -+ return -EINVAL; -+ -+ vma_size = vma->vm_end - vma->vm_start; -+ nr_pages = (vma_size / PAGE_SIZE) - 1; -+ -+ /* -+ * If we have rb pages ensure they're a power-of-two number, so we -+ * can do bitmasks instead of modulo. -+ */ -+ if (nr_pages != 0 && !is_power_of_2(nr_pages)) -+ return -EINVAL; -+ -+ if (vma_size != PAGE_SIZE * (1 + nr_pages)) -+ return -EINVAL; -+ -+ if (vma->vm_pgoff != 0) -+ return -EINVAL; -+ -+ WARN_ON_ONCE(event->ctx->parent_ctx); -+again: -+ mutex_lock(&event->mmap_mutex); -+ if (event->rb) { -+ if (event->rb->nr_pages != nr_pages) { -+ ret = -EINVAL; -+ goto unlock; -+ } -+ -+ if (!atomic_inc_not_zero(&event->rb->mmap_count)) { -+ /* -+ * Raced against perf_mmap_close() through -+ * perf_event_set_output(). Try again, hope for better -+ * luck. -+ */ -+ mutex_unlock(&event->mmap_mutex); -+ goto again; -+ } -+ -+ goto unlock; -+ } -+ -+ user_extra = nr_pages + 1; -+ user_lock_limit = sysctl_perf_event_mlock >> (PAGE_SHIFT - 10); -+ -+ /* -+ * Increase the limit linearly with more CPUs: -+ */ -+ user_lock_limit *= num_online_cpus(); -+ -+ user_locked = atomic_long_read(&user->locked_vm) + user_extra; -+ -+ extra = 0; -+ if (user_locked > user_lock_limit) -+ extra = user_locked - user_lock_limit; -+ -+ lock_limit = rlimit(RLIMIT_MEMLOCK); -+ lock_limit >>= PAGE_SHIFT; -+ locked = vma->vm_mm->pinned_vm + extra; -+ -+ if ((locked > lock_limit) && perf_paranoid_tracepoint_raw() && -+ !capable(CAP_IPC_LOCK)) { -+ ret = -EPERM; -+ goto unlock; -+ } -+ -+ WARN_ON(event->rb); -+ -+ if (vma->vm_flags & VM_WRITE) -+ flags |= RING_BUFFER_WRITABLE; -+ -+ rb = rb_alloc(nr_pages, -+ event->attr.watermark ? event->attr.wakeup_watermark : 0, -+ event->cpu, flags); -+ -+ if (!rb) { -+ ret = -ENOMEM; -+ goto unlock; -+ } -+ -+ atomic_set(&rb->mmap_count, 1); -+ rb->mmap_locked = extra; -+ rb->mmap_user = get_current_user(); -+ -+ atomic_long_add(user_extra, &user->locked_vm); -+ vma->vm_mm->pinned_vm += extra; -+ -+ ring_buffer_attach(event, rb); -+ -+ perf_event_init_userpage(event); -+ perf_event_update_userpage(event); -+ -+unlock: -+ if (!ret) -+ atomic_inc(&event->mmap_count); -+ mutex_unlock(&event->mmap_mutex); -+ -+ /* -+ * Since pinned accounting is per vm we cannot allow fork() to copy our -+ * vma. -+ */ -+ vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP; -+ vma->vm_ops = &perf_mmap_vmops; -+ -+ return ret; -+} -+ -+static int perf_fasync(int fd, struct file *filp, int on) -+{ -+ struct inode *inode = file_inode(filp); -+ struct perf_event *event = filp->private_data; -+ int retval; -+ -+ mutex_lock(&inode->i_mutex); -+ retval = fasync_helper(fd, filp, on, &event->fasync); -+ mutex_unlock(&inode->i_mutex); -+ -+ if (retval < 0) -+ return retval; -+ -+ return 0; -+} -+ -+static const struct file_operations perf_fops = { -+ .llseek = no_llseek, -+ .release = perf_release, -+ .read = perf_read, -+ .poll = perf_poll, -+ .unlocked_ioctl = perf_ioctl, -+ .compat_ioctl = perf_compat_ioctl, -+ .mmap = perf_mmap, -+ .fasync = perf_fasync, -+}; -+ -+/* -+ * Perf event wakeup -+ * -+ * If there's data, ensure we set the poll() state and publish everything -+ * to user-space before waking everybody up. -+ */ -+ -+void perf_event_wakeup(struct perf_event *event) -+{ -+ ring_buffer_wakeup(event); -+ -+ if (event->pending_kill) { -+ kill_fasync(&event->fasync, SIGIO, event->pending_kill); -+ event->pending_kill = 0; -+ } -+} -+ -+static void perf_pending_event(struct irq_work *entry) -+{ -+ struct perf_event *event = container_of(entry, -+ struct perf_event, pending); -+ int rctx; -+ -+ rctx = perf_swevent_get_recursion_context(); -+ /* -+ * If we 'fail' here, that's OK, it means recursion is already disabled -+ * and we won't recurse 'further'. -+ */ -+ -+ if (event->pending_disable) { -+ event->pending_disable = 0; -+ __perf_event_disable(event); -+ } -+ -+ if (event->pending_wakeup) { -+ event->pending_wakeup = 0; -+ perf_event_wakeup(event); -+ } -+ -+ if (rctx >= 0) -+ perf_swevent_put_recursion_context(rctx); -+} -+ -+/* -+ * We assume there is only KVM supporting the callbacks. -+ * Later on, we might change it to a list if there is -+ * another virtualization implementation supporting the callbacks. -+ */ -+struct perf_guest_info_callbacks *perf_guest_cbs; -+ -+int perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *cbs) -+{ -+ perf_guest_cbs = cbs; -+ return 0; -+} -+EXPORT_SYMBOL_GPL(perf_register_guest_info_callbacks); -+ -+int perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *cbs) -+{ -+ perf_guest_cbs = NULL; -+ return 0; -+} -+EXPORT_SYMBOL_GPL(perf_unregister_guest_info_callbacks); -+ -+static void -+perf_output_sample_regs(struct perf_output_handle *handle, -+ struct pt_regs *regs, u64 mask) -+{ -+ int bit; -+ -+ for_each_set_bit(bit, (const unsigned long *) &mask, -+ sizeof(mask) * BITS_PER_BYTE) { -+ u64 val; -+ -+ val = perf_reg_value(regs, bit); -+ perf_output_put(handle, val); -+ } -+} -+ -+static void perf_sample_regs_user(struct perf_regs_user *regs_user, -+ struct pt_regs *regs) -+{ -+ if (!user_mode(regs)) { -+ if (current->mm) -+ regs = task_pt_regs(current); -+ else -+ regs = NULL; -+ } -+ -+ if (regs) { -+ regs_user->regs = regs; -+ regs_user->abi = perf_reg_abi(current); -+ } -+} -+ -+/* -+ * Get remaining task size from user stack pointer. -+ * -+ * It'd be better to take stack vma map and limit this more -+ * precisly, but there's no way to get it safely under interrupt, -+ * so using TASK_SIZE as limit. -+ */ -+static u64 perf_ustack_task_size(struct pt_regs *regs) -+{ -+ unsigned long addr = perf_user_stack_pointer(regs); -+ -+ if (!addr || addr >= TASK_SIZE) -+ return 0; -+ -+ return TASK_SIZE - addr; -+} -+ -+static u16 -+perf_sample_ustack_size(u16 stack_size, u16 header_size, -+ struct pt_regs *regs) -+{ -+ u64 task_size; -+ -+ /* No regs, no stack pointer, no dump. */ -+ if (!regs) -+ return 0; -+ -+ /* -+ * Check if we fit in with the requested stack size into the: -+ * - TASK_SIZE -+ * If we don't, we limit the size to the TASK_SIZE. -+ * -+ * - remaining sample size -+ * If we don't, we customize the stack size to -+ * fit in to the remaining sample size. -+ */ -+ -+ task_size = min((u64) USHRT_MAX, perf_ustack_task_size(regs)); -+ stack_size = min(stack_size, (u16) task_size); -+ -+ /* Current header size plus static size and dynamic size. */ -+ header_size += 2 * sizeof(u64); -+ -+ /* Do we fit in with the current stack dump size? */ -+ if ((u16) (header_size + stack_size) < header_size) { -+ /* -+ * If we overflow the maximum size for the sample, -+ * we customize the stack dump size to fit in. -+ */ -+ stack_size = USHRT_MAX - header_size - sizeof(u64); -+ stack_size = round_up(stack_size, sizeof(u64)); -+ } -+ -+ return stack_size; -+} -+ -+static void -+perf_output_sample_ustack(struct perf_output_handle *handle, u64 dump_size, -+ struct pt_regs *regs) -+{ -+ /* Case of a kernel thread, nothing to dump */ -+ if (!regs) { -+ u64 size = 0; -+ perf_output_put(handle, size); -+ } else { -+ unsigned long sp; -+ unsigned int rem; -+ u64 dyn_size; -+ -+ /* -+ * We dump: -+ * static size -+ * - the size requested by user or the best one we can fit -+ * in to the sample max size -+ * data -+ * - user stack dump data -+ * dynamic size -+ * - the actual dumped size -+ */ -+ -+ /* Static size. */ -+ perf_output_put(handle, dump_size); -+ -+ /* Data. */ -+ sp = perf_user_stack_pointer(regs); -+ rem = __output_copy_user(handle, (void *) sp, dump_size); -+ dyn_size = dump_size - rem; -+ -+ perf_output_skip(handle, rem); -+ -+ /* Dynamic size. */ -+ perf_output_put(handle, dyn_size); -+ } -+} -+ -+static void __perf_event_header__init_id(struct perf_event_header *header, -+ struct perf_sample_data *data, -+ struct perf_event *event) -+{ -+ u64 sample_type = event->attr.sample_type; -+ -+ data->type = sample_type; -+ header->size += event->id_header_size; -+ -+ if (sample_type & PERF_SAMPLE_TID) { -+ /* namespace issues */ -+ data->tid_entry.pid = perf_event_pid(event, current); -+ data->tid_entry.tid = perf_event_tid(event, current); -+ } -+ -+ if (sample_type & PERF_SAMPLE_TIME) -+ data->time = perf_clock(); -+ -+ if (sample_type & (PERF_SAMPLE_ID | PERF_SAMPLE_IDENTIFIER)) -+ data->id = primary_event_id(event); -+ -+ if (sample_type & PERF_SAMPLE_STREAM_ID) -+ data->stream_id = event->id; -+ -+ if (sample_type & PERF_SAMPLE_CPU) { -+ data->cpu_entry.cpu = raw_smp_processor_id(); -+ data->cpu_entry.reserved = 0; -+ } -+} -+ -+void perf_event_header__init_id(struct perf_event_header *header, -+ struct perf_sample_data *data, -+ struct perf_event *event) -+{ -+ if (event->attr.sample_id_all) -+ __perf_event_header__init_id(header, data, event); -+} -+ -+static void __perf_event__output_id_sample(struct perf_output_handle *handle, -+ struct perf_sample_data *data) -+{ -+ u64 sample_type = data->type; -+ -+ if (sample_type & PERF_SAMPLE_TID) -+ perf_output_put(handle, data->tid_entry); -+ -+ if (sample_type & PERF_SAMPLE_TIME) -+ perf_output_put(handle, data->time); -+ -+ if (sample_type & PERF_SAMPLE_ID) -+ perf_output_put(handle, data->id); -+ -+ if (sample_type & PERF_SAMPLE_STREAM_ID) -+ perf_output_put(handle, data->stream_id); -+ -+ if (sample_type & PERF_SAMPLE_CPU) -+ perf_output_put(handle, data->cpu_entry); -+ -+ if (sample_type & PERF_SAMPLE_IDENTIFIER) -+ perf_output_put(handle, data->id); -+} -+ -+void perf_event__output_id_sample(struct perf_event *event, -+ struct perf_output_handle *handle, -+ struct perf_sample_data *sample) -+{ -+ if (event->attr.sample_id_all) -+ __perf_event__output_id_sample(handle, sample); -+} -+ -+static void perf_output_read_one(struct perf_output_handle *handle, -+ struct perf_event *event, -+ u64 enabled, u64 running) -+{ -+ u64 read_format = event->attr.read_format; -+ u64 values[4]; -+ int n = 0; -+ -+ values[n++] = perf_event_count(event); -+ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) { -+ values[n++] = enabled + -+ atomic64_read(&event->child_total_time_enabled); -+ } -+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) { -+ values[n++] = running + -+ atomic64_read(&event->child_total_time_running); -+ } -+ if (read_format & PERF_FORMAT_ID) -+ values[n++] = primary_event_id(event); -+ -+ __output_copy(handle, values, n * sizeof(u64)); -+} -+ -+/* -+ * XXX PERF_FORMAT_GROUP vs inherited events seems difficult. -+ */ -+static void perf_output_read_group(struct perf_output_handle *handle, -+ struct perf_event *event, -+ u64 enabled, u64 running) -+{ -+ struct perf_event *leader = event->group_leader, *sub; -+ u64 read_format = event->attr.read_format; -+ u64 values[5]; -+ int n = 0; -+ -+ values[n++] = 1 + leader->nr_siblings; -+ -+ if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) -+ values[n++] = enabled; -+ -+ if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) -+ values[n++] = running; -+ -+ if (leader != event) -+ leader->pmu->read(leader); -+ -+ values[n++] = perf_event_count(leader); -+ if (read_format & PERF_FORMAT_ID) -+ values[n++] = primary_event_id(leader); -+ -+ __output_copy(handle, values, n * sizeof(u64)); -+ -+ list_for_each_entry(sub, &leader->sibling_list, group_entry) { -+ n = 0; -+ -+ if ((sub != event) && -+ (sub->state == PERF_EVENT_STATE_ACTIVE)) -+ sub->pmu->read(sub); -+ -+ values[n++] = perf_event_count(sub); -+ if (read_format & PERF_FORMAT_ID) -+ values[n++] = primary_event_id(sub); -+ -+ __output_copy(handle, values, n * sizeof(u64)); -+ } -+} -+ -+#define PERF_FORMAT_TOTAL_TIMES (PERF_FORMAT_TOTAL_TIME_ENABLED|\ -+ PERF_FORMAT_TOTAL_TIME_RUNNING) -+ -+static void perf_output_read(struct perf_output_handle *handle, -+ struct perf_event *event) -+{ -+ u64 enabled = 0, running = 0, now; -+ u64 read_format = event->attr.read_format; -+ -+ /* -+ * compute total_time_enabled, total_time_running -+ * based on snapshot values taken when the event -+ * was last scheduled in. -+ * -+ * we cannot simply called update_context_time() -+ * because of locking issue as we are called in -+ * NMI context -+ */ -+ if (read_format & PERF_FORMAT_TOTAL_TIMES) -+ calc_timer_values(event, &now, &enabled, &running); -+ -+ if (event->attr.read_format & PERF_FORMAT_GROUP) -+ perf_output_read_group(handle, event, enabled, running); -+ else -+ perf_output_read_one(handle, event, enabled, running); -+} -+ -+void perf_output_sample(struct perf_output_handle *handle, -+ struct perf_event_header *header, -+ struct perf_sample_data *data, -+ struct perf_event *event) -+{ -+ u64 sample_type = data->type; -+ -+ perf_output_put(handle, *header); -+ -+ if (sample_type & PERF_SAMPLE_IDENTIFIER) -+ perf_output_put(handle, data->id); -+ -+ if (sample_type & PERF_SAMPLE_IP) -+ perf_output_put(handle, data->ip); -+ -+ if (sample_type & PERF_SAMPLE_TID) -+ perf_output_put(handle, data->tid_entry); -+ -+ if (sample_type & PERF_SAMPLE_TIME) -+ perf_output_put(handle, data->time); -+ -+ if (sample_type & PERF_SAMPLE_ADDR) -+ perf_output_put(handle, data->addr); -+ -+ if (sample_type & PERF_SAMPLE_ID) -+ perf_output_put(handle, data->id); -+ -+ if (sample_type & PERF_SAMPLE_STREAM_ID) -+ perf_output_put(handle, data->stream_id); -+ -+ if (sample_type & PERF_SAMPLE_CPU) -+ perf_output_put(handle, data->cpu_entry); -+ -+ if (sample_type & PERF_SAMPLE_PERIOD) -+ perf_output_put(handle, data->period); -+ -+ if (sample_type & PERF_SAMPLE_READ) -+ perf_output_read(handle, event); -+ -+ if (sample_type & PERF_SAMPLE_CALLCHAIN) { -+ if (data->callchain) { -+ int size = 1; -+ -+ if (data->callchain) -+ size += data->callchain->nr; -+ -+ size *= sizeof(u64); -+ -+ __output_copy(handle, data->callchain, size); -+ } else { -+ u64 nr = 0; -+ perf_output_put(handle, nr); -+ } -+ } -+ -+ if (sample_type & PERF_SAMPLE_RAW) { -+ if (data->raw) { -+ perf_output_put(handle, data->raw->size); -+ __output_copy(handle, data->raw->data, -+ data->raw->size); -+ } else { -+ struct { -+ u32 size; -+ u32 data; -+ } raw = { -+ .size = sizeof(u32), -+ .data = 0, -+ }; -+ perf_output_put(handle, raw); -+ } -+ } -+ -+ if (sample_type & PERF_SAMPLE_BRANCH_STACK) { -+ if (data->br_stack) { -+ size_t size; -+ -+ size = data->br_stack->nr -+ * sizeof(struct perf_branch_entry); -+ -+ perf_output_put(handle, data->br_stack->nr); -+ perf_output_copy(handle, data->br_stack->entries, size); -+ } else { -+ /* -+ * we always store at least the value of nr -+ */ -+ u64 nr = 0; -+ perf_output_put(handle, nr); -+ } -+ } -+ -+ if (sample_type & PERF_SAMPLE_REGS_USER) { -+ u64 abi = data->regs_user.abi; -+ -+ /* -+ * If there are no regs to dump, notice it through -+ * first u64 being zero (PERF_SAMPLE_REGS_ABI_NONE). -+ */ -+ perf_output_put(handle, abi); -+ -+ if (abi) { -+ u64 mask = event->attr.sample_regs_user; -+ perf_output_sample_regs(handle, -+ data->regs_user.regs, -+ mask); -+ } -+ } -+ -+ if (sample_type & PERF_SAMPLE_STACK_USER) { -+ perf_output_sample_ustack(handle, -+ data->stack_user_size, -+ data->regs_user.regs); -+ } -+ -+ if (sample_type & PERF_SAMPLE_WEIGHT) -+ perf_output_put(handle, data->weight); -+ -+ if (sample_type & PERF_SAMPLE_DATA_SRC) -+ perf_output_put(handle, data->data_src.val); -+ -+ if (sample_type & PERF_SAMPLE_TRANSACTION) -+ perf_output_put(handle, data->txn); -+ -+ if (!event->attr.watermark) { -+ int wakeup_events = event->attr.wakeup_events; -+ -+ if (wakeup_events) { -+ struct ring_buffer *rb = handle->rb; -+ int events = local_inc_return(&rb->events); -+ -+ if (events >= wakeup_events) { -+ local_sub(wakeup_events, &rb->events); -+ local_inc(&rb->wakeup); -+ } -+ } -+ } -+} -+ -+void perf_prepare_sample(struct perf_event_header *header, -+ struct perf_sample_data *data, -+ struct perf_event *event, -+ struct pt_regs *regs) -+{ -+ u64 sample_type = event->attr.sample_type; -+ -+ header->type = PERF_RECORD_SAMPLE; -+ header->size = sizeof(*header) + event->header_size; -+ -+ header->misc = 0; -+ header->misc |= perf_misc_flags(regs); -+ -+ __perf_event_header__init_id(header, data, event); -+ -+ if (sample_type & PERF_SAMPLE_IP) -+ data->ip = perf_instruction_pointer(regs); -+ -+ if (sample_type & PERF_SAMPLE_CALLCHAIN) { -+ int size = 1; -+ -+ data->callchain = perf_callchain(event, regs); -+ -+ if (data->callchain) -+ size += data->callchain->nr; -+ -+ header->size += size * sizeof(u64); -+ } -+ -+ if (sample_type & PERF_SAMPLE_RAW) { -+ int size = sizeof(u32); -+ -+ if (data->raw) -+ size += data->raw->size; -+ else -+ size += sizeof(u32); -+ -+ WARN_ON_ONCE(size & (sizeof(u64)-1)); -+ header->size += size; -+ } -+ -+ if (sample_type & PERF_SAMPLE_BRANCH_STACK) { -+ int size = sizeof(u64); /* nr */ -+ if (data->br_stack) { -+ size += data->br_stack->nr -+ * sizeof(struct perf_branch_entry); -+ } -+ header->size += size; -+ } -+ -+ if (sample_type & PERF_SAMPLE_REGS_USER) { -+ /* regs dump ABI info */ -+ int size = sizeof(u64); -+ -+ perf_sample_regs_user(&data->regs_user, regs); -+ -+ if (data->regs_user.regs) { -+ u64 mask = event->attr.sample_regs_user; -+ size += hweight64(mask) * sizeof(u64); -+ } -+ -+ header->size += size; -+ } -+ -+ if (sample_type & PERF_SAMPLE_STACK_USER) { -+ /* -+ * Either we need PERF_SAMPLE_STACK_USER bit to be allways -+ * processed as the last one or have additional check added -+ * in case new sample type is added, because we could eat -+ * up the rest of the sample size. -+ */ -+ struct perf_regs_user *uregs = &data->regs_user; -+ u16 stack_size = event->attr.sample_stack_user; -+ u16 size = sizeof(u64); -+ -+ if (!uregs->abi) -+ perf_sample_regs_user(uregs, regs); -+ -+ stack_size = perf_sample_ustack_size(stack_size, header->size, -+ uregs->regs); -+ -+ /* -+ * If there is something to dump, add space for the dump -+ * itself and for the field that tells the dynamic size, -+ * which is how many have been actually dumped. -+ */ -+ if (stack_size) -+ size += sizeof(u64) + stack_size; -+ -+ data->stack_user_size = stack_size; -+ header->size += size; -+ } -+} -+ -+static void perf_event_output(struct perf_event *event, -+ struct perf_sample_data *data, -+ struct pt_regs *regs) -+{ -+ struct perf_output_handle handle; -+ struct perf_event_header header; -+ -+ /* protect the callchain buffers */ -+ rcu_read_lock(); -+ -+ perf_prepare_sample(&header, data, event, regs); -+ -+ if (perf_output_begin(&handle, event, header.size)) -+ goto exit; -+ -+ perf_output_sample(&handle, &header, data, event); -+ -+ perf_output_end(&handle); -+ -+exit: -+ rcu_read_unlock(); -+} -+ -+/* -+ * read event_id -+ */ -+ -+struct perf_read_event { -+ struct perf_event_header header; -+ -+ u32 pid; -+ u32 tid; -+}; -+ -+static void -+perf_event_read_event(struct perf_event *event, -+ struct task_struct *task) -+{ -+ struct perf_output_handle handle; -+ struct perf_sample_data sample; -+ struct perf_read_event read_event = { -+ .header = { -+ .type = PERF_RECORD_READ, -+ .misc = 0, -+ .size = sizeof(read_event) + event->read_size, -+ }, -+ .pid = perf_event_pid(event, task), -+ .tid = perf_event_tid(event, task), -+ }; -+ int ret; -+ -+ perf_event_header__init_id(&read_event.header, &sample, event); -+ ret = perf_output_begin(&handle, event, read_event.header.size); -+ if (ret) -+ return; -+ -+ perf_output_put(&handle, read_event); -+ perf_output_read(&handle, event); -+ perf_event__output_id_sample(event, &handle, &sample); -+ -+ perf_output_end(&handle); -+} -+ -+typedef void (perf_event_aux_output_cb)(struct perf_event *event, void *data); -+ -+static void -+perf_event_aux_ctx(struct perf_event_context *ctx, -+ perf_event_aux_output_cb output, -+ void *data) -+{ -+ struct perf_event *event; -+ -+ list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { -+ if (event->state < PERF_EVENT_STATE_INACTIVE) -+ continue; -+ if (!event_filter_match(event)) -+ continue; -+ output(event, data); -+ } -+} -+ -+static void -+perf_event_aux(perf_event_aux_output_cb output, void *data, -+ struct perf_event_context *task_ctx) -+{ -+ struct perf_cpu_context *cpuctx; -+ struct perf_event_context *ctx; -+ struct pmu *pmu; -+ int ctxn; -+ -+ rcu_read_lock(); -+ list_for_each_entry_rcu(pmu, &pmus, entry) { -+ cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); -+ if (cpuctx->unique_pmu != pmu) -+ goto next; -+ perf_event_aux_ctx(&cpuctx->ctx, output, data); -+ if (task_ctx) -+ goto next; -+ ctxn = pmu->task_ctx_nr; -+ if (ctxn < 0) -+ goto next; -+ ctx = rcu_dereference(current->perf_event_ctxp[ctxn]); -+ if (ctx) -+ perf_event_aux_ctx(ctx, output, data); -+next: -+ put_cpu_ptr(pmu->pmu_cpu_context); -+ } -+ -+ if (task_ctx) { -+ preempt_disable(); -+ perf_event_aux_ctx(task_ctx, output, data); -+ preempt_enable(); -+ } -+ rcu_read_unlock(); -+} -+ -+/* -+ * task tracking -- fork/exit -+ * -+ * enabled by: attr.comm | attr.mmap | attr.mmap2 | attr.mmap_data | attr.task -+ */ -+ -+struct perf_task_event { -+ struct task_struct *task; -+ struct perf_event_context *task_ctx; -+ -+ struct { -+ struct perf_event_header header; -+ -+ u32 pid; -+ u32 ppid; -+ u32 tid; -+ u32 ptid; -+ u64 time; -+ } event_id; -+}; -+ -+static int perf_event_task_match(struct perf_event *event) -+{ -+ return event->attr.comm || event->attr.mmap || -+ event->attr.mmap2 || event->attr.mmap_data || -+ event->attr.task; -+} -+ -+static void perf_event_task_output(struct perf_event *event, -+ void *data) -+{ -+ struct perf_task_event *task_event = data; -+ struct perf_output_handle handle; -+ struct perf_sample_data sample; -+ struct task_struct *task = task_event->task; -+ int ret, size = task_event->event_id.header.size; -+ -+ if (!perf_event_task_match(event)) -+ return; -+ -+ perf_event_header__init_id(&task_event->event_id.header, &sample, event); -+ -+ ret = perf_output_begin(&handle, event, -+ task_event->event_id.header.size); -+ if (ret) -+ goto out; -+ -+ task_event->event_id.pid = perf_event_pid(event, task); -+ task_event->event_id.ppid = perf_event_pid(event, current); -+ -+ task_event->event_id.tid = perf_event_tid(event, task); -+ task_event->event_id.ptid = perf_event_tid(event, current); -+ -+ perf_output_put(&handle, task_event->event_id); -+ -+ perf_event__output_id_sample(event, &handle, &sample); -+ -+ perf_output_end(&handle); -+out: -+ task_event->event_id.header.size = size; -+} -+ -+static void perf_event_task(struct task_struct *task, -+ struct perf_event_context *task_ctx, -+ int new) -+{ -+ struct perf_task_event task_event; -+ -+ if (!atomic_read(&nr_comm_events) && -+ !atomic_read(&nr_mmap_events) && -+ !atomic_read(&nr_task_events)) -+ return; -+ -+ task_event = (struct perf_task_event){ -+ .task = task, -+ .task_ctx = task_ctx, -+ .event_id = { -+ .header = { -+ .type = new ? PERF_RECORD_FORK : PERF_RECORD_EXIT, -+ .misc = 0, -+ .size = sizeof(task_event.event_id), -+ }, -+ /* .pid */ -+ /* .ppid */ -+ /* .tid */ -+ /* .ptid */ -+ .time = perf_clock(), -+ }, -+ }; -+ -+ perf_event_aux(perf_event_task_output, -+ &task_event, -+ task_ctx); -+} -+ -+void perf_event_fork(struct task_struct *task) -+{ -+ perf_event_task(task, NULL, 1); -+} -+ -+/* -+ * comm tracking -+ */ -+ -+struct perf_comm_event { -+ struct task_struct *task; -+ char *comm; -+ int comm_size; -+ -+ struct { -+ struct perf_event_header header; -+ -+ u32 pid; -+ u32 tid; -+ } event_id; -+}; -+ -+static int perf_event_comm_match(struct perf_event *event) -+{ -+ return event->attr.comm; -+} -+ -+static void perf_event_comm_output(struct perf_event *event, -+ void *data) -+{ -+ struct perf_comm_event *comm_event = data; -+ struct perf_output_handle handle; -+ struct perf_sample_data sample; -+ int size = comm_event->event_id.header.size; -+ int ret; -+ -+ if (!perf_event_comm_match(event)) -+ return; -+ -+ perf_event_header__init_id(&comm_event->event_id.header, &sample, event); -+ ret = perf_output_begin(&handle, event, -+ comm_event->event_id.header.size); -+ -+ if (ret) -+ goto out; -+ -+ comm_event->event_id.pid = perf_event_pid(event, comm_event->task); -+ comm_event->event_id.tid = perf_event_tid(event, comm_event->task); -+ -+ perf_output_put(&handle, comm_event->event_id); -+ __output_copy(&handle, comm_event->comm, -+ comm_event->comm_size); -+ -+ perf_event__output_id_sample(event, &handle, &sample); -+ -+ perf_output_end(&handle); -+out: -+ comm_event->event_id.header.size = size; -+} -+ -+static void perf_event_comm_event(struct perf_comm_event *comm_event) -+{ -+ char comm[TASK_COMM_LEN]; -+ unsigned int size; -+ -+ memset(comm, 0, sizeof(comm)); -+ strlcpy(comm, comm_event->task->comm, sizeof(comm)); -+ size = ALIGN(strlen(comm)+1, sizeof(u64)); -+ -+ comm_event->comm = comm; -+ comm_event->comm_size = size; -+ -+ comm_event->event_id.header.size = sizeof(comm_event->event_id) + size; -+ -+ perf_event_aux(perf_event_comm_output, -+ comm_event, -+ NULL); -+} -+ -+void perf_event_comm(struct task_struct *task, bool exec) -+{ -+ struct perf_comm_event comm_event; -+ -+ if (!atomic_read(&nr_comm_events)) -+ return; -+ -+ comm_event = (struct perf_comm_event){ -+ .task = task, -+ /* .comm */ -+ /* .comm_size */ -+ .event_id = { -+ .header = { -+ .type = PERF_RECORD_COMM, -+ .misc = exec ? PERF_RECORD_MISC_COMM_EXEC : 0, -+ /* .size */ -+ }, -+ /* .pid */ -+ /* .tid */ -+ }, -+ }; -+ -+ perf_event_comm_event(&comm_event); -+} -+ -+/* -+ * mmap tracking -+ */ -+ -+struct perf_mmap_event { -+ struct vm_area_struct *vma; -+ -+ const char *file_name; -+ int file_size; -+ int maj, min; -+ u64 ino; -+ u64 ino_generation; -+ u32 prot, flags; -+ -+ struct { -+ struct perf_event_header header; -+ -+ u32 pid; -+ u32 tid; -+ u64 start; -+ u64 len; -+ u64 pgoff; -+ } event_id; -+}; -+ -+static int perf_event_mmap_match(struct perf_event *event, -+ void *data) -+{ -+ struct perf_mmap_event *mmap_event = data; -+ struct vm_area_struct *vma = mmap_event->vma; -+ int executable = vma->vm_flags & VM_EXEC; -+ -+ return (!executable && event->attr.mmap_data) || -+ (executable && (event->attr.mmap || event->attr.mmap2)); -+} -+ -+static void perf_event_mmap_output(struct perf_event *event, -+ void *data) -+{ -+ struct perf_mmap_event *mmap_event = data; -+ struct perf_output_handle handle; -+ struct perf_sample_data sample; -+ int size = mmap_event->event_id.header.size; -+ int ret; -+ -+ if (!perf_event_mmap_match(event, data)) -+ return; -+ -+ if (event->attr.mmap2) { -+ mmap_event->event_id.header.type = PERF_RECORD_MMAP2; -+ mmap_event->event_id.header.size += sizeof(mmap_event->maj); -+ mmap_event->event_id.header.size += sizeof(mmap_event->min); -+ mmap_event->event_id.header.size += sizeof(mmap_event->ino); -+ mmap_event->event_id.header.size += sizeof(mmap_event->ino_generation); -+ mmap_event->event_id.header.size += sizeof(mmap_event->prot); -+ mmap_event->event_id.header.size += sizeof(mmap_event->flags); -+ } -+ -+ perf_event_header__init_id(&mmap_event->event_id.header, &sample, event); -+ ret = perf_output_begin(&handle, event, -+ mmap_event->event_id.header.size); -+ if (ret) -+ goto out; -+ -+ mmap_event->event_id.pid = perf_event_pid(event, current); -+ mmap_event->event_id.tid = perf_event_tid(event, current); -+ -+ perf_output_put(&handle, mmap_event->event_id); -+ -+ if (event->attr.mmap2) { -+ perf_output_put(&handle, mmap_event->maj); -+ perf_output_put(&handle, mmap_event->min); -+ perf_output_put(&handle, mmap_event->ino); -+ perf_output_put(&handle, mmap_event->ino_generation); -+ perf_output_put(&handle, mmap_event->prot); -+ perf_output_put(&handle, mmap_event->flags); -+ } -+ -+ __output_copy(&handle, mmap_event->file_name, -+ mmap_event->file_size); -+ -+ perf_event__output_id_sample(event, &handle, &sample); -+ -+ perf_output_end(&handle); -+out: -+ mmap_event->event_id.header.size = size; -+} -+ -+static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) -+{ -+ struct vm_area_struct *vma = mmap_event->vma; -+ struct file *file = vma->vm_file; -+ int maj = 0, min = 0; -+ u64 ino = 0, gen = 0; -+ u32 prot = 0, flags = 0; -+ unsigned int size; -+ char tmp[16]; -+ char *buf = NULL; -+ char *name; -+ -+ if (file) { -+ struct inode *inode; -+ dev_t dev; -+ -+ buf = kmalloc(PATH_MAX, GFP_KERNEL); -+ if (!buf) { -+ name = "//enomem"; -+ goto cpy_name; -+ } -+ /* -+ * d_path() works from the end of the rb backwards, so we -+ * need to add enough zero bytes after the string to handle -+ * the 64bit alignment we do later. -+ */ -+ name = d_path(&file->f_path, buf, PATH_MAX - sizeof(u64)); -+ if (IS_ERR(name)) { -+ name = "//toolong"; -+ goto cpy_name; -+ } -+ inode = file_inode(vma->vm_file); -+ dev = inode->i_sb->s_dev; -+ ino = inode->i_ino; -+ gen = inode->i_generation; -+ maj = MAJOR(dev); -+ min = MINOR(dev); -+ -+ if (vma->vm_flags & VM_READ) -+ prot |= PROT_READ; -+ if (vma->vm_flags & VM_WRITE) -+ prot |= PROT_WRITE; -+ if (vma->vm_flags & VM_EXEC) -+ prot |= PROT_EXEC; -+ -+ if (vma->vm_flags & VM_MAYSHARE) -+ flags = MAP_SHARED; -+ else -+ flags = MAP_PRIVATE; -+ -+ if (vma->vm_flags & VM_DENYWRITE) -+ flags |= MAP_DENYWRITE; -+ if (vma->vm_flags & VM_MAYEXEC) -+ flags |= MAP_EXECUTABLE; -+ if (vma->vm_flags & VM_LOCKED) -+ flags |= MAP_LOCKED; -+ if (vma->vm_flags & VM_HUGETLB) -+ flags |= MAP_HUGETLB; -+ -+ goto got_name; -+ } else { -+ if (vma->vm_ops && vma->vm_ops->name) { -+ name = (char *) vma->vm_ops->name(vma); -+ if (name) -+ goto cpy_name; -+ } -+ -+ name = (char *)arch_vma_name(vma); -+ if (name) -+ goto cpy_name; -+ -+ if (vma->vm_start <= vma->vm_mm->start_brk && -+ vma->vm_end >= vma->vm_mm->brk) { -+ name = "[heap]"; -+ goto cpy_name; -+ } -+ if (vma->vm_start <= vma->vm_mm->start_stack && -+ vma->vm_end >= vma->vm_mm->start_stack) { -+ name = "[stack]"; -+ goto cpy_name; -+ } -+ -+ name = "//anon"; -+ goto cpy_name; -+ } -+ -+cpy_name: -+ strlcpy(tmp, name, sizeof(tmp)); -+ name = tmp; -+got_name: -+ /* -+ * Since our buffer works in 8 byte units we need to align our string -+ * size to a multiple of 8. However, we must guarantee the tail end is -+ * zero'd out to avoid leaking random bits to userspace. -+ */ -+ size = strlen(name)+1; -+ while (!IS_ALIGNED(size, sizeof(u64))) -+ name[size++] = '\0'; -+ -+ mmap_event->file_name = name; -+ mmap_event->file_size = size; -+ mmap_event->maj = maj; -+ mmap_event->min = min; -+ mmap_event->ino = ino; -+ mmap_event->ino_generation = gen; -+ mmap_event->prot = prot; -+ mmap_event->flags = flags; -+ -+ if (!(vma->vm_flags & VM_EXEC)) -+ mmap_event->event_id.header.misc |= PERF_RECORD_MISC_MMAP_DATA; -+ -+ mmap_event->event_id.header.size = sizeof(mmap_event->event_id) + size; -+ -+ perf_event_aux(perf_event_mmap_output, -+ mmap_event, -+ NULL); -+ -+ kfree(buf); -+} -+ -+void perf_event_mmap(struct vm_area_struct *vma) -+{ -+ struct perf_mmap_event mmap_event; -+ -+ if (!atomic_read(&nr_mmap_events)) -+ return; -+ -+ mmap_event = (struct perf_mmap_event){ -+ .vma = vma, -+ /* .file_name */ -+ /* .file_size */ -+ .event_id = { -+ .header = { -+ .type = PERF_RECORD_MMAP, -+ .misc = PERF_RECORD_MISC_USER, -+ /* .size */ -+ }, -+ /* .pid */ -+ /* .tid */ -+ .start = vma->vm_start, -+ .len = vma->vm_end - vma->vm_start, -+ .pgoff = (u64)vma->vm_pgoff << PAGE_SHIFT, -+ }, -+ /* .maj (attr_mmap2 only) */ -+ /* .min (attr_mmap2 only) */ -+ /* .ino (attr_mmap2 only) */ -+ /* .ino_generation (attr_mmap2 only) */ -+ /* .prot (attr_mmap2 only) */ -+ /* .flags (attr_mmap2 only) */ -+ }; -+ -+ perf_event_mmap_event(&mmap_event); -+} -+ -+/* -+ * IRQ throttle logging -+ */ -+ -+static void perf_log_throttle(struct perf_event *event, int enable) -+{ -+ struct perf_output_handle handle; -+ struct perf_sample_data sample; -+ int ret; -+ -+ struct { -+ struct perf_event_header header; -+ u64 time; -+ u64 id; -+ u64 stream_id; -+ } throttle_event = { -+ .header = { -+ .type = PERF_RECORD_THROTTLE, -+ .misc = 0, -+ .size = sizeof(throttle_event), -+ }, -+ .time = perf_clock(), -+ .id = primary_event_id(event), -+ .stream_id = event->id, -+ }; -+ -+ if (enable) -+ throttle_event.header.type = PERF_RECORD_UNTHROTTLE; -+ -+ perf_event_header__init_id(&throttle_event.header, &sample, event); -+ -+ ret = perf_output_begin(&handle, event, -+ throttle_event.header.size); -+ if (ret) -+ return; -+ -+ perf_output_put(&handle, throttle_event); -+ perf_event__output_id_sample(event, &handle, &sample); -+ perf_output_end(&handle); -+} -+ -+/* -+ * Generic event overflow handling, sampling. -+ */ -+ -+static int __perf_event_overflow(struct perf_event *event, -+ int throttle, struct perf_sample_data *data, -+ struct pt_regs *regs) -+{ -+ int events = atomic_read(&event->event_limit); -+ struct hw_perf_event *hwc = &event->hw; -+ u64 seq; -+ int ret = 0; -+ -+ /* -+ * Non-sampling counters might still use the PMI to fold short -+ * hardware counters, ignore those. -+ */ -+ if (unlikely(!is_sampling_event(event))) -+ return 0; -+ -+ seq = __this_cpu_read(perf_throttled_seq); -+ if (seq != hwc->interrupts_seq) { -+ hwc->interrupts_seq = seq; -+ hwc->interrupts = 1; -+ } else { -+ hwc->interrupts++; -+ if (unlikely(throttle -+ && hwc->interrupts >= max_samples_per_tick)) { -+ __this_cpu_inc(perf_throttled_count); -+ hwc->interrupts = MAX_INTERRUPTS; -+ perf_log_throttle(event, 0); -+ tick_nohz_full_kick(); -+ ret = 1; -+ } -+ } -+ -+ if (event->attr.freq) { -+ u64 now = perf_clock(); -+ s64 delta = now - hwc->freq_time_stamp; -+ -+ hwc->freq_time_stamp = now; -+ -+ if (delta > 0 && delta < 2*TICK_NSEC) -+ perf_adjust_period(event, delta, hwc->last_period, true); -+ } -+ -+ /* -+ * XXX event_limit might not quite work as expected on inherited -+ * events -+ */ -+ -+ event->pending_kill = POLL_IN; -+ if (events && atomic_dec_and_test(&event->event_limit)) { -+ ret = 1; -+ event->pending_kill = POLL_HUP; -+ event->pending_disable = 1; -+ irq_work_queue(&event->pending); -+ } -+ -+ if (event->overflow_handler) -+ event->overflow_handler(event, data, regs); -+ else -+ perf_event_output(event, data, regs); -+ -+ if (event->fasync && event->pending_kill) { -+ event->pending_wakeup = 1; -+ irq_work_queue(&event->pending); -+ } -+ -+ return ret; -+} -+ -+int perf_event_overflow(struct perf_event *event, -+ struct perf_sample_data *data, -+ struct pt_regs *regs) -+{ -+ return __perf_event_overflow(event, 1, data, regs); -+} -+ -+/* -+ * Generic software event infrastructure -+ */ -+ -+struct swevent_htable { -+ struct swevent_hlist *swevent_hlist; -+ struct mutex hlist_mutex; -+ int hlist_refcount; -+ -+ /* Recursion avoidance in each contexts */ -+ int recursion[PERF_NR_CONTEXTS]; -+ -+ /* Keeps track of cpu being initialized/exited */ -+ bool online; -+}; -+ -+static DEFINE_PER_CPU(struct swevent_htable, swevent_htable); -+ -+/* -+ * We directly increment event->count and keep a second value in -+ * event->hw.period_left to count intervals. This period event -+ * is kept in the range [-sample_period, 0] so that we can use the -+ * sign as trigger. -+ */ -+ -+u64 perf_swevent_set_period(struct perf_event *event) -+{ -+ struct hw_perf_event *hwc = &event->hw; -+ u64 period = hwc->last_period; -+ u64 nr, offset; -+ s64 old, val; -+ -+ hwc->last_period = hwc->sample_period; -+ -+again: -+ old = val = local64_read(&hwc->period_left); -+ if (val < 0) -+ return 0; -+ -+ nr = div64_u64(period + val, period); -+ offset = nr * period; -+ val -= offset; -+ if (local64_cmpxchg(&hwc->period_left, old, val) != old) -+ goto again; -+ -+ return nr; -+} -+ -+static void perf_swevent_overflow(struct perf_event *event, u64 overflow, -+ struct perf_sample_data *data, -+ struct pt_regs *regs) -+{ -+ struct hw_perf_event *hwc = &event->hw; -+ int throttle = 0; -+ -+ if (!overflow) -+ overflow = perf_swevent_set_period(event); -+ -+ if (hwc->interrupts == MAX_INTERRUPTS) -+ return; -+ -+ for (; overflow; overflow--) { -+ if (__perf_event_overflow(event, throttle, -+ data, regs)) { -+ /* -+ * We inhibit the overflow from happening when -+ * hwc->interrupts == MAX_INTERRUPTS. -+ */ -+ break; -+ } -+ throttle = 1; -+ } -+} -+ -+static void perf_swevent_event(struct perf_event *event, u64 nr, -+ struct perf_sample_data *data, -+ struct pt_regs *regs) -+{ -+ struct hw_perf_event *hwc = &event->hw; -+ -+ local64_add(nr, &event->count); -+ -+ if (!regs) -+ return; -+ -+ if (!is_sampling_event(event)) -+ return; -+ -+ if ((event->attr.sample_type & PERF_SAMPLE_PERIOD) && !event->attr.freq) { -+ data->period = nr; -+ return perf_swevent_overflow(event, 1, data, regs); -+ } else -+ data->period = event->hw.last_period; -+ -+ if (nr == 1 && hwc->sample_period == 1 && !event->attr.freq) -+ return perf_swevent_overflow(event, 1, data, regs); -+ -+ if (local64_add_negative(nr, &hwc->period_left)) -+ return; -+ -+ perf_swevent_overflow(event, 0, data, regs); -+} -+ -+static int perf_exclude_event(struct perf_event *event, -+ struct pt_regs *regs) -+{ -+ if (event->hw.state & PERF_HES_STOPPED) -+ return 1; -+ -+ if (regs) { -+ if (event->attr.exclude_user && user_mode(regs)) -+ return 1; -+ -+ if (event->attr.exclude_kernel && !user_mode(regs)) -+ return 1; -+ } -+ -+ return 0; -+} -+ -+static int perf_swevent_match(struct perf_event *event, -+ enum perf_type_id type, -+ u32 event_id, -+ struct perf_sample_data *data, -+ struct pt_regs *regs) -+{ -+ if (event->attr.type != type) -+ return 0; -+ -+ if (event->attr.config != event_id) -+ return 0; -+ -+ if (perf_exclude_event(event, regs)) -+ return 0; -+ -+ return 1; -+} -+ -+static inline u64 swevent_hash(u64 type, u32 event_id) -+{ -+ u64 val = event_id | (type << 32); -+ -+ return hash_64(val, SWEVENT_HLIST_BITS); -+} -+ -+static inline struct hlist_head * -+__find_swevent_head(struct swevent_hlist *hlist, u64 type, u32 event_id) -+{ -+ u64 hash = swevent_hash(type, event_id); -+ -+ return &hlist->heads[hash]; -+} -+ -+/* For the read side: events when they trigger */ -+static inline struct hlist_head * -+find_swevent_head_rcu(struct swevent_htable *swhash, u64 type, u32 event_id) -+{ -+ struct swevent_hlist *hlist; -+ -+ hlist = rcu_dereference(swhash->swevent_hlist); -+ if (!hlist) -+ return NULL; -+ -+ return __find_swevent_head(hlist, type, event_id); -+} -+ -+/* For the event head insertion and removal in the hlist */ -+static inline struct hlist_head * -+find_swevent_head(struct swevent_htable *swhash, struct perf_event *event) -+{ -+ struct swevent_hlist *hlist; -+ u32 event_id = event->attr.config; -+ u64 type = event->attr.type; -+ -+ /* -+ * Event scheduling is always serialized against hlist allocation -+ * and release. Which makes the protected version suitable here. -+ * The context lock guarantees that. -+ */ -+ hlist = rcu_dereference_protected(swhash->swevent_hlist, -+ lockdep_is_held(&event->ctx->lock)); -+ if (!hlist) -+ return NULL; -+ -+ return __find_swevent_head(hlist, type, event_id); -+} -+ -+static void do_perf_sw_event(enum perf_type_id type, u32 event_id, -+ u64 nr, -+ struct perf_sample_data *data, -+ struct pt_regs *regs) -+{ -+ struct swevent_htable *swhash = this_cpu_ptr(&swevent_htable); -+ struct perf_event *event; -+ struct hlist_head *head; -+ -+ rcu_read_lock(); -+ head = find_swevent_head_rcu(swhash, type, event_id); -+ if (!head) -+ goto end; -+ -+ hlist_for_each_entry_rcu(event, head, hlist_entry) { -+ if (perf_swevent_match(event, type, event_id, data, regs)) -+ perf_swevent_event(event, nr, data, regs); -+ } -+end: -+ rcu_read_unlock(); -+} -+ -+int perf_swevent_get_recursion_context(void) -+{ -+ struct swevent_htable *swhash = this_cpu_ptr(&swevent_htable); -+ -+ return get_recursion_context(swhash->recursion); -+} -+EXPORT_SYMBOL_GPL(perf_swevent_get_recursion_context); -+ -+inline void perf_swevent_put_recursion_context(int rctx) -+{ -+ struct swevent_htable *swhash = this_cpu_ptr(&swevent_htable); -+ -+ put_recursion_context(swhash->recursion, rctx); -+} -+ -+void __perf_sw_event(u32 event_id, u64 nr, struct pt_regs *regs, u64 addr) -+{ -+ struct perf_sample_data data; -+ int rctx; -+ -+ preempt_disable_notrace(); -+ rctx = perf_swevent_get_recursion_context(); -+ if (rctx < 0) -+ return; -+ -+ perf_sample_data_init(&data, addr, 0); -+ -+ do_perf_sw_event(PERF_TYPE_SOFTWARE, event_id, nr, &data, regs); -+ -+ perf_swevent_put_recursion_context(rctx); -+ preempt_enable_notrace(); -+} -+ -+static void perf_swevent_read(struct perf_event *event) -+{ -+} -+ -+static int perf_swevent_add(struct perf_event *event, int flags) -+{ -+ struct swevent_htable *swhash = this_cpu_ptr(&swevent_htable); -+ struct hw_perf_event *hwc = &event->hw; -+ struct hlist_head *head; -+ -+ if (is_sampling_event(event)) { -+ hwc->last_period = hwc->sample_period; -+ perf_swevent_set_period(event); -+ } -+ -+ hwc->state = !(flags & PERF_EF_START); -+ -+ head = find_swevent_head(swhash, event); -+ if (!head) { -+ /* -+ * We can race with cpu hotplug code. Do not -+ * WARN if the cpu just got unplugged. -+ */ -+ WARN_ON_ONCE(swhash->online); -+ return -EINVAL; -+ } -+ -+ hlist_add_head_rcu(&event->hlist_entry, head); -+ -+ return 0; -+} -+ -+static void perf_swevent_del(struct perf_event *event, int flags) -+{ -+ hlist_del_rcu(&event->hlist_entry); -+} -+ -+static void perf_swevent_start(struct perf_event *event, int flags) -+{ -+ event->hw.state = 0; -+} -+ -+static void perf_swevent_stop(struct perf_event *event, int flags) -+{ -+ event->hw.state = PERF_HES_STOPPED; -+} -+ -+/* Deref the hlist from the update side */ -+static inline struct swevent_hlist * -+swevent_hlist_deref(struct swevent_htable *swhash) -+{ -+ return rcu_dereference_protected(swhash->swevent_hlist, -+ lockdep_is_held(&swhash->hlist_mutex)); -+} -+ -+static void swevent_hlist_release(struct swevent_htable *swhash) -+{ -+ struct swevent_hlist *hlist = swevent_hlist_deref(swhash); -+ -+ if (!hlist) -+ return; -+ -+ RCU_INIT_POINTER(swhash->swevent_hlist, NULL); -+ kfree_rcu(hlist, rcu_head); -+} -+ -+static void swevent_hlist_put_cpu(struct perf_event *event, int cpu) -+{ -+ struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); -+ -+ mutex_lock(&swhash->hlist_mutex); -+ -+ if (!--swhash->hlist_refcount) -+ swevent_hlist_release(swhash); -+ -+ mutex_unlock(&swhash->hlist_mutex); -+} -+ -+static void swevent_hlist_put(struct perf_event *event) -+{ -+ int cpu; -+ -+ for_each_possible_cpu(cpu) -+ swevent_hlist_put_cpu(event, cpu); -+} -+ -+static int swevent_hlist_get_cpu(struct perf_event *event, int cpu) -+{ -+ struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); -+ int err = 0; -+ -+ mutex_lock(&swhash->hlist_mutex); -+ -+ if (!swevent_hlist_deref(swhash) && cpu_online(cpu)) { -+ struct swevent_hlist *hlist; -+ -+ hlist = kzalloc(sizeof(*hlist), GFP_KERNEL); -+ if (!hlist) { -+ err = -ENOMEM; -+ goto exit; -+ } -+ rcu_assign_pointer(swhash->swevent_hlist, hlist); -+ } -+ swhash->hlist_refcount++; -+exit: -+ mutex_unlock(&swhash->hlist_mutex); -+ -+ return err; -+} -+ -+static int swevent_hlist_get(struct perf_event *event) -+{ -+ int err; -+ int cpu, failed_cpu; -+ -+ get_online_cpus(); -+ for_each_possible_cpu(cpu) { -+ err = swevent_hlist_get_cpu(event, cpu); -+ if (err) { -+ failed_cpu = cpu; -+ goto fail; -+ } -+ } -+ put_online_cpus(); -+ -+ return 0; -+fail: -+ for_each_possible_cpu(cpu) { -+ if (cpu == failed_cpu) -+ break; -+ swevent_hlist_put_cpu(event, cpu); -+ } -+ -+ put_online_cpus(); -+ return err; -+} -+ -+struct static_key perf_swevent_enabled[PERF_COUNT_SW_MAX]; -+ -+static void sw_perf_event_destroy(struct perf_event *event) -+{ -+ u64 event_id = event->attr.config; -+ -+ WARN_ON(event->parent); -+ -+ static_key_slow_dec(&perf_swevent_enabled[event_id]); -+ swevent_hlist_put(event); -+} -+ -+static int perf_swevent_init(struct perf_event *event) -+{ -+ u64 event_id = event->attr.config; -+ -+ if (event->attr.type != PERF_TYPE_SOFTWARE) -+ return -ENOENT; -+ -+ /* -+ * no branch sampling for software events -+ */ -+ if (has_branch_stack(event)) -+ return -EOPNOTSUPP; -+ -+ switch (event_id) { -+ case PERF_COUNT_SW_CPU_CLOCK: -+ case PERF_COUNT_SW_TASK_CLOCK: -+ return -ENOENT; -+ -+ default: -+ break; -+ } -+ -+ if (event_id >= PERF_COUNT_SW_MAX) -+ return -ENOENT; -+ -+ if (!event->parent) { -+ int err; -+ -+ err = swevent_hlist_get(event); -+ if (err) -+ return err; -+ -+ static_key_slow_inc(&perf_swevent_enabled[event_id]); -+ event->destroy = sw_perf_event_destroy; -+ } -+ -+ return 0; -+} -+ -+static struct pmu perf_swevent = { -+ .task_ctx_nr = perf_sw_context, -+ -+ .event_init = perf_swevent_init, -+ .add = perf_swevent_add, -+ .del = perf_swevent_del, -+ .start = perf_swevent_start, -+ .stop = perf_swevent_stop, -+ .read = perf_swevent_read, -+}; -+ -+#ifdef CONFIG_EVENT_TRACING -+ -+static int perf_tp_filter_match(struct perf_event *event, -+ struct perf_sample_data *data) -+{ -+ void *record = data->raw->data; -+ -+ if (likely(!event->filter) || filter_match_preds(event->filter, record)) -+ return 1; -+ return 0; -+} -+ -+static int perf_tp_event_match(struct perf_event *event, -+ struct perf_sample_data *data, -+ struct pt_regs *regs) -+{ -+ if (event->hw.state & PERF_HES_STOPPED) -+ return 0; -+ /* -+ * All tracepoints are from kernel-space. -+ */ -+ if (event->attr.exclude_kernel) -+ return 0; -+ -+ if (!perf_tp_filter_match(event, data)) -+ return 0; -+ -+ return 1; -+} -+ -+void perf_tp_event(u64 addr, u64 count, void *record, int entry_size, -+ struct pt_regs *regs, struct hlist_head *head, int rctx, -+ struct task_struct *task) -+{ -+ struct perf_sample_data data; -+ struct perf_event *event; -+ -+ struct perf_raw_record raw = { -+ .size = entry_size, -+ .data = record, -+ }; -+ -+ perf_sample_data_init(&data, addr, 0); -+ data.raw = &raw; -+ -+ hlist_for_each_entry_rcu(event, head, hlist_entry) { -+ if (perf_tp_event_match(event, &data, regs)) -+ perf_swevent_event(event, count, &data, regs); -+ } -+ -+ /* -+ * If we got specified a target task, also iterate its context and -+ * deliver this event there too. -+ */ -+ if (task && task != current) { -+ struct perf_event_context *ctx; -+ struct trace_entry *entry = record; -+ -+ rcu_read_lock(); -+ ctx = rcu_dereference(task->perf_event_ctxp[perf_sw_context]); -+ if (!ctx) -+ goto unlock; -+ -+ list_for_each_entry_rcu(event, &ctx->event_list, event_entry) { -+ if (event->attr.type != PERF_TYPE_TRACEPOINT) -+ continue; -+ if (event->attr.config != entry->type) -+ continue; -+ if (perf_tp_event_match(event, &data, regs)) -+ perf_swevent_event(event, count, &data, regs); -+ } -+unlock: -+ rcu_read_unlock(); -+ } -+ -+ perf_swevent_put_recursion_context(rctx); -+} -+EXPORT_SYMBOL_GPL(perf_tp_event); -+ -+static void tp_perf_event_destroy(struct perf_event *event) -+{ -+ perf_trace_destroy(event); -+} -+ -+static int perf_tp_event_init(struct perf_event *event) -+{ -+ int err; -+ -+ if (event->attr.type != PERF_TYPE_TRACEPOINT) -+ return -ENOENT; -+ -+ /* -+ * no branch sampling for tracepoint events -+ */ -+ if (has_branch_stack(event)) -+ return -EOPNOTSUPP; -+ -+ err = perf_trace_init(event); -+ if (err) -+ return err; -+ -+ event->destroy = tp_perf_event_destroy; -+ -+ return 0; -+} -+ -+static struct pmu perf_tracepoint = { -+ .task_ctx_nr = perf_sw_context, -+ -+ .event_init = perf_tp_event_init, -+ .add = perf_trace_add, -+ .del = perf_trace_del, -+ .start = perf_swevent_start, -+ .stop = perf_swevent_stop, -+ .read = perf_swevent_read, -+}; -+ -+static inline void perf_tp_register(void) -+{ -+ perf_pmu_register(&perf_tracepoint, "tracepoint", PERF_TYPE_TRACEPOINT); -+} -+ -+static int perf_event_set_filter(struct perf_event *event, void __user *arg) -+{ -+ char *filter_str; -+ int ret; -+ -+ if (event->attr.type != PERF_TYPE_TRACEPOINT) -+ return -EINVAL; -+ -+ filter_str = strndup_user(arg, PAGE_SIZE); -+ if (IS_ERR(filter_str)) -+ return PTR_ERR(filter_str); -+ -+ ret = ftrace_profile_set_filter(event, event->attr.config, filter_str); -+ -+ kfree(filter_str); -+ return ret; -+} -+ -+static void perf_event_free_filter(struct perf_event *event) -+{ -+ ftrace_profile_free_filter(event); -+} -+ -+#else -+ -+static inline void perf_tp_register(void) -+{ -+} -+ -+static int perf_event_set_filter(struct perf_event *event, void __user *arg) -+{ -+ return -ENOENT; -+} -+ -+static void perf_event_free_filter(struct perf_event *event) -+{ -+} -+ -+#endif /* CONFIG_EVENT_TRACING */ -+ -+#ifdef CONFIG_HAVE_HW_BREAKPOINT -+void perf_bp_event(struct perf_event *bp, void *data) -+{ -+ struct perf_sample_data sample; -+ struct pt_regs *regs = data; -+ -+ perf_sample_data_init(&sample, bp->attr.bp_addr, 0); -+ -+ if (!bp->hw.state && !perf_exclude_event(bp, regs)) -+ perf_swevent_event(bp, 1, &sample, regs); -+} -+#endif -+ -+/* -+ * hrtimer based swevent callback -+ */ -+ -+static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer) -+{ -+ enum hrtimer_restart ret = HRTIMER_RESTART; -+ struct perf_sample_data data; -+ struct pt_regs *regs; -+ struct perf_event *event; -+ u64 period; -+ -+ event = container_of(hrtimer, struct perf_event, hw.hrtimer); -+ -+ if (event->state != PERF_EVENT_STATE_ACTIVE) -+ return HRTIMER_NORESTART; -+ -+ event->pmu->read(event); -+ -+ perf_sample_data_init(&data, 0, event->hw.last_period); -+ regs = get_irq_regs(); -+ -+ if (regs && !perf_exclude_event(event, regs)) { -+ if (!(event->attr.exclude_idle && is_idle_task(current))) -+ if (__perf_event_overflow(event, 1, &data, regs)) -+ ret = HRTIMER_NORESTART; -+ } -+ -+ period = max_t(u64, 10000, event->hw.sample_period); -+ hrtimer_forward_now(hrtimer, ns_to_ktime(period)); -+ -+ return ret; -+} -+ -+static void perf_swevent_start_hrtimer(struct perf_event *event) -+{ -+ struct hw_perf_event *hwc = &event->hw; -+ s64 period; -+ -+ if (!is_sampling_event(event)) -+ return; -+ -+ period = local64_read(&hwc->period_left); -+ if (period) { -+ if (period < 0) -+ period = 10000; -+ -+ local64_set(&hwc->period_left, 0); -+ } else { -+ period = max_t(u64, 10000, hwc->sample_period); -+ } -+ __hrtimer_start_range_ns(&hwc->hrtimer, -+ ns_to_ktime(period), 0, -+ HRTIMER_MODE_REL_PINNED, 0); -+} -+ -+static void perf_swevent_cancel_hrtimer(struct perf_event *event) -+{ -+ struct hw_perf_event *hwc = &event->hw; -+ -+ if (is_sampling_event(event)) { -+ ktime_t remaining = hrtimer_get_remaining(&hwc->hrtimer); -+ local64_set(&hwc->period_left, ktime_to_ns(remaining)); -+ -+ hrtimer_cancel(&hwc->hrtimer); -+ } -+} -+ -+static void perf_swevent_init_hrtimer(struct perf_event *event) -+{ -+ struct hw_perf_event *hwc = &event->hw; -+ -+ if (!is_sampling_event(event)) -+ return; -+ -+ hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); -+ hwc->hrtimer.function = perf_swevent_hrtimer; -+ -+ /* -+ * Since hrtimers have a fixed rate, we can do a static freq->period -+ * mapping and avoid the whole period adjust feedback stuff. -+ */ -+ if (event->attr.freq) { -+ long freq = event->attr.sample_freq; -+ -+ event->attr.sample_period = NSEC_PER_SEC / freq; -+ hwc->sample_period = event->attr.sample_period; -+ local64_set(&hwc->period_left, hwc->sample_period); -+ hwc->last_period = hwc->sample_period; -+ event->attr.freq = 0; -+ } -+} -+ -+/* -+ * Software event: cpu wall time clock -+ */ -+ -+static void cpu_clock_event_update(struct perf_event *event) -+{ -+ s64 prev; -+ u64 now; -+ -+ now = local_clock(); -+ prev = local64_xchg(&event->hw.prev_count, now); -+ local64_add(now - prev, &event->count); -+} -+ -+static void cpu_clock_event_start(struct perf_event *event, int flags) -+{ -+ local64_set(&event->hw.prev_count, local_clock()); -+ perf_swevent_start_hrtimer(event); -+} -+ -+static void cpu_clock_event_stop(struct perf_event *event, int flags) -+{ -+ perf_swevent_cancel_hrtimer(event); -+ cpu_clock_event_update(event); -+} -+ -+static int cpu_clock_event_add(struct perf_event *event, int flags) -+{ -+ if (flags & PERF_EF_START) -+ cpu_clock_event_start(event, flags); -+ -+ return 0; -+} -+ -+static void cpu_clock_event_del(struct perf_event *event, int flags) -+{ -+ cpu_clock_event_stop(event, flags); -+} -+ -+static void cpu_clock_event_read(struct perf_event *event) -+{ -+ cpu_clock_event_update(event); -+} -+ -+static int cpu_clock_event_init(struct perf_event *event) -+{ -+ if (event->attr.type != PERF_TYPE_SOFTWARE) -+ return -ENOENT; -+ -+ if (event->attr.config != PERF_COUNT_SW_CPU_CLOCK) -+ return -ENOENT; -+ -+ /* -+ * no branch sampling for software events -+ */ -+ if (has_branch_stack(event)) -+ return -EOPNOTSUPP; -+ -+ perf_swevent_init_hrtimer(event); -+ -+ return 0; -+} -+ -+static struct pmu perf_cpu_clock = { -+ .task_ctx_nr = perf_sw_context, -+ -+ .event_init = cpu_clock_event_init, -+ .add = cpu_clock_event_add, -+ .del = cpu_clock_event_del, -+ .start = cpu_clock_event_start, -+ .stop = cpu_clock_event_stop, -+ .read = cpu_clock_event_read, -+}; -+ -+/* -+ * Software event: task time clock -+ */ -+ -+static void task_clock_event_update(struct perf_event *event, u64 now) -+{ -+ u64 prev; -+ s64 delta; -+ -+ prev = local64_xchg(&event->hw.prev_count, now); -+ delta = now - prev; -+ local64_add(delta, &event->count); -+} -+ -+static void task_clock_event_start(struct perf_event *event, int flags) -+{ -+ local64_set(&event->hw.prev_count, event->ctx->time); -+ perf_swevent_start_hrtimer(event); -+} -+ -+static void task_clock_event_stop(struct perf_event *event, int flags) -+{ -+ perf_swevent_cancel_hrtimer(event); -+ task_clock_event_update(event, event->ctx->time); -+} -+ -+static int task_clock_event_add(struct perf_event *event, int flags) -+{ -+ if (flags & PERF_EF_START) -+ task_clock_event_start(event, flags); -+ -+ return 0; -+} -+ -+static void task_clock_event_del(struct perf_event *event, int flags) -+{ -+ task_clock_event_stop(event, PERF_EF_UPDATE); -+} -+ -+static void task_clock_event_read(struct perf_event *event) -+{ -+ u64 now = perf_clock(); -+ u64 delta = now - event->ctx->timestamp; -+ u64 time = event->ctx->time + delta; -+ -+ task_clock_event_update(event, time); -+} -+ -+static int task_clock_event_init(struct perf_event *event) -+{ -+ if (event->attr.type != PERF_TYPE_SOFTWARE) -+ return -ENOENT; -+ -+ if (event->attr.config != PERF_COUNT_SW_TASK_CLOCK) -+ return -ENOENT; -+ -+ /* -+ * no branch sampling for software events -+ */ -+ if (has_branch_stack(event)) -+ return -EOPNOTSUPP; -+ -+ perf_swevent_init_hrtimer(event); -+ -+ return 0; -+} -+ -+static struct pmu perf_task_clock = { -+ .task_ctx_nr = perf_sw_context, -+ -+ .event_init = task_clock_event_init, -+ .add = task_clock_event_add, -+ .del = task_clock_event_del, -+ .start = task_clock_event_start, -+ .stop = task_clock_event_stop, -+ .read = task_clock_event_read, -+}; -+ -+static void perf_pmu_nop_void(struct pmu *pmu) -+{ -+} -+ -+static int perf_pmu_nop_int(struct pmu *pmu) -+{ -+ return 0; -+} -+ -+static void perf_pmu_start_txn(struct pmu *pmu) -+{ -+ perf_pmu_disable(pmu); -+} -+ -+static int perf_pmu_commit_txn(struct pmu *pmu) -+{ -+ perf_pmu_enable(pmu); -+ return 0; -+} -+ -+static void perf_pmu_cancel_txn(struct pmu *pmu) -+{ -+ perf_pmu_enable(pmu); -+} -+ -+static int perf_event_idx_default(struct perf_event *event) -+{ -+ return 0; -+} -+ -+/* -+ * Ensures all contexts with the same task_ctx_nr have the same -+ * pmu_cpu_context too. -+ */ -+static struct perf_cpu_context __percpu *find_pmu_context(int ctxn) -+{ -+ struct pmu *pmu; -+ -+ if (ctxn < 0) -+ return NULL; -+ -+ list_for_each_entry(pmu, &pmus, entry) { -+ if (pmu->task_ctx_nr == ctxn) -+ return pmu->pmu_cpu_context; -+ } -+ -+ return NULL; -+} -+ -+static void update_pmu_context(struct pmu *pmu, struct pmu *old_pmu) -+{ -+ int cpu; -+ -+ for_each_possible_cpu(cpu) { -+ struct perf_cpu_context *cpuctx; -+ -+ cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); -+ -+ if (cpuctx->unique_pmu == old_pmu) -+ cpuctx->unique_pmu = pmu; -+ } -+} -+ -+static void free_pmu_context(struct pmu *pmu) -+{ -+ struct pmu *i; -+ -+ mutex_lock(&pmus_lock); -+ /* -+ * Like a real lame refcount. -+ */ -+ list_for_each_entry(i, &pmus, entry) { -+ if (i->pmu_cpu_context == pmu->pmu_cpu_context) { -+ update_pmu_context(i, pmu); -+ goto out; -+ } -+ } -+ -+ free_percpu(pmu->pmu_cpu_context); -+out: -+ mutex_unlock(&pmus_lock); -+} -+static struct idr pmu_idr; -+ -+static ssize_t -+type_show(struct device *dev, struct device_attribute *attr, char *page) -+{ -+ struct pmu *pmu = dev_get_drvdata(dev); -+ -+ return snprintf(page, PAGE_SIZE-1, "%d\n", pmu->type); -+} -+static DEVICE_ATTR_RO(type); -+ -+static ssize_t -+perf_event_mux_interval_ms_show(struct device *dev, -+ struct device_attribute *attr, -+ char *page) -+{ -+ struct pmu *pmu = dev_get_drvdata(dev); -+ -+ return snprintf(page, PAGE_SIZE-1, "%d\n", pmu->hrtimer_interval_ms); -+} -+ -+static ssize_t -+perf_event_mux_interval_ms_store(struct device *dev, -+ struct device_attribute *attr, -+ const char *buf, size_t count) -+{ -+ struct pmu *pmu = dev_get_drvdata(dev); -+ int timer, cpu, ret; -+ -+ ret = kstrtoint(buf, 0, &timer); -+ if (ret) -+ return ret; -+ -+ if (timer < 1) -+ return -EINVAL; -+ -+ /* same value, noting to do */ -+ if (timer == pmu->hrtimer_interval_ms) -+ return count; -+ -+ pmu->hrtimer_interval_ms = timer; -+ -+ /* update all cpuctx for this PMU */ -+ for_each_possible_cpu(cpu) { -+ struct perf_cpu_context *cpuctx; -+ cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); -+ cpuctx->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * timer); -+ -+ if (hrtimer_active(&cpuctx->hrtimer)) -+ hrtimer_forward_now(&cpuctx->hrtimer, cpuctx->hrtimer_interval); -+ } -+ -+ return count; -+} -+static DEVICE_ATTR_RW(perf_event_mux_interval_ms); -+ -+static struct attribute *pmu_dev_attrs[] = { -+ &dev_attr_type.attr, -+ &dev_attr_perf_event_mux_interval_ms.attr, -+ NULL, -+}; -+ATTRIBUTE_GROUPS(pmu_dev); -+ -+static int pmu_bus_running; -+static struct bus_type pmu_bus = { -+ .name = "event_source", -+ .dev_groups = pmu_dev_groups, -+}; -+ -+static void pmu_dev_release(struct device *dev) -+{ -+ kfree(dev); -+} -+ -+static int pmu_dev_alloc(struct pmu *pmu) -+{ -+ int ret = -ENOMEM; -+ -+ pmu->dev = kzalloc(sizeof(struct device), GFP_KERNEL); -+ if (!pmu->dev) -+ goto out; -+ -+ pmu->dev->groups = pmu->attr_groups; -+ device_initialize(pmu->dev); -+ ret = dev_set_name(pmu->dev, "%s", pmu->name); -+ if (ret) -+ goto free_dev; -+ -+ dev_set_drvdata(pmu->dev, pmu); -+ pmu->dev->bus = &pmu_bus; -+ pmu->dev->release = pmu_dev_release; -+ ret = device_add(pmu->dev); -+ if (ret) -+ goto free_dev; -+ -+out: -+ return ret; -+ -+free_dev: -+ put_device(pmu->dev); -+ goto out; -+} -+ -+static struct lock_class_key cpuctx_mutex; -+static struct lock_class_key cpuctx_lock; -+ -+int perf_pmu_register(struct pmu *pmu, const char *name, int type) -+{ -+ int cpu, ret; -+ -+ mutex_lock(&pmus_lock); -+ ret = -ENOMEM; -+ pmu->pmu_disable_count = alloc_percpu(int); -+ if (!pmu->pmu_disable_count) -+ goto unlock; -+ -+ pmu->type = -1; -+ if (!name) -+ goto skip_type; -+ pmu->name = name; -+ -+ if (type < 0) { -+ type = idr_alloc(&pmu_idr, pmu, PERF_TYPE_MAX, 0, GFP_KERNEL); -+ if (type < 0) { -+ ret = type; -+ goto free_pdc; -+ } -+ } -+ pmu->type = type; -+ -+ if (pmu_bus_running) { -+ ret = pmu_dev_alloc(pmu); -+ if (ret) -+ goto free_idr; -+ } -+ -+skip_type: -+ pmu->pmu_cpu_context = find_pmu_context(pmu->task_ctx_nr); -+ if (pmu->pmu_cpu_context) -+ goto got_cpu_context; -+ -+ ret = -ENOMEM; -+ pmu->pmu_cpu_context = alloc_percpu(struct perf_cpu_context); -+ if (!pmu->pmu_cpu_context) -+ goto free_dev; -+ -+ for_each_possible_cpu(cpu) { -+ struct perf_cpu_context *cpuctx; -+ -+ cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); -+ __perf_event_init_context(&cpuctx->ctx); -+ lockdep_set_class(&cpuctx->ctx.mutex, &cpuctx_mutex); -+ lockdep_set_class(&cpuctx->ctx.lock, &cpuctx_lock); -+ cpuctx->ctx.type = cpu_context; -+ cpuctx->ctx.pmu = pmu; -+ -+ __perf_cpu_hrtimer_init(cpuctx, cpu); -+ -+ INIT_LIST_HEAD(&cpuctx->rotation_list); -+ cpuctx->unique_pmu = pmu; -+ } -+ -+got_cpu_context: -+ if (!pmu->start_txn) { -+ if (pmu->pmu_enable) { -+ /* -+ * If we have pmu_enable/pmu_disable calls, install -+ * transaction stubs that use that to try and batch -+ * hardware accesses. -+ */ -+ pmu->start_txn = perf_pmu_start_txn; -+ pmu->commit_txn = perf_pmu_commit_txn; -+ pmu->cancel_txn = perf_pmu_cancel_txn; -+ } else { -+ pmu->start_txn = perf_pmu_nop_void; -+ pmu->commit_txn = perf_pmu_nop_int; -+ pmu->cancel_txn = perf_pmu_nop_void; -+ } -+ } -+ -+ if (!pmu->pmu_enable) { -+ pmu->pmu_enable = perf_pmu_nop_void; -+ pmu->pmu_disable = perf_pmu_nop_void; -+ } -+ -+ if (!pmu->event_idx) -+ pmu->event_idx = perf_event_idx_default; -+ -+ list_add_rcu(&pmu->entry, &pmus); -+ ret = 0; -+unlock: -+ mutex_unlock(&pmus_lock); -+ -+ return ret; -+ -+free_dev: -+ device_del(pmu->dev); -+ put_device(pmu->dev); -+ -+free_idr: -+ if (pmu->type >= PERF_TYPE_MAX) -+ idr_remove(&pmu_idr, pmu->type); -+ -+free_pdc: -+ free_percpu(pmu->pmu_disable_count); -+ goto unlock; -+} -+EXPORT_SYMBOL_GPL(perf_pmu_register); -+ -+void perf_pmu_unregister(struct pmu *pmu) -+{ -+ mutex_lock(&pmus_lock); -+ list_del_rcu(&pmu->entry); -+ mutex_unlock(&pmus_lock); -+ -+ /* -+ * We dereference the pmu list under both SRCU and regular RCU, so -+ * synchronize against both of those. -+ */ -+ synchronize_srcu(&pmus_srcu); -+ synchronize_rcu(); -+ -+ free_percpu(pmu->pmu_disable_count); -+ if (pmu->type >= PERF_TYPE_MAX) -+ idr_remove(&pmu_idr, pmu->type); -+ device_del(pmu->dev); -+ put_device(pmu->dev); -+ free_pmu_context(pmu); -+} -+EXPORT_SYMBOL_GPL(perf_pmu_unregister); -+ -+struct pmu *perf_init_event(struct perf_event *event) -+{ -+ struct pmu *pmu = NULL; -+ int idx; -+ int ret; -+ -+ idx = srcu_read_lock(&pmus_srcu); -+ -+ rcu_read_lock(); -+ pmu = idr_find(&pmu_idr, event->attr.type); -+ rcu_read_unlock(); -+ if (pmu) { -+ if (!try_module_get(pmu->module)) { -+ pmu = ERR_PTR(-ENODEV); -+ goto unlock; -+ } -+ event->pmu = pmu; -+ ret = pmu->event_init(event); -+ if (ret) -+ pmu = ERR_PTR(ret); -+ goto unlock; -+ } -+ -+ list_for_each_entry_rcu(pmu, &pmus, entry) { -+ if (!try_module_get(pmu->module)) { -+ pmu = ERR_PTR(-ENODEV); -+ goto unlock; -+ } -+ event->pmu = pmu; -+ ret = pmu->event_init(event); -+ if (!ret) -+ goto unlock; -+ -+ if (ret != -ENOENT) { -+ pmu = ERR_PTR(ret); -+ goto unlock; -+ } -+ } -+ pmu = ERR_PTR(-ENOENT); -+unlock: -+ srcu_read_unlock(&pmus_srcu, idx); -+ -+ return pmu; -+} -+ -+static void account_event_cpu(struct perf_event *event, int cpu) -+{ -+ if (event->parent) -+ return; -+ -+ if (has_branch_stack(event)) { -+ if (!(event->attach_state & PERF_ATTACH_TASK)) -+ atomic_inc(&per_cpu(perf_branch_stack_events, cpu)); -+ } -+ if (is_cgroup_event(event)) -+ atomic_inc(&per_cpu(perf_cgroup_events, cpu)); -+} -+ -+static void account_event(struct perf_event *event) -+{ -+ if (event->parent) -+ return; -+ -+ if (event->attach_state & PERF_ATTACH_TASK) -+ static_key_slow_inc(&perf_sched_events.key); -+ if (event->attr.mmap || event->attr.mmap_data) -+ atomic_inc(&nr_mmap_events); -+ if (event->attr.comm) -+ atomic_inc(&nr_comm_events); -+ if (event->attr.task) -+ atomic_inc(&nr_task_events); -+ if (event->attr.freq) { -+ if (atomic_inc_return(&nr_freq_events) == 1) -+ tick_nohz_full_kick_all(); -+ } -+ if (has_branch_stack(event)) -+ static_key_slow_inc(&perf_sched_events.key); -+ if (is_cgroup_event(event)) -+ static_key_slow_inc(&perf_sched_events.key); -+ -+ account_event_cpu(event, event->cpu); -+} -+ -+/* -+ * Allocate and initialize a event structure -+ */ -+static struct perf_event * -+perf_event_alloc(struct perf_event_attr *attr, int cpu, -+ struct task_struct *task, -+ struct perf_event *group_leader, -+ struct perf_event *parent_event, -+ perf_overflow_handler_t overflow_handler, -+ void *context) -+{ -+ struct pmu *pmu; -+ struct perf_event *event; -+ struct hw_perf_event *hwc; -+ long err = -EINVAL; -+ -+ if ((unsigned)cpu >= nr_cpu_ids) { -+ if (!task || cpu != -1) -+ return ERR_PTR(-EINVAL); -+ } -+ -+ event = kzalloc(sizeof(*event), GFP_KERNEL); -+ if (!event) -+ return ERR_PTR(-ENOMEM); -+ -+ /* -+ * Single events are their own group leaders, with an -+ * empty sibling list: -+ */ -+ if (!group_leader) -+ group_leader = event; -+ -+ mutex_init(&event->child_mutex); -+ INIT_LIST_HEAD(&event->child_list); -+ -+ INIT_LIST_HEAD(&event->group_entry); -+ INIT_LIST_HEAD(&event->event_entry); -+ INIT_LIST_HEAD(&event->sibling_list); -+ INIT_LIST_HEAD(&event->rb_entry); -+ INIT_LIST_HEAD(&event->active_entry); -+ INIT_HLIST_NODE(&event->hlist_entry); -+ -+ -+ init_waitqueue_head(&event->waitq); -+ init_irq_work(&event->pending, perf_pending_event); -+ -+ mutex_init(&event->mmap_mutex); -+ -+ atomic_long_set(&event->refcount, 1); -+ event->cpu = cpu; -+ event->attr = *attr; -+ event->group_leader = group_leader; -+ event->pmu = NULL; -+ event->oncpu = -1; -+ -+ event->parent = parent_event; -+ -+ event->ns = get_pid_ns(task_active_pid_ns(current)); -+ event->id = atomic64_inc_return(&perf_event_id); -+ -+ event->state = PERF_EVENT_STATE_INACTIVE; -+ -+ if (task) { -+ event->attach_state = PERF_ATTACH_TASK; -+ -+ if (attr->type == PERF_TYPE_TRACEPOINT) -+ event->hw.tp_target = task; -+#ifdef CONFIG_HAVE_HW_BREAKPOINT -+ /* -+ * hw_breakpoint is a bit difficult here.. -+ */ -+ else if (attr->type == PERF_TYPE_BREAKPOINT) -+ event->hw.bp_target = task; -+#endif -+ } -+ -+ if (!overflow_handler && parent_event) { -+ overflow_handler = parent_event->overflow_handler; -+ context = parent_event->overflow_handler_context; -+ } -+ -+ event->overflow_handler = overflow_handler; -+ event->overflow_handler_context = context; -+ -+ perf_event__state_init(event); -+ -+ pmu = NULL; -+ -+ hwc = &event->hw; -+ hwc->sample_period = attr->sample_period; -+ if (attr->freq && attr->sample_freq) -+ hwc->sample_period = 1; -+ hwc->last_period = hwc->sample_period; -+ -+ local64_set(&hwc->period_left, hwc->sample_period); -+ -+ /* -+ * we currently do not support PERF_FORMAT_GROUP on inherited events -+ */ -+ if (attr->inherit && (attr->read_format & PERF_FORMAT_GROUP)) -+ goto err_ns; -+ -+ pmu = perf_init_event(event); -+ if (!pmu) -+ goto err_ns; -+ else if (IS_ERR(pmu)) { -+ err = PTR_ERR(pmu); -+ goto err_ns; -+ } -+ -+ if (!event->parent) { -+ if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) { -+ err = get_callchain_buffers(); -+ if (err) -+ goto err_pmu; -+ } -+ } -+ -+ return event; -+ -+err_pmu: -+ if (event->destroy) -+ event->destroy(event); -+ module_put(pmu->module); -+err_ns: -+ if (event->ns) -+ put_pid_ns(event->ns); -+ kfree(event); -+ -+ return ERR_PTR(err); -+} -+ -+static int perf_copy_attr(struct perf_event_attr __user *uattr, -+ struct perf_event_attr *attr) -+{ -+ u32 size; -+ int ret; -+ -+ if (!access_ok(VERIFY_WRITE, uattr, PERF_ATTR_SIZE_VER0)) -+ return -EFAULT; -+ -+ /* -+ * zero the full structure, so that a short copy will be nice. -+ */ -+ memset(attr, 0, sizeof(*attr)); -+ -+ ret = get_user(size, &uattr->size); -+ if (ret) -+ return ret; -+ -+ if (size > PAGE_SIZE) /* silly large */ -+ goto err_size; -+ -+ if (!size) /* abi compat */ -+ size = PERF_ATTR_SIZE_VER0; -+ -+ if (size < PERF_ATTR_SIZE_VER0) -+ goto err_size; -+ -+ /* -+ * If we're handed a bigger struct than we know of, -+ * ensure all the unknown bits are 0 - i.e. new -+ * user-space does not rely on any kernel feature -+ * extensions we dont know about yet. -+ */ -+ if (size > sizeof(*attr)) { -+ unsigned char __user *addr; -+ unsigned char __user *end; -+ unsigned char val; -+ -+ addr = (void __user *)uattr + sizeof(*attr); -+ end = (void __user *)uattr + size; -+ -+ for (; addr < end; addr++) { -+ ret = get_user(val, addr); -+ if (ret) -+ return ret; -+ if (val) -+ goto err_size; -+ } -+ size = sizeof(*attr); -+ } -+ -+ ret = copy_from_user(attr, uattr, size); -+ if (ret) -+ return -EFAULT; -+ -+ if (attr->__reserved_1) -+ return -EINVAL; -+ -+ if (attr->sample_type & ~(PERF_SAMPLE_MAX-1)) -+ return -EINVAL; -+ -+ if (attr->read_format & ~(PERF_FORMAT_MAX-1)) -+ return -EINVAL; -+ -+ if (attr->sample_type & PERF_SAMPLE_BRANCH_STACK) { -+ u64 mask = attr->branch_sample_type; -+ -+ /* only using defined bits */ -+ if (mask & ~(PERF_SAMPLE_BRANCH_MAX-1)) -+ return -EINVAL; -+ -+ /* at least one branch bit must be set */ -+ if (!(mask & ~PERF_SAMPLE_BRANCH_PLM_ALL)) -+ return -EINVAL; -+ -+ /* propagate priv level, when not set for branch */ -+ if (!(mask & PERF_SAMPLE_BRANCH_PLM_ALL)) { -+ -+ /* exclude_kernel checked on syscall entry */ -+ if (!attr->exclude_kernel) -+ mask |= PERF_SAMPLE_BRANCH_KERNEL; -+ -+ if (!attr->exclude_user) -+ mask |= PERF_SAMPLE_BRANCH_USER; -+ -+ if (!attr->exclude_hv) -+ mask |= PERF_SAMPLE_BRANCH_HV; -+ /* -+ * adjust user setting (for HW filter setup) -+ */ -+ attr->branch_sample_type = mask; -+ } -+ /* privileged levels capture (kernel, hv): check permissions */ -+ if ((mask & PERF_SAMPLE_BRANCH_PERM_PLM) -+ && perf_paranoid_kernel() && !capable(CAP_SYS_ADMIN)) -+ return -EACCES; -+ } -+ -+ if (attr->sample_type & PERF_SAMPLE_REGS_USER) { -+ ret = perf_reg_validate(attr->sample_regs_user); -+ if (ret) -+ return ret; -+ } -+ -+ if (attr->sample_type & PERF_SAMPLE_STACK_USER) { -+ if (!arch_perf_have_user_stack_dump()) -+ return -ENOSYS; -+ -+ /* -+ * We have __u32 type for the size, but so far -+ * we can only use __u16 as maximum due to the -+ * __u16 sample size limit. -+ */ -+ if (attr->sample_stack_user >= USHRT_MAX) -+ ret = -EINVAL; -+ else if (!IS_ALIGNED(attr->sample_stack_user, sizeof(u64))) -+ ret = -EINVAL; -+ } -+ -+out: -+ return ret; -+ -+err_size: -+ put_user(sizeof(*attr), &uattr->size); -+ ret = -E2BIG; -+ goto out; -+} -+ -+static int -+perf_event_set_output(struct perf_event *event, struct perf_event *output_event) -+{ -+ struct ring_buffer *rb = NULL; -+ int ret = -EINVAL; -+ -+ if (!output_event) -+ goto set; -+ -+ /* don't allow circular references */ -+ if (event == output_event) -+ goto out; -+ -+ /* -+ * Don't allow cross-cpu buffers -+ */ -+ if (output_event->cpu != event->cpu) -+ goto out; -+ -+ /* -+ * If its not a per-cpu rb, it must be the same task. -+ */ -+ if (output_event->cpu == -1 && output_event->ctx != event->ctx) -+ goto out; -+ -+set: -+ mutex_lock(&event->mmap_mutex); -+ /* Can't redirect output if we've got an active mmap() */ -+ if (atomic_read(&event->mmap_count)) -+ goto unlock; -+ -+ if (output_event) { -+ /* get the rb we want to redirect to */ -+ rb = ring_buffer_get(output_event); -+ if (!rb) -+ goto unlock; -+ } -+ -+ ring_buffer_attach(event, rb); -+ -+ ret = 0; -+unlock: -+ mutex_unlock(&event->mmap_mutex); -+ -+out: -+ return ret; -+} -+ -+/** -+ * sys_perf_event_open - open a performance event, associate it to a task/cpu -+ * -+ * @attr_uptr: event_id type attributes for monitoring/sampling -+ * @pid: target pid -+ * @cpu: target cpu -+ * @group_fd: group leader event fd -+ */ -+SYSCALL_DEFINE5(perf_event_open, -+ struct perf_event_attr __user *, attr_uptr, -+ pid_t, pid, int, cpu, int, group_fd, unsigned long, flags) -+{ -+ struct perf_event *group_leader = NULL, *output_event = NULL; -+ struct perf_event *event, *sibling; -+ struct perf_event_attr attr; -+ struct perf_event_context *ctx; -+ struct file *event_file = NULL; -+ struct fd group = {NULL, 0}; -+ struct task_struct *task = NULL; -+ struct pmu *pmu; -+ int event_fd; -+ int move_group = 0; -+ int err; -+ int f_flags = O_RDWR; -+ -+ /* for future expandability... */ -+ if (flags & ~PERF_FLAG_ALL) -+ return -EINVAL; -+ -+ err = perf_copy_attr(attr_uptr, &attr); -+ if (err) -+ return err; -+ -+ if (!attr.exclude_kernel) { -+ if (perf_paranoid_kernel() && !capable(CAP_SYS_ADMIN)) -+ return -EACCES; -+ } -+ -+ if (attr.freq) { -+ if (attr.sample_freq > sysctl_perf_event_sample_rate) -+ return -EINVAL; -+ } else { -+ if (attr.sample_period & (1ULL << 63)) -+ return -EINVAL; -+ } -+ -+ /* -+ * In cgroup mode, the pid argument is used to pass the fd -+ * opened to the cgroup directory in cgroupfs. The cpu argument -+ * designates the cpu on which to monitor threads from that -+ * cgroup. -+ */ -+ if ((flags & PERF_FLAG_PID_CGROUP) && (pid == -1 || cpu == -1)) -+ return -EINVAL; -+ -+ if (flags & PERF_FLAG_FD_CLOEXEC) -+ f_flags |= O_CLOEXEC; -+ -+ event_fd = get_unused_fd_flags(f_flags); -+ if (event_fd < 0) -+ return event_fd; -+ -+ if (group_fd != -1) { -+ err = perf_fget_light(group_fd, &group); -+ if (err) -+ goto err_fd; -+ group_leader = group.file->private_data; -+ if (flags & PERF_FLAG_FD_OUTPUT) -+ output_event = group_leader; -+ if (flags & PERF_FLAG_FD_NO_GROUP) -+ group_leader = NULL; -+ } -+ -+ if (pid != -1 && !(flags & PERF_FLAG_PID_CGROUP)) { -+ task = find_lively_task_by_vpid(pid); -+ if (IS_ERR(task)) { -+ err = PTR_ERR(task); -+ goto err_group_fd; -+ } -+ } -+ -+ if (task && group_leader && -+ group_leader->attr.inherit != attr.inherit) { -+ err = -EINVAL; -+ goto err_task; -+ } -+ -+ get_online_cpus(); -+ -+ event = perf_event_alloc(&attr, cpu, task, group_leader, NULL, -+ NULL, NULL); -+ if (IS_ERR(event)) { -+ err = PTR_ERR(event); -+ goto err_cpus; -+ } -+ -+ if (flags & PERF_FLAG_PID_CGROUP) { -+ err = perf_cgroup_connect(pid, event, &attr, group_leader); -+ if (err) { -+ __free_event(event); -+ goto err_cpus; -+ } -+ } -+ -+ if (is_sampling_event(event)) { -+ if (event->pmu->capabilities & PERF_PMU_CAP_NO_INTERRUPT) { -+ err = -ENOTSUPP; -+ goto err_alloc; -+ } -+ } -+ -+ account_event(event); -+ -+ /* -+ * Special case software events and allow them to be part of -+ * any hardware group. -+ */ -+ pmu = event->pmu; -+ -+ if (group_leader && -+ (is_software_event(event) != is_software_event(group_leader))) { -+ if (is_software_event(event)) { -+ /* -+ * If event and group_leader are not both a software -+ * event, and event is, then group leader is not. -+ * -+ * Allow the addition of software events to !software -+ * groups, this is safe because software events never -+ * fail to schedule. -+ */ -+ pmu = group_leader->pmu; -+ } else if (is_software_event(group_leader) && -+ (group_leader->group_flags & PERF_GROUP_SOFTWARE)) { -+ /* -+ * In case the group is a pure software group, and we -+ * try to add a hardware event, move the whole group to -+ * the hardware context. -+ */ -+ move_group = 1; -+ } -+ } -+ -+ /* -+ * Get the target context (task or percpu): -+ */ -+ ctx = find_get_context(pmu, task, event->cpu); -+ if (IS_ERR(ctx)) { -+ err = PTR_ERR(ctx); -+ goto err_alloc; -+ } -+ -+ if (task) { -+ put_task_struct(task); -+ task = NULL; -+ } -+ -+ /* -+ * Look up the group leader (we will attach this event to it): -+ */ -+ if (group_leader) { -+ err = -EINVAL; -+ -+ /* -+ * Do not allow a recursive hierarchy (this new sibling -+ * becoming part of another group-sibling): -+ */ -+ if (group_leader->group_leader != group_leader) -+ goto err_context; -+ /* -+ * Do not allow to attach to a group in a different -+ * task or CPU context: -+ */ -+ if (move_group) { -+ if (group_leader->ctx->type != ctx->type) -+ goto err_context; -+ } else { -+ if (group_leader->ctx != ctx) -+ goto err_context; -+ } -+ -+ /* -+ * Only a group leader can be exclusive or pinned -+ */ -+ if (attr.exclusive || attr.pinned) -+ goto err_context; -+ } -+ -+ if (output_event) { -+ err = perf_event_set_output(event, output_event); -+ if (err) -+ goto err_context; -+ } -+ -+ event_file = anon_inode_getfile("[perf_event]", &perf_fops, event, -+ f_flags); -+ if (IS_ERR(event_file)) { -+ err = PTR_ERR(event_file); -+ goto err_context; -+ } -+ -+ if (move_group) { -+ struct perf_event_context *gctx = group_leader->ctx; -+ -+ mutex_lock(&gctx->mutex); -+ perf_remove_from_context(group_leader, false); -+ -+ /* -+ * Removing from the context ends up with disabled -+ * event. What we want here is event in the initial -+ * startup state, ready to be add into new context. -+ */ -+ perf_event__state_init(group_leader); -+ list_for_each_entry(sibling, &group_leader->sibling_list, -+ group_entry) { -+ perf_remove_from_context(sibling, false); -+ perf_event__state_init(sibling); -+ put_ctx(gctx); -+ } -+ mutex_unlock(&gctx->mutex); -+ put_ctx(gctx); -+ } -+ -+ WARN_ON_ONCE(ctx->parent_ctx); -+ mutex_lock(&ctx->mutex); -+ -+ if (move_group) { -+ synchronize_rcu(); -+ perf_install_in_context(ctx, group_leader, group_leader->cpu); -+ get_ctx(ctx); -+ list_for_each_entry(sibling, &group_leader->sibling_list, -+ group_entry) { -+ perf_install_in_context(ctx, sibling, sibling->cpu); -+ get_ctx(ctx); -+ } -+ } -+ -+ perf_install_in_context(ctx, event, event->cpu); -+ perf_unpin_context(ctx); -+ mutex_unlock(&ctx->mutex); -+ -+ put_online_cpus(); -+ -+ event->owner = current; -+ -+ mutex_lock(¤t->perf_event_mutex); -+ list_add_tail(&event->owner_entry, ¤t->perf_event_list); -+ mutex_unlock(¤t->perf_event_mutex); -+ -+ /* -+ * Precalculate sample_data sizes -+ */ -+ perf_event__header_size(event); -+ perf_event__id_header_size(event); -+ -+ /* -+ * Drop the reference on the group_event after placing the -+ * new event on the sibling_list. This ensures destruction -+ * of the group leader will find the pointer to itself in -+ * perf_group_detach(). -+ */ -+ fdput(group); -+ fd_install(event_fd, event_file); -+ return event_fd; -+ -+err_context: -+ perf_unpin_context(ctx); -+ put_ctx(ctx); -+err_alloc: -+ free_event(event); -+err_cpus: -+ put_online_cpus(); -+err_task: -+ if (task) -+ put_task_struct(task); -+err_group_fd: -+ fdput(group); -+err_fd: -+ put_unused_fd(event_fd); -+ return err; -+} -+ -+/** -+ * perf_event_create_kernel_counter -+ * -+ * @attr: attributes of the counter to create -+ * @cpu: cpu in which the counter is bound -+ * @task: task to profile (NULL for percpu) -+ */ -+struct perf_event * -+perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, -+ struct task_struct *task, -+ perf_overflow_handler_t overflow_handler, -+ void *context) -+{ -+ struct perf_event_context *ctx; -+ struct perf_event *event; -+ int err; -+ -+ /* -+ * Get the target context (task or percpu): -+ */ -+ -+ event = perf_event_alloc(attr, cpu, task, NULL, NULL, -+ overflow_handler, context); -+ if (IS_ERR(event)) { -+ err = PTR_ERR(event); -+ goto err; -+ } -+ -+ /* Mark owner so we could distinguish it from user events. */ -+ event->owner = EVENT_OWNER_KERNEL; -+ -+ account_event(event); -+ -+ ctx = find_get_context(event->pmu, task, cpu); -+ if (IS_ERR(ctx)) { -+ err = PTR_ERR(ctx); -+ goto err_free; -+ } -+ -+ WARN_ON_ONCE(ctx->parent_ctx); -+ mutex_lock(&ctx->mutex); -+ perf_install_in_context(ctx, event, cpu); -+ perf_unpin_context(ctx); -+ mutex_unlock(&ctx->mutex); -+ -+ return event; -+ -+err_free: -+ free_event(event); -+err: -+ return ERR_PTR(err); -+} -+EXPORT_SYMBOL_GPL(perf_event_create_kernel_counter); -+ -+void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu) -+{ -+ struct perf_event_context *src_ctx; -+ struct perf_event_context *dst_ctx; -+ struct perf_event *event, *tmp; -+ LIST_HEAD(events); -+ -+ src_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, src_cpu)->ctx; -+ dst_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, dst_cpu)->ctx; -+ -+ mutex_lock(&src_ctx->mutex); -+ list_for_each_entry_safe(event, tmp, &src_ctx->event_list, -+ event_entry) { -+ perf_remove_from_context(event, false); -+ unaccount_event_cpu(event, src_cpu); -+ put_ctx(src_ctx); -+ list_add(&event->migrate_entry, &events); -+ } -+ mutex_unlock(&src_ctx->mutex); -+ -+ synchronize_rcu(); -+ -+ mutex_lock(&dst_ctx->mutex); -+ list_for_each_entry_safe(event, tmp, &events, migrate_entry) { -+ list_del(&event->migrate_entry); -+ if (event->state >= PERF_EVENT_STATE_OFF) -+ event->state = PERF_EVENT_STATE_INACTIVE; -+ account_event_cpu(event, dst_cpu); -+ perf_install_in_context(dst_ctx, event, dst_cpu); -+ get_ctx(dst_ctx); -+ } -+ mutex_unlock(&dst_ctx->mutex); -+} -+EXPORT_SYMBOL_GPL(perf_pmu_migrate_context); -+ -+static void sync_child_event(struct perf_event *child_event, -+ struct task_struct *child) -+{ -+ struct perf_event *parent_event = child_event->parent; -+ u64 child_val; -+ -+ if (child_event->attr.inherit_stat) -+ perf_event_read_event(child_event, child); -+ -+ child_val = perf_event_count(child_event); -+ -+ /* -+ * Add back the child's count to the parent's count: -+ */ -+ atomic64_add(child_val, &parent_event->child_count); -+ atomic64_add(child_event->total_time_enabled, -+ &parent_event->child_total_time_enabled); -+ atomic64_add(child_event->total_time_running, -+ &parent_event->child_total_time_running); -+ -+ /* -+ * Remove this event from the parent's list -+ */ -+ WARN_ON_ONCE(parent_event->ctx->parent_ctx); -+ mutex_lock(&parent_event->child_mutex); -+ list_del_init(&child_event->child_list); -+ mutex_unlock(&parent_event->child_mutex); -+ -+ /* -+ * Make sure user/parent get notified, that we just -+ * lost one event. -+ */ -+ perf_event_wakeup(parent_event); -+ -+ /* -+ * Release the parent event, if this was the last -+ * reference to it. -+ */ -+ put_event(parent_event); -+} -+ -+static void -+__perf_event_exit_task(struct perf_event *child_event, -+ struct perf_event_context *child_ctx, -+ struct task_struct *child) -+{ -+ /* -+ * Do not destroy the 'original' grouping; because of the context -+ * switch optimization the original events could've ended up in a -+ * random child task. -+ * -+ * If we were to destroy the original group, all group related -+ * operations would cease to function properly after this random -+ * child dies. -+ * -+ * Do destroy all inherited groups, we don't care about those -+ * and being thorough is better. -+ */ -+ perf_remove_from_context(child_event, !!child_event->parent); -+ -+ /* -+ * It can happen that the parent exits first, and has events -+ * that are still around due to the child reference. These -+ * events need to be zapped. -+ */ -+ if (child_event->parent) { -+ sync_child_event(child_event, child); -+ free_event(child_event); -+ } else { -+ child_event->state = PERF_EVENT_STATE_EXIT; -+ perf_event_wakeup(child_event); -+ } -+} -+ -+static void perf_event_exit_task_context(struct task_struct *child, int ctxn) -+{ -+ struct perf_event *child_event, *next; -+ struct perf_event_context *child_ctx, *clone_ctx = NULL; -+ unsigned long flags; -+ -+ if (likely(!child->perf_event_ctxp[ctxn])) { -+ perf_event_task(child, NULL, 0); -+ return; -+ } -+ -+ local_irq_save(flags); -+ /* -+ * We can't reschedule here because interrupts are disabled, -+ * and either child is current or it is a task that can't be -+ * scheduled, so we are now safe from rescheduling changing -+ * our context. -+ */ -+ child_ctx = rcu_dereference_raw(child->perf_event_ctxp[ctxn]); -+ -+ /* -+ * Take the context lock here so that if find_get_context is -+ * reading child->perf_event_ctxp, we wait until it has -+ * incremented the context's refcount before we do put_ctx below. -+ */ -+ raw_spin_lock(&child_ctx->lock); -+ task_ctx_sched_out(child_ctx); -+ child->perf_event_ctxp[ctxn] = NULL; -+ -+ /* -+ * If this context is a clone; unclone it so it can't get -+ * swapped to another process while we're removing all -+ * the events from it. -+ */ -+ clone_ctx = unclone_ctx(child_ctx); -+ update_context_time(child_ctx); -+ raw_spin_unlock_irqrestore(&child_ctx->lock, flags); -+ -+ if (clone_ctx) -+ put_ctx(clone_ctx); -+ -+ /* -+ * Report the task dead after unscheduling the events so that we -+ * won't get any samples after PERF_RECORD_EXIT. We can however still -+ * get a few PERF_RECORD_READ events. -+ */ -+ perf_event_task(child, child_ctx, 0); -+ -+ /* -+ * We can recurse on the same lock type through: -+ * -+ * __perf_event_exit_task() -+ * sync_child_event() -+ * put_event() -+ * mutex_lock(&ctx->mutex) -+ * -+ * But since its the parent context it won't be the same instance. -+ */ -+ mutex_lock(&child_ctx->mutex); -+ -+ list_for_each_entry_safe(child_event, next, &child_ctx->event_list, event_entry) -+ __perf_event_exit_task(child_event, child_ctx, child); -+ -+ mutex_unlock(&child_ctx->mutex); -+ -+ put_ctx(child_ctx); -+} -+ -+/* -+ * When a child task exits, feed back event values to parent events. -+ */ -+void perf_event_exit_task(struct task_struct *child) -+{ -+ struct perf_event *event, *tmp; -+ int ctxn; -+ -+ mutex_lock(&child->perf_event_mutex); -+ list_for_each_entry_safe(event, tmp, &child->perf_event_list, -+ owner_entry) { -+ list_del_init(&event->owner_entry); -+ -+ /* -+ * Ensure the list deletion is visible before we clear -+ * the owner, closes a race against perf_release() where -+ * we need to serialize on the owner->perf_event_mutex. -+ */ -+ smp_wmb(); -+ event->owner = NULL; -+ } -+ mutex_unlock(&child->perf_event_mutex); -+ -+ for_each_task_context_nr(ctxn) -+ perf_event_exit_task_context(child, ctxn); -+} -+ -+static void perf_free_event(struct perf_event *event, -+ struct perf_event_context *ctx) -+{ -+ struct perf_event *parent = event->parent; -+ -+ if (WARN_ON_ONCE(!parent)) -+ return; -+ -+ mutex_lock(&parent->child_mutex); -+ list_del_init(&event->child_list); -+ mutex_unlock(&parent->child_mutex); -+ -+ put_event(parent); -+ -+ perf_group_detach(event); -+ list_del_event(event, ctx); -+ free_event(event); -+} -+ -+/* -+ * free an unexposed, unused context as created by inheritance by -+ * perf_event_init_task below, used by fork() in case of fail. -+ */ -+void perf_event_free_task(struct task_struct *task) -+{ -+ struct perf_event_context *ctx; -+ struct perf_event *event, *tmp; -+ int ctxn; -+ -+ for_each_task_context_nr(ctxn) { -+ ctx = task->perf_event_ctxp[ctxn]; -+ if (!ctx) -+ continue; -+ -+ mutex_lock(&ctx->mutex); -+again: -+ list_for_each_entry_safe(event, tmp, &ctx->pinned_groups, -+ group_entry) -+ perf_free_event(event, ctx); -+ -+ list_for_each_entry_safe(event, tmp, &ctx->flexible_groups, -+ group_entry) -+ perf_free_event(event, ctx); -+ -+ if (!list_empty(&ctx->pinned_groups) || -+ !list_empty(&ctx->flexible_groups)) -+ goto again; -+ -+ mutex_unlock(&ctx->mutex); -+ -+ put_ctx(ctx); -+ } -+} -+ -+void perf_event_delayed_put(struct task_struct *task) -+{ -+ int ctxn; -+ -+ for_each_task_context_nr(ctxn) -+ WARN_ON_ONCE(task->perf_event_ctxp[ctxn]); -+} -+ -+/* -+ * inherit a event from parent task to child task: -+ */ -+static struct perf_event * -+inherit_event(struct perf_event *parent_event, -+ struct task_struct *parent, -+ struct perf_event_context *parent_ctx, -+ struct task_struct *child, -+ struct perf_event *group_leader, -+ struct perf_event_context *child_ctx) -+{ -+ enum perf_event_active_state parent_state = parent_event->state; -+ struct perf_event *child_event; -+ unsigned long flags; -+ -+ /* -+ * Instead of creating recursive hierarchies of events, -+ * we link inherited events back to the original parent, -+ * which has a filp for sure, which we use as the reference -+ * count: -+ */ -+ if (parent_event->parent) -+ parent_event = parent_event->parent; -+ -+ child_event = perf_event_alloc(&parent_event->attr, -+ parent_event->cpu, -+ child, -+ group_leader, parent_event, -+ NULL, NULL); -+ if (IS_ERR(child_event)) -+ return child_event; -+ -+ if (is_orphaned_event(parent_event) || -+ !atomic_long_inc_not_zero(&parent_event->refcount)) { -+ free_event(child_event); -+ return NULL; -+ } -+ -+ get_ctx(child_ctx); -+ -+ /* -+ * Make the child state follow the state of the parent event, -+ * not its attr.disabled bit. We hold the parent's mutex, -+ * so we won't race with perf_event_{en, dis}able_family. -+ */ -+ if (parent_state >= PERF_EVENT_STATE_INACTIVE) -+ child_event->state = PERF_EVENT_STATE_INACTIVE; -+ else -+ child_event->state = PERF_EVENT_STATE_OFF; -+ -+ if (parent_event->attr.freq) { -+ u64 sample_period = parent_event->hw.sample_period; -+ struct hw_perf_event *hwc = &child_event->hw; -+ -+ hwc->sample_period = sample_period; -+ hwc->last_period = sample_period; -+ -+ local64_set(&hwc->period_left, sample_period); -+ } -+ -+ child_event->ctx = child_ctx; -+ child_event->overflow_handler = parent_event->overflow_handler; -+ child_event->overflow_handler_context -+ = parent_event->overflow_handler_context; -+ -+ /* -+ * Precalculate sample_data sizes -+ */ -+ perf_event__header_size(child_event); -+ perf_event__id_header_size(child_event); -+ -+ /* -+ * Link it up in the child's context: -+ */ -+ raw_spin_lock_irqsave(&child_ctx->lock, flags); -+ add_event_to_ctx(child_event, child_ctx); -+ raw_spin_unlock_irqrestore(&child_ctx->lock, flags); -+ -+ /* -+ * Link this into the parent event's child list -+ */ -+ WARN_ON_ONCE(parent_event->ctx->parent_ctx); -+ mutex_lock(&parent_event->child_mutex); -+ list_add_tail(&child_event->child_list, &parent_event->child_list); -+ mutex_unlock(&parent_event->child_mutex); -+ -+ return child_event; -+} -+ -+static int inherit_group(struct perf_event *parent_event, -+ struct task_struct *parent, -+ struct perf_event_context *parent_ctx, -+ struct task_struct *child, -+ struct perf_event_context *child_ctx) -+{ -+ struct perf_event *leader; -+ struct perf_event *sub; -+ struct perf_event *child_ctr; -+ -+ leader = inherit_event(parent_event, parent, parent_ctx, -+ child, NULL, child_ctx); -+ if (IS_ERR(leader)) -+ return PTR_ERR(leader); -+ list_for_each_entry(sub, &parent_event->sibling_list, group_entry) { -+ child_ctr = inherit_event(sub, parent, parent_ctx, -+ child, leader, child_ctx); -+ if (IS_ERR(child_ctr)) -+ return PTR_ERR(child_ctr); -+ } -+ return 0; -+} -+ -+static int -+inherit_task_group(struct perf_event *event, struct task_struct *parent, -+ struct perf_event_context *parent_ctx, -+ struct task_struct *child, int ctxn, -+ int *inherited_all) -+{ -+ int ret; -+ struct perf_event_context *child_ctx; -+ -+ if (!event->attr.inherit) { -+ *inherited_all = 0; -+ return 0; -+ } -+ -+ child_ctx = child->perf_event_ctxp[ctxn]; -+ if (!child_ctx) { -+ /* -+ * This is executed from the parent task context, so -+ * inherit events that have been marked for cloning. -+ * First allocate and initialize a context for the -+ * child. -+ */ -+ -+ child_ctx = alloc_perf_context(parent_ctx->pmu, child); -+ if (!child_ctx) -+ return -ENOMEM; -+ -+ child->perf_event_ctxp[ctxn] = child_ctx; -+ } -+ -+ ret = inherit_group(event, parent, parent_ctx, -+ child, child_ctx); -+ -+ if (ret) -+ *inherited_all = 0; -+ -+ return ret; -+} -+ -+/* -+ * Initialize the perf_event context in task_struct -+ */ -+static int perf_event_init_context(struct task_struct *child, int ctxn) -+{ -+ struct perf_event_context *child_ctx, *parent_ctx; -+ struct perf_event_context *cloned_ctx; -+ struct perf_event *event; -+ struct task_struct *parent = current; -+ int inherited_all = 1; -+ unsigned long flags; -+ int ret = 0; -+ -+ if (likely(!parent->perf_event_ctxp[ctxn])) -+ return 0; -+ -+ /* -+ * If the parent's context is a clone, pin it so it won't get -+ * swapped under us. -+ */ -+ parent_ctx = perf_pin_task_context(parent, ctxn); -+ if (!parent_ctx) -+ return 0; -+ -+ /* -+ * No need to check if parent_ctx != NULL here; since we saw -+ * it non-NULL earlier, the only reason for it to become NULL -+ * is if we exit, and since we're currently in the middle of -+ * a fork we can't be exiting at the same time. -+ */ -+ -+ /* -+ * Lock the parent list. No need to lock the child - not PID -+ * hashed yet and not running, so nobody can access it. -+ */ -+ mutex_lock(&parent_ctx->mutex); -+ -+ /* -+ * We dont have to disable NMIs - we are only looking at -+ * the list, not manipulating it: -+ */ -+ list_for_each_entry(event, &parent_ctx->pinned_groups, group_entry) { -+ ret = inherit_task_group(event, parent, parent_ctx, -+ child, ctxn, &inherited_all); -+ if (ret) -+ break; -+ } -+ -+ /* -+ * We can't hold ctx->lock when iterating the ->flexible_group list due -+ * to allocations, but we need to prevent rotation because -+ * rotate_ctx() will change the list from interrupt context. -+ */ -+ raw_spin_lock_irqsave(&parent_ctx->lock, flags); -+ parent_ctx->rotate_disable = 1; -+ raw_spin_unlock_irqrestore(&parent_ctx->lock, flags); -+ -+ list_for_each_entry(event, &parent_ctx->flexible_groups, group_entry) { -+ ret = inherit_task_group(event, parent, parent_ctx, -+ child, ctxn, &inherited_all); -+ if (ret) -+ break; -+ } -+ -+ raw_spin_lock_irqsave(&parent_ctx->lock, flags); -+ parent_ctx->rotate_disable = 0; -+ -+ child_ctx = child->perf_event_ctxp[ctxn]; -+ -+ if (child_ctx && inherited_all) { -+ /* -+ * Mark the child context as a clone of the parent -+ * context, or of whatever the parent is a clone of. -+ * -+ * Note that if the parent is a clone, the holding of -+ * parent_ctx->lock avoids it from being uncloned. -+ */ -+ cloned_ctx = parent_ctx->parent_ctx; -+ if (cloned_ctx) { -+ child_ctx->parent_ctx = cloned_ctx; -+ child_ctx->parent_gen = parent_ctx->parent_gen; -+ } else { -+ child_ctx->parent_ctx = parent_ctx; -+ child_ctx->parent_gen = parent_ctx->generation; -+ } -+ get_ctx(child_ctx->parent_ctx); -+ } -+ -+ raw_spin_unlock_irqrestore(&parent_ctx->lock, flags); -+ mutex_unlock(&parent_ctx->mutex); -+ -+ perf_unpin_context(parent_ctx); -+ put_ctx(parent_ctx); -+ -+ return ret; -+} -+ -+/* -+ * Initialize the perf_event context in task_struct -+ */ -+int perf_event_init_task(struct task_struct *child) -+{ -+ int ctxn, ret; -+ -+ memset(child->perf_event_ctxp, 0, sizeof(child->perf_event_ctxp)); -+ mutex_init(&child->perf_event_mutex); -+ INIT_LIST_HEAD(&child->perf_event_list); -+ -+ for_each_task_context_nr(ctxn) { -+ ret = perf_event_init_context(child, ctxn); -+ if (ret) { -+ perf_event_free_task(child); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static void __init perf_event_init_all_cpus(void) -+{ -+ struct swevent_htable *swhash; -+ int cpu; -+ -+ for_each_possible_cpu(cpu) { -+ swhash = &per_cpu(swevent_htable, cpu); -+ mutex_init(&swhash->hlist_mutex); -+ INIT_LIST_HEAD(&per_cpu(rotation_list, cpu)); -+ } -+} -+ -+static void perf_event_init_cpu(int cpu) -+{ -+ struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); -+ -+ mutex_lock(&swhash->hlist_mutex); -+ swhash->online = true; -+ if (swhash->hlist_refcount > 0) { -+ struct swevent_hlist *hlist; -+ -+ hlist = kzalloc_node(sizeof(*hlist), GFP_KERNEL, cpu_to_node(cpu)); -+ WARN_ON(!hlist); -+ rcu_assign_pointer(swhash->swevent_hlist, hlist); -+ } -+ mutex_unlock(&swhash->hlist_mutex); -+} -+ -+#if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC -+static void perf_pmu_rotate_stop(struct pmu *pmu) -+{ -+ struct perf_cpu_context *cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); -+ -+ WARN_ON(!irqs_disabled()); -+ -+ list_del_init(&cpuctx->rotation_list); -+} -+ -+static void __perf_event_exit_context(void *__info) -+{ -+ struct remove_event re = { .detach_group = true }; -+ struct perf_event_context *ctx = __info; -+ -+ perf_pmu_rotate_stop(ctx->pmu); -+ -+ rcu_read_lock(); -+ list_for_each_entry_rcu(re.event, &ctx->event_list, event_entry) -+ __perf_remove_from_context(&re); -+ rcu_read_unlock(); -+} -+ -+static void perf_event_exit_cpu_context(int cpu) -+{ -+ struct perf_event_context *ctx; -+ struct pmu *pmu; -+ int idx; -+ -+ idx = srcu_read_lock(&pmus_srcu); -+ list_for_each_entry_rcu(pmu, &pmus, entry) { -+ ctx = &per_cpu_ptr(pmu->pmu_cpu_context, cpu)->ctx; -+ -+ mutex_lock(&ctx->mutex); -+ smp_call_function_single(cpu, __perf_event_exit_context, ctx, 1); -+ mutex_unlock(&ctx->mutex); -+ } -+ srcu_read_unlock(&pmus_srcu, idx); -+} -+ -+static void perf_event_exit_cpu(int cpu) -+{ -+ struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); -+ -+ perf_event_exit_cpu_context(cpu); -+ -+ mutex_lock(&swhash->hlist_mutex); -+ swhash->online = false; -+ swevent_hlist_release(swhash); -+ mutex_unlock(&swhash->hlist_mutex); -+} -+#else -+static inline void perf_event_exit_cpu(int cpu) { } -+#endif -+ -+static int -+perf_reboot(struct notifier_block *notifier, unsigned long val, void *v) -+{ -+ int cpu; -+ -+ for_each_online_cpu(cpu) -+ perf_event_exit_cpu(cpu); -+ -+ return NOTIFY_OK; -+} -+ -+/* -+ * Run the perf reboot notifier at the very last possible moment so that -+ * the generic watchdog code runs as long as possible. -+ */ -+static struct notifier_block perf_reboot_notifier = { -+ .notifier_call = perf_reboot, -+ .priority = INT_MIN, -+}; -+ -+static int -+perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) -+{ -+ unsigned int cpu = (long)hcpu; -+ -+ switch (action & ~CPU_TASKS_FROZEN) { -+ -+ case CPU_UP_PREPARE: -+ case CPU_DOWN_FAILED: -+ perf_event_init_cpu(cpu); -+ break; -+ -+ case CPU_UP_CANCELED: -+ case CPU_DOWN_PREPARE: -+ perf_event_exit_cpu(cpu); -+ break; -+ default: -+ break; -+ } -+ -+ return NOTIFY_OK; -+} -+ -+void __init perf_event_init(void) -+{ -+ int ret; -+ -+ idr_init(&pmu_idr); -+ -+ perf_event_init_all_cpus(); -+ init_srcu_struct(&pmus_srcu); -+ perf_pmu_register(&perf_swevent, "software", PERF_TYPE_SOFTWARE); -+ perf_pmu_register(&perf_cpu_clock, NULL, -1); -+ perf_pmu_register(&perf_task_clock, NULL, -1); -+ perf_tp_register(); -+ perf_cpu_notifier(perf_cpu_notify); -+ register_reboot_notifier(&perf_reboot_notifier); -+ -+ ret = init_hw_breakpoint(); -+ WARN(ret, "hw_breakpoint initialization failed with: %d", ret); -+ -+ /* do not patch jump label more than once per second */ -+ jump_label_rate_limit(&perf_sched_events, HZ); -+ -+ /* -+ * Build time assertion that we keep the data_head at the intended -+ * location. IOW, validation we got the __reserved[] size right. -+ */ -+ BUILD_BUG_ON((offsetof(struct perf_event_mmap_page, data_head)) -+ != 1024); -+} -+ -+static int __init perf_event_sysfs_init(void) -+{ -+ struct pmu *pmu; -+ int ret; -+ -+ mutex_lock(&pmus_lock); -+ -+ ret = bus_register(&pmu_bus); -+ if (ret) -+ goto unlock; -+ -+ list_for_each_entry(pmu, &pmus, entry) { -+ if (!pmu->name || pmu->type < 0) -+ continue; -+ -+ ret = pmu_dev_alloc(pmu); -+ WARN(ret, "Failed to register pmu: %s, reason %d\n", pmu->name, ret); -+ } -+ pmu_bus_running = 1; -+ ret = 0; -+ -+unlock: -+ mutex_unlock(&pmus_lock); -+ -+ return ret; -+} -+device_initcall(perf_event_sysfs_init); -+ -+#ifdef CONFIG_CGROUP_PERF -+static struct cgroup_subsys_state * -+perf_cgroup_css_alloc(struct cgroup_subsys_state *parent_css) -+{ -+ struct perf_cgroup *jc; -+ -+ jc = kzalloc(sizeof(*jc), GFP_KERNEL); -+ if (!jc) -+ return ERR_PTR(-ENOMEM); -+ -+ jc->info = alloc_percpu(struct perf_cgroup_info); -+ if (!jc->info) { -+ kfree(jc); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ return &jc->css; -+} -+ -+static void perf_cgroup_css_free(struct cgroup_subsys_state *css) -+{ -+ struct perf_cgroup *jc = container_of(css, struct perf_cgroup, css); -+ -+ free_percpu(jc->info); -+ kfree(jc); -+} -+ -+static int __perf_cgroup_move(void *info) -+{ -+ struct task_struct *task = info; -+ perf_cgroup_switch(task, PERF_CGROUP_SWOUT | PERF_CGROUP_SWIN); -+ return 0; -+} -+ -+static void perf_cgroup_attach(struct cgroup_subsys_state *css, -+ struct cgroup_taskset *tset) -+{ -+ struct task_struct *task; -+ -+ cgroup_taskset_for_each(task, tset) -+ task_function_call(task, __perf_cgroup_move, task); -+} -+ -+static void perf_cgroup_exit(struct cgroup_subsys_state *css, -+ struct cgroup_subsys_state *old_css, -+ struct task_struct *task) -+{ -+ /* -+ * cgroup_exit() is called in the copy_process() failure path. -+ * Ignore this case since the task hasn't ran yet, this avoids -+ * trying to poke a half freed task state from generic code. -+ */ -+ if (!(task->flags & PF_EXITING)) -+ return; -+ -+ task_function_call(task, __perf_cgroup_move, task); -+} -+ -+struct cgroup_subsys perf_event_cgrp_subsys = { -+ .css_alloc = perf_cgroup_css_alloc, -+ .css_free = perf_cgroup_css_free, -+ .exit = perf_cgroup_exit, -+ .attach = perf_cgroup_attach, -+}; -+#endif /* CONFIG_CGROUP_PERF */ -diff -Nur linux-3.18.12.orig/kernel/exit.c linux-3.18.12/kernel/exit.c ---- linux-3.18.12.orig/kernel/exit.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/exit.c 2015-04-26 13:32:22.431684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/exit.c linux-3.18.14-rt/kernel/exit.c +--- linux-3.18.14.orig/kernel/exit.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/exit.c 2015-05-31 15:32:48.649635365 -0500 @@ -147,7 +147,7 @@ * Do this under ->siglock, we can race with another thread * doing sigqueue_free() if we have SIGQUEUE_PREALLOC signals. @@ -20169,9 +19949,9 @@ diff -Nur linux-3.18.12.orig/kernel/exit.c linux-3.18.12/kernel/exit.c tsk->sighand = NULL; spin_unlock(&sighand->siglock); -diff -Nur linux-3.18.12.orig/kernel/fork.c linux-3.18.12/kernel/fork.c ---- linux-3.18.12.orig/kernel/fork.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/fork.c 2015-04-26 13:32:22.435684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/fork.c linux-3.18.14-rt/kernel/fork.c +--- linux-3.18.14.orig/kernel/fork.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/fork.c 2015-05-31 15:32:48.657635365 -0500 @@ -97,7 +97,7 @@ DEFINE_PER_CPU(unsigned long, process_counts) = 0; @@ -20269,9 +20049,9 @@ diff -Nur linux-3.18.12.orig/kernel/fork.c linux-3.18.12/kernel/fork.c #ifdef CONFIG_LOCKDEP p->lockdep_depth = 0; /* no locks held yet */ p->curr_chain_key = 0; -diff -Nur linux-3.18.12.orig/kernel/futex.c linux-3.18.12/kernel/futex.c ---- linux-3.18.12.orig/kernel/futex.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/futex.c 2015-04-26 13:32:22.435684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/futex.c linux-3.18.14-rt/kernel/futex.c +--- linux-3.18.14.orig/kernel/futex.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/futex.c 2015-05-31 15:32:48.665635365 -0500 @@ -738,7 +738,9 @@ * task still owns the PI-state: */ @@ -20410,9 +20190,9 @@ diff -Nur linux-3.18.12.orig/kernel/futex.c linux-3.18.12/kernel/futex.c /* * Fixup the pi_state owner and possibly acquire the lock if we * haven't already. -diff -Nur linux-3.18.12.orig/kernel/irq/handle.c linux-3.18.12/kernel/irq/handle.c ---- linux-3.18.12.orig/kernel/irq/handle.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/irq/handle.c 2015-04-26 13:32:22.435684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/irq/handle.c linux-3.18.14-rt/kernel/irq/handle.c +--- linux-3.18.14.orig/kernel/irq/handle.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/irq/handle.c 2015-05-31 15:32:48.677635365 -0500 @@ -133,6 +133,8 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) @@ -20435,9 +20215,9 @@ diff -Nur linux-3.18.12.orig/kernel/irq/handle.c linux-3.18.12/kernel/irq/handle if (!noirqdebug) note_interrupt(irq, desc, retval); -diff -Nur linux-3.18.12.orig/kernel/irq/manage.c linux-3.18.12/kernel/irq/manage.c ---- linux-3.18.12.orig/kernel/irq/manage.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/irq/manage.c 2015-04-26 13:32:22.435684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/irq/manage.c linux-3.18.14-rt/kernel/irq/manage.c +--- linux-3.18.14.orig/kernel/irq/manage.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/irq/manage.c 2015-05-31 15:32:48.697635365 -0500 @@ -22,6 +22,7 @@ #include "internals.h" @@ -20610,9 +20390,9 @@ diff -Nur linux-3.18.12.orig/kernel/irq/manage.c linux-3.18.12/kernel/irq/manage /* Set default affinity mask once everything is setup */ setup_affinity(irq, desc, mask); -diff -Nur linux-3.18.12.orig/kernel/irq/settings.h linux-3.18.12/kernel/irq/settings.h ---- linux-3.18.12.orig/kernel/irq/settings.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/irq/settings.h 2015-04-26 13:32:22.435684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/irq/settings.h linux-3.18.14-rt/kernel/irq/settings.h +--- linux-3.18.14.orig/kernel/irq/settings.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/irq/settings.h 2015-05-31 15:32:48.697635365 -0500 @@ -15,6 +15,7 @@ _IRQ_NESTED_THREAD = IRQ_NESTED_THREAD, _IRQ_PER_CPU_DEVID = IRQ_PER_CPU_DEVID, @@ -20646,9 +20426,9 @@ diff -Nur linux-3.18.12.orig/kernel/irq/settings.h linux-3.18.12/kernel/irq/sett static inline bool irq_settings_is_per_cpu(struct irq_desc *desc) { return desc->status_use_accessors & _IRQ_PER_CPU; -diff -Nur linux-3.18.12.orig/kernel/irq/spurious.c linux-3.18.12/kernel/irq/spurious.c ---- linux-3.18.12.orig/kernel/irq/spurious.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/irq/spurious.c 2015-04-26 13:32:22.435684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/irq/spurious.c linux-3.18.14-rt/kernel/irq/spurious.c +--- linux-3.18.14.orig/kernel/irq/spurious.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/irq/spurious.c 2015-05-31 15:32:48.709635364 -0500 @@ -444,6 +444,10 @@ static int __init irqfixup_setup(char *str) @@ -20671,10 +20451,10 @@ diff -Nur linux-3.18.12.orig/kernel/irq/spurious.c linux-3.18.12/kernel/irq/spur irqfixup = 2; printk(KERN_WARNING "Misrouted IRQ fixup and polling support " "enabled\n"); -diff -Nur linux-3.18.12.orig/kernel/irq_work.c linux-3.18.12/kernel/irq_work.c ---- linux-3.18.12.orig/kernel/irq_work.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/irq_work.c 2015-04-26 13:32:22.435684003 -0500 -@@ -17,12 +17,15 @@ +diff -Nur linux-3.18.14.orig/kernel/irq_work.c linux-3.18.14-rt/kernel/irq_work.c +--- linux-3.18.14.orig/kernel/irq_work.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/irq_work.c 2015-05-31 15:32:48.713635365 -0500 +@@ -17,6 +17,7 @@ #include <linux/cpu.h> #include <linux/notifier.h> #include <linux/smp.h> @@ -20682,126 +20462,116 @@ diff -Nur linux-3.18.12.orig/kernel/irq_work.c linux-3.18.12/kernel/irq_work.c #include <asm/processor.h> - static DEFINE_PER_CPU(struct llist_head, raised_list); - static DEFINE_PER_CPU(struct llist_head, lazy_list); -- -+#ifdef CONFIG_PREEMPT_RT_FULL -+static DEFINE_PER_CPU(struct llist_head, hirq_work_list); -+#endif - /* - * Claim the entry so that no one else will poke at it. - */ -@@ -65,6 +68,8 @@ +@@ -65,6 +66,8 @@ */ bool irq_work_queue_on(struct irq_work *work, int cpu) { -+ bool raise_irqwork; ++ struct llist_head *list; + /* All work should have been flushed before going offline */ WARN_ON_ONCE(cpu_is_offline(cpu)); -@@ -75,7 +80,19 @@ +@@ -75,7 +78,12 @@ if (!irq_work_claim(work)) return false; - if (llist_add(&work->llnode, &per_cpu(raised_list, cpu))) -+#ifdef CONFIG_PREEMPT_RT_FULL -+ if (work->flags & IRQ_WORK_HARD_IRQ) -+ raise_irqwork = llist_add(&work->llnode, -+ &per_cpu(hirq_work_list, cpu)); ++ if (IS_ENABLED(CONFIG_PREEMPT_RT_FULL) && !(work->flags & IRQ_WORK_HARD_IRQ)) ++ list = &per_cpu(lazy_list, cpu); + else -+ raise_irqwork = llist_add(&work->llnode, -+ &per_cpu(lazy_list, cpu)); -+#else -+ raise_irqwork = llist_add(&work->llnode, -+ &per_cpu(raised_list, cpu)); -+#endif ++ list = &per_cpu(raised_list, cpu); + -+ if (raise_irqwork) ++ if (llist_add(&work->llnode, list)) arch_send_call_function_single_ipi(cpu); return true; -@@ -93,7 +110,16 @@ +@@ -86,6 +94,9 @@ + /* Enqueue the irq work @work on the current CPU */ + bool irq_work_queue(struct irq_work *work) + { ++ struct llist_head *list; ++ bool lazy_work, realtime = IS_ENABLED(CONFIG_PREEMPT_RT_FULL); ++ + /* Only queue if not already pending */ + if (!irq_work_claim(work)) + return false; +@@ -93,13 +104,15 @@ /* Queue the entry and raise the IPI if needed. */ preempt_disable(); - /* If the work is "lazy", handle it from next tick if any */ -+#ifdef CONFIG_PREEMPT_RT_FULL -+ if (work->flags & IRQ_WORK_HARD_IRQ) { -+ if (llist_add(&work->llnode, this_cpu_ptr(&hirq_work_list))) -+ arch_irq_work_raise(); -+ } else { -+ if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list)) && -+ tick_nohz_tick_stopped()) -+ raise_softirq(TIMER_SOFTIRQ); -+ } -+#else - if (work->flags & IRQ_WORK_LAZY) { - if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list)) && - tick_nohz_tick_stopped()) -@@ -102,6 +128,7 @@ - if (llist_add(&work->llnode, this_cpu_ptr(&raised_list))) +- if (work->flags & IRQ_WORK_LAZY) { +- if (llist_add(&work->llnode, this_cpu_ptr(&lazy_list)) && +- tick_nohz_tick_stopped()) +- arch_irq_work_raise(); +- } else { +- if (llist_add(&work->llnode, this_cpu_ptr(&raised_list))) ++ lazy_work = work->flags & IRQ_WORK_LAZY; ++ ++ if (lazy_work || (realtime && !(work->flags & IRQ_WORK_HARD_IRQ))) ++ list = this_cpu_ptr(&lazy_list); ++ else ++ list = this_cpu_ptr(&raised_list); ++ ++ if (llist_add(&work->llnode, list)) { ++ if (!lazy_work || tick_nohz_tick_stopped()) arch_irq_work_raise(); } -+#endif - preempt_enable(); - -@@ -116,9 +143,12 @@ +@@ -116,9 +129,8 @@ raised = this_cpu_ptr(&raised_list); lazy = this_cpu_ptr(&lazy_list); - if (llist_empty(raised) || arch_irq_work_has_interrupt()) -+ if (llist_empty(raised)) - if (llist_empty(lazy)) +- if (llist_empty(lazy)) - return false; -+#ifdef CONFIG_PREEMPT_RT_FULL -+ if (llist_empty(this_cpu_ptr(&hirq_work_list))) -+#endif -+ return false; ++ if (llist_empty(raised) && llist_empty(lazy)) ++ return false; /* All work should have been flushed before going offline */ WARN_ON_ONCE(cpu_is_offline(smp_processor_id())); -@@ -132,7 +162,9 @@ +@@ -132,7 +144,7 @@ struct irq_work *work; struct llist_node *llnode; -+#ifndef CONFIG_PREEMPT_RT_FULL - BUG_ON(!irqs_disabled()); -+#endif +- BUG_ON(!irqs_disabled()); ++ BUG_ON(!IS_ENABLED(CONFIG_PREEMPT_RT_FULL) && !irqs_disabled()); if (llist_empty(list)) return; -@@ -168,18 +200,26 @@ - */ +@@ -169,17 +181,26 @@ void irq_work_run(void) { -+#ifdef CONFIG_PREEMPT_RT_FULL -+ irq_work_run_list(this_cpu_ptr(&hirq_work_list)); -+#else irq_work_run_list(this_cpu_ptr(&raised_list)); - irq_work_run_list(this_cpu_ptr(&lazy_list)); -+#endif +- irq_work_run_list(this_cpu_ptr(&lazy_list)); ++ if (IS_ENABLED(CONFIG_PREEMPT_RT_FULL)) { ++ /* ++ * NOTE: we raise softirq via IPI for safety, ++ * and execute in irq_work_tick() to move the ++ * overhead from hard to soft irq context. ++ */ ++ if (!llist_empty(this_cpu_ptr(&lazy_list))) ++ raise_softirq(TIMER_SOFTIRQ); ++ } else ++ irq_work_run_list(this_cpu_ptr(&lazy_list)); } EXPORT_SYMBOL_GPL(irq_work_run); void irq_work_tick(void) { -+#ifdef CONFIG_PREEMPT_RT_FULL -+ irq_work_run_list(this_cpu_ptr(&lazy_list)); -+#else - struct llist_head *raised = &__get_cpu_var(raised_list); +- struct llist_head *raised = &__get_cpu_var(raised_list); ++ struct llist_head *raised = this_cpu_ptr(&raised_list); if (!llist_empty(raised) && !arch_irq_work_has_interrupt()) irq_work_run_list(raised); - irq_work_run_list(&__get_cpu_var(lazy_list)); -+#endif +- irq_work_run_list(&__get_cpu_var(lazy_list)); ++ irq_work_run_list(this_cpu_ptr(&lazy_list)); } /* -diff -Nur linux-3.18.12.orig/kernel/Kconfig.locks linux-3.18.12/kernel/Kconfig.locks ---- linux-3.18.12.orig/kernel/Kconfig.locks 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/Kconfig.locks 2015-04-26 13:32:22.431684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/Kconfig.locks linux-3.18.14-rt/kernel/Kconfig.locks +--- linux-3.18.14.orig/kernel/Kconfig.locks 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/Kconfig.locks 2015-05-31 15:32:48.585635365 -0500 @@ -225,11 +225,11 @@ config MUTEX_SPIN_ON_OWNER @@ -20816,9 +20586,9 @@ diff -Nur linux-3.18.12.orig/kernel/Kconfig.locks linux-3.18.12/kernel/Kconfig.l config ARCH_USE_QUEUE_RWLOCK bool -diff -Nur linux-3.18.12.orig/kernel/Kconfig.preempt linux-3.18.12/kernel/Kconfig.preempt ---- linux-3.18.12.orig/kernel/Kconfig.preempt 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/Kconfig.preempt 2015-04-26 13:32:22.431684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/Kconfig.preempt linux-3.18.14-rt/kernel/Kconfig.preempt +--- linux-3.18.14.orig/kernel/Kconfig.preempt 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/Kconfig.preempt 2015-05-31 15:32:48.589635366 -0500 @@ -1,3 +1,16 @@ +config PREEMPT + bool @@ -20871,9 +20641,9 @@ diff -Nur linux-3.18.12.orig/kernel/Kconfig.preempt linux-3.18.12/kernel/Kconfig endchoice config PREEMPT_COUNT -diff -Nur linux-3.18.12.orig/kernel/ksysfs.c linux-3.18.12/kernel/ksysfs.c ---- linux-3.18.12.orig/kernel/ksysfs.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/ksysfs.c 2015-04-26 13:32:22.435684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/ksysfs.c linux-3.18.14-rt/kernel/ksysfs.c +--- linux-3.18.14.orig/kernel/ksysfs.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/ksysfs.c 2015-05-31 15:32:48.733635364 -0500 @@ -136,6 +136,15 @@ #endif /* CONFIG_KEXEC */ @@ -20900,9 +20670,9 @@ diff -Nur linux-3.18.12.orig/kernel/ksysfs.c linux-3.18.12/kernel/ksysfs.c NULL }; -diff -Nur linux-3.18.12.orig/kernel/locking/lglock.c linux-3.18.12/kernel/locking/lglock.c ---- linux-3.18.12.orig/kernel/locking/lglock.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/locking/lglock.c 2015-04-26 13:32:22.435684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/locking/lglock.c linux-3.18.14-rt/kernel/locking/lglock.c +--- linux-3.18.14.orig/kernel/locking/lglock.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/locking/lglock.c 2015-05-31 15:32:48.749635364 -0500 @@ -4,6 +4,15 @@ #include <linux/cpu.h> #include <linux/string.h> @@ -21047,9 +20817,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/lglock.c linux-3.18.12/kernel/lockin + } +} +#endif -diff -Nur linux-3.18.12.orig/kernel/locking/lockdep.c linux-3.18.12/kernel/locking/lockdep.c ---- linux-3.18.12.orig/kernel/locking/lockdep.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/locking/lockdep.c 2015-04-26 13:32:22.435684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/locking/lockdep.c linux-3.18.14-rt/kernel/locking/lockdep.c +--- linux-3.18.14.orig/kernel/locking/lockdep.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/locking/lockdep.c 2015-05-31 15:32:48.749635364 -0500 @@ -3542,6 +3542,7 @@ } } @@ -21066,9 +20836,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/lockdep.c linux-3.18.12/kernel/locki if (!debug_locks) print_irqtrace_events(current); -diff -Nur linux-3.18.12.orig/kernel/locking/Makefile linux-3.18.12/kernel/locking/Makefile ---- linux-3.18.12.orig/kernel/locking/Makefile 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/locking/Makefile 2015-04-26 13:32:22.435684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/locking/Makefile linux-3.18.14-rt/kernel/locking/Makefile +--- linux-3.18.14.orig/kernel/locking/Makefile 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/locking/Makefile 2015-05-31 15:32:48.737635364 -0500 @@ -1,5 +1,5 @@ -obj-y += mutex.o semaphore.o rwsem.o mcs_spinlock.o @@ -21100,9 +20870,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/Makefile linux-3.18.12/kernel/lockin +obj-$(CONFIG_PREEMPT_RT_FULL) += rt.o obj-$(CONFIG_QUEUE_RWLOCK) += qrwlock.o obj-$(CONFIG_LOCK_TORTURE_TEST) += locktorture.o -diff -Nur linux-3.18.12.orig/kernel/locking/percpu-rwsem.c linux-3.18.12/kernel/locking/percpu-rwsem.c ---- linux-3.18.12.orig/kernel/locking/percpu-rwsem.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/locking/percpu-rwsem.c 2015-04-26 13:32:22.435684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/locking/percpu-rwsem.c linux-3.18.14-rt/kernel/locking/percpu-rwsem.c +--- linux-3.18.14.orig/kernel/locking/percpu-rwsem.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/locking/percpu-rwsem.c 2015-05-31 15:32:48.757635364 -0500 @@ -84,8 +84,12 @@ down_read(&brw->rw_sem); @@ -21116,9 +20886,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/percpu-rwsem.c linux-3.18.12/kernel/ } void percpu_up_read(struct percpu_rw_semaphore *brw) -diff -Nur linux-3.18.12.orig/kernel/locking/rt.c linux-3.18.12/kernel/locking/rt.c ---- linux-3.18.12.orig/kernel/locking/rt.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/kernel/locking/rt.c 2015-04-26 13:32:22.435684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/locking/rt.c linux-3.18.14-rt/kernel/locking/rt.c +--- linux-3.18.14.orig/kernel/locking/rt.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/kernel/locking/rt.c 2015-05-31 15:32:48.757635364 -0500 @@ -0,0 +1,456 @@ +/* + * kernel/rt.c @@ -21576,9 +21346,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/rt.c linux-3.18.12/kernel/locking/rt + return 1; +} +EXPORT_SYMBOL(atomic_dec_and_mutex_lock); -diff -Nur linux-3.18.12.orig/kernel/locking/rtmutex.c linux-3.18.12/kernel/locking/rtmutex.c ---- linux-3.18.12.orig/kernel/locking/rtmutex.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/locking/rtmutex.c 2015-04-26 13:32:22.439684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/locking/rtmutex.c linux-3.18.14-rt/kernel/locking/rtmutex.c +--- linux-3.18.14.orig/kernel/locking/rtmutex.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/locking/rtmutex.c 2015-05-31 15:32:48.769635364 -0500 @@ -7,6 +7,11 @@ * Copyright (C) 2005-2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com> * Copyright (C) 2005 Kihon Technologies Inc., Steven Rostedt @@ -22608,9 +22378,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/rtmutex.c linux-3.18.12/kernel/locki +} +EXPORT_SYMBOL(ww_mutex_unlock); +#endif -diff -Nur linux-3.18.12.orig/kernel/locking/rtmutex_common.h linux-3.18.12/kernel/locking/rtmutex_common.h ---- linux-3.18.12.orig/kernel/locking/rtmutex_common.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/locking/rtmutex_common.h 2015-04-26 13:32:22.439684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/locking/rtmutex_common.h linux-3.18.14-rt/kernel/locking/rtmutex_common.h +--- linux-3.18.14.orig/kernel/locking/rtmutex_common.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/locking/rtmutex_common.h 2015-05-31 15:32:48.769635364 -0500 @@ -49,6 +49,7 @@ struct rb_node pi_tree_entry; struct task_struct *task; @@ -22644,9 +22414,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/rtmutex_common.h linux-3.18.12/kerne +} + #endif -diff -Nur linux-3.18.12.orig/kernel/locking/spinlock.c linux-3.18.12/kernel/locking/spinlock.c ---- linux-3.18.12.orig/kernel/locking/spinlock.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/locking/spinlock.c 2015-04-26 13:32:22.439684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/locking/spinlock.c linux-3.18.14-rt/kernel/locking/spinlock.c +--- linux-3.18.14.orig/kernel/locking/spinlock.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/locking/spinlock.c 2015-05-31 15:32:48.769635364 -0500 @@ -124,8 +124,11 @@ * __[spin|read|write]_lock_bh() */ @@ -22677,9 +22447,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/spinlock.c linux-3.18.12/kernel/lock #ifdef CONFIG_DEBUG_LOCK_ALLOC void __lockfunc _raw_spin_lock_nested(raw_spinlock_t *lock, int subclass) -diff -Nur linux-3.18.12.orig/kernel/locking/spinlock_debug.c linux-3.18.12/kernel/locking/spinlock_debug.c ---- linux-3.18.12.orig/kernel/locking/spinlock_debug.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/locking/spinlock_debug.c 2015-04-26 13:32:22.439684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/locking/spinlock_debug.c linux-3.18.14-rt/kernel/locking/spinlock_debug.c +--- linux-3.18.14.orig/kernel/locking/spinlock_debug.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/locking/spinlock_debug.c 2015-05-31 15:32:48.793635364 -0500 @@ -31,6 +31,7 @@ EXPORT_SYMBOL(__raw_spin_lock_init); @@ -22710,9 +22480,9 @@ diff -Nur linux-3.18.12.orig/kernel/locking/spinlock_debug.c linux-3.18.12/kerne } + +#endif -diff -Nur linux-3.18.12.orig/kernel/panic.c linux-3.18.12/kernel/panic.c ---- linux-3.18.12.orig/kernel/panic.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/panic.c 2015-04-26 13:32:22.439684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/panic.c linux-3.18.14-rt/kernel/panic.c +--- linux-3.18.14.orig/kernel/panic.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/panic.c 2015-05-31 15:32:48.793635364 -0500 @@ -384,9 +384,11 @@ static int init_oops_id(void) @@ -22725,9 +22495,9 @@ diff -Nur linux-3.18.12.orig/kernel/panic.c linux-3.18.12/kernel/panic.c oops_id++; return 0; -diff -Nur linux-3.18.12.orig/kernel/power/hibernate.c linux-3.18.12/kernel/power/hibernate.c ---- linux-3.18.12.orig/kernel/power/hibernate.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/power/hibernate.c 2015-04-26 13:32:22.439684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/power/hibernate.c linux-3.18.14-rt/kernel/power/hibernate.c +--- linux-3.18.14.orig/kernel/power/hibernate.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/power/hibernate.c 2015-05-31 15:32:48.797635364 -0500 @@ -287,6 +287,8 @@ local_irq_disable(); @@ -22777,9 +22547,9 @@ diff -Nur linux-3.18.12.orig/kernel/power/hibernate.c linux-3.18.12/kernel/power local_irq_enable(); enable_nonboot_cpus(); -diff -Nur linux-3.18.12.orig/kernel/power/suspend.c linux-3.18.12/kernel/power/suspend.c ---- linux-3.18.12.orig/kernel/power/suspend.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/power/suspend.c 2015-04-26 13:32:22.439684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/power/suspend.c linux-3.18.14-rt/kernel/power/suspend.c +--- linux-3.18.14.orig/kernel/power/suspend.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/power/suspend.c 2015-05-31 15:32:48.797635364 -0500 @@ -318,6 +318,8 @@ arch_suspend_disable_irqs(); BUG_ON(!irqs_disabled()); @@ -22798,9 +22568,9 @@ diff -Nur linux-3.18.12.orig/kernel/power/suspend.c linux-3.18.12/kernel/power/s arch_suspend_enable_irqs(); BUG_ON(irqs_disabled()); -diff -Nur linux-3.18.12.orig/kernel/printk/printk.c linux-3.18.12/kernel/printk/printk.c ---- linux-3.18.12.orig/kernel/printk/printk.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/printk/printk.c 2015-04-26 13:32:22.439684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/printk/printk.c linux-3.18.14-rt/kernel/printk/printk.c +--- linux-3.18.14.orig/kernel/printk/printk.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/printk/printk.c 2015-05-31 15:32:48.801635363 -0500 @@ -1165,6 +1165,7 @@ { char *text; @@ -23056,9 +22826,9 @@ diff -Nur linux-3.18.12.orig/kernel/printk/printk.c linux-3.18.12/kernel/printk/ } console_locked = 0; -diff -Nur linux-3.18.12.orig/kernel/ptrace.c linux-3.18.12/kernel/ptrace.c ---- linux-3.18.12.orig/kernel/ptrace.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/ptrace.c 2015-04-26 13:32:22.439684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/ptrace.c linux-3.18.14-rt/kernel/ptrace.c +--- linux-3.18.14.orig/kernel/ptrace.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/ptrace.c 2015-05-31 15:32:48.801635363 -0500 @@ -129,7 +129,12 @@ spin_lock_irq(&task->sighand->siglock); @@ -23073,9 +22843,9 @@ diff -Nur linux-3.18.12.orig/kernel/ptrace.c linux-3.18.12/kernel/ptrace.c ret = true; } spin_unlock_irq(&task->sighand->siglock); -diff -Nur linux-3.18.12.orig/kernel/rcu/tiny.c linux-3.18.12/kernel/rcu/tiny.c ---- linux-3.18.12.orig/kernel/rcu/tiny.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/rcu/tiny.c 2015-04-26 13:32:22.439684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/rcu/tiny.c linux-3.18.14-rt/kernel/rcu/tiny.c +--- linux-3.18.14.orig/kernel/rcu/tiny.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/rcu/tiny.c 2015-05-31 15:32:48.801635363 -0500 @@ -370,6 +370,7 @@ } EXPORT_SYMBOL_GPL(call_rcu_sched); @@ -23092,9 +22862,9 @@ diff -Nur linux-3.18.12.orig/kernel/rcu/tiny.c linux-3.18.12/kernel/rcu/tiny.c void rcu_init(void) { -diff -Nur linux-3.18.12.orig/kernel/rcu/tree.c linux-3.18.12/kernel/rcu/tree.c ---- linux-3.18.12.orig/kernel/rcu/tree.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/rcu/tree.c 2015-04-26 13:32:22.439684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/rcu/tree.c linux-3.18.14-rt/kernel/rcu/tree.c +--- linux-3.18.14.orig/kernel/rcu/tree.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/rcu/tree.c 2015-05-31 15:32:48.805635363 -0500 @@ -56,6 +56,11 @@ #include <linux/random.h> #include <linux/ftrace_event.h> @@ -23397,9 +23167,9 @@ diff -Nur linux-3.18.12.orig/kernel/rcu/tree.c linux-3.18.12/kernel/rcu/tree.c /* * We don't need protection against CPU-hotplug here because -diff -Nur linux-3.18.12.orig/kernel/rcu/tree.h linux-3.18.12/kernel/rcu/tree.h ---- linux-3.18.12.orig/kernel/rcu/tree.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/rcu/tree.h 2015-04-26 13:32:22.443684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/rcu/tree.h linux-3.18.14-rt/kernel/rcu/tree.h +--- linux-3.18.14.orig/kernel/rcu/tree.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/rcu/tree.h 2015-05-31 15:32:48.809635364 -0500 @@ -28,6 +28,7 @@ #include <linux/cpumask.h> #include <linux/seqlock.h> @@ -23459,9 +23229,9 @@ diff -Nur linux-3.18.12.orig/kernel/rcu/tree.h linux-3.18.12/kernel/rcu/tree.h static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp, struct rcu_node *rnp); #endif /* #ifdef CONFIG_RCU_BOOST */ -diff -Nur linux-3.18.12.orig/kernel/rcu/tree_plugin.h linux-3.18.12/kernel/rcu/tree_plugin.h ---- linux-3.18.12.orig/kernel/rcu/tree_plugin.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/rcu/tree_plugin.h 2015-04-26 13:32:22.443684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/rcu/tree_plugin.h linux-3.18.14-rt/kernel/rcu/tree_plugin.h +--- linux-3.18.14.orig/kernel/rcu/tree_plugin.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/rcu/tree_plugin.h 2015-05-31 15:32:48.829635363 -0500 @@ -24,12 +24,6 @@ * Paul E. McKenney <paulmck@linux.vnet.ibm.com> */ @@ -23807,9 +23577,9 @@ diff -Nur linux-3.18.12.orig/kernel/rcu/tree_plugin.h linux-3.18.12/kernel/rcu/t rdp->nocb_follower_tail = &rdp->nocb_follower_head; } -diff -Nur linux-3.18.12.orig/kernel/rcu/update.c linux-3.18.12/kernel/rcu/update.c ---- linux-3.18.12.orig/kernel/rcu/update.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/rcu/update.c 2015-04-26 13:32:22.443684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/rcu/update.c linux-3.18.14-rt/kernel/rcu/update.c +--- linux-3.18.14.orig/kernel/rcu/update.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/rcu/update.c 2015-05-31 15:32:48.829635363 -0500 @@ -170,6 +170,7 @@ } EXPORT_SYMBOL_GPL(rcu_read_lock_held); @@ -23826,9 +23596,9 @@ diff -Nur linux-3.18.12.orig/kernel/rcu/update.c linux-3.18.12/kernel/rcu/update #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ -diff -Nur linux-3.18.12.orig/kernel/relay.c linux-3.18.12/kernel/relay.c ---- linux-3.18.12.orig/kernel/relay.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/relay.c 2015-04-26 13:32:22.443684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/relay.c linux-3.18.14-rt/kernel/relay.c +--- linux-3.18.14.orig/kernel/relay.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/relay.c 2015-05-31 15:32:48.829635363 -0500 @@ -339,6 +339,10 @@ { struct rchan_buf *buf = (struct rchan_buf *)data; @@ -23864,9 +23634,9 @@ diff -Nur linux-3.18.12.orig/kernel/relay.c linux-3.18.12/kernel/relay.c } old = buf->data; -diff -Nur linux-3.18.12.orig/kernel/res_counter.c linux-3.18.12/kernel/res_counter.c ---- linux-3.18.12.orig/kernel/res_counter.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/res_counter.c 2015-04-26 13:32:22.443684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/res_counter.c linux-3.18.14-rt/kernel/res_counter.c +--- linux-3.18.14.orig/kernel/res_counter.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/res_counter.c 2015-05-31 15:32:48.845635363 -0500 @@ -59,7 +59,7 @@ r = ret = 0; @@ -23903,9 +23673,9 @@ diff -Nur linux-3.18.12.orig/kernel/res_counter.c linux-3.18.12/kernel/res_count return ret; } -diff -Nur linux-3.18.12.orig/kernel/sched/completion.c linux-3.18.12/kernel/sched/completion.c ---- linux-3.18.12.orig/kernel/sched/completion.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/sched/completion.c 2015-04-26 13:32:22.443684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/sched/completion.c linux-3.18.14-rt/kernel/sched/completion.c +--- linux-3.18.14.orig/kernel/sched/completion.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/sched/completion.c 2015-05-31 15:32:48.889635363 -0500 @@ -30,10 +30,10 @@ { unsigned long flags; @@ -24000,9 +23770,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/completion.c linux-3.18.12/kernel/sche return ret; } EXPORT_SYMBOL(completion_done); -diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core.c ---- linux-3.18.12.orig/kernel/sched/core.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/sched/core.c 2015-04-26 13:32:22.443684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/sched/core.c linux-3.18.14-rt/kernel/sched/core.c +--- linux-3.18.14.orig/kernel/sched/core.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/sched/core.c 2015-05-31 15:32:48.893635363 -0500 @@ -280,7 +280,11 @@ * Number of tasks to iterate in a single balance run. * Limited because this is done with IRQs disabled. @@ -24529,16 +24299,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core __preempt_count_sub(PREEMPT_ACTIVE); /* -@@ -3097,6 +3316,8 @@ - } else { - if (dl_prio(oldprio)) - p->dl.dl_boosted = 0; -+ if (rt_prio(oldprio)) -+ p->rt.timeout = 0; - p->sched_class = &fair_sched_class; - } - -@@ -4234,9 +4455,16 @@ +@@ -4236,9 +4455,16 @@ static void __cond_resched(void) { @@ -24558,7 +24319,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core } int __sched _cond_resched(void) -@@ -4277,6 +4505,7 @@ +@@ -4279,6 +4505,7 @@ } EXPORT_SYMBOL(__cond_resched_lock); @@ -24566,7 +24327,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core int __sched __cond_resched_softirq(void) { BUG_ON(!in_softirq()); -@@ -4290,6 +4519,7 @@ +@@ -4292,6 +4519,7 @@ return 0; } EXPORT_SYMBOL(__cond_resched_softirq); @@ -24574,7 +24335,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core /** * yield - yield the current processor to other threads. -@@ -4651,7 +4881,9 @@ +@@ -4653,7 +4881,9 @@ /* Set the preempt count _outside_ the spinlocks! */ init_idle_preempt_count(idle, cpu); @@ -24585,7 +24346,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core /* * The idle tasks have their own, simple scheduling class: */ -@@ -4693,11 +4925,91 @@ +@@ -4695,11 +4925,91 @@ void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask) { @@ -24680,7 +24441,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core } /* -@@ -4743,7 +5055,7 @@ +@@ -4745,7 +5055,7 @@ do_set_cpus_allowed(p, new_mask); /* Can the task run on the task's current CPU? If so, we're done */ @@ -24689,7 +24450,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core goto out; dest_cpu = cpumask_any_and(cpu_active_mask, new_mask); -@@ -4883,6 +5195,8 @@ +@@ -4885,6 +5195,8 @@ #ifdef CONFIG_HOTPLUG_CPU @@ -24698,7 +24459,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core /* * Ensures that the idle task is using init_mm right before its cpu goes * offline. -@@ -4897,7 +5211,11 @@ +@@ -4899,7 +5211,11 @@ switch_mm(mm, &init_mm, current); finish_arch_post_lock_switch(); } @@ -24711,7 +24472,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core } /* -@@ -5240,6 +5558,10 @@ +@@ -5242,6 +5558,10 @@ case CPU_DEAD: calc_load_migrate(rq); @@ -24722,7 +24483,7 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core break; #endif } -@@ -7181,7 +7503,8 @@ +@@ -7183,7 +7503,8 @@ #ifdef CONFIG_DEBUG_ATOMIC_SLEEP static inline int preempt_count_equals(int preempt_offset) { @@ -24732,9 +24493,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/core.c linux-3.18.12/kernel/sched/core return (nested == preempt_offset); } -diff -Nur linux-3.18.12.orig/kernel/sched/cputime.c linux-3.18.12/kernel/sched/cputime.c ---- linux-3.18.12.orig/kernel/sched/cputime.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/sched/cputime.c 2015-04-26 13:32:22.443684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/sched/cputime.c linux-3.18.14-rt/kernel/sched/cputime.c +--- linux-3.18.14.orig/kernel/sched/cputime.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/sched/cputime.c 2015-05-31 15:32:48.893635363 -0500 @@ -675,37 +675,45 @@ void vtime_account_system(struct task_struct *tsk) @@ -24888,9 +24649,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/cputime.c linux-3.18.12/kernel/sched/c } -diff -Nur linux-3.18.12.orig/kernel/sched/deadline.c linux-3.18.12/kernel/sched/deadline.c ---- linux-3.18.12.orig/kernel/sched/deadline.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/sched/deadline.c 2015-04-26 13:32:22.447684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/sched/deadline.c linux-3.18.14-rt/kernel/sched/deadline.c +--- linux-3.18.14.orig/kernel/sched/deadline.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/sched/deadline.c 2015-05-31 15:32:48.893635363 -0500 @@ -570,6 +570,7 @@ hrtimer_init(timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); @@ -24899,9 +24660,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/deadline.c linux-3.18.12/kernel/sched/ } static -diff -Nur linux-3.18.12.orig/kernel/sched/debug.c linux-3.18.12/kernel/sched/debug.c ---- linux-3.18.12.orig/kernel/sched/debug.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/sched/debug.c 2015-04-26 13:32:22.447684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/sched/debug.c linux-3.18.14-rt/kernel/sched/debug.c +--- linux-3.18.14.orig/kernel/sched/debug.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/sched/debug.c 2015-05-31 15:32:48.897635363 -0500 @@ -256,6 +256,9 @@ P(rt_throttled); PN(rt_time); @@ -24923,9 +24684,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/debug.c linux-3.18.12/kernel/sched/deb #undef PN #undef __PN #undef P -diff -Nur linux-3.18.12.orig/kernel/sched/fair.c linux-3.18.12/kernel/sched/fair.c ---- linux-3.18.12.orig/kernel/sched/fair.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/sched/fair.c 2015-04-26 13:32:22.447684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/sched/fair.c linux-3.18.14-rt/kernel/sched/fair.c +--- linux-3.18.14.orig/kernel/sched/fair.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/sched/fair.c 2015-05-31 15:32:48.897635363 -0500 @@ -2951,7 +2951,7 @@ ideal_runtime = sched_slice(cfs_rq, curr); delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime; @@ -24998,9 +24759,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/fair.c linux-3.18.12/kernel/sched/fair } else check_preempt_curr(rq, p, 0); } -diff -Nur linux-3.18.12.orig/kernel/sched/features.h linux-3.18.12/kernel/sched/features.h ---- linux-3.18.12.orig/kernel/sched/features.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/sched/features.h 2015-04-26 13:32:22.447684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/sched/features.h linux-3.18.14-rt/kernel/sched/features.h +--- linux-3.18.14.orig/kernel/sched/features.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/sched/features.h 2015-05-31 15:32:48.897635363 -0500 @@ -50,12 +50,18 @@ */ SCHED_FEAT(NONTASK_CAPACITY, true) @@ -25021,9 +24782,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/features.h linux-3.18.12/kernel/sched/ SCHED_FEAT(FORCE_SD_OVERLAP, false) SCHED_FEAT(RT_RUNTIME_SHARE, true) SCHED_FEAT(LB_MIN, false) -diff -Nur linux-3.18.12.orig/kernel/sched/Makefile linux-3.18.12/kernel/sched/Makefile ---- linux-3.18.12.orig/kernel/sched/Makefile 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/sched/Makefile 2015-04-26 13:32:22.443684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/sched/Makefile linux-3.18.14-rt/kernel/sched/Makefile +--- linux-3.18.14.orig/kernel/sched/Makefile 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/sched/Makefile 2015-05-31 15:32:48.861635363 -0500 @@ -13,7 +13,7 @@ obj-y += core.o proc.o clock.o cputime.o @@ -25033,9 +24794,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/Makefile linux-3.18.12/kernel/sched/Ma obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o obj-$(CONFIG_SCHEDSTATS) += stats.o -diff -Nur linux-3.18.12.orig/kernel/sched/rt.c linux-3.18.12/kernel/sched/rt.c ---- linux-3.18.12.orig/kernel/sched/rt.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/sched/rt.c 2015-04-26 13:32:22.447684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/sched/rt.c linux-3.18.14-rt/kernel/sched/rt.c +--- linux-3.18.14.orig/kernel/sched/rt.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/sched/rt.c 2015-05-31 15:32:48.897635363 -0500 @@ -43,6 +43,7 @@ hrtimer_init(&rt_b->rt_period_timer, @@ -25044,9 +24805,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/rt.c linux-3.18.12/kernel/sched/rt.c rt_b->rt_period_timer.function = sched_rt_period_timer; } -diff -Nur linux-3.18.12.orig/kernel/sched/sched.h linux-3.18.12/kernel/sched/sched.h ---- linux-3.18.12.orig/kernel/sched/sched.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/sched/sched.h 2015-04-26 13:32:22.447684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/sched/sched.h linux-3.18.14-rt/kernel/sched/sched.h +--- linux-3.18.14.orig/kernel/sched/sched.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/sched/sched.h 2015-05-31 15:32:48.897635363 -0500 @@ -1018,6 +1018,7 @@ #define WF_SYNC 0x01 /* waker goes to sleep after wakeup */ #define WF_FORK 0x02 /* child wakeup after fork */ @@ -25071,9 +24832,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/sched.h linux-3.18.12/kernel/sched/sch extern struct rt_bandwidth def_rt_bandwidth; extern void init_rt_bandwidth(struct rt_bandwidth *rt_b, u64 period, u64 runtime); -diff -Nur linux-3.18.12.orig/kernel/sched/wait-simple.c linux-3.18.12/kernel/sched/wait-simple.c ---- linux-3.18.12.orig/kernel/sched/wait-simple.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/kernel/sched/wait-simple.c 2015-04-26 13:32:22.447684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/sched/wait-simple.c linux-3.18.14-rt/kernel/sched/wait-simple.c +--- linux-3.18.14.orig/kernel/sched/wait-simple.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/kernel/sched/wait-simple.c 2015-05-31 15:32:48.897635363 -0500 @@ -0,0 +1,115 @@ +/* + * Simple waitqueues without fancy flags and callbacks @@ -25190,9 +24951,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/wait-simple.c linux-3.18.12/kernel/sch + return woken; +} +EXPORT_SYMBOL(__swait_wake); -diff -Nur linux-3.18.12.orig/kernel/sched/work-simple.c linux-3.18.12/kernel/sched/work-simple.c ---- linux-3.18.12.orig/kernel/sched/work-simple.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/kernel/sched/work-simple.c 2015-04-26 13:32:22.447684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/sched/work-simple.c linux-3.18.14-rt/kernel/sched/work-simple.c +--- linux-3.18.14.orig/kernel/sched/work-simple.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/kernel/sched/work-simple.c 2015-05-31 15:32:48.901635363 -0500 @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2014 BMW Car IT GmbH, Daniel Wagner daniel.wagner@bmw-carit.de @@ -25366,9 +25127,9 @@ diff -Nur linux-3.18.12.orig/kernel/sched/work-simple.c linux-3.18.12/kernel/sch + mutex_unlock(&worker_mutex); +} +EXPORT_SYMBOL_GPL(swork_put); -diff -Nur linux-3.18.12.orig/kernel/signal.c linux-3.18.12/kernel/signal.c ---- linux-3.18.12.orig/kernel/signal.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/signal.c 2015-04-26 13:32:22.447684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/signal.c linux-3.18.14-rt/kernel/signal.c +--- linux-3.18.14.orig/kernel/signal.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/signal.c 2015-05-31 15:32:48.921635363 -0500 @@ -14,6 +14,7 @@ #include <linux/export.h> #include <linux/init.h> @@ -25613,9 +25374,9 @@ diff -Nur linux-3.18.12.orig/kernel/signal.c linux-3.18.12/kernel/signal.c freezable_schedule(); } else { /* -diff -Nur linux-3.18.12.orig/kernel/softirq.c linux-3.18.12/kernel/softirq.c ---- linux-3.18.12.orig/kernel/softirq.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/softirq.c 2015-04-26 13:32:22.451684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/softirq.c linux-3.18.14-rt/kernel/softirq.c +--- linux-3.18.14.orig/kernel/softirq.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/softirq.c 2015-05-31 15:32:48.921635363 -0500 @@ -21,10 +21,12 @@ #include <linux/freezer.h> #include <linux/kthread.h> @@ -26507,9 +26268,9 @@ diff -Nur linux-3.18.12.orig/kernel/softirq.c linux-3.18.12/kernel/softirq.c .thread_should_run = ksoftirqd_should_run, .thread_fn = run_ksoftirqd, .thread_comm = "ksoftirqd/%u", -diff -Nur linux-3.18.12.orig/kernel/stop_machine.c linux-3.18.12/kernel/stop_machine.c ---- linux-3.18.12.orig/kernel/stop_machine.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/stop_machine.c 2015-04-26 13:32:22.451684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/stop_machine.c linux-3.18.14-rt/kernel/stop_machine.c +--- linux-3.18.14.orig/kernel/stop_machine.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/stop_machine.c 2015-05-31 15:32:48.925635362 -0500 @@ -30,12 +30,12 @@ atomic_t nr_todo; /* nr left to execute */ bool executed; /* actually executed? */ @@ -26770,9 +26531,9 @@ diff -Nur linux-3.18.12.orig/kernel/stop_machine.c linux-3.18.12/kernel/stop_mac cpu_relax(); mutex_unlock(&stop_cpus_mutex); -diff -Nur linux-3.18.12.orig/kernel/time/hrtimer.c linux-3.18.12/kernel/time/hrtimer.c ---- linux-3.18.12.orig/kernel/time/hrtimer.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/time/hrtimer.c 2015-04-26 13:32:22.451684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/time/hrtimer.c linux-3.18.14-rt/kernel/time/hrtimer.c +--- linux-3.18.14.orig/kernel/time/hrtimer.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/time/hrtimer.c 2015-05-31 15:32:48.925635362 -0500 @@ -48,11 +48,13 @@ #include <linux/sched/rt.h> #include <linux/sched/deadline.h> @@ -27377,9 +27138,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/hrtimer.c linux-3.18.12/kernel/time/hrt } /** -diff -Nur linux-3.18.12.orig/kernel/time/itimer.c linux-3.18.12/kernel/time/itimer.c ---- linux-3.18.12.orig/kernel/time/itimer.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/time/itimer.c 2015-04-26 13:32:22.451684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/time/itimer.c linux-3.18.14-rt/kernel/time/itimer.c +--- linux-3.18.14.orig/kernel/time/itimer.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/time/itimer.c 2015-05-31 15:32:48.957635362 -0500 @@ -213,6 +213,7 @@ /* We are sharing ->siglock with it_real_fn() */ if (hrtimer_try_to_cancel(timer) < 0) { @@ -27388,9 +27149,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/itimer.c linux-3.18.12/kernel/time/itim goto again; } expires = timeval_to_ktime(value->it_value); -diff -Nur linux-3.18.12.orig/kernel/time/jiffies.c linux-3.18.12/kernel/time/jiffies.c ---- linux-3.18.12.orig/kernel/time/jiffies.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/time/jiffies.c 2015-04-26 13:32:22.451684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/time/jiffies.c linux-3.18.14-rt/kernel/time/jiffies.c +--- linux-3.18.14.orig/kernel/time/jiffies.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/time/jiffies.c 2015-05-31 15:32:48.957635362 -0500 @@ -73,7 +73,8 @@ .shift = JIFFIES_SHIFT, }; @@ -27413,9 +27174,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/jiffies.c linux-3.18.12/kernel/time/jif return ret; } EXPORT_SYMBOL(get_jiffies_64); -diff -Nur linux-3.18.12.orig/kernel/time/ntp.c linux-3.18.12/kernel/time/ntp.c ---- linux-3.18.12.orig/kernel/time/ntp.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/time/ntp.c 2015-04-26 13:32:22.451684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/time/ntp.c linux-3.18.14-rt/kernel/time/ntp.c +--- linux-3.18.14.orig/kernel/time/ntp.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/time/ntp.c 2015-05-31 15:32:48.957635362 -0500 @@ -10,6 +10,7 @@ #include <linux/workqueue.h> #include <linux/hrtimer.h> @@ -27477,9 +27238,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/ntp.c linux-3.18.12/kernel/time/ntp.c #else void ntp_notify_cmos_timer(void) { } -diff -Nur linux-3.18.12.orig/kernel/time/posix-cpu-timers.c linux-3.18.12/kernel/time/posix-cpu-timers.c ---- linux-3.18.12.orig/kernel/time/posix-cpu-timers.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/time/posix-cpu-timers.c 2015-04-26 13:32:22.451684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/time/posix-cpu-timers.c linux-3.18.14-rt/kernel/time/posix-cpu-timers.c +--- linux-3.18.14.orig/kernel/time/posix-cpu-timers.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/time/posix-cpu-timers.c 2015-05-31 15:32:48.961635362 -0500 @@ -3,6 +3,7 @@ */ @@ -27727,9 +27488,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/posix-cpu-timers.c linux-3.18.12/kernel /* * Set one of the process-wide special case CPU timers or RLIMIT_CPU. * The tsk->sighand->siglock must be held by the caller. -diff -Nur linux-3.18.12.orig/kernel/time/posix-timers.c linux-3.18.12/kernel/time/posix-timers.c ---- linux-3.18.12.orig/kernel/time/posix-timers.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/time/posix-timers.c 2015-04-26 13:32:22.451684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/time/posix-timers.c linux-3.18.14-rt/kernel/time/posix-timers.c +--- linux-3.18.14.orig/kernel/time/posix-timers.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/time/posix-timers.c 2015-05-31 15:32:48.961635362 -0500 @@ -499,6 +499,7 @@ static struct pid *good_sigevent(sigevent_t * event) { @@ -27825,9 +27586,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/posix-timers.c linux-3.18.12/kernel/tim goto retry_delete; } list_del(&timer->list); -diff -Nur linux-3.18.12.orig/kernel/time/tick-common.c linux-3.18.12/kernel/time/tick-common.c ---- linux-3.18.12.orig/kernel/time/tick-common.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/time/tick-common.c 2015-04-26 13:32:22.451684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/time/tick-common.c linux-3.18.14-rt/kernel/time/tick-common.c +--- linux-3.18.14.orig/kernel/time/tick-common.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/time/tick-common.c 2015-05-31 15:32:48.961635362 -0500 @@ -78,13 +78,15 @@ static void tick_periodic(int cpu) { @@ -27858,9 +27619,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/tick-common.c linux-3.18.12/kernel/time clockevents_set_mode(dev, CLOCK_EVT_MODE_ONESHOT); -diff -Nur linux-3.18.12.orig/kernel/time/tick-internal.h linux-3.18.12/kernel/time/tick-internal.h ---- linux-3.18.12.orig/kernel/time/tick-internal.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/time/tick-internal.h 2015-04-26 13:32:22.451684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/time/tick-internal.h linux-3.18.14-rt/kernel/time/tick-internal.h +--- linux-3.18.14.orig/kernel/time/tick-internal.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/time/tick-internal.h 2015-05-31 15:32:48.961635362 -0500 @@ -6,7 +6,8 @@ #include "timekeeping.h" @@ -27871,9 +27632,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/tick-internal.h linux-3.18.12/kernel/ti #define CS_NAME_LEN 32 -diff -Nur linux-3.18.12.orig/kernel/time/tick-sched.c linux-3.18.12/kernel/time/tick-sched.c ---- linux-3.18.12.orig/kernel/time/tick-sched.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/time/tick-sched.c 2015-04-26 13:32:22.451684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/time/tick-sched.c linux-3.18.14-rt/kernel/time/tick-sched.c +--- linux-3.18.14.orig/kernel/time/tick-sched.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/time/tick-sched.c 2015-05-31 15:32:48.961635362 -0500 @@ -62,7 +62,8 @@ return; @@ -27983,9 +27744,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/tick-sched.c linux-3.18.12/kernel/time/ ts->sched_timer.function = tick_sched_timer; /* Get the next period (per cpu) */ -diff -Nur linux-3.18.12.orig/kernel/time/timekeeping.c linux-3.18.12/kernel/time/timekeeping.c ---- linux-3.18.12.orig/kernel/time/timekeeping.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/time/timekeeping.c 2015-04-26 13:32:22.451684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/time/timekeeping.c linux-3.18.14-rt/kernel/time/timekeeping.c +--- linux-3.18.14.orig/kernel/time/timekeeping.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/time/timekeeping.c 2015-05-31 15:32:48.969635362 -0500 @@ -1814,8 +1814,10 @@ */ void xtime_update(unsigned long ticks) @@ -27999,9 +27760,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/timekeeping.c linux-3.18.12/kernel/time + raw_spin_unlock(&jiffies_lock); update_wall_time(); } -diff -Nur linux-3.18.12.orig/kernel/time/timer.c linux-3.18.12/kernel/time/timer.c ---- linux-3.18.12.orig/kernel/time/timer.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/time/timer.c 2015-04-26 13:32:22.455684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/time/timer.c linux-3.18.14-rt/kernel/time/timer.c +--- linux-3.18.14.orig/kernel/time/timer.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/time/timer.c 2015-05-31 15:32:48.973635362 -0500 @@ -78,6 +78,9 @@ struct tvec_base { spinlock_t lock; @@ -28223,9 +27984,9 @@ diff -Nur linux-3.18.12.orig/kernel/time/timer.c linux-3.18.12/kernel/time/timer } #endif /* CONFIG_HOTPLUG_CPU */ -diff -Nur linux-3.18.12.orig/kernel/trace/Kconfig linux-3.18.12/kernel/trace/Kconfig ---- linux-3.18.12.orig/kernel/trace/Kconfig 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/trace/Kconfig 2015-04-26 13:32:22.455684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/trace/Kconfig linux-3.18.14-rt/kernel/trace/Kconfig +--- linux-3.18.14.orig/kernel/trace/Kconfig 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/trace/Kconfig 2015-05-31 15:32:48.973635362 -0500 @@ -187,6 +187,24 @@ enabled. This option and the preempt-off timing option can be used together or separately.) @@ -28351,9 +28112,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/Kconfig linux-3.18.12/kernel/trace/Kco config ENABLE_DEFAULT_TRACERS bool "Trace process context switches and events" depends on !GENERIC_TRACER -diff -Nur linux-3.18.12.orig/kernel/trace/latency_hist.c linux-3.18.12/kernel/trace/latency_hist.c ---- linux-3.18.12.orig/kernel/trace/latency_hist.c 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/kernel/trace/latency_hist.c 2015-04-26 13:32:22.455684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/trace/latency_hist.c linux-3.18.14-rt/kernel/trace/latency_hist.c +--- linux-3.18.14.orig/kernel/trace/latency_hist.c 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/kernel/trace/latency_hist.c 2015-05-31 15:32:48.989635362 -0500 @@ -0,0 +1,1178 @@ +/* + * kernel/trace/latency_hist.c @@ -29533,9 +29294,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/latency_hist.c linux-3.18.12/kernel/tr +} + +device_initcall(latency_hist_init); -diff -Nur linux-3.18.12.orig/kernel/trace/Makefile linux-3.18.12/kernel/trace/Makefile ---- linux-3.18.12.orig/kernel/trace/Makefile 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/trace/Makefile 2015-04-26 13:32:22.455684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/trace/Makefile linux-3.18.14-rt/kernel/trace/Makefile +--- linux-3.18.14.orig/kernel/trace/Makefile 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/trace/Makefile 2015-05-31 15:32:48.989635362 -0500 @@ -36,6 +36,10 @@ obj-$(CONFIG_IRQSOFF_TRACER) += trace_irqsoff.o obj-$(CONFIG_PREEMPT_TRACER) += trace_irqsoff.o @@ -29547,9 +29308,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/Makefile linux-3.18.12/kernel/trace/Ma obj-$(CONFIG_NOP_TRACER) += trace_nop.o obj-$(CONFIG_STACK_TRACER) += trace_stack.o obj-$(CONFIG_MMIOTRACE) += trace_mmiotrace.o -diff -Nur linux-3.18.12.orig/kernel/trace/trace.c linux-3.18.12/kernel/trace/trace.c ---- linux-3.18.12.orig/kernel/trace/trace.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/trace/trace.c 2015-04-26 13:32:22.455684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/trace/trace.c linux-3.18.14-rt/kernel/trace/trace.c +--- linux-3.18.14.orig/kernel/trace/trace.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/trace/trace.c 2015-05-31 15:32:49.021635361 -0500 @@ -1579,6 +1579,7 @@ struct task_struct *tsk = current; @@ -29621,9 +29382,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/trace.c linux-3.18.12/kernel/trace/tra } void -diff -Nur linux-3.18.12.orig/kernel/trace/trace_events.c linux-3.18.12/kernel/trace/trace_events.c ---- linux-3.18.12.orig/kernel/trace/trace_events.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/trace/trace_events.c 2015-04-26 13:32:22.455684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/trace/trace_events.c linux-3.18.14-rt/kernel/trace/trace_events.c +--- linux-3.18.14.orig/kernel/trace/trace_events.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/trace/trace_events.c 2015-05-31 15:32:49.025635362 -0500 @@ -162,6 +162,8 @@ __common_field(unsigned char, flags); __common_field(unsigned char, preempt_count); @@ -29633,9 +29394,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/trace_events.c linux-3.18.12/kernel/tr return ret; } -diff -Nur linux-3.18.12.orig/kernel/trace/trace.h linux-3.18.12/kernel/trace/trace.h ---- linux-3.18.12.orig/kernel/trace/trace.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/trace/trace.h 2015-04-26 13:32:22.455684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/trace/trace.h linux-3.18.14-rt/kernel/trace/trace.h +--- linux-3.18.14.orig/kernel/trace/trace.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/trace/trace.h 2015-05-31 15:32:49.021635361 -0500 @@ -119,6 +119,7 @@ * NEED_RESCHED - reschedule is requested * HARDIRQ - inside an interrupt handler @@ -29652,9 +29413,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/trace.h linux-3.18.12/kernel/trace/tra }; #define TRACE_BUF_SIZE 1024 -diff -Nur linux-3.18.12.orig/kernel/trace/trace_irqsoff.c linux-3.18.12/kernel/trace/trace_irqsoff.c ---- linux-3.18.12.orig/kernel/trace/trace_irqsoff.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/trace/trace_irqsoff.c 2015-04-26 13:32:22.455684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/trace/trace_irqsoff.c linux-3.18.14-rt/kernel/trace/trace_irqsoff.c +--- linux-3.18.14.orig/kernel/trace/trace_irqsoff.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/trace/trace_irqsoff.c 2015-05-31 15:32:49.025635362 -0500 @@ -17,6 +17,7 @@ #include <linux/fs.h> @@ -29738,9 +29499,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/trace_irqsoff.c linux-3.18.12/kernel/t if (preempt_trace() && !irq_trace()) start_critical_timing(a0, a1); } -diff -Nur linux-3.18.12.orig/kernel/trace/trace_output.c linux-3.18.12/kernel/trace/trace_output.c ---- linux-3.18.12.orig/kernel/trace/trace_output.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/trace/trace_output.c 2015-04-26 13:32:22.455684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/trace/trace_output.c linux-3.18.14-rt/kernel/trace/trace_output.c +--- linux-3.18.14.orig/kernel/trace/trace_output.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/trace/trace_output.c 2015-05-31 15:32:49.025635362 -0500 @@ -410,6 +410,7 @@ { char hardsoft_irq; @@ -29787,9 +29548,9 @@ diff -Nur linux-3.18.12.orig/kernel/trace/trace_output.c linux-3.18.12/kernel/tr return ret; } -diff -Nur linux-3.18.12.orig/kernel/user.c linux-3.18.12/kernel/user.c ---- linux-3.18.12.orig/kernel/user.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/user.c 2015-04-26 13:32:22.455684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/user.c linux-3.18.14-rt/kernel/user.c +--- linux-3.18.14.orig/kernel/user.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/user.c 2015-05-31 15:32:49.045635362 -0500 @@ -158,11 +158,11 @@ if (!up) return; @@ -29804,9 +29565,9 @@ diff -Nur linux-3.18.12.orig/kernel/user.c linux-3.18.12/kernel/user.c } struct user_struct *alloc_uid(kuid_t uid) -diff -Nur linux-3.18.12.orig/kernel/watchdog.c linux-3.18.12/kernel/watchdog.c ---- linux-3.18.12.orig/kernel/watchdog.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/watchdog.c 2015-04-26 13:32:22.459684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/watchdog.c linux-3.18.14-rt/kernel/watchdog.c +--- linux-3.18.14.orig/kernel/watchdog.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/watchdog.c 2015-05-31 15:32:49.065635361 -0500 @@ -248,6 +248,8 @@ #ifdef CONFIG_HARDLOCKUP_DETECTOR @@ -29848,9 +29609,9 @@ diff -Nur linux-3.18.12.orig/kernel/watchdog.c linux-3.18.12/kernel/watchdog.c /* Enable the perf event */ watchdog_nmi_enable(cpu); -diff -Nur linux-3.18.12.orig/kernel/workqueue.c linux-3.18.12/kernel/workqueue.c ---- linux-3.18.12.orig/kernel/workqueue.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/workqueue.c 2015-04-26 13:32:22.459684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/workqueue.c linux-3.18.14-rt/kernel/workqueue.c +--- linux-3.18.14.orig/kernel/workqueue.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/workqueue.c 2015-05-31 15:32:49.069635361 -0500 @@ -48,6 +48,8 @@ #include <linux/nodemask.h> #include <linux/moduleparam.h> @@ -30448,9 +30209,9 @@ diff -Nur linux-3.18.12.orig/kernel/workqueue.c linux-3.18.12/kernel/workqueue.c } out_unlock: mutex_unlock(&wq_pool_mutex); -diff -Nur linux-3.18.12.orig/kernel/workqueue_internal.h linux-3.18.12/kernel/workqueue_internal.h ---- linux-3.18.12.orig/kernel/workqueue_internal.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/kernel/workqueue_internal.h 2015-04-26 13:32:22.459684003 -0500 +diff -Nur linux-3.18.14.orig/kernel/workqueue_internal.h linux-3.18.14-rt/kernel/workqueue_internal.h +--- linux-3.18.14.orig/kernel/workqueue_internal.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/kernel/workqueue_internal.h 2015-05-31 15:32:49.069635361 -0500 @@ -43,6 +43,7 @@ unsigned long last_active; /* L: last active timestamp */ unsigned int flags; /* X: flags */ @@ -30469,9 +30230,9 @@ diff -Nur linux-3.18.12.orig/kernel/workqueue_internal.h linux-3.18.12/kernel/wo +void wq_worker_sleeping(struct task_struct *task); #endif /* _KERNEL_WORKQUEUE_INTERNAL_H */ -diff -Nur linux-3.18.12.orig/lib/debugobjects.c linux-3.18.12/lib/debugobjects.c ---- linux-3.18.12.orig/lib/debugobjects.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/lib/debugobjects.c 2015-04-26 13:32:22.459684003 -0500 +diff -Nur linux-3.18.14.orig/lib/debugobjects.c linux-3.18.14-rt/lib/debugobjects.c +--- linux-3.18.14.orig/lib/debugobjects.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/lib/debugobjects.c 2015-05-31 15:32:49.113635361 -0500 @@ -309,7 +309,10 @@ struct debug_obj *obj; unsigned long flags; @@ -30484,9 +30245,9 @@ diff -Nur linux-3.18.12.orig/lib/debugobjects.c linux-3.18.12/lib/debugobjects.c db = get_bucket((unsigned long) addr); -diff -Nur linux-3.18.12.orig/lib/idr.c linux-3.18.12/lib/idr.c ---- linux-3.18.12.orig/lib/idr.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/lib/idr.c 2015-04-26 13:32:22.459684003 -0500 +diff -Nur linux-3.18.14.orig/lib/idr.c linux-3.18.14-rt/lib/idr.c +--- linux-3.18.14.orig/lib/idr.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/lib/idr.c 2015-05-31 15:32:49.141635361 -0500 @@ -31,6 +31,7 @@ #include <linux/spinlock.h> #include <linux/percpu.h> @@ -30552,9 +30313,9 @@ diff -Nur linux-3.18.12.orig/lib/idr.c linux-3.18.12/lib/idr.c if (!new) break; -diff -Nur linux-3.18.12.orig/lib/Kconfig linux-3.18.12/lib/Kconfig ---- linux-3.18.12.orig/lib/Kconfig 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/lib/Kconfig 2015-04-26 13:32:22.459684003 -0500 +diff -Nur linux-3.18.14.orig/lib/Kconfig linux-3.18.14-rt/lib/Kconfig +--- linux-3.18.14.orig/lib/Kconfig 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/lib/Kconfig 2015-05-31 15:32:49.085635361 -0500 @@ -383,6 +383,7 @@ config CPUMASK_OFFSTACK @@ -30563,9 +30324,9 @@ diff -Nur linux-3.18.12.orig/lib/Kconfig linux-3.18.12/lib/Kconfig help Use dynamic allocation for cpumask_var_t, instead of putting them on the stack. This is a bit more expensive, but avoids -diff -Nur linux-3.18.12.orig/lib/Kconfig.debug linux-3.18.12/lib/Kconfig.debug ---- linux-3.18.12.orig/lib/Kconfig.debug 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/lib/Kconfig.debug 2015-04-26 13:32:22.459684003 -0500 +diff -Nur linux-3.18.14.orig/lib/Kconfig.debug linux-3.18.14-rt/lib/Kconfig.debug +--- linux-3.18.14.orig/lib/Kconfig.debug 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/lib/Kconfig.debug 2015-05-31 15:32:49.097635361 -0500 @@ -639,7 +639,7 @@ config DEBUG_SHIRQ @@ -30575,9 +30336,9 @@ diff -Nur linux-3.18.12.orig/lib/Kconfig.debug linux-3.18.12/lib/Kconfig.debug help Enable this to generate a spurious interrupt as soon as a shared interrupt handler is registered, and just before one is deregistered. -diff -Nur linux-3.18.12.orig/lib/locking-selftest.c linux-3.18.12/lib/locking-selftest.c ---- linux-3.18.12.orig/lib/locking-selftest.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/lib/locking-selftest.c 2015-04-26 13:32:22.459684003 -0500 +diff -Nur linux-3.18.14.orig/lib/locking-selftest.c linux-3.18.14-rt/lib/locking-selftest.c +--- linux-3.18.14.orig/lib/locking-selftest.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/lib/locking-selftest.c 2015-05-31 15:32:49.141635361 -0500 @@ -590,6 +590,8 @@ #include "locking-selftest-spin-hardirq.h" GENERATE_PERMUTATIONS_2_EVENTS(irqsafe1_hard_spin) @@ -30726,9 +30487,9 @@ diff -Nur linux-3.18.12.orig/lib/locking-selftest.c linux-3.18.12/lib/locking-se ww_tests(); -diff -Nur linux-3.18.12.orig/lib/percpu_ida.c linux-3.18.12/lib/percpu_ida.c ---- linux-3.18.12.orig/lib/percpu_ida.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/lib/percpu_ida.c 2015-04-26 13:32:22.459684003 -0500 +diff -Nur linux-3.18.14.orig/lib/percpu_ida.c linux-3.18.14-rt/lib/percpu_ida.c +--- linux-3.18.14.orig/lib/percpu_ida.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/lib/percpu_ida.c 2015-05-31 15:32:49.161635360 -0500 @@ -29,6 +29,9 @@ #include <linux/string.h> #include <linux/spinlock.h> @@ -30817,9 +30578,9 @@ diff -Nur linux-3.18.12.orig/lib/percpu_ida.c linux-3.18.12/lib/percpu_ida.c return err; } EXPORT_SYMBOL_GPL(percpu_ida_for_each_free); -diff -Nur linux-3.18.12.orig/lib/radix-tree.c linux-3.18.12/lib/radix-tree.c ---- linux-3.18.12.orig/lib/radix-tree.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/lib/radix-tree.c 2015-04-26 13:32:22.459684003 -0500 +diff -Nur linux-3.18.14.orig/lib/radix-tree.c linux-3.18.14-rt/lib/radix-tree.c +--- linux-3.18.14.orig/lib/radix-tree.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/lib/radix-tree.c 2015-05-31 15:32:49.161635360 -0500 @@ -195,12 +195,13 @@ * succeed in getting a node here (and never reach * kmem_cache_alloc) @@ -30851,9 +30612,9 @@ diff -Nur linux-3.18.12.orig/lib/radix-tree.c linux-3.18.12/lib/radix-tree.c /* * Return the maximum key which can be store into a -diff -Nur linux-3.18.12.orig/lib/scatterlist.c linux-3.18.12/lib/scatterlist.c ---- linux-3.18.12.orig/lib/scatterlist.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/lib/scatterlist.c 2015-04-26 13:32:22.459684003 -0500 +diff -Nur linux-3.18.14.orig/lib/scatterlist.c linux-3.18.14-rt/lib/scatterlist.c +--- linux-3.18.14.orig/lib/scatterlist.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/lib/scatterlist.c 2015-05-31 15:32:49.161635360 -0500 @@ -592,7 +592,7 @@ flush_kernel_dcache_page(miter->page); @@ -30881,9 +30642,9 @@ diff -Nur linux-3.18.12.orig/lib/scatterlist.c linux-3.18.12/lib/scatterlist.c return offset; } -diff -Nur linux-3.18.12.orig/lib/smp_processor_id.c linux-3.18.12/lib/smp_processor_id.c ---- linux-3.18.12.orig/lib/smp_processor_id.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/lib/smp_processor_id.c 2015-04-26 13:32:22.459684003 -0500 +diff -Nur linux-3.18.14.orig/lib/smp_processor_id.c linux-3.18.14-rt/lib/smp_processor_id.c +--- linux-3.18.14.orig/lib/smp_processor_id.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/lib/smp_processor_id.c 2015-05-31 15:32:49.161635360 -0500 @@ -39,8 +39,9 @@ if (!printk_ratelimit()) goto out_enable; @@ -30896,9 +30657,9 @@ diff -Nur linux-3.18.12.orig/lib/smp_processor_id.c linux-3.18.12/lib/smp_proces print_symbol("caller is %s\n", (long)__builtin_return_address(0)); dump_stack(); -diff -Nur linux-3.18.12.orig/mm/filemap.c linux-3.18.12/mm/filemap.c ---- linux-3.18.12.orig/mm/filemap.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/mm/filemap.c 2015-04-26 13:32:22.463684003 -0500 +diff -Nur linux-3.18.14.orig/mm/filemap.c linux-3.18.14-rt/mm/filemap.c +--- linux-3.18.14.orig/mm/filemap.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/mm/filemap.c 2015-05-31 15:32:49.181635360 -0500 @@ -168,7 +168,9 @@ if (!workingset_node_pages(node) && list_empty(&node->private_list)) { @@ -30925,9 +30686,9 @@ diff -Nur linux-3.18.12.orig/mm/filemap.c linux-3.18.12/mm/filemap.c } return 0; } -diff -Nur linux-3.18.12.orig/mm/highmem.c linux-3.18.12/mm/highmem.c ---- linux-3.18.12.orig/mm/highmem.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/mm/highmem.c 2015-04-26 13:32:22.463684003 -0500 +diff -Nur linux-3.18.14.orig/mm/highmem.c linux-3.18.14-rt/mm/highmem.c +--- linux-3.18.14.orig/mm/highmem.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/mm/highmem.c 2015-05-31 15:32:49.201635360 -0500 @@ -29,10 +29,11 @@ #include <linux/kgdb.h> #include <asm/tlbflush.h> @@ -30952,9 +30713,9 @@ diff -Nur linux-3.18.12.orig/mm/highmem.c linux-3.18.12/mm/highmem.c unsigned int nr_free_highpages (void) { -diff -Nur linux-3.18.12.orig/mm/Kconfig linux-3.18.12/mm/Kconfig ---- linux-3.18.12.orig/mm/Kconfig 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/mm/Kconfig 2015-04-26 13:32:22.463684003 -0500 +diff -Nur linux-3.18.14.orig/mm/Kconfig linux-3.18.14-rt/mm/Kconfig +--- linux-3.18.14.orig/mm/Kconfig 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/mm/Kconfig 2015-05-31 15:32:49.177635360 -0500 @@ -408,7 +408,7 @@ config TRANSPARENT_HUGEPAGE @@ -30964,9 +30725,9 @@ diff -Nur linux-3.18.12.orig/mm/Kconfig linux-3.18.12/mm/Kconfig select COMPACTION help Transparent Hugepages allows the kernel to use huge pages and -diff -Nur linux-3.18.12.orig/mm/memcontrol.c linux-3.18.12/mm/memcontrol.c ---- linux-3.18.12.orig/mm/memcontrol.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/mm/memcontrol.c 2015-04-26 13:32:22.463684003 -0500 +diff -Nur linux-3.18.14.orig/mm/memcontrol.c linux-3.18.14-rt/mm/memcontrol.c +--- linux-3.18.14.orig/mm/memcontrol.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/mm/memcontrol.c 2015-05-31 15:32:49.213635360 -0500 @@ -60,6 +60,8 @@ #include <net/sock.h> #include <net/ip.h> @@ -31067,9 +30828,9 @@ diff -Nur linux-3.18.12.orig/mm/memcontrol.c linux-3.18.12/mm/memcontrol.c } static void uncharge_list(struct list_head *page_list) -diff -Nur linux-3.18.12.orig/mm/memory.c linux-3.18.12/mm/memory.c ---- linux-3.18.12.orig/mm/memory.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/mm/memory.c 2015-04-26 13:32:22.463684003 -0500 +diff -Nur linux-3.18.14.orig/mm/memory.c linux-3.18.14-rt/mm/memory.c +--- linux-3.18.14.orig/mm/memory.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/mm/memory.c 2015-05-31 15:32:49.229635360 -0500 @@ -3244,6 +3244,32 @@ return 0; } @@ -31103,9 +30864,9 @@ diff -Nur linux-3.18.12.orig/mm/memory.c linux-3.18.12/mm/memory.c /* * By the time we get here, we already hold the mm semaphore * -diff -Nur linux-3.18.12.orig/mm/mmu_context.c linux-3.18.12/mm/mmu_context.c ---- linux-3.18.12.orig/mm/mmu_context.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/mm/mmu_context.c 2015-04-26 13:32:22.463684003 -0500 +diff -Nur linux-3.18.14.orig/mm/mmu_context.c linux-3.18.14-rt/mm/mmu_context.c +--- linux-3.18.14.orig/mm/mmu_context.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/mm/mmu_context.c 2015-05-31 15:32:49.249635360 -0500 @@ -23,6 +23,7 @@ struct task_struct *tsk = current; @@ -31122,9 +30883,9 @@ diff -Nur linux-3.18.12.orig/mm/mmu_context.c linux-3.18.12/mm/mmu_context.c task_unlock(tsk); #ifdef finish_arch_post_lock_switch finish_arch_post_lock_switch(); -diff -Nur linux-3.18.12.orig/mm/page_alloc.c linux-3.18.12/mm/page_alloc.c ---- linux-3.18.12.orig/mm/page_alloc.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/mm/page_alloc.c 2015-04-26 13:32:22.463684003 -0500 +diff -Nur linux-3.18.14.orig/mm/page_alloc.c linux-3.18.14-rt/mm/page_alloc.c +--- linux-3.18.14.orig/mm/page_alloc.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/mm/page_alloc.c 2015-05-31 15:32:49.253635359 -0500 @@ -59,6 +59,7 @@ #include <linux/page-debug-flags.h> #include <linux/hugetlb.h> @@ -31457,9 +31218,9 @@ diff -Nur linux-3.18.12.orig/mm/page_alloc.c linux-3.18.12/mm/page_alloc.c } #ifdef CONFIG_MEMORY_HOTREMOVE -diff -Nur linux-3.18.12.orig/mm/slab.h linux-3.18.12/mm/slab.h ---- linux-3.18.12.orig/mm/slab.h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/mm/slab.h 2015-04-26 13:32:22.467684003 -0500 +diff -Nur linux-3.18.14.orig/mm/slab.h linux-3.18.14-rt/mm/slab.h +--- linux-3.18.14.orig/mm/slab.h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/mm/slab.h 2015-05-31 15:32:49.257635359 -0500 @@ -315,7 +315,11 @@ * The slab lists for all objects. */ @@ -31472,9 +31233,9 @@ diff -Nur linux-3.18.12.orig/mm/slab.h linux-3.18.12/mm/slab.h #ifdef CONFIG_SLAB struct list_head slabs_partial; /* partial list first, better asm code */ -diff -Nur linux-3.18.12.orig/mm/slub.c linux-3.18.12/mm/slub.c ---- linux-3.18.12.orig/mm/slub.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/mm/slub.c 2015-04-26 13:32:22.467684003 -0500 +diff -Nur linux-3.18.14.orig/mm/slub.c linux-3.18.14-rt/mm/slub.c +--- linux-3.18.14.orig/mm/slub.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/mm/slub.c 2015-05-31 15:32:49.257635359 -0500 @@ -1044,7 +1044,7 @@ { struct kmem_cache_node *n = get_node(s, page_to_nid(page)); @@ -31864,9 +31625,9 @@ diff -Nur linux-3.18.12.orig/mm/slub.c linux-3.18.12/mm/slub.c } for (i = 0; i < t.count; i++) { -diff -Nur linux-3.18.12.orig/mm/swap.c linux-3.18.12/mm/swap.c ---- linux-3.18.12.orig/mm/swap.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/mm/swap.c 2015-04-26 13:32:22.467684003 -0500 +diff -Nur linux-3.18.14.orig/mm/swap.c linux-3.18.14-rt/mm/swap.c +--- linux-3.18.14.orig/mm/swap.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/mm/swap.c 2015-05-31 15:32:49.285635359 -0500 @@ -31,6 +31,7 @@ #include <linux/memcontrol.h> #include <linux/gfp.h> @@ -31985,9 +31746,9 @@ diff -Nur linux-3.18.12.orig/mm/swap.c linux-3.18.12/mm/swap.c } static void lru_add_drain_per_cpu(struct work_struct *dummy) -diff -Nur linux-3.18.12.orig/mm/truncate.c linux-3.18.12/mm/truncate.c ---- linux-3.18.12.orig/mm/truncate.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/mm/truncate.c 2015-04-26 13:32:22.467684003 -0500 +diff -Nur linux-3.18.14.orig/mm/truncate.c linux-3.18.14-rt/mm/truncate.c +--- linux-3.18.14.orig/mm/truncate.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/mm/truncate.c 2015-05-31 15:32:49.293635359 -0500 @@ -56,8 +56,11 @@ * protected by mapping->tree_lock. */ @@ -32002,9 +31763,9 @@ diff -Nur linux-3.18.12.orig/mm/truncate.c linux-3.18.12/mm/truncate.c __radix_tree_delete_node(&mapping->page_tree, node); unlock: spin_unlock_irq(&mapping->tree_lock); -diff -Nur linux-3.18.12.orig/mm/vmalloc.c linux-3.18.12/mm/vmalloc.c ---- linux-3.18.12.orig/mm/vmalloc.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/mm/vmalloc.c 2015-04-26 13:32:22.467684003 -0500 +diff -Nur linux-3.18.14.orig/mm/vmalloc.c linux-3.18.14-rt/mm/vmalloc.c +--- linux-3.18.14.orig/mm/vmalloc.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/mm/vmalloc.c 2015-05-31 15:32:49.297635359 -0500 @@ -798,7 +798,7 @@ struct vmap_block *vb; struct vmap_area *va; @@ -32056,9 +31817,9 @@ diff -Nur linux-3.18.12.orig/mm/vmalloc.c linux-3.18.12/mm/vmalloc.c rcu_read_unlock(); if (!addr) { -diff -Nur linux-3.18.12.orig/mm/vmstat.c linux-3.18.12/mm/vmstat.c ---- linux-3.18.12.orig/mm/vmstat.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/mm/vmstat.c 2015-04-26 13:32:22.467684003 -0500 +diff -Nur linux-3.18.14.orig/mm/vmstat.c linux-3.18.14-rt/mm/vmstat.c +--- linux-3.18.14.orig/mm/vmstat.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/mm/vmstat.c 2015-05-31 15:32:49.297635359 -0500 @@ -221,6 +221,7 @@ long x; long t; @@ -32107,9 +31868,9 @@ diff -Nur linux-3.18.12.orig/mm/vmstat.c linux-3.18.12/mm/vmstat.c } void __dec_zone_page_state(struct page *page, enum zone_stat_item item) -diff -Nur linux-3.18.12.orig/mm/workingset.c linux-3.18.12/mm/workingset.c ---- linux-3.18.12.orig/mm/workingset.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/mm/workingset.c 2015-04-26 13:32:22.467684003 -0500 +diff -Nur linux-3.18.14.orig/mm/workingset.c linux-3.18.14-rt/mm/workingset.c +--- linux-3.18.14.orig/mm/workingset.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/mm/workingset.c 2015-05-31 15:32:49.321635359 -0500 @@ -264,7 +264,8 @@ * point where they would still be useful. */ @@ -32177,9 +31938,9 @@ diff -Nur linux-3.18.12.orig/mm/workingset.c linux-3.18.12/mm/workingset.c err: return ret; } -diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c ---- linux-3.18.12.orig/net/core/dev.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/net/core/dev.c 2015-04-26 13:32:22.471684003 -0500 +diff -Nur linux-3.18.14.orig/net/core/dev.c linux-3.18.14-rt/net/core/dev.c +--- linux-3.18.14.orig/net/core/dev.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/net/core/dev.c 2015-05-31 15:32:49.369635359 -0500 @@ -182,6 +182,7 @@ static DEFINE_HASHTABLE(napi_hash, 8); @@ -32296,7 +32057,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c } EXPORT_SYMBOL(__dev_kfree_skb_irq); -@@ -3336,6 +3344,7 @@ +@@ -3334,6 +3342,7 @@ rps_unlock(sd); local_irq_restore(flags); @@ -32304,7 +32065,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c atomic_long_inc(&skb->dev->rx_dropped); kfree_skb(skb); -@@ -3354,7 +3363,7 @@ +@@ -3352,7 +3361,7 @@ struct rps_dev_flow voidflow, *rflow = &voidflow; int cpu; @@ -32313,7 +32074,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c rcu_read_lock(); cpu = get_rps_cpu(skb->dev, skb, &rflow); -@@ -3364,13 +3373,13 @@ +@@ -3362,13 +3371,13 @@ ret = enqueue_to_backlog(skb, cpu, &rflow->last_qtail); rcu_read_unlock(); @@ -32330,7 +32091,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c } return ret; } -@@ -3404,16 +3413,44 @@ +@@ -3402,16 +3411,44 @@ trace_netif_rx_ni_entry(skb); @@ -32379,7 +32140,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c static void net_tx_action(struct softirq_action *h) { struct softnet_data *sd = this_cpu_ptr(&softnet_data); -@@ -3455,7 +3492,7 @@ +@@ -3453,7 +3490,7 @@ head = head->next_sched; root_lock = qdisc_lock(q); @@ -32388,7 +32149,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c smp_mb__before_atomic(); clear_bit(__QDISC_STATE_SCHED, &q->state); -@@ -3848,7 +3885,7 @@ +@@ -3846,7 +3883,7 @@ skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) { if (skb->dev == dev) { __skb_unlink(skb, &sd->input_pkt_queue); @@ -32397,7 +32158,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c input_queue_head_incr(sd); } } -@@ -3857,10 +3894,13 @@ +@@ -3855,10 +3892,13 @@ skb_queue_walk_safe(&sd->process_queue, skb, tmp) { if (skb->dev == dev) { __skb_unlink(skb, &sd->process_queue); @@ -32412,7 +32173,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c } static int napi_gro_complete(struct sk_buff *skb) -@@ -4323,6 +4363,7 @@ +@@ -4321,6 +4361,7 @@ } else #endif local_irq_enable(); @@ -32420,7 +32181,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c } static int process_backlog(struct napi_struct *napi, int quota) -@@ -4394,6 +4435,7 @@ +@@ -4392,6 +4433,7 @@ local_irq_save(flags); ____napi_schedule(this_cpu_ptr(&softnet_data), n); local_irq_restore(flags); @@ -32428,7 +32189,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c } EXPORT_SYMBOL(__napi_schedule); -@@ -4516,10 +4558,17 @@ +@@ -4514,10 +4556,17 @@ struct softnet_data *sd = this_cpu_ptr(&softnet_data); unsigned long time_limit = jiffies + 2; int budget = netdev_budget; @@ -32446,7 +32207,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c while (!list_empty(&sd->poll_list)) { struct napi_struct *n; int work, weight; -@@ -7008,6 +7057,7 @@ +@@ -7006,6 +7055,7 @@ raise_softirq_irqoff(NET_TX_SOFTIRQ); local_irq_enable(); @@ -32454,7 +32215,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c /* Process offline CPU's input_pkt_queue */ while ((skb = __skb_dequeue(&oldsd->process_queue))) { -@@ -7018,6 +7068,9 @@ +@@ -7016,6 +7066,9 @@ netif_rx_internal(skb); input_queue_head_incr(oldsd); } @@ -32464,7 +32225,7 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c return NOTIFY_OK; } -@@ -7319,8 +7372,9 @@ +@@ -7317,8 +7370,9 @@ for_each_possible_cpu(i) { struct softnet_data *sd = &per_cpu(softnet_data, i); @@ -32476,9 +32237,9 @@ diff -Nur linux-3.18.12.orig/net/core/dev.c linux-3.18.12/net/core/dev.c INIT_LIST_HEAD(&sd->poll_list); sd->output_queue_tailp = &sd->output_queue; #ifdef CONFIG_RPS -diff -Nur linux-3.18.12.orig/net/core/skbuff.c linux-3.18.12/net/core/skbuff.c ---- linux-3.18.12.orig/net/core/skbuff.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/net/core/skbuff.c 2015-04-26 13:32:22.471684003 -0500 +diff -Nur linux-3.18.14.orig/net/core/skbuff.c linux-3.18.14-rt/net/core/skbuff.c +--- linux-3.18.14.orig/net/core/skbuff.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/net/core/skbuff.c 2015-05-31 15:32:49.393635358 -0500 @@ -63,6 +63,7 @@ #include <linux/errqueue.h> #include <linux/prefetch.h> @@ -32487,7 +32248,7 @@ diff -Nur linux-3.18.12.orig/net/core/skbuff.c linux-3.18.12/net/core/skbuff.c #include <net/protocol.h> #include <net/dst.h> -@@ -336,6 +337,7 @@ +@@ -353,6 +354,7 @@ unsigned int pagecnt_bias; }; static DEFINE_PER_CPU(struct netdev_alloc_cache, netdev_alloc_cache); @@ -32495,7 +32256,7 @@ diff -Nur linux-3.18.12.orig/net/core/skbuff.c linux-3.18.12/net/core/skbuff.c static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask) { -@@ -344,7 +346,7 @@ +@@ -361,7 +363,7 @@ int order; unsigned long flags; @@ -32504,7 +32265,7 @@ diff -Nur linux-3.18.12.orig/net/core/skbuff.c linux-3.18.12/net/core/skbuff.c nc = this_cpu_ptr(&netdev_alloc_cache); if (unlikely(!nc->frag.page)) { refill: -@@ -389,7 +391,7 @@ +@@ -407,7 +409,7 @@ nc->frag.offset += fragsz; nc->pagecnt_bias--; end: @@ -32513,3589 +32274,4344 @@ diff -Nur linux-3.18.12.orig/net/core/skbuff.c linux-3.18.12/net/core/skbuff.c return data; } -diff -Nur linux-3.18.12.orig/net/core/sock.c linux-3.18.12/net/core/sock.c ---- linux-3.18.12.orig/net/core/sock.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/net/core/sock.c 2015-04-26 13:32:22.471684003 -0500 -@@ -2326,12 +2326,11 @@ - if (sk->sk_lock.owned) - __lock_sock(sk); - sk->sk_lock.owned = 1; -- spin_unlock(&sk->sk_lock.slock); -+ spin_unlock_bh(&sk->sk_lock.slock); - /* - * The sk_lock has mutex_lock() semantics here: - */ - mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_); -- local_bh_enable(); - } - EXPORT_SYMBOL(lock_sock_nested); - -diff -Nur linux-3.18.12.orig/net/ipv4/icmp.c linux-3.18.12/net/ipv4/icmp.c ---- linux-3.18.12.orig/net/ipv4/icmp.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/net/ipv4/icmp.c 2015-04-26 13:32:22.471684003 -0500 -@@ -69,6 +69,7 @@ - #include <linux/jiffies.h> - #include <linux/kernel.h> - #include <linux/fcntl.h> -+#include <linux/sysrq.h> - #include <linux/socket.h> - #include <linux/in.h> - #include <linux/inet.h> -@@ -864,6 +865,30 @@ - } - - /* -+ * 32bit and 64bit have different timestamp length, so we check for -+ * the cookie at offset 20 and verify it is repeated at offset 50 +diff -Nur linux-3.18.14.orig/net/core/skbuff.c.orig linux-3.18.14-rt/net/core/skbuff.c.orig +--- linux-3.18.14.orig/net/core/skbuff.c.orig 1969-12-31 18:00:00.000000000 -0600 ++++ linux-3.18.14-rt/net/core/skbuff.c.orig 2015-05-20 10:04:50.000000000 -0500 +@@ -0,0 +1,4231 @@ ++/* ++ * Routines having to do with the 'struct sk_buff' memory handlers. ++ * ++ * Authors: Alan Cox <alan@lxorguk.ukuu.org.uk> ++ * Florian La Roche <rzsfl@rz.uni-sb.de> ++ * ++ * Fixes: ++ * Alan Cox : Fixed the worst of the load ++ * balancer bugs. ++ * Dave Platt : Interrupt stacking fix. ++ * Richard Kooijman : Timestamp fixes. ++ * Alan Cox : Changed buffer format. ++ * Alan Cox : destructor hook for AF_UNIX etc. ++ * Linus Torvalds : Better skb_clone. ++ * Alan Cox : Added skb_copy. ++ * Alan Cox : Added all the changed routines Linus ++ * only put in the headers ++ * Ray VanTassle : Fixed --skb->lock in free ++ * Alan Cox : skb_copy copy arp field ++ * Andi Kleen : slabified it. ++ * Robert Olsson : Removed skb_head_pool ++ * ++ * NOTE: ++ * The __skb_ routines should be called with interrupts ++ * disabled, or you better be *real* sure that the operation is atomic ++ * with respect to whatever list is being frobbed (e.g. via lock_sock() ++ * or via disabling bottom half handlers, etc). ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License ++ * as published by the Free Software Foundation; either version ++ * 2 of the License, or (at your option) any later version. + */ -+#define CO_POS0 20 -+#define CO_POS1 50 -+#define CO_SIZE sizeof(int) -+#define ICMP_SYSRQ_SIZE 57 + +/* -+ * We got a ICMP_SYSRQ_SIZE sized ping request. Check for the cookie -+ * pattern and if it matches send the next byte as a trigger to sysrq. ++ * The functions in this file will not compile correctly with gcc 2.4.x + */ -+static void icmp_check_sysrq(struct net *net, struct sk_buff *skb) ++ ++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ++ ++#include <linux/module.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/kmemcheck.h> ++#include <linux/mm.h> ++#include <linux/interrupt.h> ++#include <linux/in.h> ++#include <linux/inet.h> ++#include <linux/slab.h> ++#include <linux/tcp.h> ++#include <linux/udp.h> ++#include <linux/netdevice.h> ++#ifdef CONFIG_NET_CLS_ACT ++#include <net/pkt_sched.h> ++#endif ++#include <linux/string.h> ++#include <linux/skbuff.h> ++#include <linux/splice.h> ++#include <linux/cache.h> ++#include <linux/rtnetlink.h> ++#include <linux/init.h> ++#include <linux/scatterlist.h> ++#include <linux/errqueue.h> ++#include <linux/prefetch.h> ++#include <linux/if_vlan.h> ++ ++#include <net/protocol.h> ++#include <net/dst.h> ++#include <net/sock.h> ++#include <net/checksum.h> ++#include <net/ip6_checksum.h> ++#include <net/xfrm.h> ++ ++#include <asm/uaccess.h> ++#include <trace/events/skb.h> ++#include <linux/highmem.h> ++ ++struct kmem_cache *skbuff_head_cache __read_mostly; ++static struct kmem_cache *skbuff_fclone_cache __read_mostly; ++ ++/** ++ * skb_panic - private function for out-of-line support ++ * @skb: buffer ++ * @sz: size ++ * @addr: address ++ * @msg: skb_over_panic or skb_under_panic ++ * ++ * Out-of-line support for skb_put() and skb_push(). ++ * Called via the wrapper skb_over_panic() or skb_under_panic(). ++ * Keep out of line to prevent kernel bloat. ++ * __builtin_return_address is not used because it is not always reliable. ++ */ ++static void skb_panic(struct sk_buff *skb, unsigned int sz, void *addr, ++ const char msg[]) +{ -+ int cookie = htonl(net->ipv4.sysctl_icmp_echo_sysrq); -+ char *p = skb->data; ++ pr_emerg("%s: text:%p len:%d put:%d head:%p data:%p tail:%#lx end:%#lx dev:%s\n", ++ msg, addr, skb->len, sz, skb->head, skb->data, ++ (unsigned long)skb->tail, (unsigned long)skb->end, ++ skb->dev ? skb->dev->name : "<NULL>"); ++ BUG(); ++} + -+ if (!memcmp(&cookie, p + CO_POS0, CO_SIZE) && -+ !memcmp(&cookie, p + CO_POS1, CO_SIZE) && -+ p[CO_POS0 + CO_SIZE] == p[CO_POS1 + CO_SIZE]) -+ handle_sysrq(p[CO_POS0 + CO_SIZE]); ++static void skb_over_panic(struct sk_buff *skb, unsigned int sz, void *addr) ++{ ++ skb_panic(skb, sz, addr, __func__); +} + -+/* - * Handle ICMP_ECHO ("ping") requests. - * - * RFC 1122: 3.2.2.6 MUST have an echo server that answers ICMP echo -@@ -890,6 +915,11 @@ - icmp_param.data_len = skb->len; - icmp_param.head_len = sizeof(struct icmphdr); - icmp_reply(&icmp_param, skb); ++static void skb_under_panic(struct sk_buff *skb, unsigned int sz, void *addr) ++{ ++ skb_panic(skb, sz, addr, __func__); ++} + -+ if (skb->len == ICMP_SYSRQ_SIZE && -+ net->ipv4.sysctl_icmp_echo_sysrq) { -+ icmp_check_sysrq(net, skb); -+ } - } - } - -diff -Nur linux-3.18.12.orig/net/ipv4/sysctl_net_ipv4.c linux-3.18.12/net/ipv4/sysctl_net_ipv4.c ---- linux-3.18.12.orig/net/ipv4/sysctl_net_ipv4.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/net/ipv4/sysctl_net_ipv4.c 2015-04-26 13:32:22.471684003 -0500 -@@ -779,6 +779,13 @@ - .proc_handler = proc_dointvec - }, - { -+ .procname = "icmp_echo_sysrq", -+ .data = &init_net.ipv4.sysctl_icmp_echo_sysrq, -+ .maxlen = sizeof(int), -+ .mode = 0644, -+ .proc_handler = proc_dointvec -+ }, -+ { - .procname = "icmp_ignore_bogus_error_responses", - .data = &init_net.ipv4.sysctl_icmp_ignore_bogus_error_responses, - .maxlen = sizeof(int), -diff -Nur linux-3.18.12.orig/net/mac80211/rx.c linux-3.18.12/net/mac80211/rx.c ---- linux-3.18.12.orig/net/mac80211/rx.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/net/mac80211/rx.c 2015-04-26 13:32:22.471684003 -0500 -@@ -3359,7 +3359,7 @@ - struct ieee80211_supported_band *sband; - struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); - -- WARN_ON_ONCE(softirq_count() == 0); -+ WARN_ON_ONCE_NONRT(softirq_count() == 0); - - if (WARN_ON(status->band >= IEEE80211_NUM_BANDS)) - goto drop; -diff -Nur linux-3.18.12.orig/net/mac80211/rx.c.orig linux-3.18.12/net/mac80211/rx.c.orig ---- linux-3.18.12.orig/net/mac80211/rx.c.orig 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.12/net/mac80211/rx.c.orig 2015-04-20 14:48:02.000000000 -0500 -@@ -0,0 +1,3476 @@ +/* -+ * Copyright 2002-2005, Instant802 Networks, Inc. -+ * Copyright 2005-2006, Devicescape Software, Inc. -+ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> -+ * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net> -+ * Copyright 2013-2014 Intel Mobile Communications GmbH -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. ++ * kmalloc_reserve is a wrapper around kmalloc_node_track_caller that tells ++ * the caller if emergency pfmemalloc reserves are being used. If it is and ++ * the socket is later found to be SOCK_MEMALLOC then PFMEMALLOC reserves ++ * may be used. Otherwise, the packet data may be discarded until enough ++ * memory is free + */ ++#define kmalloc_reserve(size, gfp, node, pfmemalloc) \ ++ __kmalloc_reserve(size, gfp, node, _RET_IP_, pfmemalloc) + -+#include <linux/jiffies.h> -+#include <linux/slab.h> -+#include <linux/kernel.h> -+#include <linux/skbuff.h> -+#include <linux/netdevice.h> -+#include <linux/etherdevice.h> -+#include <linux/rcupdate.h> -+#include <linux/export.h> -+#include <net/mac80211.h> -+#include <net/ieee80211_radiotap.h> -+#include <asm/unaligned.h> -+ -+#include "ieee80211_i.h" -+#include "driver-ops.h" -+#include "led.h" -+#include "mesh.h" -+#include "wep.h" -+#include "wpa.h" -+#include "tkip.h" -+#include "wme.h" -+#include "rate.h" ++static void *__kmalloc_reserve(size_t size, gfp_t flags, int node, ++ unsigned long ip, bool *pfmemalloc) ++{ ++ void *obj; ++ bool ret_pfmemalloc = false; + -+/* -+ * monitor mode reception ++ /* ++ * Try a regular allocation, when that fails and we're not entitled ++ * to the reserves, fail. ++ */ ++ obj = kmalloc_node_track_caller(size, ++ flags | __GFP_NOMEMALLOC | __GFP_NOWARN, ++ node); ++ if (obj || !(gfp_pfmemalloc_allowed(flags))) ++ goto out; ++ ++ /* Try again but now we are using pfmemalloc reserves */ ++ ret_pfmemalloc = true; ++ obj = kmalloc_node_track_caller(size, flags, node); ++ ++out: ++ if (pfmemalloc) ++ *pfmemalloc = ret_pfmemalloc; ++ ++ return obj; ++} ++ ++/* Allocate a new skbuff. We do this ourselves so we can fill in a few ++ * 'private' fields and also do memory statistics to find all the ++ * [BEEP] leaks. + * -+ * This function cleans up the SKB, i.e. it removes all the stuff -+ * only useful for monitoring. + */ -+static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, -+ struct sk_buff *skb) ++ ++struct sk_buff *__alloc_skb_head(gfp_t gfp_mask, int node) +{ -+ if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { -+ if (likely(skb->len > FCS_LEN)) -+ __pskb_trim(skb, skb->len - FCS_LEN); -+ else { -+ /* driver bug */ -+ WARN_ON(1); -+ dev_kfree_skb(skb); -+ return NULL; -+ } -+ } ++ struct sk_buff *skb; ++ ++ /* Get the HEAD */ ++ skb = kmem_cache_alloc_node(skbuff_head_cache, ++ gfp_mask & ~__GFP_DMA, node); ++ if (!skb) ++ goto out; ++ ++ /* ++ * Only clear those fields we need to clear, not those that we will ++ * actually initialise below. Hence, don't put any more fields after ++ * the tail pointer in struct sk_buff! ++ */ ++ memset(skb, 0, offsetof(struct sk_buff, tail)); ++ skb->head = NULL; ++ skb->truesize = sizeof(struct sk_buff); ++ atomic_set(&skb->users, 1); + ++ skb->mac_header = (typeof(skb->mac_header))~0U; ++out: + return skb; +} + -+static inline bool should_drop_frame(struct sk_buff *skb, int present_fcs_len) ++/** ++ * __alloc_skb - allocate a network buffer ++ * @size: size to allocate ++ * @gfp_mask: allocation mask ++ * @flags: If SKB_ALLOC_FCLONE is set, allocate from fclone cache ++ * instead of head cache and allocate a cloned (child) skb. ++ * If SKB_ALLOC_RX is set, __GFP_MEMALLOC will be used for ++ * allocations in case the data is required for writeback ++ * @node: numa node to allocate memory on ++ * ++ * Allocate a new &sk_buff. The returned buffer has no headroom and a ++ * tail room of at least size bytes. The object has a reference count ++ * of one. The return is the buffer. On a failure the return is %NULL. ++ * ++ * Buffers may only be allocated from interrupts using a @gfp_mask of ++ * %GFP_ATOMIC. ++ */ ++struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask, ++ int flags, int node) +{ -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); -+ struct ieee80211_hdr *hdr = (void *)skb->data; ++ struct kmem_cache *cache; ++ struct skb_shared_info *shinfo; ++ struct sk_buff *skb; ++ u8 *data; ++ bool pfmemalloc; + -+ if (status->flag & (RX_FLAG_FAILED_FCS_CRC | -+ RX_FLAG_FAILED_PLCP_CRC | -+ RX_FLAG_AMPDU_IS_ZEROLEN)) -+ return true; ++ cache = (flags & SKB_ALLOC_FCLONE) ++ ? skbuff_fclone_cache : skbuff_head_cache; + -+ if (unlikely(skb->len < 16 + present_fcs_len)) -+ return true; ++ if (sk_memalloc_socks() && (flags & SKB_ALLOC_RX)) ++ gfp_mask |= __GFP_MEMALLOC; + -+ if (ieee80211_is_ctl(hdr->frame_control) && -+ !ieee80211_is_pspoll(hdr->frame_control) && -+ !ieee80211_is_back_req(hdr->frame_control)) -+ return true; ++ /* Get the HEAD */ ++ skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node); ++ if (!skb) ++ goto out; ++ prefetchw(skb); + -+ return false; ++ /* We do our best to align skb_shared_info on a separate cache ++ * line. It usually works because kmalloc(X > SMP_CACHE_BYTES) gives ++ * aligned memory blocks, unless SLUB/SLAB debug is enabled. ++ * Both skb->head and skb_shared_info are cache line aligned. ++ */ ++ size = SKB_DATA_ALIGN(size); ++ size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); ++ data = kmalloc_reserve(size, gfp_mask, node, &pfmemalloc); ++ if (!data) ++ goto nodata; ++ /* kmalloc(size) might give us more room than requested. ++ * Put skb_shared_info exactly at the end of allocated zone, ++ * to allow max possible filling before reallocation. ++ */ ++ size = SKB_WITH_OVERHEAD(ksize(data)); ++ prefetchw(data + size); ++ ++ /* ++ * Only clear those fields we need to clear, not those that we will ++ * actually initialise below. Hence, don't put any more fields after ++ * the tail pointer in struct sk_buff! ++ */ ++ memset(skb, 0, offsetof(struct sk_buff, tail)); ++ /* Account for allocated memory : skb + skb->head */ ++ skb->truesize = SKB_TRUESIZE(size); ++ skb->pfmemalloc = pfmemalloc; ++ atomic_set(&skb->users, 1); ++ skb->head = data; ++ skb->data = data; ++ skb_reset_tail_pointer(skb); ++ skb->end = skb->tail + size; ++ skb->mac_header = (typeof(skb->mac_header))~0U; ++ skb->transport_header = (typeof(skb->transport_header))~0U; ++ ++ /* make sure we initialize shinfo sequentially */ ++ shinfo = skb_shinfo(skb); ++ memset(shinfo, 0, offsetof(struct skb_shared_info, dataref)); ++ atomic_set(&shinfo->dataref, 1); ++ kmemcheck_annotate_variable(shinfo->destructor_arg); ++ ++ if (flags & SKB_ALLOC_FCLONE) { ++ struct sk_buff_fclones *fclones; ++ ++ fclones = container_of(skb, struct sk_buff_fclones, skb1); ++ ++ kmemcheck_annotate_bitfield(&fclones->skb2, flags1); ++ skb->fclone = SKB_FCLONE_ORIG; ++ atomic_set(&fclones->fclone_ref, 1); ++ ++ fclones->skb2.fclone = SKB_FCLONE_FREE; ++ fclones->skb2.pfmemalloc = pfmemalloc; ++ } ++out: ++ return skb; ++nodata: ++ kmem_cache_free(cache, skb); ++ skb = NULL; ++ goto out; +} ++EXPORT_SYMBOL(__alloc_skb); + -+static int -+ieee80211_rx_radiotap_space(struct ieee80211_local *local, -+ struct ieee80211_rx_status *status) ++/** ++ * __build_skb - build a network buffer ++ * @data: data buffer provided by caller ++ * @frag_size: size of data, or 0 if head was kmalloced ++ * ++ * Allocate a new &sk_buff. Caller provides space holding head and ++ * skb_shared_info. @data must have been allocated by kmalloc() only if ++ * @frag_size is 0, otherwise data should come from the page allocator ++ * or vmalloc() ++ * The return is the new skb buffer. ++ * On a failure the return is %NULL, and @data is not freed. ++ * Notes : ++ * Before IO, driver allocates only data buffer where NIC put incoming frame ++ * Driver should add room at head (NET_SKB_PAD) and ++ * MUST add room at tail (SKB_DATA_ALIGN(skb_shared_info)) ++ * After IO, driver calls build_skb(), to allocate sk_buff and populate it ++ * before giving packet to stack. ++ * RX rings only contains data buffers, not full skbs. ++ */ ++struct sk_buff *__build_skb(void *data, unsigned int frag_size) +{ -+ int len; ++ struct skb_shared_info *shinfo; ++ struct sk_buff *skb; ++ unsigned int size = frag_size ? : ksize(data); + -+ /* always present fields */ -+ len = sizeof(struct ieee80211_radiotap_header) + 8; ++ skb = kmem_cache_alloc(skbuff_head_cache, GFP_ATOMIC); ++ if (!skb) ++ return NULL; + -+ /* allocate extra bitmaps */ -+ if (status->chains) -+ len += 4 * hweight8(status->chains); ++ size -= SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + -+ if (ieee80211_have_rx_timestamp(status)) { -+ len = ALIGN(len, 8); -+ len += 8; -+ } -+ if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) -+ len += 1; ++ memset(skb, 0, offsetof(struct sk_buff, tail)); ++ skb->truesize = SKB_TRUESIZE(size); ++ atomic_set(&skb->users, 1); ++ skb->head = data; ++ skb->data = data; ++ skb_reset_tail_pointer(skb); ++ skb->end = skb->tail + size; ++ skb->mac_header = (typeof(skb->mac_header))~0U; ++ skb->transport_header = (typeof(skb->transport_header))~0U; + -+ /* antenna field, if we don't have per-chain info */ -+ if (!status->chains) -+ len += 1; ++ /* make sure we initialize shinfo sequentially */ ++ shinfo = skb_shinfo(skb); ++ memset(shinfo, 0, offsetof(struct skb_shared_info, dataref)); ++ atomic_set(&shinfo->dataref, 1); ++ kmemcheck_annotate_variable(shinfo->destructor_arg); + -+ /* padding for RX_FLAGS if necessary */ -+ len = ALIGN(len, 2); ++ return skb; ++} + -+ if (status->flag & RX_FLAG_HT) /* HT info */ -+ len += 3; ++/* build_skb() is wrapper over __build_skb(), that specifically ++ * takes care of skb->head and skb->pfmemalloc ++ * This means that if @frag_size is not zero, then @data must be backed ++ * by a page fragment, not kmalloc() or vmalloc() ++ */ ++struct sk_buff *build_skb(void *data, unsigned int frag_size) ++{ ++ struct sk_buff *skb = __build_skb(data, frag_size); + -+ if (status->flag & RX_FLAG_AMPDU_DETAILS) { -+ len = ALIGN(len, 4); -+ len += 8; ++ if (skb && frag_size) { ++ skb->head_frag = 1; ++ if (virt_to_head_page(data)->pfmemalloc) ++ skb->pfmemalloc = 1; + } ++ return skb; ++} ++EXPORT_SYMBOL(build_skb); + -+ if (status->flag & RX_FLAG_VHT) { -+ len = ALIGN(len, 2); -+ len += 12; -+ } ++struct netdev_alloc_cache { ++ struct page_frag frag; ++ /* we maintain a pagecount bias, so that we dont dirty cache line ++ * containing page->_count every time we allocate a fragment. ++ */ ++ unsigned int pagecnt_bias; ++}; ++static DEFINE_PER_CPU(struct netdev_alloc_cache, netdev_alloc_cache); ++ ++static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask) ++{ ++ struct netdev_alloc_cache *nc; ++ void *data = NULL; ++ int order; ++ unsigned long flags; + -+ if (status->chains) { -+ /* antenna and antenna signal fields */ -+ len += 2 * hweight8(status->chains); ++ local_irq_save(flags); ++ nc = this_cpu_ptr(&netdev_alloc_cache); ++ if (unlikely(!nc->frag.page)) { ++refill: ++ for (order = NETDEV_FRAG_PAGE_MAX_ORDER; ;) { ++ gfp_t gfp = gfp_mask; ++ ++ if (order) ++ gfp |= __GFP_COMP | __GFP_NOWARN | ++ __GFP_NOMEMALLOC; ++ nc->frag.page = alloc_pages(gfp, order); ++ if (likely(nc->frag.page)) ++ break; ++ if (--order < 0) ++ goto end; ++ } ++ nc->frag.size = PAGE_SIZE << order; ++ /* Even if we own the page, we do not use atomic_set(). ++ * This would break get_page_unless_zero() users. ++ */ ++ atomic_add(NETDEV_PAGECNT_MAX_BIAS - 1, ++ &nc->frag.page->_count); ++ nc->pagecnt_bias = NETDEV_PAGECNT_MAX_BIAS; ++ nc->frag.offset = 0; ++ } ++ ++ if (nc->frag.offset + fragsz > nc->frag.size) { ++ if (atomic_read(&nc->frag.page->_count) != nc->pagecnt_bias) { ++ if (!atomic_sub_and_test(nc->pagecnt_bias, ++ &nc->frag.page->_count)) ++ goto refill; ++ /* OK, page count is 0, we can safely set it */ ++ atomic_set(&nc->frag.page->_count, ++ NETDEV_PAGECNT_MAX_BIAS); ++ } else { ++ atomic_add(NETDEV_PAGECNT_MAX_BIAS - nc->pagecnt_bias, ++ &nc->frag.page->_count); ++ } ++ nc->pagecnt_bias = NETDEV_PAGECNT_MAX_BIAS; ++ nc->frag.offset = 0; + } + -+ return len; ++ data = page_address(nc->frag.page) + nc->frag.offset; ++ nc->frag.offset += fragsz; ++ nc->pagecnt_bias--; ++end: ++ local_irq_restore(flags); ++ return data; +} + -+/* -+ * ieee80211_add_rx_radiotap_header - add radiotap header -+ * -+ * add a radiotap header containing all the fields which the hardware provided. -+ */ -+static void -+ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, -+ struct sk_buff *skb, -+ struct ieee80211_rate *rate, -+ int rtap_len, bool has_fcs) -+{ -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); -+ struct ieee80211_radiotap_header *rthdr; -+ unsigned char *pos; -+ __le32 *it_present; -+ u32 it_present_val; -+ u16 rx_flags = 0; -+ u16 channel_flags = 0; -+ int mpdulen, chain; -+ unsigned long chains = status->chains; -+ -+ mpdulen = skb->len; -+ if (!(has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS))) -+ mpdulen += FCS_LEN; -+ -+ rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len); -+ memset(rthdr, 0, rtap_len); -+ it_present = &rthdr->it_present; -+ -+ /* radiotap header, set always present flags */ -+ rthdr->it_len = cpu_to_le16(rtap_len); -+ it_present_val = BIT(IEEE80211_RADIOTAP_FLAGS) | -+ BIT(IEEE80211_RADIOTAP_CHANNEL) | -+ BIT(IEEE80211_RADIOTAP_RX_FLAGS); -+ -+ if (!status->chains) -+ it_present_val |= BIT(IEEE80211_RADIOTAP_ANTENNA); -+ -+ for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) { -+ it_present_val |= -+ BIT(IEEE80211_RADIOTAP_EXT) | -+ BIT(IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE); -+ put_unaligned_le32(it_present_val, it_present); -+ it_present++; -+ it_present_val = BIT(IEEE80211_RADIOTAP_ANTENNA) | -+ BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL); -+ } -+ -+ put_unaligned_le32(it_present_val, it_present); -+ -+ pos = (void *)(it_present + 1); -+ -+ /* the order of the following fields is important */ -+ -+ /* IEEE80211_RADIOTAP_TSFT */ -+ if (ieee80211_have_rx_timestamp(status)) { -+ /* padding */ -+ while ((pos - (u8 *)rthdr) & 7) -+ *pos++ = 0; -+ put_unaligned_le64( -+ ieee80211_calculate_rx_timestamp(local, status, -+ mpdulen, 0), -+ pos); -+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT); -+ pos += 8; -+ } -+ -+ /* IEEE80211_RADIOTAP_FLAGS */ -+ if (has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)) -+ *pos |= IEEE80211_RADIOTAP_F_FCS; -+ if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) -+ *pos |= IEEE80211_RADIOTAP_F_BADFCS; -+ if (status->flag & RX_FLAG_SHORTPRE) -+ *pos |= IEEE80211_RADIOTAP_F_SHORTPRE; -+ pos++; -+ -+ /* IEEE80211_RADIOTAP_RATE */ -+ if (!rate || status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) { -+ /* -+ * Without rate information don't add it. If we have, -+ * MCS information is a separate field in radiotap, -+ * added below. The byte here is needed as padding -+ * for the channel though, so initialise it to 0. -+ */ -+ *pos = 0; -+ } else { -+ int shift = 0; -+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); -+ if (status->flag & RX_FLAG_10MHZ) -+ shift = 1; -+ else if (status->flag & RX_FLAG_5MHZ) -+ shift = 2; -+ *pos = DIV_ROUND_UP(rate->bitrate, 5 * (1 << shift)); -+ } -+ pos++; -+ -+ /* IEEE80211_RADIOTAP_CHANNEL */ -+ put_unaligned_le16(status->freq, pos); -+ pos += 2; -+ if (status->flag & RX_FLAG_10MHZ) -+ channel_flags |= IEEE80211_CHAN_HALF; -+ else if (status->flag & RX_FLAG_5MHZ) -+ channel_flags |= IEEE80211_CHAN_QUARTER; -+ -+ if (status->band == IEEE80211_BAND_5GHZ) -+ channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ; -+ else if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) -+ channel_flags |= IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ; -+ else if (rate && rate->flags & IEEE80211_RATE_ERP_G) -+ channel_flags |= IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ; -+ else if (rate) -+ channel_flags |= IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ; -+ else -+ channel_flags |= IEEE80211_CHAN_2GHZ; -+ put_unaligned_le16(channel_flags, pos); -+ pos += 2; -+ -+ /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */ -+ if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM && -+ !(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { -+ *pos = status->signal; -+ rthdr->it_present |= -+ cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL); -+ pos++; -+ } -+ -+ /* IEEE80211_RADIOTAP_LOCK_QUALITY is missing */ -+ -+ if (!status->chains) { -+ /* IEEE80211_RADIOTAP_ANTENNA */ -+ *pos = status->antenna; -+ pos++; -+ } -+ -+ /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */ -+ -+ /* IEEE80211_RADIOTAP_RX_FLAGS */ -+ /* ensure 2 byte alignment for the 2 byte field as required */ -+ if ((pos - (u8 *)rthdr) & 1) -+ *pos++ = 0; -+ if (status->flag & RX_FLAG_FAILED_PLCP_CRC) -+ rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP; -+ put_unaligned_le16(rx_flags, pos); -+ pos += 2; -+ -+ if (status->flag & RX_FLAG_HT) { -+ unsigned int stbc; -+ -+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS); -+ *pos++ = local->hw.radiotap_mcs_details; -+ *pos = 0; -+ if (status->flag & RX_FLAG_SHORT_GI) -+ *pos |= IEEE80211_RADIOTAP_MCS_SGI; -+ if (status->flag & RX_FLAG_40MHZ) -+ *pos |= IEEE80211_RADIOTAP_MCS_BW_40; -+ if (status->flag & RX_FLAG_HT_GF) -+ *pos |= IEEE80211_RADIOTAP_MCS_FMT_GF; -+ if (status->flag & RX_FLAG_LDPC) -+ *pos |= IEEE80211_RADIOTAP_MCS_FEC_LDPC; -+ stbc = (status->flag & RX_FLAG_STBC_MASK) >> RX_FLAG_STBC_SHIFT; -+ *pos |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT; -+ pos++; -+ *pos++ = status->rate_idx; -+ } -+ -+ if (status->flag & RX_FLAG_AMPDU_DETAILS) { -+ u16 flags = 0; -+ -+ /* ensure 4 byte alignment */ -+ while ((pos - (u8 *)rthdr) & 3) -+ pos++; -+ rthdr->it_present |= -+ cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS); -+ put_unaligned_le32(status->ampdu_reference, pos); -+ pos += 4; -+ if (status->flag & RX_FLAG_AMPDU_REPORT_ZEROLEN) -+ flags |= IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN; -+ if (status->flag & RX_FLAG_AMPDU_IS_ZEROLEN) -+ flags |= IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN; -+ if (status->flag & RX_FLAG_AMPDU_LAST_KNOWN) -+ flags |= IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN; -+ if (status->flag & RX_FLAG_AMPDU_IS_LAST) -+ flags |= IEEE80211_RADIOTAP_AMPDU_IS_LAST; -+ if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_ERROR) -+ flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR; -+ if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN) -+ flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN; -+ put_unaligned_le16(flags, pos); -+ pos += 2; -+ if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN) -+ *pos++ = status->ampdu_delimiter_crc; -+ else -+ *pos++ = 0; -+ *pos++ = 0; -+ } -+ -+ if (status->flag & RX_FLAG_VHT) { -+ u16 known = local->hw.radiotap_vht_details; -+ -+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); -+ /* known field - how to handle 80+80? */ -+ if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) -+ known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; -+ put_unaligned_le16(known, pos); -+ pos += 2; -+ /* flags */ -+ if (status->flag & RX_FLAG_SHORT_GI) -+ *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; -+ /* in VHT, STBC is binary */ -+ if (status->flag & RX_FLAG_STBC_MASK) -+ *pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC; -+ if (status->vht_flag & RX_VHT_FLAG_BF) -+ *pos |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED; -+ pos++; -+ /* bandwidth */ -+ if (status->vht_flag & RX_VHT_FLAG_80MHZ) -+ *pos++ = 4; -+ else if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) -+ *pos++ = 0; /* marked not known above */ -+ else if (status->vht_flag & RX_VHT_FLAG_160MHZ) -+ *pos++ = 11; -+ else if (status->flag & RX_FLAG_40MHZ) -+ *pos++ = 1; -+ else /* 20 MHz */ -+ *pos++ = 0; -+ /* MCS/NSS */ -+ *pos = (status->rate_idx << 4) | status->vht_nss; -+ pos += 4; -+ /* coding field */ -+ if (status->flag & RX_FLAG_LDPC) -+ *pos |= IEEE80211_RADIOTAP_CODING_LDPC_USER0; -+ pos++; -+ /* group ID */ -+ pos++; -+ /* partial_aid */ -+ pos += 2; -+ } -+ -+ for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) { -+ *pos++ = status->chain_signal[chain]; -+ *pos++ = chain; -+ } ++/** ++ * netdev_alloc_frag - allocate a page fragment ++ * @fragsz: fragment size ++ * ++ * Allocates a frag from a page for receive buffer. ++ * Uses GFP_ATOMIC allocations. ++ */ ++void *netdev_alloc_frag(unsigned int fragsz) ++{ ++ return __netdev_alloc_frag(fragsz, GFP_ATOMIC | __GFP_COLD); +} ++EXPORT_SYMBOL(netdev_alloc_frag); + -+/* -+ * This function copies a received frame to all monitor interfaces and -+ * returns a cleaned-up SKB that no longer includes the FCS nor the -+ * radiotap header the driver might have added. ++/** ++ * __netdev_alloc_skb - allocate an skbuff for rx on a specific device ++ * @dev: network device to receive on ++ * @length: length to allocate ++ * @gfp_mask: get_free_pages mask, passed to alloc_skb ++ * ++ * Allocate a new &sk_buff and assign it a usage count of one. The ++ * buffer has unspecified headroom built in. Users should allocate ++ * the headroom they think they need without accounting for the ++ * built in space. The built in space is used for optimisations. ++ * ++ * %NULL is returned if there is no free memory. + */ -+static struct sk_buff * -+ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, -+ struct ieee80211_rate *rate) ++struct sk_buff *__netdev_alloc_skb(struct net_device *dev, ++ unsigned int length, gfp_t gfp_mask) +{ -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb); -+ struct ieee80211_sub_if_data *sdata; -+ int needed_headroom; -+ struct sk_buff *skb, *skb2; -+ struct net_device *prev_dev = NULL; -+ int present_fcs_len = 0; ++ struct sk_buff *skb = NULL; ++ unsigned int fragsz = SKB_DATA_ALIGN(length + NET_SKB_PAD) + ++ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + -+ /* -+ * First, we may need to make a copy of the skb because -+ * (1) we need to modify it for radiotap (if not present), and -+ * (2) the other RX handlers will modify the skb we got. -+ * -+ * We don't need to, of course, if we aren't going to return -+ * the SKB because it has a bad FCS/PLCP checksum. -+ */ ++ if (fragsz <= PAGE_SIZE && !(gfp_mask & (__GFP_WAIT | GFP_DMA))) { ++ void *data; + -+ if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) -+ present_fcs_len = FCS_LEN; ++ if (sk_memalloc_socks()) ++ gfp_mask |= __GFP_MEMALLOC; + -+ /* ensure hdr->frame_control is in skb head */ -+ if (!pskb_may_pull(origskb, 2)) { -+ dev_kfree_skb(origskb); -+ return NULL; -+ } ++ data = __netdev_alloc_frag(fragsz, gfp_mask); + -+ if (!local->monitors) { -+ if (should_drop_frame(origskb, present_fcs_len)) { -+ dev_kfree_skb(origskb); -+ return NULL; ++ if (likely(data)) { ++ skb = build_skb(data, fragsz); ++ if (unlikely(!skb)) ++ put_page(virt_to_head_page(data)); + } -+ -+ return remove_monitor_info(local, origskb); ++ } else { ++ skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, ++ SKB_ALLOC_RX, NUMA_NO_NODE); ++ } ++ if (likely(skb)) { ++ skb_reserve(skb, NET_SKB_PAD); ++ skb->dev = dev; + } ++ return skb; ++} ++EXPORT_SYMBOL(__netdev_alloc_skb); + -+ /* room for the radiotap header based on driver features */ -+ needed_headroom = ieee80211_rx_radiotap_space(local, status); ++void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page, int off, ++ int size, unsigned int truesize) ++{ ++ skb_fill_page_desc(skb, i, page, off, size); ++ skb->len += size; ++ skb->data_len += size; ++ skb->truesize += truesize; ++} ++EXPORT_SYMBOL(skb_add_rx_frag); + -+ if (should_drop_frame(origskb, present_fcs_len)) { -+ /* only need to expand headroom if necessary */ -+ skb = origskb; -+ origskb = NULL; ++void skb_coalesce_rx_frag(struct sk_buff *skb, int i, int size, ++ unsigned int truesize) ++{ ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + -+ /* -+ * This shouldn't trigger often because most devices have an -+ * RX header they pull before we get here, and that should -+ * be big enough for our radiotap information. We should -+ * probably export the length to drivers so that we can have -+ * them allocate enough headroom to start with. -+ */ -+ if (skb_headroom(skb) < needed_headroom && -+ pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC)) { -+ dev_kfree_skb(skb); -+ return NULL; -+ } -+ } else { -+ /* -+ * Need to make a copy and possibly remove radiotap header -+ * and FCS from the original. -+ */ -+ skb = skb_copy_expand(origskb, needed_headroom, 0, GFP_ATOMIC); ++ skb_frag_size_add(frag, size); ++ skb->len += size; ++ skb->data_len += size; ++ skb->truesize += truesize; ++} ++EXPORT_SYMBOL(skb_coalesce_rx_frag); + -+ origskb = remove_monitor_info(local, origskb); ++static void skb_drop_list(struct sk_buff **listp) ++{ ++ kfree_skb_list(*listp); ++ *listp = NULL; ++} + -+ if (!skb) -+ return origskb; -+ } ++static inline void skb_drop_fraglist(struct sk_buff *skb) ++{ ++ skb_drop_list(&skb_shinfo(skb)->frag_list); ++} + -+ /* prepend radiotap information */ -+ ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom, -+ true); ++static void skb_clone_fraglist(struct sk_buff *skb) ++{ ++ struct sk_buff *list; + -+ skb_reset_mac_header(skb); -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ skb->pkt_type = PACKET_OTHERHOST; -+ skb->protocol = htons(ETH_P_802_2); ++ skb_walk_frags(skb, list) ++ skb_get(list); ++} + -+ list_for_each_entry_rcu(sdata, &local->interfaces, list) { -+ if (sdata->vif.type != NL80211_IFTYPE_MONITOR) -+ continue; ++static void skb_free_head(struct sk_buff *skb) ++{ ++ if (skb->head_frag) ++ put_page(virt_to_head_page(skb->head)); ++ else ++ kfree(skb->head); ++} + -+ if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) -+ continue; ++static void skb_release_data(struct sk_buff *skb) ++{ ++ struct skb_shared_info *shinfo = skb_shinfo(skb); ++ int i; + -+ if (!ieee80211_sdata_running(sdata)) -+ continue; ++ if (skb->cloned && ++ atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1, ++ &shinfo->dataref)) ++ return; + -+ if (prev_dev) { -+ skb2 = skb_clone(skb, GFP_ATOMIC); -+ if (skb2) { -+ skb2->dev = prev_dev; -+ netif_receive_skb(skb2); -+ } -+ } ++ for (i = 0; i < shinfo->nr_frags; i++) ++ __skb_frag_unref(&shinfo->frags[i]); ++ ++ /* ++ * If skb buf is from userspace, we need to notify the caller ++ * the lower device DMA has done; ++ */ ++ if (shinfo->tx_flags & SKBTX_DEV_ZEROCOPY) { ++ struct ubuf_info *uarg; + -+ prev_dev = sdata->dev; -+ sdata->dev->stats.rx_packets++; -+ sdata->dev->stats.rx_bytes += skb->len; ++ uarg = shinfo->destructor_arg; ++ if (uarg->callback) ++ uarg->callback(uarg, true); + } + -+ if (prev_dev) { -+ skb->dev = prev_dev; -+ netif_receive_skb(skb); -+ } else -+ dev_kfree_skb(skb); ++ if (shinfo->frag_list) ++ kfree_skb_list(shinfo->frag_list); + -+ return origskb; ++ skb_free_head(skb); +} + -+static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) ++/* ++ * Free an skbuff by memory without cleaning the state. ++ */ ++static void kfree_skbmem(struct sk_buff *skb) +{ -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); -+ int tid, seqno_idx, security_idx; ++ struct sk_buff_fclones *fclones; + -+ /* does the frame have a qos control field? */ -+ if (ieee80211_is_data_qos(hdr->frame_control)) { -+ u8 *qc = ieee80211_get_qos_ctl(hdr); -+ /* frame has qos control */ -+ tid = *qc & IEEE80211_QOS_CTL_TID_MASK; -+ if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) -+ status->rx_flags |= IEEE80211_RX_AMSDU; ++ switch (skb->fclone) { ++ case SKB_FCLONE_UNAVAILABLE: ++ kmem_cache_free(skbuff_head_cache, skb); ++ break; + -+ seqno_idx = tid; -+ security_idx = tid; -+ } else { -+ /* -+ * IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"): -+ * -+ * Sequence numbers for management frames, QoS data -+ * frames with a broadcast/multicast address in the -+ * Address 1 field, and all non-QoS data frames sent -+ * by QoS STAs are assigned using an additional single -+ * modulo-4096 counter, [...] -+ * -+ * We also use that counter for non-QoS STAs. ++ case SKB_FCLONE_ORIG: ++ fclones = container_of(skb, struct sk_buff_fclones, skb1); ++ if (atomic_dec_and_test(&fclones->fclone_ref)) ++ kmem_cache_free(skbuff_fclone_cache, fclones); ++ break; ++ ++ case SKB_FCLONE_CLONE: ++ fclones = container_of(skb, struct sk_buff_fclones, skb2); ++ ++ /* The clone portion is available for ++ * fast-cloning again. + */ -+ seqno_idx = IEEE80211_NUM_TIDS; -+ security_idx = 0; -+ if (ieee80211_is_mgmt(hdr->frame_control)) -+ security_idx = IEEE80211_NUM_TIDS; -+ tid = 0; ++ skb->fclone = SKB_FCLONE_FREE; ++ ++ if (atomic_dec_and_test(&fclones->fclone_ref)) ++ kmem_cache_free(skbuff_fclone_cache, fclones); ++ break; ++ } ++} ++ ++static void skb_release_head_state(struct sk_buff *skb) ++{ ++ skb_dst_drop(skb); ++#ifdef CONFIG_XFRM ++ secpath_put(skb->sp); ++#endif ++ if (skb->destructor) { ++ WARN_ON(in_irq()); ++ skb->destructor(skb); + } ++#if IS_ENABLED(CONFIG_NF_CONNTRACK) ++ nf_conntrack_put(skb->nfct); ++#endif ++#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) ++ nf_bridge_put(skb->nf_bridge); ++#endif ++/* XXX: IS this still necessary? - JHS */ ++#ifdef CONFIG_NET_SCHED ++ skb->tc_index = 0; ++#ifdef CONFIG_NET_CLS_ACT ++ skb->tc_verd = 0; ++#endif ++#endif ++} + -+ rx->seqno_idx = seqno_idx; -+ rx->security_idx = security_idx; -+ /* Set skb->priority to 1d tag if highest order bit of TID is not set. -+ * For now, set skb->priority to 0 for other cases. */ -+ rx->skb->priority = (tid > 7) ? 0 : tid; ++/* Free everything but the sk_buff shell. */ ++static void skb_release_all(struct sk_buff *skb) ++{ ++ skb_release_head_state(skb); ++ if (likely(skb->head)) ++ skb_release_data(skb); +} + +/** -+ * DOC: Packet alignment -+ * -+ * Drivers always need to pass packets that are aligned to two-byte boundaries -+ * to the stack. -+ * -+ * Additionally, should, if possible, align the payload data in a way that -+ * guarantees that the contained IP header is aligned to a four-byte -+ * boundary. In the case of regular frames, this simply means aligning the -+ * payload to a four-byte boundary (because either the IP header is directly -+ * contained, or IV/RFC1042 headers that have a length divisible by four are -+ * in front of it). If the payload data is not properly aligned and the -+ * architecture doesn't support efficient unaligned operations, mac80211 -+ * will align the data. -+ * -+ * With A-MSDU frames, however, the payload data address must yield two modulo -+ * four because there are 14-byte 802.3 headers within the A-MSDU frames that -+ * push the IP header further back to a multiple of four again. Thankfully, the -+ * specs were sane enough this time around to require padding each A-MSDU -+ * subframe to a length that is a multiple of four. ++ * __kfree_skb - private function ++ * @skb: buffer + * -+ * Padding like Atheros hardware adds which is between the 802.11 header and -+ * the payload is not supported, the driver is required to move the 802.11 -+ * header to be directly in front of the payload in that case. ++ * Free an sk_buff. Release anything attached to the buffer. ++ * Clean the state. This is an internal helper function. Users should ++ * always call kfree_skb + */ -+static void ieee80211_verify_alignment(struct ieee80211_rx_data *rx) ++ ++void __kfree_skb(struct sk_buff *skb) +{ -+#ifdef CONFIG_MAC80211_VERBOSE_DEBUG -+ WARN_ONCE((unsigned long)rx->skb->data & 1, -+ "unaligned packet at 0x%p\n", rx->skb->data); -+#endif ++ skb_release_all(skb); ++ kfree_skbmem(skb); +} ++EXPORT_SYMBOL(__kfree_skb); + -+ -+/* rx handlers */ -+ -+static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb) ++/** ++ * kfree_skb - free an sk_buff ++ * @skb: buffer to free ++ * ++ * Drop a reference to the buffer and free it if the usage count has ++ * hit zero. ++ */ ++void kfree_skb(struct sk_buff *skb) +{ -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; ++ if (unlikely(!skb)) ++ return; ++ if (likely(atomic_read(&skb->users) == 1)) ++ smp_rmb(); ++ else if (likely(!atomic_dec_and_test(&skb->users))) ++ return; ++ trace_kfree_skb(skb, __builtin_return_address(0)); ++ __kfree_skb(skb); ++} ++EXPORT_SYMBOL(kfree_skb); + -+ if (is_multicast_ether_addr(hdr->addr1)) -+ return 0; ++void kfree_skb_list(struct sk_buff *segs) ++{ ++ while (segs) { ++ struct sk_buff *next = segs->next; + -+ return ieee80211_is_robust_mgmt_frame(skb); ++ kfree_skb(segs); ++ segs = next; ++ } +} ++EXPORT_SYMBOL(kfree_skb_list); + -+ -+static int ieee80211_is_multicast_robust_mgmt_frame(struct sk_buff *skb) ++/** ++ * skb_tx_error - report an sk_buff xmit error ++ * @skb: buffer that triggered an error ++ * ++ * Report xmit error if a device callback is tracking this skb. ++ * skb must be freed afterwards. ++ */ ++void skb_tx_error(struct sk_buff *skb) +{ -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; ++ if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) { ++ struct ubuf_info *uarg; + -+ if (!is_multicast_ether_addr(hdr->addr1)) -+ return 0; ++ uarg = skb_shinfo(skb)->destructor_arg; ++ if (uarg->callback) ++ uarg->callback(uarg, false); ++ skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY; ++ } ++} ++EXPORT_SYMBOL(skb_tx_error); + -+ return ieee80211_is_robust_mgmt_frame(skb); ++/** ++ * consume_skb - free an skbuff ++ * @skb: buffer to free ++ * ++ * Drop a ref to the buffer and free it if the usage count has hit zero ++ * Functions identically to kfree_skb, but kfree_skb assumes that the frame ++ * is being dropped after a failure and notes that ++ */ ++void consume_skb(struct sk_buff *skb) ++{ ++ if (unlikely(!skb)) ++ return; ++ if (likely(atomic_read(&skb->users) == 1)) ++ smp_rmb(); ++ else if (likely(!atomic_dec_and_test(&skb->users))) ++ return; ++ trace_consume_skb(skb); ++ __kfree_skb(skb); +} ++EXPORT_SYMBOL(consume_skb); + ++/* Make sure a field is enclosed inside headers_start/headers_end section */ ++#define CHECK_SKB_FIELD(field) \ ++ BUILD_BUG_ON(offsetof(struct sk_buff, field) < \ ++ offsetof(struct sk_buff, headers_start)); \ ++ BUILD_BUG_ON(offsetof(struct sk_buff, field) > \ ++ offsetof(struct sk_buff, headers_end)); \ + -+/* Get the BIP key index from MMIE; return -1 if this is not a BIP frame */ -+static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) ++static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old) +{ -+ struct ieee80211_mgmt *hdr = (struct ieee80211_mgmt *) skb->data; -+ struct ieee80211_mmie *mmie; -+ -+ if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da)) -+ return -1; ++ new->tstamp = old->tstamp; ++ /* We do not copy old->sk */ ++ new->dev = old->dev; ++ memcpy(new->cb, old->cb, sizeof(old->cb)); ++ skb_dst_copy(new, old); ++#ifdef CONFIG_XFRM ++ new->sp = secpath_get(old->sp); ++#endif ++ __nf_copy(new, old, false); + -+ if (!ieee80211_is_robust_mgmt_frame(skb)) -+ return -1; /* not a robust management frame */ ++ /* Note : this field could be in headers_start/headers_end section ++ * It is not yet because we do not want to have a 16 bit hole ++ */ ++ new->queue_mapping = old->queue_mapping; + -+ mmie = (struct ieee80211_mmie *) -+ (skb->data + skb->len - sizeof(*mmie)); -+ if (mmie->element_id != WLAN_EID_MMIE || -+ mmie->length != sizeof(*mmie) - 2) -+ return -1; ++ memcpy(&new->headers_start, &old->headers_start, ++ offsetof(struct sk_buff, headers_end) - ++ offsetof(struct sk_buff, headers_start)); ++ CHECK_SKB_FIELD(protocol); ++ CHECK_SKB_FIELD(csum); ++ CHECK_SKB_FIELD(hash); ++ CHECK_SKB_FIELD(priority); ++ CHECK_SKB_FIELD(skb_iif); ++ CHECK_SKB_FIELD(vlan_proto); ++ CHECK_SKB_FIELD(vlan_tci); ++ CHECK_SKB_FIELD(transport_header); ++ CHECK_SKB_FIELD(network_header); ++ CHECK_SKB_FIELD(mac_header); ++ CHECK_SKB_FIELD(inner_protocol); ++ CHECK_SKB_FIELD(inner_transport_header); ++ CHECK_SKB_FIELD(inner_network_header); ++ CHECK_SKB_FIELD(inner_mac_header); ++ CHECK_SKB_FIELD(mark); ++#ifdef CONFIG_NETWORK_SECMARK ++ CHECK_SKB_FIELD(secmark); ++#endif ++#ifdef CONFIG_NET_RX_BUSY_POLL ++ CHECK_SKB_FIELD(napi_id); ++#endif ++#ifdef CONFIG_NET_SCHED ++ CHECK_SKB_FIELD(tc_index); ++#ifdef CONFIG_NET_CLS_ACT ++ CHECK_SKB_FIELD(tc_verd); ++#endif ++#endif + -+ return le16_to_cpu(mmie->key_id); +} + -+static int iwl80211_get_cs_keyid(const struct ieee80211_cipher_scheme *cs, -+ struct sk_buff *skb) ++/* ++ * You should not add any new code to this function. Add it to ++ * __copy_skb_header above instead. ++ */ ++static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) +{ -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; -+ __le16 fc; -+ int hdrlen; -+ u8 keyid; ++#define C(x) n->x = skb->x + -+ fc = hdr->frame_control; -+ hdrlen = ieee80211_hdrlen(fc); ++ n->next = n->prev = NULL; ++ n->sk = NULL; ++ __copy_skb_header(n, skb); + -+ if (skb->len < hdrlen + cs->hdr_len) -+ return -EINVAL; ++ C(len); ++ C(data_len); ++ C(mac_len); ++ n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; ++ n->cloned = 1; ++ n->nohdr = 0; ++ n->destructor = NULL; ++ C(tail); ++ C(end); ++ C(head); ++ C(head_frag); ++ C(data); ++ C(truesize); ++ atomic_set(&n->users, 1); + -+ skb_copy_bits(skb, hdrlen + cs->key_idx_off, &keyid, 1); -+ keyid &= cs->key_idx_mask; -+ keyid >>= cs->key_idx_shift; ++ atomic_inc(&(skb_shinfo(skb)->dataref)); ++ skb->cloned = 1; ++ ++ return n; ++#undef C ++} + -+ return keyid; ++/** ++ * skb_morph - morph one skb into another ++ * @dst: the skb to receive the contents ++ * @src: the skb to supply the contents ++ * ++ * This is identical to skb_clone except that the target skb is ++ * supplied by the user. ++ * ++ * The target skb is returned upon exit. ++ */ ++struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src) ++{ ++ skb_release_all(dst); ++ return __skb_clone(dst, src); +} ++EXPORT_SYMBOL_GPL(skb_morph); + -+static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) ++/** ++ * skb_copy_ubufs - copy userspace skb frags buffers to kernel ++ * @skb: the skb to modify ++ * @gfp_mask: allocation priority ++ * ++ * This must be called on SKBTX_DEV_ZEROCOPY skb. ++ * It will copy all frags into kernel and drop the reference ++ * to userspace pages. ++ * ++ * If this function is called from an interrupt gfp_mask() must be ++ * %GFP_ATOMIC. ++ * ++ * Returns 0 on success or a negative error code on failure ++ * to allocate kernel memory to copy to. ++ */ ++int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask) +{ -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; -+ char *dev_addr = rx->sdata->vif.addr; ++ int i; ++ int num_frags = skb_shinfo(skb)->nr_frags; ++ struct page *page, *head = NULL; ++ struct ubuf_info *uarg = skb_shinfo(skb)->destructor_arg; + -+ if (ieee80211_is_data(hdr->frame_control)) { -+ if (is_multicast_ether_addr(hdr->addr1)) { -+ if (ieee80211_has_tods(hdr->frame_control) || -+ !ieee80211_has_fromds(hdr->frame_control)) -+ return RX_DROP_MONITOR; -+ if (ether_addr_equal(hdr->addr3, dev_addr)) -+ return RX_DROP_MONITOR; -+ } else { -+ if (!ieee80211_has_a4(hdr->frame_control)) -+ return RX_DROP_MONITOR; -+ if (ether_addr_equal(hdr->addr4, dev_addr)) -+ return RX_DROP_MONITOR; ++ for (i = 0; i < num_frags; i++) { ++ u8 *vaddr; ++ skb_frag_t *f = &skb_shinfo(skb)->frags[i]; ++ ++ page = alloc_page(gfp_mask); ++ if (!page) { ++ while (head) { ++ struct page *next = (struct page *)page_private(head); ++ put_page(head); ++ head = next; ++ } ++ return -ENOMEM; + } ++ vaddr = kmap_atomic(skb_frag_page(f)); ++ memcpy(page_address(page), ++ vaddr + f->page_offset, skb_frag_size(f)); ++ kunmap_atomic(vaddr); ++ set_page_private(page, (unsigned long)head); ++ head = page; + } + -+ /* If there is not an established peer link and this is not a peer link -+ * establisment frame, beacon or probe, drop the frame. -+ */ ++ /* skb frags release userspace buffers */ ++ for (i = 0; i < num_frags; i++) ++ skb_frag_unref(skb, i); ++ ++ uarg->callback(uarg, false); ++ ++ /* skb frags point to kernel buffers */ ++ for (i = num_frags - 1; i >= 0; i--) { ++ __skb_fill_page_desc(skb, i, head, 0, ++ skb_shinfo(skb)->frags[i].size); ++ head = (struct page *)page_private(head); ++ } + -+ if (!rx->sta || sta_plink_state(rx->sta) != NL80211_PLINK_ESTAB) { -+ struct ieee80211_mgmt *mgmt; ++ skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(skb_copy_ubufs); + -+ if (!ieee80211_is_mgmt(hdr->frame_control)) -+ return RX_DROP_MONITOR; ++/** ++ * skb_clone - duplicate an sk_buff ++ * @skb: buffer to clone ++ * @gfp_mask: allocation priority ++ * ++ * Duplicate an &sk_buff. The new one is not owned by a socket. Both ++ * copies share the same packet data but not structure. The new ++ * buffer has a reference count of 1. If the allocation fails the ++ * function returns %NULL otherwise the new buffer is returned. ++ * ++ * If this function is called from an interrupt gfp_mask() must be ++ * %GFP_ATOMIC. ++ */ + -+ if (ieee80211_is_action(hdr->frame_control)) { -+ u8 category; ++struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) ++{ ++ struct sk_buff_fclones *fclones = container_of(skb, ++ struct sk_buff_fclones, ++ skb1); ++ struct sk_buff *n = &fclones->skb2; + -+ /* make sure category field is present */ -+ if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE) -+ return RX_DROP_MONITOR; ++ if (skb_orphan_frags(skb, gfp_mask)) ++ return NULL; + -+ mgmt = (struct ieee80211_mgmt *)hdr; -+ category = mgmt->u.action.category; -+ if (category != WLAN_CATEGORY_MESH_ACTION && -+ category != WLAN_CATEGORY_SELF_PROTECTED) -+ return RX_DROP_MONITOR; -+ return RX_CONTINUE; -+ } ++ if (skb->fclone == SKB_FCLONE_ORIG && ++ n->fclone == SKB_FCLONE_FREE) { ++ n->fclone = SKB_FCLONE_CLONE; ++ atomic_inc(&fclones->fclone_ref); ++ } else { ++ if (skb_pfmemalloc(skb)) ++ gfp_mask |= __GFP_MEMALLOC; + -+ if (ieee80211_is_probe_req(hdr->frame_control) || -+ ieee80211_is_probe_resp(hdr->frame_control) || -+ ieee80211_is_beacon(hdr->frame_control) || -+ ieee80211_is_auth(hdr->frame_control)) -+ return RX_CONTINUE; ++ n = kmem_cache_alloc(skbuff_head_cache, gfp_mask); ++ if (!n) ++ return NULL; + -+ return RX_DROP_MONITOR; ++ kmemcheck_annotate_bitfield(n, flags1); ++ n->fclone = SKB_FCLONE_UNAVAILABLE; + } + -+ return RX_CONTINUE; ++ return __skb_clone(n, skb); +} ++EXPORT_SYMBOL(skb_clone); + -+static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, -+ struct tid_ampdu_rx *tid_agg_rx, -+ int index, -+ struct sk_buff_head *frames) ++static void skb_headers_offset_update(struct sk_buff *skb, int off) +{ -+ struct sk_buff_head *skb_list = &tid_agg_rx->reorder_buf[index]; -+ struct sk_buff *skb; -+ struct ieee80211_rx_status *status; -+ -+ lockdep_assert_held(&tid_agg_rx->reorder_lock); -+ -+ if (skb_queue_empty(skb_list)) -+ goto no_frame; ++ /* Only adjust this if it actually is csum_start rather than csum */ ++ if (skb->ip_summed == CHECKSUM_PARTIAL) ++ skb->csum_start += off; ++ /* {transport,network,mac}_header and tail are relative to skb->head */ ++ skb->transport_header += off; ++ skb->network_header += off; ++ if (skb_mac_header_was_set(skb)) ++ skb->mac_header += off; ++ skb->inner_transport_header += off; ++ skb->inner_network_header += off; ++ skb->inner_mac_header += off; ++} + -+ if (!ieee80211_rx_reorder_ready(skb_list)) { -+ __skb_queue_purge(skb_list); -+ goto no_frame; -+ } ++static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) ++{ ++ __copy_skb_header(new, old); + -+ /* release frames from the reorder ring buffer */ -+ tid_agg_rx->stored_mpdu_num--; -+ while ((skb = __skb_dequeue(skb_list))) { -+ status = IEEE80211_SKB_RXCB(skb); -+ status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE; -+ __skb_queue_tail(frames, skb); -+ } ++ skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size; ++ skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs; ++ skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type; ++} + -+no_frame: -+ tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num); ++static inline int skb_alloc_rx_flag(const struct sk_buff *skb) ++{ ++ if (skb_pfmemalloc(skb)) ++ return SKB_ALLOC_RX; ++ return 0; +} + -+static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata, -+ struct tid_ampdu_rx *tid_agg_rx, -+ u16 head_seq_num, -+ struct sk_buff_head *frames) ++/** ++ * skb_copy - create private copy of an sk_buff ++ * @skb: buffer to copy ++ * @gfp_mask: allocation priority ++ * ++ * Make a copy of both an &sk_buff and its data. This is used when the ++ * caller wishes to modify the data and needs a private copy of the ++ * data to alter. Returns %NULL on failure or the pointer to the buffer ++ * on success. The returned buffer has a reference count of 1. ++ * ++ * As by-product this function converts non-linear &sk_buff to linear ++ * one, so that &sk_buff becomes completely private and caller is allowed ++ * to modify all the data of returned buffer. This means that this ++ * function is not recommended for use in circumstances when only ++ * header is going to be modified. Use pskb_copy() instead. ++ */ ++ ++struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask) +{ -+ int index; ++ int headerlen = skb_headroom(skb); ++ unsigned int size = skb_end_offset(skb) + skb->data_len; ++ struct sk_buff *n = __alloc_skb(size, gfp_mask, ++ skb_alloc_rx_flag(skb), NUMA_NO_NODE); + -+ lockdep_assert_held(&tid_agg_rx->reorder_lock); ++ if (!n) ++ return NULL; + -+ while (ieee80211_sn_less(tid_agg_rx->head_seq_num, head_seq_num)) { -+ index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; -+ ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, -+ frames); -+ } ++ /* Set the data pointer */ ++ skb_reserve(n, headerlen); ++ /* Set the tail pointer and length */ ++ skb_put(n, skb->len); ++ ++ if (skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len)) ++ BUG(); ++ ++ copy_skb_header(n, skb); ++ return n; +} ++EXPORT_SYMBOL(skb_copy); + -+/* -+ * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If -+ * the skb was added to the buffer longer than this time ago, the earlier -+ * frames that have not yet been received are assumed to be lost and the skb -+ * can be released for processing. This may also release other skb's from the -+ * reorder buffer if there are no additional gaps between the frames. ++/** ++ * __pskb_copy_fclone - create copy of an sk_buff with private head. ++ * @skb: buffer to copy ++ * @headroom: headroom of new skb ++ * @gfp_mask: allocation priority ++ * @fclone: if true allocate the copy of the skb from the fclone ++ * cache instead of the head cache; it is recommended to set this ++ * to true for the cases where the copy will likely be cloned + * -+ * Callers must hold tid_agg_rx->reorder_lock. ++ * Make a copy of both an &sk_buff and part of its data, located ++ * in header. Fragmented data remain shared. This is used when ++ * the caller wishes to modify only header of &sk_buff and needs ++ * private copy of the header to alter. Returns %NULL on failure ++ * or the pointer to the buffer on success. ++ * The returned buffer has a reference count of 1. + */ -+#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) + -+static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, -+ struct tid_ampdu_rx *tid_agg_rx, -+ struct sk_buff_head *frames) ++struct sk_buff *__pskb_copy_fclone(struct sk_buff *skb, int headroom, ++ gfp_t gfp_mask, bool fclone) +{ -+ int index, i, j; ++ unsigned int size = skb_headlen(skb) + headroom; ++ int flags = skb_alloc_rx_flag(skb) | (fclone ? SKB_ALLOC_FCLONE : 0); ++ struct sk_buff *n = __alloc_skb(size, gfp_mask, flags, NUMA_NO_NODE); + -+ lockdep_assert_held(&tid_agg_rx->reorder_lock); ++ if (!n) ++ goto out; + -+ /* release the buffer until next missing frame */ -+ index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; -+ if (!ieee80211_rx_reorder_ready(&tid_agg_rx->reorder_buf[index]) && -+ tid_agg_rx->stored_mpdu_num) { -+ /* -+ * No buffers ready to be released, but check whether any -+ * frames in the reorder buffer have timed out. -+ */ -+ int skipped = 1; -+ for (j = (index + 1) % tid_agg_rx->buf_size; j != index; -+ j = (j + 1) % tid_agg_rx->buf_size) { -+ if (!ieee80211_rx_reorder_ready( -+ &tid_agg_rx->reorder_buf[j])) { -+ skipped++; -+ continue; -+ } -+ if (skipped && -+ !time_after(jiffies, tid_agg_rx->reorder_time[j] + -+ HT_RX_REORDER_BUF_TIMEOUT)) -+ goto set_release_timer; ++ /* Set the data pointer */ ++ skb_reserve(n, headroom); ++ /* Set the tail pointer and length */ ++ skb_put(n, skb_headlen(skb)); ++ /* Copy the bytes */ ++ skb_copy_from_linear_data(skb, n->data, n->len); + -+ /* don't leave incomplete A-MSDUs around */ -+ for (i = (index + 1) % tid_agg_rx->buf_size; i != j; -+ i = (i + 1) % tid_agg_rx->buf_size) -+ __skb_queue_purge(&tid_agg_rx->reorder_buf[i]); ++ n->truesize += skb->data_len; ++ n->data_len = skb->data_len; ++ n->len = skb->len; + -+ ht_dbg_ratelimited(sdata, -+ "release an RX reorder frame due to timeout on earlier frames\n"); -+ ieee80211_release_reorder_frame(sdata, tid_agg_rx, j, -+ frames); ++ if (skb_shinfo(skb)->nr_frags) { ++ int i; + -+ /* -+ * Increment the head seq# also for the skipped slots. -+ */ -+ tid_agg_rx->head_seq_num = -+ (tid_agg_rx->head_seq_num + -+ skipped) & IEEE80211_SN_MASK; -+ skipped = 0; ++ if (skb_orphan_frags(skb, gfp_mask)) { ++ kfree_skb(n); ++ n = NULL; ++ goto out; + } -+ } else while (ieee80211_rx_reorder_ready( -+ &tid_agg_rx->reorder_buf[index])) { -+ ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, -+ frames); -+ index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; -+ } -+ -+ if (tid_agg_rx->stored_mpdu_num) { -+ j = index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; -+ -+ for (; j != (index - 1) % tid_agg_rx->buf_size; -+ j = (j + 1) % tid_agg_rx->buf_size) { -+ if (ieee80211_rx_reorder_ready( -+ &tid_agg_rx->reorder_buf[j])) -+ break; ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i]; ++ skb_frag_ref(skb, i); + } ++ skb_shinfo(n)->nr_frags = i; ++ } + -+ set_release_timer: -+ -+ mod_timer(&tid_agg_rx->reorder_timer, -+ tid_agg_rx->reorder_time[j] + 1 + -+ HT_RX_REORDER_BUF_TIMEOUT); -+ } else { -+ del_timer(&tid_agg_rx->reorder_timer); ++ if (skb_has_frag_list(skb)) { ++ skb_shinfo(n)->frag_list = skb_shinfo(skb)->frag_list; ++ skb_clone_fraglist(n); + } ++ ++ copy_skb_header(n, skb); ++out: ++ return n; +} ++EXPORT_SYMBOL(__pskb_copy_fclone); + -+/* -+ * As this function belongs to the RX path it must be under -+ * rcu_read_lock protection. It returns false if the frame -+ * can be processed immediately, true if it was consumed. ++/** ++ * pskb_expand_head - reallocate header of &sk_buff ++ * @skb: buffer to reallocate ++ * @nhead: room to add at head ++ * @ntail: room to add at tail ++ * @gfp_mask: allocation priority ++ * ++ * Expands (or creates identical copy, if @nhead and @ntail are zero) ++ * header of @skb. &sk_buff itself is not changed. &sk_buff MUST have ++ * reference count of 1. Returns zero in the case of success or error, ++ * if expansion failed. In the last case, &sk_buff is not changed. ++ * ++ * All the pointers pointing into skb header may change and must be ++ * reloaded after call to this function. + */ -+static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata, -+ struct tid_ampdu_rx *tid_agg_rx, -+ struct sk_buff *skb, -+ struct sk_buff_head *frames) ++ ++int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, ++ gfp_t gfp_mask) +{ -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); -+ u16 sc = le16_to_cpu(hdr->seq_ctrl); -+ u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; -+ u16 head_seq_num, buf_size; -+ int index; -+ bool ret = true; ++ int i; ++ u8 *data; ++ int size = nhead + skb_end_offset(skb) + ntail; ++ long off; + -+ spin_lock(&tid_agg_rx->reorder_lock); ++ BUG_ON(nhead < 0); + -+ /* -+ * Offloaded BA sessions have no known starting sequence number so pick -+ * one from first Rxed frame for this tid after BA was started. -+ */ -+ if (unlikely(tid_agg_rx->auto_seq)) { -+ tid_agg_rx->auto_seq = false; -+ tid_agg_rx->ssn = mpdu_seq_num; -+ tid_agg_rx->head_seq_num = mpdu_seq_num; -+ } ++ if (skb_shared(skb)) ++ BUG(); + -+ buf_size = tid_agg_rx->buf_size; -+ head_seq_num = tid_agg_rx->head_seq_num; ++ size = SKB_DATA_ALIGN(size); + -+ /* frame with out of date sequence number */ -+ if (ieee80211_sn_less(mpdu_seq_num, head_seq_num)) { -+ dev_kfree_skb(skb); -+ goto out; -+ } ++ if (skb_pfmemalloc(skb)) ++ gfp_mask |= __GFP_MEMALLOC; ++ data = kmalloc_reserve(size + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)), ++ gfp_mask, NUMA_NO_NODE, NULL); ++ if (!data) ++ goto nodata; ++ size = SKB_WITH_OVERHEAD(ksize(data)); + -+ /* -+ * If frame the sequence number exceeds our buffering window -+ * size release some previous frames to make room for this one. ++ /* Copy only real data... and, alas, header. This should be ++ * optimized for the cases when header is void. + */ -+ if (!ieee80211_sn_less(mpdu_seq_num, head_seq_num + buf_size)) { -+ head_seq_num = ieee80211_sn_inc( -+ ieee80211_sn_sub(mpdu_seq_num, buf_size)); -+ /* release stored frames up to new head to stack */ -+ ieee80211_release_reorder_frames(sdata, tid_agg_rx, -+ head_seq_num, frames); -+ } -+ -+ /* Now the new frame is always in the range of the reordering buffer */ ++ memcpy(data + nhead, skb->head, skb_tail_pointer(skb) - skb->head); + -+ index = mpdu_seq_num % tid_agg_rx->buf_size; -+ -+ /* check if we already stored this frame */ -+ if (ieee80211_rx_reorder_ready(&tid_agg_rx->reorder_buf[index])) { -+ dev_kfree_skb(skb); -+ goto out; -+ } ++ memcpy((struct skb_shared_info *)(data + size), ++ skb_shinfo(skb), ++ offsetof(struct skb_shared_info, frags[skb_shinfo(skb)->nr_frags])); + + /* -+ * If the current MPDU is in the right order and nothing else -+ * is stored we can process it directly, no need to buffer it. -+ * If it is first but there's something stored, we may be able -+ * to release frames after this one. ++ * if shinfo is shared we must drop the old head gracefully, but if it ++ * is not we can just drop the old head and let the existing refcount ++ * be since all we did is relocate the values + */ -+ if (mpdu_seq_num == tid_agg_rx->head_seq_num && -+ tid_agg_rx->stored_mpdu_num == 0) { -+ if (!(status->flag & RX_FLAG_AMSDU_MORE)) -+ tid_agg_rx->head_seq_num = -+ ieee80211_sn_inc(tid_agg_rx->head_seq_num); -+ ret = false; -+ goto out; -+ } ++ if (skb_cloned(skb)) { ++ /* copy this zero copy skb frags */ ++ if (skb_orphan_frags(skb, gfp_mask)) ++ goto nofrags; ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) ++ skb_frag_ref(skb, i); ++ ++ if (skb_has_frag_list(skb)) ++ skb_clone_fraglist(skb); + -+ /* put the frame in the reordering buffer */ -+ __skb_queue_tail(&tid_agg_rx->reorder_buf[index], skb); -+ if (!(status->flag & RX_FLAG_AMSDU_MORE)) { -+ tid_agg_rx->reorder_time[index] = jiffies; -+ tid_agg_rx->stored_mpdu_num++; -+ ieee80211_sta_reorder_release(sdata, tid_agg_rx, frames); ++ skb_release_data(skb); ++ } else { ++ skb_free_head(skb); + } ++ off = (data + nhead) - skb->head; + -+ out: -+ spin_unlock(&tid_agg_rx->reorder_lock); -+ return ret; ++ skb->head = data; ++ skb->head_frag = 0; ++ skb->data += off; ++#ifdef NET_SKBUFF_DATA_USES_OFFSET ++ skb->end = size; ++ off = nhead; ++#else ++ skb->end = skb->head + size; ++#endif ++ skb->tail += off; ++ skb_headers_offset_update(skb, nhead); ++ skb->cloned = 0; ++ skb->hdr_len = 0; ++ skb->nohdr = 0; ++ atomic_set(&skb_shinfo(skb)->dataref, 1); ++ return 0; ++ ++nofrags: ++ kfree(data); ++nodata: ++ return -ENOMEM; +} ++EXPORT_SYMBOL(pskb_expand_head); + -+/* -+ * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns -+ * true if the MPDU was buffered, false if it should be processed. -+ */ -+static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, -+ struct sk_buff_head *frames) ++/* Make private copy of skb with writable head and some headroom */ ++ ++struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, unsigned int headroom) +{ -+ struct sk_buff *skb = rx->skb; -+ struct ieee80211_local *local = rx->local; -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); -+ struct sta_info *sta = rx->sta; -+ struct tid_ampdu_rx *tid_agg_rx; -+ u16 sc; -+ u8 tid, ack_policy; ++ struct sk_buff *skb2; ++ int delta = headroom - skb_headroom(skb); + -+ if (!ieee80211_is_data_qos(hdr->frame_control) || -+ is_multicast_ether_addr(hdr->addr1)) -+ goto dont_reorder; ++ if (delta <= 0) ++ skb2 = pskb_copy(skb, GFP_ATOMIC); ++ else { ++ skb2 = skb_clone(skb, GFP_ATOMIC); ++ if (skb2 && pskb_expand_head(skb2, SKB_DATA_ALIGN(delta), 0, ++ GFP_ATOMIC)) { ++ kfree_skb(skb2); ++ skb2 = NULL; ++ } ++ } ++ return skb2; ++} ++EXPORT_SYMBOL(skb_realloc_headroom); + ++/** ++ * skb_copy_expand - copy and expand sk_buff ++ * @skb: buffer to copy ++ * @newheadroom: new free bytes at head ++ * @newtailroom: new free bytes at tail ++ * @gfp_mask: allocation priority ++ * ++ * Make a copy of both an &sk_buff and its data and while doing so ++ * allocate additional space. ++ * ++ * This is used when the caller wishes to modify the data and needs a ++ * private copy of the data to alter as well as more space for new fields. ++ * Returns %NULL on failure or the pointer to the buffer ++ * on success. The returned buffer has a reference count of 1. ++ * ++ * You must pass %GFP_ATOMIC as the allocation priority if this function ++ * is called from an interrupt. ++ */ ++struct sk_buff *skb_copy_expand(const struct sk_buff *skb, ++ int newheadroom, int newtailroom, ++ gfp_t gfp_mask) ++{ + /* -+ * filter the QoS data rx stream according to -+ * STA/TID and check if this STA/TID is on aggregation ++ * Allocate the copy buffer + */ ++ struct sk_buff *n = __alloc_skb(newheadroom + skb->len + newtailroom, ++ gfp_mask, skb_alloc_rx_flag(skb), ++ NUMA_NO_NODE); ++ int oldheadroom = skb_headroom(skb); ++ int head_copy_len, head_copy_off; + -+ if (!sta) -+ goto dont_reorder; ++ if (!n) ++ return NULL; + -+ ack_policy = *ieee80211_get_qos_ctl(hdr) & -+ IEEE80211_QOS_CTL_ACK_POLICY_MASK; -+ tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; ++ skb_reserve(n, newheadroom); + -+ tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]); -+ if (!tid_agg_rx) -+ goto dont_reorder; ++ /* Set the tail pointer and length */ ++ skb_put(n, skb->len); + -+ /* qos null data frames are excluded */ -+ if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) -+ goto dont_reorder; ++ head_copy_len = oldheadroom; ++ head_copy_off = 0; ++ if (newheadroom <= head_copy_len) ++ head_copy_len = newheadroom; ++ else ++ head_copy_off = newheadroom - head_copy_len; + -+ /* not part of a BA session */ -+ if (ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK && -+ ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL) -+ goto dont_reorder; ++ /* Copy the linear header and data. */ ++ if (skb_copy_bits(skb, -head_copy_len, n->head + head_copy_off, ++ skb->len + head_copy_len)) ++ BUG(); + -+ /* not actually part of this BA session */ -+ if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) -+ goto dont_reorder; ++ copy_skb_header(n, skb); + -+ /* new, potentially un-ordered, ampdu frame - process it */ ++ skb_headers_offset_update(n, newheadroom - oldheadroom); + -+ /* reset session timer */ -+ if (tid_agg_rx->timeout) -+ tid_agg_rx->last_rx = jiffies; ++ return n; ++} ++EXPORT_SYMBOL(skb_copy_expand); + -+ /* if this mpdu is fragmented - terminate rx aggregation session */ -+ sc = le16_to_cpu(hdr->seq_ctrl); -+ if (sc & IEEE80211_SCTL_FRAG) { -+ skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; -+ skb_queue_tail(&rx->sdata->skb_queue, skb); -+ ieee80211_queue_work(&local->hw, &rx->sdata->work); -+ return; ++/** ++ * skb_pad - zero pad the tail of an skb ++ * @skb: buffer to pad ++ * @pad: space to pad ++ * ++ * Ensure that a buffer is followed by a padding area that is zero ++ * filled. Used by network drivers which may DMA or transfer data ++ * beyond the buffer end onto the wire. ++ * ++ * May return error in out of memory cases. The skb is freed on error. ++ */ ++ ++int skb_pad(struct sk_buff *skb, int pad) ++{ ++ int err; ++ int ntail; ++ ++ /* If the skbuff is non linear tailroom is always zero.. */ ++ if (!skb_cloned(skb) && skb_tailroom(skb) >= pad) { ++ memset(skb->data+skb->len, 0, pad); ++ return 0; + } + -+ /* -+ * No locking needed -- we will only ever process one -+ * RX packet at a time, and thus own tid_agg_rx. All -+ * other code manipulating it needs to (and does) make -+ * sure that we cannot get to it any more before doing -+ * anything with it. ++ ntail = skb->data_len + pad - (skb->end - skb->tail); ++ if (likely(skb_cloned(skb) || ntail > 0)) { ++ err = pskb_expand_head(skb, 0, ntail, GFP_ATOMIC); ++ if (unlikely(err)) ++ goto free_skb; ++ } ++ ++ /* FIXME: The use of this function with non-linear skb's really needs ++ * to be audited. + */ -+ if (ieee80211_sta_manage_reorder_buf(rx->sdata, tid_agg_rx, skb, -+ frames)) -+ return; ++ err = skb_linearize(skb); ++ if (unlikely(err)) ++ goto free_skb; ++ ++ memset(skb->data + skb->len, 0, pad); ++ return 0; + -+ dont_reorder: -+ __skb_queue_tail(frames, skb); ++free_skb: ++ kfree_skb(skb); ++ return err; +} ++EXPORT_SYMBOL(skb_pad); ++ ++/** ++ * pskb_put - add data to the tail of a potentially fragmented buffer ++ * @skb: start of the buffer to use ++ * @tail: tail fragment of the buffer to use ++ * @len: amount of data to add ++ * ++ * This function extends the used data area of the potentially ++ * fragmented buffer. @tail must be the last fragment of @skb -- or ++ * @skb itself. If this would exceed the total buffer size the kernel ++ * will panic. A pointer to the first byte of the extra data is ++ * returned. ++ */ + -+static ieee80211_rx_result debug_noinline -+ieee80211_rx_h_check(struct ieee80211_rx_data *rx) ++unsigned char *pskb_put(struct sk_buff *skb, struct sk_buff *tail, int len) +{ -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); ++ if (tail != skb) { ++ skb->data_len += len; ++ skb->len += len; ++ } ++ return skb_put(tail, len); ++} ++EXPORT_SYMBOL_GPL(pskb_put); + -+ /* -+ * Drop duplicate 802.11 retransmissions -+ * (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery") -+ */ -+ if (rx->skb->len >= 24 && rx->sta && -+ !ieee80211_is_ctl(hdr->frame_control) && -+ !ieee80211_is_qos_nullfunc(hdr->frame_control) && -+ !is_multicast_ether_addr(hdr->addr1)) { -+ if (unlikely(ieee80211_has_retry(hdr->frame_control) && -+ rx->sta->last_seq_ctrl[rx->seqno_idx] == -+ hdr->seq_ctrl)) { -+ if (status->rx_flags & IEEE80211_RX_RA_MATCH) { -+ rx->local->dot11FrameDuplicateCount++; -+ rx->sta->num_duplicates++; -+ } -+ return RX_DROP_UNUSABLE; -+ } else if (!(status->flag & RX_FLAG_AMSDU_MORE)) { -+ rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl; ++/** ++ * skb_put - add data to a buffer ++ * @skb: buffer to use ++ * @len: amount of data to add ++ * ++ * This function extends the used data area of the buffer. If this would ++ * exceed the total buffer size the kernel will panic. A pointer to the ++ * first byte of the extra data is returned. ++ */ ++unsigned char *skb_put(struct sk_buff *skb, unsigned int len) ++{ ++ unsigned char *tmp = skb_tail_pointer(skb); ++ SKB_LINEAR_ASSERT(skb); ++ skb->tail += len; ++ skb->len += len; ++ if (unlikely(skb->tail > skb->end)) ++ skb_over_panic(skb, len, __builtin_return_address(0)); ++ return tmp; ++} ++EXPORT_SYMBOL(skb_put); ++ ++/** ++ * skb_push - add data to the start of a buffer ++ * @skb: buffer to use ++ * @len: amount of data to add ++ * ++ * This function extends the used data area of the buffer at the buffer ++ * start. If this would exceed the total buffer headroom the kernel will ++ * panic. A pointer to the first byte of the extra data is returned. ++ */ ++unsigned char *skb_push(struct sk_buff *skb, unsigned int len) ++{ ++ skb->data -= len; ++ skb->len += len; ++ if (unlikely(skb->data<skb->head)) ++ skb_under_panic(skb, len, __builtin_return_address(0)); ++ return skb->data; ++} ++EXPORT_SYMBOL(skb_push); ++ ++/** ++ * skb_pull - remove data from the start of a buffer ++ * @skb: buffer to use ++ * @len: amount of data to remove ++ * ++ * This function removes data from the start of a buffer, returning ++ * the memory to the headroom. A pointer to the next data in the buffer ++ * is returned. Once the data has been pulled future pushes will overwrite ++ * the old data. ++ */ ++unsigned char *skb_pull(struct sk_buff *skb, unsigned int len) ++{ ++ return skb_pull_inline(skb, len); ++} ++EXPORT_SYMBOL(skb_pull); ++ ++/** ++ * skb_trim - remove end from a buffer ++ * @skb: buffer to alter ++ * @len: new length ++ * ++ * Cut the length of a buffer down by removing data from the tail. If ++ * the buffer is already under the length specified it is not modified. ++ * The skb must be linear. ++ */ ++void skb_trim(struct sk_buff *skb, unsigned int len) ++{ ++ if (skb->len > len) ++ __skb_trim(skb, len); ++} ++EXPORT_SYMBOL(skb_trim); ++ ++/* Trims skb to length len. It can change skb pointers. ++ */ ++ ++int ___pskb_trim(struct sk_buff *skb, unsigned int len) ++{ ++ struct sk_buff **fragp; ++ struct sk_buff *frag; ++ int offset = skb_headlen(skb); ++ int nfrags = skb_shinfo(skb)->nr_frags; ++ int i; ++ int err; ++ ++ if (skb_cloned(skb) && ++ unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))) ++ return err; ++ ++ i = 0; ++ if (offset >= len) ++ goto drop_pages; ++ ++ for (; i < nfrags; i++) { ++ int end = offset + skb_frag_size(&skb_shinfo(skb)->frags[i]); ++ ++ if (end < len) { ++ offset = end; ++ continue; + } -+ } + -+ if (unlikely(rx->skb->len < 16)) { -+ I802_DEBUG_INC(rx->local->rx_handlers_drop_short); -+ return RX_DROP_MONITOR; -+ } ++ skb_frag_size_set(&skb_shinfo(skb)->frags[i++], len - offset); + -+ /* Drop disallowed frame classes based on STA auth/assoc state; -+ * IEEE 802.11, Chap 5.5. -+ * -+ * mac80211 filters only based on association state, i.e. it drops -+ * Class 3 frames from not associated stations. hostapd sends -+ * deauth/disassoc frames when needed. In addition, hostapd is -+ * responsible for filtering on both auth and assoc states. -+ */ ++drop_pages: ++ skb_shinfo(skb)->nr_frags = i; + -+ if (ieee80211_vif_is_mesh(&rx->sdata->vif)) -+ return ieee80211_rx_mesh_check(rx); ++ for (; i < nfrags; i++) ++ skb_frag_unref(skb, i); + -+ if (unlikely((ieee80211_is_data(hdr->frame_control) || -+ ieee80211_is_pspoll(hdr->frame_control)) && -+ rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && -+ rx->sdata->vif.type != NL80211_IFTYPE_WDS && -+ (!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) { -+ /* -+ * accept port control frames from the AP even when it's not -+ * yet marked ASSOC to prevent a race where we don't set the -+ * assoc bit quickly enough before it sends the first frame -+ */ -+ if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && -+ ieee80211_is_data_present(hdr->frame_control)) { -+ unsigned int hdrlen; -+ __be16 ethertype; ++ if (skb_has_frag_list(skb)) ++ skb_drop_fraglist(skb); ++ goto done; ++ } ++ ++ for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp); ++ fragp = &frag->next) { ++ int end = offset + frag->len; + -+ hdrlen = ieee80211_hdrlen(hdr->frame_control); ++ if (skb_shared(frag)) { ++ struct sk_buff *nfrag; + -+ if (rx->skb->len < hdrlen + 8) -+ return RX_DROP_MONITOR; ++ nfrag = skb_clone(frag, GFP_ATOMIC); ++ if (unlikely(!nfrag)) ++ return -ENOMEM; ++ ++ nfrag->next = frag->next; ++ consume_skb(frag); ++ frag = nfrag; ++ *fragp = frag; ++ } + -+ skb_copy_bits(rx->skb, hdrlen + 6, ðertype, 2); -+ if (ethertype == rx->sdata->control_port_protocol) -+ return RX_CONTINUE; ++ if (end < len) { ++ offset = end; ++ continue; + } + -+ if (rx->sdata->vif.type == NL80211_IFTYPE_AP && -+ cfg80211_rx_spurious_frame(rx->sdata->dev, -+ hdr->addr2, -+ GFP_ATOMIC)) -+ return RX_DROP_UNUSABLE; ++ if (end > len && ++ unlikely((err = pskb_trim(frag, len - offset)))) ++ return err; ++ ++ if (frag->next) ++ skb_drop_list(&frag->next); ++ break; ++ } + -+ return RX_DROP_MONITOR; ++done: ++ if (len > skb_headlen(skb)) { ++ skb->data_len -= skb->len - len; ++ skb->len = len; ++ } else { ++ skb->len = len; ++ skb->data_len = 0; ++ skb_set_tail_pointer(skb, len); + } + -+ return RX_CONTINUE; ++ return 0; +} ++EXPORT_SYMBOL(___pskb_trim); + ++/** ++ * __pskb_pull_tail - advance tail of skb header ++ * @skb: buffer to reallocate ++ * @delta: number of bytes to advance tail ++ * ++ * The function makes a sense only on a fragmented &sk_buff, ++ * it expands header moving its tail forward and copying necessary ++ * data from fragmented part. ++ * ++ * &sk_buff MUST have reference count of 1. ++ * ++ * Returns %NULL (and &sk_buff does not change) if pull failed ++ * or value of new tail of skb in the case of success. ++ * ++ * All the pointers pointing into skb header may change and must be ++ * reloaded after call to this function. ++ */ + -+static ieee80211_rx_result debug_noinline -+ieee80211_rx_h_check_more_data(struct ieee80211_rx_data *rx) ++/* Moves tail of skb head forward, copying data from fragmented part, ++ * when it is necessary. ++ * 1. It may fail due to malloc failure. ++ * 2. It may change skb pointers. ++ * ++ * It is pretty complicated. Luckily, it is called only in exceptional cases. ++ */ ++unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta) +{ -+ struct ieee80211_local *local; -+ struct ieee80211_hdr *hdr; -+ struct sk_buff *skb; ++ /* If skb has not enough free space at tail, get new one ++ * plus 128 bytes for future expansions. If we have enough ++ * room at tail, reallocate without expansion only if skb is cloned. ++ */ ++ int i, k, eat = (skb->tail + delta) - skb->end; + -+ local = rx->local; -+ skb = rx->skb; -+ hdr = (struct ieee80211_hdr *) skb->data; ++ if (eat > 0 || skb_cloned(skb)) { ++ if (pskb_expand_head(skb, 0, eat > 0 ? eat + 128 : 0, ++ GFP_ATOMIC)) ++ return NULL; ++ } + -+ if (!local->pspolling) -+ return RX_CONTINUE; ++ if (skb_copy_bits(skb, skb_headlen(skb), skb_tail_pointer(skb), delta)) ++ BUG(); + -+ if (!ieee80211_has_fromds(hdr->frame_control)) -+ /* this is not from AP */ -+ return RX_CONTINUE; ++ /* Optimization: no fragments, no reasons to preestimate ++ * size of pulled pages. Superb. ++ */ ++ if (!skb_has_frag_list(skb)) ++ goto pull_pages; + -+ if (!ieee80211_is_data(hdr->frame_control)) -+ return RX_CONTINUE; ++ /* Estimate size of pulled pages. */ ++ eat = delta; ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ int size = skb_frag_size(&skb_shinfo(skb)->frags[i]); + -+ if (!ieee80211_has_moredata(hdr->frame_control)) { -+ /* AP has no more frames buffered for us */ -+ local->pspolling = false; -+ return RX_CONTINUE; ++ if (size >= eat) ++ goto pull_pages; ++ eat -= size; + } + -+ /* more data bit is set, let's request a new frame from the AP */ -+ ieee80211_send_pspoll(local, rx->sdata); -+ -+ return RX_CONTINUE; -+} ++ /* If we need update frag list, we are in troubles. ++ * Certainly, it possible to add an offset to skb data, ++ * but taking into account that pulling is expected to ++ * be very rare operation, it is worth to fight against ++ * further bloating skb head and crucify ourselves here instead. ++ * Pure masohism, indeed. 8)8) ++ */ ++ if (eat) { ++ struct sk_buff *list = skb_shinfo(skb)->frag_list; ++ struct sk_buff *clone = NULL; ++ struct sk_buff *insp = NULL; + -+static void sta_ps_start(struct sta_info *sta) -+{ -+ struct ieee80211_sub_if_data *sdata = sta->sdata; -+ struct ieee80211_local *local = sdata->local; -+ struct ps_data *ps; ++ do { ++ BUG_ON(!list); + -+ if (sta->sdata->vif.type == NL80211_IFTYPE_AP || -+ sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) -+ ps = &sdata->bss->ps; -+ else -+ return; ++ if (list->len <= eat) { ++ /* Eaten as whole. */ ++ eat -= list->len; ++ list = list->next; ++ insp = list; ++ } else { ++ /* Eaten partially. */ ++ ++ if (skb_shared(list)) { ++ /* Sucks! We need to fork list. :-( */ ++ clone = skb_clone(list, GFP_ATOMIC); ++ if (!clone) ++ return NULL; ++ insp = list->next; ++ list = clone; ++ } else { ++ /* This may be pulled without ++ * problems. */ ++ insp = list; ++ } ++ if (!pskb_pull(list, eat)) { ++ kfree_skb(clone); ++ return NULL; ++ } ++ break; ++ } ++ } while (eat); + -+ atomic_inc(&ps->num_sta_ps); -+ set_sta_flag(sta, WLAN_STA_PS_STA); -+ if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) -+ drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta); -+ ps_dbg(sdata, "STA %pM aid %d enters power save mode\n", -+ sta->sta.addr, sta->sta.aid); -+} ++ /* Free pulled out fragments. */ ++ while ((list = skb_shinfo(skb)->frag_list) != insp) { ++ skb_shinfo(skb)->frag_list = list->next; ++ kfree_skb(list); ++ } ++ /* And insert new clone at head. */ ++ if (clone) { ++ clone->next = list; ++ skb_shinfo(skb)->frag_list = clone; ++ } ++ } ++ /* Success! Now we may commit changes to skb data. */ + -+static void sta_ps_end(struct sta_info *sta) -+{ -+ ps_dbg(sta->sdata, "STA %pM aid %d exits power save mode\n", -+ sta->sta.addr, sta->sta.aid); ++pull_pages: ++ eat = delta; ++ k = 0; ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ int size = skb_frag_size(&skb_shinfo(skb)->frags[i]); + -+ if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { -+ /* -+ * Clear the flag only if the other one is still set -+ * so that the TX path won't start TX'ing new frames -+ * directly ... In the case that the driver flag isn't -+ * set ieee80211_sta_ps_deliver_wakeup() will clear it. -+ */ -+ clear_sta_flag(sta, WLAN_STA_PS_STA); -+ ps_dbg(sta->sdata, "STA %pM aid %d driver-ps-blocked\n", -+ sta->sta.addr, sta->sta.aid); -+ return; ++ if (size <= eat) { ++ skb_frag_unref(skb, i); ++ eat -= size; ++ } else { ++ skb_shinfo(skb)->frags[k] = skb_shinfo(skb)->frags[i]; ++ if (eat) { ++ skb_shinfo(skb)->frags[k].page_offset += eat; ++ skb_frag_size_sub(&skb_shinfo(skb)->frags[k], eat); ++ eat = 0; ++ } ++ k++; ++ } + } ++ skb_shinfo(skb)->nr_frags = k; ++ ++ skb->tail += delta; ++ skb->data_len -= delta; + -+ set_sta_flag(sta, WLAN_STA_PS_DELIVER); -+ clear_sta_flag(sta, WLAN_STA_PS_STA); -+ ieee80211_sta_ps_deliver_wakeup(sta); ++ return skb_tail_pointer(skb); +} ++EXPORT_SYMBOL(__pskb_pull_tail); + -+int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start) ++/** ++ * skb_copy_bits - copy bits from skb to kernel buffer ++ * @skb: source skb ++ * @offset: offset in source ++ * @to: destination buffer ++ * @len: number of bytes to copy ++ * ++ * Copy the specified number of bytes from the source skb to the ++ * destination buffer. ++ * ++ * CAUTION ! : ++ * If its prototype is ever changed, ++ * check arch/{*}/net/{*}.S files, ++ * since it is called from BPF assembly code. ++ */ ++int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len) +{ -+ struct sta_info *sta_inf = container_of(sta, struct sta_info, sta); -+ bool in_ps; ++ int start = skb_headlen(skb); ++ struct sk_buff *frag_iter; ++ int i, copy; + -+ WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS)); ++ if (offset > (int)skb->len - len) ++ goto fault; + -+ /* Don't let the same PS state be set twice */ -+ in_ps = test_sta_flag(sta_inf, WLAN_STA_PS_STA); -+ if ((start && in_ps) || (!start && !in_ps)) -+ return -EINVAL; ++ /* Copy header. */ ++ if ((copy = start - offset) > 0) { ++ if (copy > len) ++ copy = len; ++ skb_copy_from_linear_data_offset(skb, offset, to, copy); ++ if ((len -= copy) == 0) ++ return 0; ++ offset += copy; ++ to += copy; ++ } + -+ if (start) -+ sta_ps_start(sta_inf); -+ else -+ sta_ps_end(sta_inf); ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ int end; ++ skb_frag_t *f = &skb_shinfo(skb)->frags[i]; + -+ return 0; -+} -+EXPORT_SYMBOL(ieee80211_sta_ps_transition); ++ WARN_ON(start > offset + len); + -+static ieee80211_rx_result debug_noinline -+ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx) -+{ -+ struct ieee80211_sub_if_data *sdata = rx->sdata; -+ struct ieee80211_hdr *hdr = (void *)rx->skb->data; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); -+ int tid, ac; ++ end = start + skb_frag_size(f); ++ if ((copy = end - offset) > 0) { ++ u8 *vaddr; + -+ if (!rx->sta || !(status->rx_flags & IEEE80211_RX_RA_MATCH)) -+ return RX_CONTINUE; ++ if (copy > len) ++ copy = len; + -+ if (sdata->vif.type != NL80211_IFTYPE_AP && -+ sdata->vif.type != NL80211_IFTYPE_AP_VLAN) -+ return RX_CONTINUE; ++ vaddr = kmap_atomic(skb_frag_page(f)); ++ memcpy(to, ++ vaddr + f->page_offset + offset - start, ++ copy); ++ kunmap_atomic(vaddr); + -+ /* -+ * The device handles station powersave, so don't do anything about -+ * uAPSD and PS-Poll frames (the latter shouldn't even come up from -+ * it to mac80211 since they're handled.) -+ */ -+ if (sdata->local->hw.flags & IEEE80211_HW_AP_LINK_PS) -+ return RX_CONTINUE; ++ if ((len -= copy) == 0) ++ return 0; ++ offset += copy; ++ to += copy; ++ } ++ start = end; ++ } + -+ /* -+ * Don't do anything if the station isn't already asleep. In -+ * the uAPSD case, the station will probably be marked asleep, -+ * in the PS-Poll case the station must be confused ... -+ */ -+ if (!test_sta_flag(rx->sta, WLAN_STA_PS_STA)) -+ return RX_CONTINUE; ++ skb_walk_frags(skb, frag_iter) { ++ int end; + -+ if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) { -+ if (!test_sta_flag(rx->sta, WLAN_STA_SP)) { -+ if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER)) -+ ieee80211_sta_ps_deliver_poll_response(rx->sta); -+ else -+ set_sta_flag(rx->sta, WLAN_STA_PSPOLL); ++ WARN_ON(start > offset + len); ++ ++ end = start + frag_iter->len; ++ if ((copy = end - offset) > 0) { ++ if (copy > len) ++ copy = len; ++ if (skb_copy_bits(frag_iter, offset - start, to, copy)) ++ goto fault; ++ if ((len -= copy) == 0) ++ return 0; ++ offset += copy; ++ to += copy; + } ++ start = end; ++ } + -+ /* Free PS Poll skb here instead of returning RX_DROP that would -+ * count as an dropped frame. */ -+ dev_kfree_skb(rx->skb); ++ if (!len) ++ return 0; + -+ return RX_QUEUED; -+ } else if (!ieee80211_has_morefrags(hdr->frame_control) && -+ !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && -+ ieee80211_has_pm(hdr->frame_control) && -+ (ieee80211_is_data_qos(hdr->frame_control) || -+ ieee80211_is_qos_nullfunc(hdr->frame_control))) { -+ tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; -+ ac = ieee802_1d_to_ac[tid & 7]; ++fault: ++ return -EFAULT; ++} ++EXPORT_SYMBOL(skb_copy_bits); + -+ /* -+ * If this AC is not trigger-enabled do nothing. -+ * -+ * NB: This could/should check a separate bitmap of trigger- -+ * enabled queues, but for now we only implement uAPSD w/o -+ * TSPEC changes to the ACs, so they're always the same. -+ */ -+ if (!(rx->sta->sta.uapsd_queues & BIT(ac))) -+ return RX_CONTINUE; ++/* ++ * Callback from splice_to_pipe(), if we need to release some pages ++ * at the end of the spd in case we error'ed out in filling the pipe. ++ */ ++static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i) ++{ ++ put_page(spd->pages[i]); ++} ++ ++static struct page *linear_to_page(struct page *page, unsigned int *len, ++ unsigned int *offset, ++ struct sock *sk) ++{ ++ struct page_frag *pfrag = sk_page_frag(sk); + -+ /* if we are in a service period, do nothing */ -+ if (test_sta_flag(rx->sta, WLAN_STA_SP)) -+ return RX_CONTINUE; ++ if (!sk_page_frag_refill(sk, pfrag)) ++ return NULL; + -+ if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER)) -+ ieee80211_sta_ps_deliver_uapsd(rx->sta); -+ else -+ set_sta_flag(rx->sta, WLAN_STA_UAPSD); -+ } ++ *len = min_t(unsigned int, *len, pfrag->size - pfrag->offset); + -+ return RX_CONTINUE; ++ memcpy(page_address(pfrag->page) + pfrag->offset, ++ page_address(page) + *offset, *len); ++ *offset = pfrag->offset; ++ pfrag->offset += *len; ++ ++ return pfrag->page; +} + -+static ieee80211_rx_result debug_noinline -+ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) ++static bool spd_can_coalesce(const struct splice_pipe_desc *spd, ++ struct page *page, ++ unsigned int offset) +{ -+ struct sta_info *sta = rx->sta; -+ struct sk_buff *skb = rx->skb; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; -+ int i; ++ return spd->nr_pages && ++ spd->pages[spd->nr_pages - 1] == page && ++ (spd->partial[spd->nr_pages - 1].offset + ++ spd->partial[spd->nr_pages - 1].len == offset); ++} + -+ if (!sta) -+ return RX_CONTINUE; ++/* ++ * Fill page/offset/length into spd, if it can hold more pages. ++ */ ++static bool spd_fill_page(struct splice_pipe_desc *spd, ++ struct pipe_inode_info *pipe, struct page *page, ++ unsigned int *len, unsigned int offset, ++ bool linear, ++ struct sock *sk) ++{ ++ if (unlikely(spd->nr_pages == MAX_SKB_FRAGS)) ++ return true; + -+ /* -+ * Update last_rx only for IBSS packets which are for the current -+ * BSSID and for station already AUTHORIZED to avoid keeping the -+ * current IBSS network alive in cases where other STAs start -+ * using different BSSID. This will also give the station another -+ * chance to restart the authentication/authorization in case -+ * something went wrong the first time. -+ */ -+ if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { -+ u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, -+ NL80211_IFTYPE_ADHOC); -+ if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) && -+ test_sta_flag(sta, WLAN_STA_AUTHORIZED)) { -+ sta->last_rx = jiffies; -+ if (ieee80211_is_data(hdr->frame_control) && -+ !is_multicast_ether_addr(hdr->addr1)) { -+ sta->last_rx_rate_idx = status->rate_idx; -+ sta->last_rx_rate_flag = status->flag; -+ sta->last_rx_rate_vht_flag = status->vht_flag; -+ sta->last_rx_rate_vht_nss = status->vht_nss; -+ } -+ } -+ } else if (!is_multicast_ether_addr(hdr->addr1)) { -+ /* -+ * Mesh beacons will update last_rx when if they are found to -+ * match the current local configuration when processed. -+ */ -+ sta->last_rx = jiffies; -+ if (ieee80211_is_data(hdr->frame_control)) { -+ sta->last_rx_rate_idx = status->rate_idx; -+ sta->last_rx_rate_flag = status->flag; -+ sta->last_rx_rate_vht_flag = status->vht_flag; -+ sta->last_rx_rate_vht_nss = status->vht_nss; -+ } ++ if (linear) { ++ page = linear_to_page(page, len, &offset, sk); ++ if (!page) ++ return true; ++ } ++ if (spd_can_coalesce(spd, page, offset)) { ++ spd->partial[spd->nr_pages - 1].len += *len; ++ return false; + } ++ get_page(page); ++ spd->pages[spd->nr_pages] = page; ++ spd->partial[spd->nr_pages].len = *len; ++ spd->partial[spd->nr_pages].offset = offset; ++ spd->nr_pages++; + -+ if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) -+ return RX_CONTINUE; ++ return false; ++} + -+ if (rx->sdata->vif.type == NL80211_IFTYPE_STATION) -+ ieee80211_sta_rx_notify(rx->sdata, hdr); ++static bool __splice_segment(struct page *page, unsigned int poff, ++ unsigned int plen, unsigned int *off, ++ unsigned int *len, ++ struct splice_pipe_desc *spd, bool linear, ++ struct sock *sk, ++ struct pipe_inode_info *pipe) ++{ ++ if (!*len) ++ return true; + -+ sta->rx_fragments++; -+ sta->rx_bytes += rx->skb->len; -+ if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { -+ sta->last_signal = status->signal; -+ ewma_add(&sta->avg_signal, -status->signal); ++ /* skip this segment if already processed */ ++ if (*off >= plen) { ++ *off -= plen; ++ return false; + } + -+ if (status->chains) { -+ sta->chains = status->chains; -+ for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) { -+ int signal = status->chain_signal[i]; ++ /* ignore any bits we already processed */ ++ poff += *off; ++ plen -= *off; ++ *off = 0; + -+ if (!(status->chains & BIT(i))) -+ continue; ++ do { ++ unsigned int flen = min(*len, plen); + -+ sta->chain_signal_last[i] = signal; -+ ewma_add(&sta->chain_signal_avg[i], -signal); -+ } -+ } ++ if (spd_fill_page(spd, pipe, page, &flen, poff, ++ linear, sk)) ++ return true; ++ poff += flen; ++ plen -= flen; ++ *len -= flen; ++ } while (*len && plen); + -+ /* -+ * Change STA power saving mode only at the end of a frame -+ * exchange sequence. -+ */ -+ if (!(sta->local->hw.flags & IEEE80211_HW_AP_LINK_PS) && -+ !ieee80211_has_morefrags(hdr->frame_control) && -+ !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && -+ (rx->sdata->vif.type == NL80211_IFTYPE_AP || -+ rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && -+ /* PM bit is only checked in frames where it isn't reserved, -+ * in AP mode it's reserved in non-bufferable management frames -+ * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field) -+ */ -+ (!ieee80211_is_mgmt(hdr->frame_control) || -+ ieee80211_is_bufferable_mmpdu(hdr->frame_control))) { -+ if (test_sta_flag(sta, WLAN_STA_PS_STA)) { -+ if (!ieee80211_has_pm(hdr->frame_control)) -+ sta_ps_end(sta); -+ } else { -+ if (ieee80211_has_pm(hdr->frame_control)) -+ sta_ps_start(sta); -+ } -+ } ++ return false; ++} ++ ++/* ++ * Map linear and fragment data from the skb to spd. It reports true if the ++ * pipe is full or if we already spliced the requested length. ++ */ ++static bool __skb_splice_bits(struct sk_buff *skb, struct pipe_inode_info *pipe, ++ unsigned int *offset, unsigned int *len, ++ struct splice_pipe_desc *spd, struct sock *sk) ++{ ++ int seg; + -+ /* mesh power save support */ -+ if (ieee80211_vif_is_mesh(&rx->sdata->vif)) -+ ieee80211_mps_rx_h_sta_process(sta, hdr); ++ /* map the linear part : ++ * If skb->head_frag is set, this 'linear' part is backed by a ++ * fragment, and if the head is not shared with any clones then ++ * we can avoid a copy since we own the head portion of this page. ++ */ ++ if (__splice_segment(virt_to_page(skb->data), ++ (unsigned long) skb->data & (PAGE_SIZE - 1), ++ skb_headlen(skb), ++ offset, len, spd, ++ skb_head_is_locked(skb), ++ sk, pipe)) ++ return true; + + /* -+ * Drop (qos-)data::nullfunc frames silently, since they -+ * are used only to control station power saving mode. ++ * then map the fragments + */ -+ if (ieee80211_is_nullfunc(hdr->frame_control) || -+ ieee80211_is_qos_nullfunc(hdr->frame_control)) { -+ I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc); ++ for (seg = 0; seg < skb_shinfo(skb)->nr_frags; seg++) { ++ const skb_frag_t *f = &skb_shinfo(skb)->frags[seg]; + -+ /* -+ * If we receive a 4-addr nullfunc frame from a STA -+ * that was not moved to a 4-addr STA vlan yet send -+ * the event to userspace and for older hostapd drop -+ * the frame to the monitor interface. -+ */ -+ if (ieee80211_has_a4(hdr->frame_control) && -+ (rx->sdata->vif.type == NL80211_IFTYPE_AP || -+ (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && -+ !rx->sdata->u.vlan.sta))) { -+ if (!test_and_set_sta_flag(sta, WLAN_STA_4ADDR_EVENT)) -+ cfg80211_rx_unexpected_4addr_frame( -+ rx->sdata->dev, sta->sta.addr, -+ GFP_ATOMIC); -+ return RX_DROP_MONITOR; -+ } -+ /* -+ * Update counter and free packet here to avoid -+ * counting this as a dropped packed. -+ */ -+ sta->rx_packets++; -+ dev_kfree_skb(rx->skb); -+ return RX_QUEUED; ++ if (__splice_segment(skb_frag_page(f), ++ f->page_offset, skb_frag_size(f), ++ offset, len, spd, false, sk, pipe)) ++ return true; + } + -+ return RX_CONTINUE; -+} /* ieee80211_rx_h_sta_process */ ++ return false; ++} + -+static ieee80211_rx_result debug_noinline -+ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) -+{ -+ struct sk_buff *skb = rx->skb; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; -+ int keyidx; -+ int hdrlen; -+ ieee80211_rx_result result = RX_DROP_UNUSABLE; -+ struct ieee80211_key *sta_ptk = NULL; -+ int mmie_keyidx = -1; -+ __le16 fc; -+ const struct ieee80211_cipher_scheme *cs = NULL; ++/* ++ * Map data from the skb to a pipe. Should handle both the linear part, ++ * the fragments, and the frag list. It does NOT handle frag lists within ++ * the frag list, if such a thing exists. We'd probably need to recurse to ++ * handle that cleanly. ++ */ ++int skb_splice_bits(struct sk_buff *skb, unsigned int offset, ++ struct pipe_inode_info *pipe, unsigned int tlen, ++ unsigned int flags) ++{ ++ struct partial_page partial[MAX_SKB_FRAGS]; ++ struct page *pages[MAX_SKB_FRAGS]; ++ struct splice_pipe_desc spd = { ++ .pages = pages, ++ .partial = partial, ++ .nr_pages_max = MAX_SKB_FRAGS, ++ .flags = flags, ++ .ops = &nosteal_pipe_buf_ops, ++ .spd_release = sock_spd_release, ++ }; ++ struct sk_buff *frag_iter; ++ struct sock *sk = skb->sk; ++ int ret = 0; + + /* -+ * Key selection 101 -+ * -+ * There are four types of keys: -+ * - GTK (group keys) -+ * - IGTK (group keys for management frames) -+ * - PTK (pairwise keys) -+ * - STK (station-to-station pairwise keys) -+ * -+ * When selecting a key, we have to distinguish between multicast -+ * (including broadcast) and unicast frames, the latter can only -+ * use PTKs and STKs while the former always use GTKs and IGTKs. -+ * Unless, of course, actual WEP keys ("pre-RSNA") are used, then -+ * unicast frames can also use key indices like GTKs. Hence, if we -+ * don't have a PTK/STK we check the key index for a WEP key. -+ * -+ * Note that in a regular BSS, multicast frames are sent by the -+ * AP only, associated stations unicast the frame to the AP first -+ * which then multicasts it on their behalf. -+ * -+ * There is also a slight problem in IBSS mode: GTKs are negotiated -+ * with each station, that is something we don't currently handle. -+ * The spec seems to expect that one negotiates the same key with -+ * every station but there's no such requirement; VLANs could be -+ * possible. ++ * __skb_splice_bits() only fails if the output has no room left, ++ * so no point in going over the frag_list for the error case. + */ ++ if (__skb_splice_bits(skb, pipe, &offset, &tlen, &spd, sk)) ++ goto done; ++ else if (!tlen) ++ goto done; + + /* -+ * No point in finding a key and decrypting if the frame is neither -+ * addressed to us nor a multicast frame. ++ * now see if we have a frag_list to map + */ -+ if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) -+ return RX_CONTINUE; -+ -+ /* start without a key */ -+ rx->key = NULL; -+ fc = hdr->frame_control; -+ -+ if (rx->sta) { -+ int keyid = rx->sta->ptk_idx; ++ skb_walk_frags(skb, frag_iter) { ++ if (!tlen) ++ break; ++ if (__skb_splice_bits(frag_iter, pipe, &offset, &tlen, &spd, sk)) ++ break; ++ } + -+ if (ieee80211_has_protected(fc) && rx->sta->cipher_scheme) { -+ cs = rx->sta->cipher_scheme; -+ keyid = iwl80211_get_cs_keyid(cs, rx->skb); -+ if (unlikely(keyid < 0)) -+ return RX_DROP_UNUSABLE; -+ } -+ sta_ptk = rcu_dereference(rx->sta->ptk[keyid]); -+ } -+ -+ if (!ieee80211_has_protected(fc)) -+ mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb); -+ -+ if (!is_multicast_ether_addr(hdr->addr1) && sta_ptk) { -+ rx->key = sta_ptk; -+ if ((status->flag & RX_FLAG_DECRYPTED) && -+ (status->flag & RX_FLAG_IV_STRIPPED)) -+ return RX_CONTINUE; -+ /* Skip decryption if the frame is not protected. */ -+ if (!ieee80211_has_protected(fc)) -+ return RX_CONTINUE; -+ } else if (mmie_keyidx >= 0) { -+ /* Broadcast/multicast robust management frame / BIP */ -+ if ((status->flag & RX_FLAG_DECRYPTED) && -+ (status->flag & RX_FLAG_IV_STRIPPED)) -+ return RX_CONTINUE; -+ -+ if (mmie_keyidx < NUM_DEFAULT_KEYS || -+ mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) -+ return RX_DROP_MONITOR; /* unexpected BIP keyidx */ -+ if (rx->sta) -+ rx->key = rcu_dereference(rx->sta->gtk[mmie_keyidx]); -+ if (!rx->key) -+ rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]); -+ } else if (!ieee80211_has_protected(fc)) { ++done: ++ if (spd.nr_pages) { + /* -+ * The frame was not protected, so skip decryption. However, we -+ * need to set rx->key if there is a key that could have been -+ * used so that the frame may be dropped if encryption would -+ * have been expected. ++ * Drop the socket lock, otherwise we have reverse ++ * locking dependencies between sk_lock and i_mutex ++ * here as compared to sendfile(). We enter here ++ * with the socket lock held, and splice_to_pipe() will ++ * grab the pipe inode lock. For sendfile() emulation, ++ * we call into ->sendpage() with the i_mutex lock held ++ * and networking will grab the socket lock. + */ -+ struct ieee80211_key *key = NULL; -+ struct ieee80211_sub_if_data *sdata = rx->sdata; -+ int i; ++ release_sock(sk); ++ ret = splice_to_pipe(pipe, &spd); ++ lock_sock(sk); ++ } + -+ if (ieee80211_is_mgmt(fc) && -+ is_multicast_ether_addr(hdr->addr1) && -+ (key = rcu_dereference(rx->sdata->default_mgmt_key))) -+ rx->key = key; -+ else { -+ if (rx->sta) { -+ for (i = 0; i < NUM_DEFAULT_KEYS; i++) { -+ key = rcu_dereference(rx->sta->gtk[i]); -+ if (key) -+ break; -+ } -+ } -+ if (!key) { -+ for (i = 0; i < NUM_DEFAULT_KEYS; i++) { -+ key = rcu_dereference(sdata->keys[i]); -+ if (key) -+ break; -+ } -+ } -+ if (key) -+ rx->key = key; -+ } -+ return RX_CONTINUE; -+ } else { -+ u8 keyid; ++ return ret; ++} + -+ /* -+ * The device doesn't give us the IV so we won't be -+ * able to look up the key. That's ok though, we -+ * don't need to decrypt the frame, we just won't -+ * be able to keep statistics accurate. -+ * Except for key threshold notifications, should -+ * we somehow allow the driver to tell us which key -+ * the hardware used if this flag is set? -+ */ -+ if ((status->flag & RX_FLAG_DECRYPTED) && -+ (status->flag & RX_FLAG_IV_STRIPPED)) -+ return RX_CONTINUE; ++/** ++ * skb_store_bits - store bits from kernel buffer to skb ++ * @skb: destination buffer ++ * @offset: offset in destination ++ * @from: source buffer ++ * @len: number of bytes to copy ++ * ++ * Copy the specified number of bytes from the source buffer to the ++ * destination skb. This function handles all the messy bits of ++ * traversing fragment lists and such. ++ */ + -+ hdrlen = ieee80211_hdrlen(fc); ++int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len) ++{ ++ int start = skb_headlen(skb); ++ struct sk_buff *frag_iter; ++ int i, copy; + -+ if (cs) { -+ keyidx = iwl80211_get_cs_keyid(cs, rx->skb); ++ if (offset > (int)skb->len - len) ++ goto fault; + -+ if (unlikely(keyidx < 0)) -+ return RX_DROP_UNUSABLE; -+ } else { -+ if (rx->skb->len < 8 + hdrlen) -+ return RX_DROP_UNUSABLE; /* TODO: count this? */ -+ /* -+ * no need to call ieee80211_wep_get_keyidx, -+ * it verifies a bunch of things we've done already -+ */ -+ skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1); -+ keyidx = keyid >> 6; -+ } ++ if ((copy = start - offset) > 0) { ++ if (copy > len) ++ copy = len; ++ skb_copy_to_linear_data_offset(skb, offset, from, copy); ++ if ((len -= copy) == 0) ++ return 0; ++ offset += copy; ++ from += copy; ++ } + -+ /* check per-station GTK first, if multicast packet */ -+ if (is_multicast_ether_addr(hdr->addr1) && rx->sta) -+ rx->key = rcu_dereference(rx->sta->gtk[keyidx]); ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ int end; + -+ /* if not found, try default key */ -+ if (!rx->key) { -+ rx->key = rcu_dereference(rx->sdata->keys[keyidx]); ++ WARN_ON(start > offset + len); + -+ /* -+ * RSNA-protected unicast frames should always be -+ * sent with pairwise or station-to-station keys, -+ * but for WEP we allow using a key index as well. -+ */ -+ if (rx->key && -+ rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 && -+ rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 && -+ !is_multicast_ether_addr(hdr->addr1)) -+ rx->key = NULL; ++ end = start + skb_frag_size(frag); ++ if ((copy = end - offset) > 0) { ++ u8 *vaddr; ++ ++ if (copy > len) ++ copy = len; ++ ++ vaddr = kmap_atomic(skb_frag_page(frag)); ++ memcpy(vaddr + frag->page_offset + offset - start, ++ from, copy); ++ kunmap_atomic(vaddr); ++ ++ if ((len -= copy) == 0) ++ return 0; ++ offset += copy; ++ from += copy; + } ++ start = end; + } + -+ if (rx->key) { -+ if (unlikely(rx->key->flags & KEY_FLAG_TAINTED)) -+ return RX_DROP_MONITOR; ++ skb_walk_frags(skb, frag_iter) { ++ int end; + -+ rx->key->tx_rx_count++; -+ /* TODO: add threshold stuff again */ -+ } else { -+ return RX_DROP_MONITOR; ++ WARN_ON(start > offset + len); ++ ++ end = start + frag_iter->len; ++ if ((copy = end - offset) > 0) { ++ if (copy > len) ++ copy = len; ++ if (skb_store_bits(frag_iter, offset - start, ++ from, copy)) ++ goto fault; ++ if ((len -= copy) == 0) ++ return 0; ++ offset += copy; ++ from += copy; ++ } ++ start = end; + } ++ if (!len) ++ return 0; + -+ switch (rx->key->conf.cipher) { -+ case WLAN_CIPHER_SUITE_WEP40: -+ case WLAN_CIPHER_SUITE_WEP104: -+ result = ieee80211_crypto_wep_decrypt(rx); -+ break; -+ case WLAN_CIPHER_SUITE_TKIP: -+ result = ieee80211_crypto_tkip_decrypt(rx); -+ break; -+ case WLAN_CIPHER_SUITE_CCMP: -+ result = ieee80211_crypto_ccmp_decrypt(rx); -+ break; -+ case WLAN_CIPHER_SUITE_AES_CMAC: -+ result = ieee80211_crypto_aes_cmac_decrypt(rx); -+ break; -+ default: -+ result = ieee80211_crypto_hw_decrypt(rx); ++fault: ++ return -EFAULT; ++} ++EXPORT_SYMBOL(skb_store_bits); ++ ++/* Checksum skb data. */ ++__wsum __skb_checksum(const struct sk_buff *skb, int offset, int len, ++ __wsum csum, const struct skb_checksum_ops *ops) ++{ ++ int start = skb_headlen(skb); ++ int i, copy = start - offset; ++ struct sk_buff *frag_iter; ++ int pos = 0; ++ ++ /* Checksum header. */ ++ if (copy > 0) { ++ if (copy > len) ++ copy = len; ++ csum = ops->update(skb->data + offset, copy, csum); ++ if ((len -= copy) == 0) ++ return csum; ++ offset += copy; ++ pos = copy; ++ } ++ ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ int end; ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ ++ WARN_ON(start > offset + len); ++ ++ end = start + skb_frag_size(frag); ++ if ((copy = end - offset) > 0) { ++ __wsum csum2; ++ u8 *vaddr; ++ ++ if (copy > len) ++ copy = len; ++ vaddr = kmap_atomic(skb_frag_page(frag)); ++ csum2 = ops->update(vaddr + frag->page_offset + ++ offset - start, copy, 0); ++ kunmap_atomic(vaddr); ++ csum = ops->combine(csum, csum2, pos, copy); ++ if (!(len -= copy)) ++ return csum; ++ offset += copy; ++ pos += copy; ++ } ++ start = end; ++ } ++ ++ skb_walk_frags(skb, frag_iter) { ++ int end; ++ ++ WARN_ON(start > offset + len); ++ ++ end = start + frag_iter->len; ++ if ((copy = end - offset) > 0) { ++ __wsum csum2; ++ if (copy > len) ++ copy = len; ++ csum2 = __skb_checksum(frag_iter, offset - start, ++ copy, 0, ops); ++ csum = ops->combine(csum, csum2, pos, copy); ++ if ((len -= copy) == 0) ++ return csum; ++ offset += copy; ++ pos += copy; ++ } ++ start = end; + } ++ BUG_ON(len); + -+ /* the hdr variable is invalid after the decrypt handlers */ ++ return csum; ++} ++EXPORT_SYMBOL(__skb_checksum); + -+ /* either the frame has been decrypted or will be dropped */ -+ status->flag |= RX_FLAG_DECRYPTED; ++__wsum skb_checksum(const struct sk_buff *skb, int offset, ++ int len, __wsum csum) ++{ ++ const struct skb_checksum_ops ops = { ++ .update = csum_partial_ext, ++ .combine = csum_block_add_ext, ++ }; + -+ return result; ++ return __skb_checksum(skb, offset, len, csum, &ops); ++} ++EXPORT_SYMBOL(skb_checksum); ++ ++/* Both of above in one bottle. */ ++ ++__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, ++ u8 *to, int len, __wsum csum) ++{ ++ int start = skb_headlen(skb); ++ int i, copy = start - offset; ++ struct sk_buff *frag_iter; ++ int pos = 0; ++ ++ /* Copy header. */ ++ if (copy > 0) { ++ if (copy > len) ++ copy = len; ++ csum = csum_partial_copy_nocheck(skb->data + offset, to, ++ copy, csum); ++ if ((len -= copy) == 0) ++ return csum; ++ offset += copy; ++ to += copy; ++ pos = copy; ++ } ++ ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ int end; ++ ++ WARN_ON(start > offset + len); ++ ++ end = start + skb_frag_size(&skb_shinfo(skb)->frags[i]); ++ if ((copy = end - offset) > 0) { ++ __wsum csum2; ++ u8 *vaddr; ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ ++ if (copy > len) ++ copy = len; ++ vaddr = kmap_atomic(skb_frag_page(frag)); ++ csum2 = csum_partial_copy_nocheck(vaddr + ++ frag->page_offset + ++ offset - start, to, ++ copy, 0); ++ kunmap_atomic(vaddr); ++ csum = csum_block_add(csum, csum2, pos); ++ if (!(len -= copy)) ++ return csum; ++ offset += copy; ++ to += copy; ++ pos += copy; ++ } ++ start = end; ++ } ++ ++ skb_walk_frags(skb, frag_iter) { ++ __wsum csum2; ++ int end; ++ ++ WARN_ON(start > offset + len); ++ ++ end = start + frag_iter->len; ++ if ((copy = end - offset) > 0) { ++ if (copy > len) ++ copy = len; ++ csum2 = skb_copy_and_csum_bits(frag_iter, ++ offset - start, ++ to, copy, 0); ++ csum = csum_block_add(csum, csum2, pos); ++ if ((len -= copy) == 0) ++ return csum; ++ offset += copy; ++ to += copy; ++ pos += copy; ++ } ++ start = end; ++ } ++ BUG_ON(len); ++ return csum; +} ++EXPORT_SYMBOL(skb_copy_and_csum_bits); + -+static inline struct ieee80211_fragment_entry * -+ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, -+ unsigned int frag, unsigned int seq, int rx_queue, -+ struct sk_buff **skb) ++ /** ++ * skb_zerocopy_headlen - Calculate headroom needed for skb_zerocopy() ++ * @from: source buffer ++ * ++ * Calculates the amount of linear headroom needed in the 'to' skb passed ++ * into skb_zerocopy(). ++ */ ++unsigned int ++skb_zerocopy_headlen(const struct sk_buff *from) +{ -+ struct ieee80211_fragment_entry *entry; ++ unsigned int hlen = 0; + -+ entry = &sdata->fragments[sdata->fragment_next++]; -+ if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX) -+ sdata->fragment_next = 0; ++ if (!from->head_frag || ++ skb_headlen(from) < L1_CACHE_BYTES || ++ skb_shinfo(from)->nr_frags >= MAX_SKB_FRAGS) ++ hlen = skb_headlen(from); + -+ if (!skb_queue_empty(&entry->skb_list)) -+ __skb_queue_purge(&entry->skb_list); ++ if (skb_has_frag_list(from)) ++ hlen = from->len; + -+ __skb_queue_tail(&entry->skb_list, *skb); /* no need for locking */ -+ *skb = NULL; -+ entry->first_frag_time = jiffies; -+ entry->seq = seq; -+ entry->rx_queue = rx_queue; -+ entry->last_frag = frag; -+ entry->ccmp = 0; -+ entry->extra_len = 0; -+ -+ return entry; ++ return hlen; +} ++EXPORT_SYMBOL_GPL(skb_zerocopy_headlen); + -+static inline struct ieee80211_fragment_entry * -+ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, -+ unsigned int frag, unsigned int seq, -+ int rx_queue, struct ieee80211_hdr *hdr) ++/** ++ * skb_zerocopy - Zero copy skb to skb ++ * @to: destination buffer ++ * @from: source buffer ++ * @len: number of bytes to copy from source buffer ++ * @hlen: size of linear headroom in destination buffer ++ * ++ * Copies up to `len` bytes from `from` to `to` by creating references ++ * to the frags in the source buffer. ++ * ++ * The `hlen` as calculated by skb_zerocopy_headlen() specifies the ++ * headroom in the `to` buffer. ++ * ++ * Return value: ++ * 0: everything is OK ++ * -ENOMEM: couldn't orphan frags of @from due to lack of memory ++ * -EFAULT: skb_copy_bits() found some problem with skb geometry ++ */ ++int ++skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen) +{ -+ struct ieee80211_fragment_entry *entry; -+ int i, idx; ++ int i, j = 0; ++ int plen = 0; /* length of skb->head fragment */ ++ int ret; ++ struct page *page; ++ unsigned int offset; + -+ idx = sdata->fragment_next; -+ for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) { -+ struct ieee80211_hdr *f_hdr; ++ BUG_ON(!from->head_frag && !hlen); + -+ idx--; -+ if (idx < 0) -+ idx = IEEE80211_FRAGMENT_MAX - 1; ++ /* dont bother with small payloads */ ++ if (len <= skb_tailroom(to)) ++ return skb_copy_bits(from, 0, skb_put(to, len), len); + -+ entry = &sdata->fragments[idx]; -+ if (skb_queue_empty(&entry->skb_list) || entry->seq != seq || -+ entry->rx_queue != rx_queue || -+ entry->last_frag + 1 != frag) -+ continue; ++ if (hlen) { ++ ret = skb_copy_bits(from, 0, skb_put(to, hlen), hlen); ++ if (unlikely(ret)) ++ return ret; ++ len -= hlen; ++ } else { ++ plen = min_t(int, skb_headlen(from), len); ++ if (plen) { ++ page = virt_to_head_page(from->head); ++ offset = from->data - (unsigned char *)page_address(page); ++ __skb_fill_page_desc(to, 0, page, offset, plen); ++ get_page(page); ++ j = 1; ++ len -= plen; ++ } ++ } + -+ f_hdr = (struct ieee80211_hdr *)entry->skb_list.next->data; ++ to->truesize += len + plen; ++ to->len += len + plen; ++ to->data_len += len + plen; + -+ /* -+ * Check ftype and addresses are equal, else check next fragment -+ */ -+ if (((hdr->frame_control ^ f_hdr->frame_control) & -+ cpu_to_le16(IEEE80211_FCTL_FTYPE)) || -+ !ether_addr_equal(hdr->addr1, f_hdr->addr1) || -+ !ether_addr_equal(hdr->addr2, f_hdr->addr2)) -+ continue; ++ if (unlikely(skb_orphan_frags(from, GFP_ATOMIC))) { ++ skb_tx_error(from); ++ return -ENOMEM; ++ } + -+ if (time_after(jiffies, entry->first_frag_time + 2 * HZ)) { -+ __skb_queue_purge(&entry->skb_list); -+ continue; -+ } -+ return entry; ++ for (i = 0; i < skb_shinfo(from)->nr_frags; i++) { ++ if (!len) ++ break; ++ skb_shinfo(to)->frags[j] = skb_shinfo(from)->frags[i]; ++ skb_shinfo(to)->frags[j].size = min_t(int, skb_shinfo(to)->frags[j].size, len); ++ len -= skb_shinfo(to)->frags[j].size; ++ skb_frag_ref(to, j); ++ j++; + } ++ skb_shinfo(to)->nr_frags = j; + -+ return NULL; ++ return 0; +} ++EXPORT_SYMBOL_GPL(skb_zerocopy); + -+static ieee80211_rx_result debug_noinline -+ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) ++void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to) +{ -+ struct ieee80211_hdr *hdr; -+ u16 sc; -+ __le16 fc; -+ unsigned int frag, seq; -+ struct ieee80211_fragment_entry *entry; -+ struct sk_buff *skb; -+ struct ieee80211_rx_status *status; ++ __wsum csum; ++ long csstart; + -+ hdr = (struct ieee80211_hdr *)rx->skb->data; -+ fc = hdr->frame_control; -+ -+ if (ieee80211_is_ctl(fc)) -+ return RX_CONTINUE; -+ -+ sc = le16_to_cpu(hdr->seq_ctrl); -+ frag = sc & IEEE80211_SCTL_FRAG; -+ -+ if (is_multicast_ether_addr(hdr->addr1)) { -+ rx->local->dot11MulticastReceivedFrameCount++; -+ goto out_no_led; -+ } ++ if (skb->ip_summed == CHECKSUM_PARTIAL) ++ csstart = skb_checksum_start_offset(skb); ++ else ++ csstart = skb_headlen(skb); + -+ if (likely(!ieee80211_has_morefrags(fc) && frag == 0)) -+ goto out; ++ BUG_ON(csstart > skb_headlen(skb)); + -+ I802_DEBUG_INC(rx->local->rx_handlers_fragments); ++ skb_copy_from_linear_data(skb, to, csstart); + -+ if (skb_linearize(rx->skb)) -+ return RX_DROP_UNUSABLE; ++ csum = 0; ++ if (csstart != skb->len) ++ csum = skb_copy_and_csum_bits(skb, csstart, to + csstart, ++ skb->len - csstart, 0); + -+ /* -+ * skb_linearize() might change the skb->data and -+ * previously cached variables (in this case, hdr) need to -+ * be refreshed with the new data. -+ */ -+ hdr = (struct ieee80211_hdr *)rx->skb->data; -+ seq = (sc & IEEE80211_SCTL_SEQ) >> 4; -+ -+ if (frag == 0) { -+ /* This is the first fragment of a new frame. */ -+ entry = ieee80211_reassemble_add(rx->sdata, frag, seq, -+ rx->seqno_idx, &(rx->skb)); -+ if (rx->key && rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP && -+ ieee80211_has_protected(fc)) { -+ int queue = rx->security_idx; -+ /* Store CCMP PN so that we can verify that the next -+ * fragment has a sequential PN value. */ -+ entry->ccmp = 1; -+ memcpy(entry->last_pn, -+ rx->key->u.ccmp.rx_pn[queue], -+ IEEE80211_CCMP_PN_LEN); -+ } -+ return RX_QUEUED; -+ } ++ if (skb->ip_summed == CHECKSUM_PARTIAL) { ++ long csstuff = csstart + skb->csum_offset; + -+ /* This is a fragment for a frame that should already be pending in -+ * fragment cache. Add this fragment to the end of the pending entry. -+ */ -+ entry = ieee80211_reassemble_find(rx->sdata, frag, seq, -+ rx->seqno_idx, hdr); -+ if (!entry) { -+ I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); -+ return RX_DROP_MONITOR; ++ *((__sum16 *)(to + csstuff)) = csum_fold(csum); + } ++} ++EXPORT_SYMBOL(skb_copy_and_csum_dev); + -+ /* Verify that MPDUs within one MSDU have sequential PN values. -+ * (IEEE 802.11i, 8.3.3.4.5) */ -+ if (entry->ccmp) { -+ int i; -+ u8 pn[IEEE80211_CCMP_PN_LEN], *rpn; -+ int queue; -+ if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP) -+ return RX_DROP_UNUSABLE; -+ memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN); -+ for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) { -+ pn[i]++; -+ if (pn[i]) -+ break; -+ } -+ queue = rx->security_idx; -+ rpn = rx->key->u.ccmp.rx_pn[queue]; -+ if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN)) -+ return RX_DROP_UNUSABLE; -+ memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN); -+ } -+ -+ skb_pull(rx->skb, ieee80211_hdrlen(fc)); -+ __skb_queue_tail(&entry->skb_list, rx->skb); -+ entry->last_frag = frag; -+ entry->extra_len += rx->skb->len; -+ if (ieee80211_has_morefrags(fc)) { -+ rx->skb = NULL; -+ return RX_QUEUED; -+ } -+ -+ rx->skb = __skb_dequeue(&entry->skb_list); -+ if (skb_tailroom(rx->skb) < entry->extra_len) { -+ I802_DEBUG_INC(rx->local->rx_expand_skb_head2); -+ if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len, -+ GFP_ATOMIC))) { -+ I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); -+ __skb_queue_purge(&entry->skb_list); -+ return RX_DROP_UNUSABLE; -+ } -+ } -+ while ((skb = __skb_dequeue(&entry->skb_list))) { -+ memcpy(skb_put(rx->skb, skb->len), skb->data, skb->len); -+ dev_kfree_skb(skb); -+ } ++/** ++ * skb_dequeue - remove from the head of the queue ++ * @list: list to dequeue from ++ * ++ * Remove the head of the list. The list lock is taken so the function ++ * may be used safely with other locking list functions. The head item is ++ * returned or %NULL if the list is empty. ++ */ + -+ /* Complete frame has been reassembled - process it now */ -+ status = IEEE80211_SKB_RXCB(rx->skb); -+ status->rx_flags |= IEEE80211_RX_FRAGMENTED; ++struct sk_buff *skb_dequeue(struct sk_buff_head *list) ++{ ++ unsigned long flags; ++ struct sk_buff *result; + -+ out: -+ ieee80211_led_rx(rx->local); -+ out_no_led: -+ if (rx->sta) -+ rx->sta->rx_packets++; -+ return RX_CONTINUE; ++ spin_lock_irqsave(&list->lock, flags); ++ result = __skb_dequeue(list); ++ spin_unlock_irqrestore(&list->lock, flags); ++ return result; +} ++EXPORT_SYMBOL(skb_dequeue); + -+static int ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) ++/** ++ * skb_dequeue_tail - remove from the tail of the queue ++ * @list: list to dequeue from ++ * ++ * Remove the tail of the list. The list lock is taken so the function ++ * may be used safely with other locking list functions. The tail item is ++ * returned or %NULL if the list is empty. ++ */ ++struct sk_buff *skb_dequeue_tail(struct sk_buff_head *list) +{ -+ if (unlikely(!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_AUTHORIZED))) -+ return -EACCES; ++ unsigned long flags; ++ struct sk_buff *result; + -+ return 0; ++ spin_lock_irqsave(&list->lock, flags); ++ result = __skb_dequeue_tail(list); ++ spin_unlock_irqrestore(&list->lock, flags); ++ return result; +} ++EXPORT_SYMBOL(skb_dequeue_tail); + -+static int ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) ++/** ++ * skb_queue_purge - empty a list ++ * @list: list to empty ++ * ++ * Delete all buffers on an &sk_buff list. Each buffer is removed from ++ * the list and one reference dropped. This function takes the list ++ * lock and is atomic with respect to other list locking functions. ++ */ ++void skb_queue_purge(struct sk_buff_head *list) +{ -+ struct sk_buff *skb = rx->skb; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); ++ struct sk_buff *skb; ++ while ((skb = skb_dequeue(list)) != NULL) ++ kfree_skb(skb); ++} ++EXPORT_SYMBOL(skb_queue_purge); + -+ /* -+ * Pass through unencrypted frames if the hardware has -+ * decrypted them already. -+ */ -+ if (status->flag & RX_FLAG_DECRYPTED) -+ return 0; ++/** ++ * skb_queue_head - queue a buffer at the list head ++ * @list: list to use ++ * @newsk: buffer to queue ++ * ++ * Queue a buffer at the start of the list. This function takes the ++ * list lock and can be used safely with other locking &sk_buff functions ++ * safely. ++ * ++ * A buffer cannot be placed on two lists at the same time. ++ */ ++void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk) ++{ ++ unsigned long flags; + -+ /* Drop unencrypted frames if key is set. */ -+ if (unlikely(!ieee80211_has_protected(fc) && -+ !ieee80211_is_nullfunc(fc) && -+ ieee80211_is_data(fc) && -+ (rx->key || rx->sdata->drop_unencrypted))) -+ return -EACCES; ++ spin_lock_irqsave(&list->lock, flags); ++ __skb_queue_head(list, newsk); ++ spin_unlock_irqrestore(&list->lock, flags); ++} ++EXPORT_SYMBOL(skb_queue_head); + -+ return 0; ++/** ++ * skb_queue_tail - queue a buffer at the list tail ++ * @list: list to use ++ * @newsk: buffer to queue ++ * ++ * Queue a buffer at the tail of the list. This function takes the ++ * list lock and can be used safely with other locking &sk_buff functions ++ * safely. ++ * ++ * A buffer cannot be placed on two lists at the same time. ++ */ ++void skb_queue_tail(struct sk_buff_head *list, struct sk_buff *newsk) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&list->lock, flags); ++ __skb_queue_tail(list, newsk); ++ spin_unlock_irqrestore(&list->lock, flags); +} ++EXPORT_SYMBOL(skb_queue_tail); + -+static int ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) ++/** ++ * skb_unlink - remove a buffer from a list ++ * @skb: buffer to remove ++ * @list: list to use ++ * ++ * Remove a packet from a list. The list locks are taken and this ++ * function is atomic with respect to other list locked calls ++ * ++ * You must know what list the SKB is on. ++ */ ++void skb_unlink(struct sk_buff *skb, struct sk_buff_head *list) +{ -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); -+ __le16 fc = hdr->frame_control; ++ unsigned long flags; + -+ /* -+ * Pass through unencrypted frames if the hardware has -+ * decrypted them already. -+ */ -+ if (status->flag & RX_FLAG_DECRYPTED) -+ return 0; ++ spin_lock_irqsave(&list->lock, flags); ++ __skb_unlink(skb, list); ++ spin_unlock_irqrestore(&list->lock, flags); ++} ++EXPORT_SYMBOL(skb_unlink); + -+ if (rx->sta && test_sta_flag(rx->sta, WLAN_STA_MFP)) { -+ if (unlikely(!ieee80211_has_protected(fc) && -+ ieee80211_is_unicast_robust_mgmt_frame(rx->skb) && -+ rx->key)) { -+ if (ieee80211_is_deauth(fc) || -+ ieee80211_is_disassoc(fc)) -+ cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev, -+ rx->skb->data, -+ rx->skb->len); -+ return -EACCES; -+ } -+ /* BIP does not use Protected field, so need to check MMIE */ -+ if (unlikely(ieee80211_is_multicast_robust_mgmt_frame(rx->skb) && -+ ieee80211_get_mmie_keyidx(rx->skb) < 0)) { -+ if (ieee80211_is_deauth(fc) || -+ ieee80211_is_disassoc(fc)) -+ cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev, -+ rx->skb->data, -+ rx->skb->len); -+ return -EACCES; -+ } -+ /* -+ * When using MFP, Action frames are not allowed prior to -+ * having configured keys. -+ */ -+ if (unlikely(ieee80211_is_action(fc) && !rx->key && -+ ieee80211_is_robust_mgmt_frame(rx->skb))) -+ return -EACCES; -+ } ++/** ++ * skb_append - append a buffer ++ * @old: buffer to insert after ++ * @newsk: buffer to insert ++ * @list: list to use ++ * ++ * Place a packet after a given packet in a list. The list locks are taken ++ * and this function is atomic with respect to other list locked calls. ++ * A buffer cannot be placed on two lists at the same time. ++ */ ++void skb_append(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list) ++{ ++ unsigned long flags; + -+ return 0; ++ spin_lock_irqsave(&list->lock, flags); ++ __skb_queue_after(list, old, newsk); ++ spin_unlock_irqrestore(&list->lock, flags); +} ++EXPORT_SYMBOL(skb_append); + -+static int -+__ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control) ++/** ++ * skb_insert - insert a buffer ++ * @old: buffer to insert before ++ * @newsk: buffer to insert ++ * @list: list to use ++ * ++ * Place a packet before a given packet in a list. The list locks are ++ * taken and this function is atomic with respect to other list locked ++ * calls. ++ * ++ * A buffer cannot be placed on two lists at the same time. ++ */ ++void skb_insert(struct sk_buff *old, struct sk_buff *newsk, struct sk_buff_head *list) +{ -+ struct ieee80211_sub_if_data *sdata = rx->sdata; -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; -+ bool check_port_control = false; -+ struct ethhdr *ehdr; -+ int ret; ++ unsigned long flags; + -+ *port_control = false; -+ if (ieee80211_has_a4(hdr->frame_control) && -+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta) -+ return -1; ++ spin_lock_irqsave(&list->lock, flags); ++ __skb_insert(newsk, old->prev, old, list); ++ spin_unlock_irqrestore(&list->lock, flags); ++} ++EXPORT_SYMBOL(skb_insert); + -+ if (sdata->vif.type == NL80211_IFTYPE_STATION && -+ !!sdata->u.mgd.use_4addr != !!ieee80211_has_a4(hdr->frame_control)) { ++static inline void skb_split_inside_header(struct sk_buff *skb, ++ struct sk_buff* skb1, ++ const u32 len, const int pos) ++{ ++ int i; + -+ if (!sdata->u.mgd.use_4addr) -+ return -1; -+ else -+ check_port_control = true; ++ skb_copy_from_linear_data_offset(skb, len, skb_put(skb1, pos - len), ++ pos - len); ++ /* And move data appendix as is. */ ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) ++ skb_shinfo(skb1)->frags[i] = skb_shinfo(skb)->frags[i]; ++ ++ skb_shinfo(skb1)->nr_frags = skb_shinfo(skb)->nr_frags; ++ skb_shinfo(skb)->nr_frags = 0; ++ skb1->data_len = skb->data_len; ++ skb1->len += skb1->data_len; ++ skb->data_len = 0; ++ skb->len = len; ++ skb_set_tail_pointer(skb, len); ++} ++ ++static inline void skb_split_no_header(struct sk_buff *skb, ++ struct sk_buff* skb1, ++ const u32 len, int pos) ++{ ++ int i, k = 0; ++ const int nfrags = skb_shinfo(skb)->nr_frags; ++ ++ skb_shinfo(skb)->nr_frags = 0; ++ skb1->len = skb1->data_len = skb->len - len; ++ skb->len = len; ++ skb->data_len = len - pos; ++ ++ for (i = 0; i < nfrags; i++) { ++ int size = skb_frag_size(&skb_shinfo(skb)->frags[i]); ++ ++ if (pos + size > len) { ++ skb_shinfo(skb1)->frags[k] = skb_shinfo(skb)->frags[i]; ++ ++ if (pos < len) { ++ /* Split frag. ++ * We have two variants in this case: ++ * 1. Move all the frag to the second ++ * part, if it is possible. F.e. ++ * this approach is mandatory for TUX, ++ * where splitting is expensive. ++ * 2. Split is accurately. We make this. ++ */ ++ skb_frag_ref(skb, i); ++ skb_shinfo(skb1)->frags[0].page_offset += len - pos; ++ skb_frag_size_sub(&skb_shinfo(skb1)->frags[0], len - pos); ++ skb_frag_size_set(&skb_shinfo(skb)->frags[i], len - pos); ++ skb_shinfo(skb)->nr_frags++; ++ } ++ k++; ++ } else ++ skb_shinfo(skb)->nr_frags++; ++ pos += size; + } ++ skb_shinfo(skb1)->nr_frags = k; ++} + -+ if (is_multicast_ether_addr(hdr->addr1) && -+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta) -+ return -1; -+ -+ ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); -+ if (ret < 0) -+ return ret; ++/** ++ * skb_split - Split fragmented skb to two parts at length len. ++ * @skb: the buffer to split ++ * @skb1: the buffer to receive the second part ++ * @len: new length for skb ++ */ ++void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len) ++{ ++ int pos = skb_headlen(skb); + -+ ehdr = (struct ethhdr *) rx->skb->data; -+ if (ehdr->h_proto == rx->sdata->control_port_protocol) -+ *port_control = true; -+ else if (check_port_control) -+ return -1; ++ skb_shinfo(skb1)->tx_flags = skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG; ++ if (len < pos) /* Split line is inside header. */ ++ skb_split_inside_header(skb, skb1, len, pos); ++ else /* Second chunk has no header, nothing to copy. */ ++ skb_split_no_header(skb, skb1, len, pos); ++} ++EXPORT_SYMBOL(skb_split); + -+ return 0; ++/* Shifting from/to a cloned skb is a no-go. ++ * ++ * Caller cannot keep skb_shinfo related pointers past calling here! ++ */ ++static int skb_prepare_for_shift(struct sk_buff *skb) ++{ ++ return skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC); +} + -+/* -+ * requires that rx->skb is a frame with ethernet header ++/** ++ * skb_shift - Shifts paged data partially from skb to another ++ * @tgt: buffer into which tail data gets added ++ * @skb: buffer from which the paged data comes from ++ * @shiftlen: shift up to this many bytes ++ * ++ * Attempts to shift up to shiftlen worth of bytes, which may be less than ++ * the length of the skb, from skb to tgt. Returns number bytes shifted. ++ * It's up to caller to free skb if everything was shifted. ++ * ++ * If @tgt runs out of frags, the whole operation is aborted. ++ * ++ * Skb cannot include anything else but paged data while tgt is allowed ++ * to have non-paged data as well. ++ * ++ * TODO: full sized shift could be optimized but that would need ++ * specialized skb free'er to handle frags without up-to-date nr_frags. + */ -+static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) ++int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen) +{ -+ static const u8 pae_group_addr[ETH_ALEN] __aligned(2) -+ = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 }; -+ struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; ++ int from, to, merge, todo; ++ struct skb_frag_struct *fragfrom, *fragto; + -+ /* -+ * Allow EAPOL frames to us/the PAE group address regardless -+ * of whether the frame was encrypted or not. -+ */ -+ if (ehdr->h_proto == rx->sdata->control_port_protocol && -+ (ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) || -+ ether_addr_equal(ehdr->h_dest, pae_group_addr))) -+ return true; ++ BUG_ON(shiftlen > skb->len); ++ BUG_ON(skb_headlen(skb)); /* Would corrupt stream */ + -+ if (ieee80211_802_1x_port_control(rx) || -+ ieee80211_drop_unencrypted(rx, fc)) -+ return false; ++ todo = shiftlen; ++ from = 0; ++ to = skb_shinfo(tgt)->nr_frags; ++ fragfrom = &skb_shinfo(skb)->frags[from]; + -+ return true; -+} ++ /* Actual merge is delayed until the point when we know we can ++ * commit all, so that we don't have to undo partial changes ++ */ ++ if (!to || ++ !skb_can_coalesce(tgt, to, skb_frag_page(fragfrom), ++ fragfrom->page_offset)) { ++ merge = -1; ++ } else { ++ merge = to - 1; + -+/* -+ * requires that rx->skb is a frame with ethernet header -+ */ -+static void -+ieee80211_deliver_skb(struct ieee80211_rx_data *rx) -+{ -+ struct ieee80211_sub_if_data *sdata = rx->sdata; -+ struct net_device *dev = sdata->dev; -+ struct sk_buff *skb, *xmit_skb; -+ struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; -+ struct sta_info *dsta; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); -+ -+ skb = rx->skb; -+ xmit_skb = NULL; -+ -+ if ((sdata->vif.type == NL80211_IFTYPE_AP || -+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && -+ !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && -+ (status->rx_flags & IEEE80211_RX_RA_MATCH) && -+ (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) { -+ if (is_multicast_ether_addr(ehdr->h_dest)) { -+ /* -+ * send multicast frames both to higher layers in -+ * local net stack and back to the wireless medium -+ */ -+ xmit_skb = skb_copy(skb, GFP_ATOMIC); -+ if (!xmit_skb) -+ net_info_ratelimited("%s: failed to clone multicast frame\n", -+ dev->name); -+ } else { -+ dsta = sta_info_get(sdata, skb->data); -+ if (dsta) { -+ /* -+ * The destination station is associated to -+ * this AP (in this VLAN), so send the frame -+ * directly to it and do not pass it to local -+ * net stack. -+ */ -+ xmit_skb = skb; -+ skb = NULL; -+ } -+ } -+ } ++ todo -= skb_frag_size(fragfrom); ++ if (todo < 0) { ++ if (skb_prepare_for_shift(skb) || ++ skb_prepare_for_shift(tgt)) ++ return 0; + -+#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS -+ if (skb) { -+ /* 'align' will only take the values 0 or 2 here since all -+ * frames are required to be aligned to 2-byte boundaries -+ * when being passed to mac80211; the code here works just -+ * as well if that isn't true, but mac80211 assumes it can -+ * access fields as 2-byte aligned (e.g. for ether_addr_equal) -+ */ -+ int align; ++ /* All previous frag pointers might be stale! */ ++ fragfrom = &skb_shinfo(skb)->frags[from]; ++ fragto = &skb_shinfo(tgt)->frags[merge]; + -+ align = (unsigned long)(skb->data + sizeof(struct ethhdr)) & 3; -+ if (align) { -+ if (WARN_ON(skb_headroom(skb) < 3)) { -+ dev_kfree_skb(skb); -+ skb = NULL; -+ } else { -+ u8 *data = skb->data; -+ size_t len = skb_headlen(skb); -+ skb->data -= align; -+ memmove(skb->data, data, len); -+ skb_set_tail_pointer(skb, len); -+ } ++ skb_frag_size_add(fragto, shiftlen); ++ skb_frag_size_sub(fragfrom, shiftlen); ++ fragfrom->page_offset += shiftlen; ++ ++ goto onlymerged; + } -+ } -+#endif + -+ if (skb) { -+ /* deliver to local stack */ -+ skb->protocol = eth_type_trans(skb, dev); -+ memset(skb->cb, 0, sizeof(skb->cb)); -+ if (rx->local->napi) -+ napi_gro_receive(rx->local->napi, skb); -+ else -+ netif_receive_skb(skb); ++ from++; + } + -+ if (xmit_skb) { -+ /* -+ * Send to wireless media and increase priority by 256 to -+ * keep the received priority instead of reclassifying -+ * the frame (see cfg80211_classify8021d). -+ */ -+ xmit_skb->priority += 256; -+ xmit_skb->protocol = htons(ETH_P_802_3); -+ skb_reset_network_header(xmit_skb); -+ skb_reset_mac_header(xmit_skb); -+ dev_queue_xmit(xmit_skb); -+ } -+} ++ /* Skip full, not-fitting skb to avoid expensive operations */ ++ if ((shiftlen == skb->len) && ++ (skb_shinfo(skb)->nr_frags - from) > (MAX_SKB_FRAGS - to)) ++ return 0; + -+static ieee80211_rx_result debug_noinline -+ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) -+{ -+ struct net_device *dev = rx->sdata->dev; -+ struct sk_buff *skb = rx->skb; -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; -+ __le16 fc = hdr->frame_control; -+ struct sk_buff_head frame_list; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); ++ if (skb_prepare_for_shift(skb) || skb_prepare_for_shift(tgt)) ++ return 0; + -+ if (unlikely(!ieee80211_is_data(fc))) -+ return RX_CONTINUE; ++ while ((todo > 0) && (from < skb_shinfo(skb)->nr_frags)) { ++ if (to == MAX_SKB_FRAGS) ++ return 0; + -+ if (unlikely(!ieee80211_is_data_present(fc))) -+ return RX_DROP_MONITOR; ++ fragfrom = &skb_shinfo(skb)->frags[from]; ++ fragto = &skb_shinfo(tgt)->frags[to]; + -+ if (!(status->rx_flags & IEEE80211_RX_AMSDU)) -+ return RX_CONTINUE; ++ if (todo >= skb_frag_size(fragfrom)) { ++ *fragto = *fragfrom; ++ todo -= skb_frag_size(fragfrom); ++ from++; ++ to++; + -+ if (ieee80211_has_a4(hdr->frame_control) && -+ rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && -+ !rx->sdata->u.vlan.sta) -+ return RX_DROP_UNUSABLE; ++ } else { ++ __skb_frag_ref(fragfrom); ++ fragto->page = fragfrom->page; ++ fragto->page_offset = fragfrom->page_offset; ++ skb_frag_size_set(fragto, todo); + -+ if (is_multicast_ether_addr(hdr->addr1) && -+ ((rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && -+ rx->sdata->u.vlan.sta) || -+ (rx->sdata->vif.type == NL80211_IFTYPE_STATION && -+ rx->sdata->u.mgd.use_4addr))) -+ return RX_DROP_UNUSABLE; ++ fragfrom->page_offset += todo; ++ skb_frag_size_sub(fragfrom, todo); ++ todo = 0; + -+ skb->dev = dev; -+ __skb_queue_head_init(&frame_list); ++ to++; ++ break; ++ } ++ } + -+ if (skb_linearize(skb)) -+ return RX_DROP_UNUSABLE; ++ /* Ready to "commit" this state change to tgt */ ++ skb_shinfo(tgt)->nr_frags = to; + -+ ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, -+ rx->sdata->vif.type, -+ rx->local->hw.extra_tx_headroom, true); ++ if (merge >= 0) { ++ fragfrom = &skb_shinfo(skb)->frags[0]; ++ fragto = &skb_shinfo(tgt)->frags[merge]; + -+ while (!skb_queue_empty(&frame_list)) { -+ rx->skb = __skb_dequeue(&frame_list); ++ skb_frag_size_add(fragto, skb_frag_size(fragfrom)); ++ __skb_frag_unref(fragfrom); ++ } + -+ if (!ieee80211_frame_allowed(rx, fc)) { -+ dev_kfree_skb(rx->skb); -+ continue; -+ } -+ dev->stats.rx_packets++; -+ dev->stats.rx_bytes += rx->skb->len; ++ /* Reposition in the original skb */ ++ to = 0; ++ while (from < skb_shinfo(skb)->nr_frags) ++ skb_shinfo(skb)->frags[to++] = skb_shinfo(skb)->frags[from++]; ++ skb_shinfo(skb)->nr_frags = to; + -+ ieee80211_deliver_skb(rx); -+ } ++ BUG_ON(todo > 0 && !skb_shinfo(skb)->nr_frags); + -+ return RX_QUEUED; -+} ++onlymerged: ++ /* Most likely the tgt won't ever need its checksum anymore, skb on ++ * the other hand might need it if it needs to be resent ++ */ ++ tgt->ip_summed = CHECKSUM_PARTIAL; ++ skb->ip_summed = CHECKSUM_PARTIAL; + -+#ifdef CONFIG_MAC80211_MESH -+static ieee80211_rx_result -+ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) -+{ -+ struct ieee80211_hdr *fwd_hdr, *hdr; -+ struct ieee80211_tx_info *info; -+ struct ieee80211s_hdr *mesh_hdr; -+ struct sk_buff *skb = rx->skb, *fwd_skb; -+ struct ieee80211_local *local = rx->local; -+ struct ieee80211_sub_if_data *sdata = rx->sdata; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); -+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; -+ u16 q, hdrlen; ++ /* Yak, is it really working this way? Some helper please? */ ++ skb->len -= shiftlen; ++ skb->data_len -= shiftlen; ++ skb->truesize -= shiftlen; ++ tgt->len += shiftlen; ++ tgt->data_len += shiftlen; ++ tgt->truesize += shiftlen; + -+ hdr = (struct ieee80211_hdr *) skb->data; -+ hdrlen = ieee80211_hdrlen(hdr->frame_control); ++ return shiftlen; ++} + -+ /* make sure fixed part of mesh header is there, also checks skb len */ -+ if (!pskb_may_pull(rx->skb, hdrlen + 6)) -+ return RX_DROP_MONITOR; ++/** ++ * skb_prepare_seq_read - Prepare a sequential read of skb data ++ * @skb: the buffer to read ++ * @from: lower offset of data to be read ++ * @to: upper offset of data to be read ++ * @st: state variable ++ * ++ * Initializes the specified state variable. Must be called before ++ * invoking skb_seq_read() for the first time. ++ */ ++void skb_prepare_seq_read(struct sk_buff *skb, unsigned int from, ++ unsigned int to, struct skb_seq_state *st) ++{ ++ st->lower_offset = from; ++ st->upper_offset = to; ++ st->root_skb = st->cur_skb = skb; ++ st->frag_idx = st->stepped_offset = 0; ++ st->frag_data = NULL; ++} ++EXPORT_SYMBOL(skb_prepare_seq_read); + -+ mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); ++/** ++ * skb_seq_read - Sequentially read skb data ++ * @consumed: number of bytes consumed by the caller so far ++ * @data: destination pointer for data to be returned ++ * @st: state variable ++ * ++ * Reads a block of skb data at @consumed relative to the ++ * lower offset specified to skb_prepare_seq_read(). Assigns ++ * the head of the data block to @data and returns the length ++ * of the block or 0 if the end of the skb data or the upper ++ * offset has been reached. ++ * ++ * The caller is not required to consume all of the data ++ * returned, i.e. @consumed is typically set to the number ++ * of bytes already consumed and the next call to ++ * skb_seq_read() will return the remaining part of the block. ++ * ++ * Note 1: The size of each block of data returned can be arbitrary, ++ * this limitation is the cost for zerocopy sequential ++ * reads of potentially non linear data. ++ * ++ * Note 2: Fragment lists within fragments are not implemented ++ * at the moment, state->root_skb could be replaced with ++ * a stack for this purpose. ++ */ ++unsigned int skb_seq_read(unsigned int consumed, const u8 **data, ++ struct skb_seq_state *st) ++{ ++ unsigned int block_limit, abs_offset = consumed + st->lower_offset; ++ skb_frag_t *frag; + -+ /* make sure full mesh header is there, also checks skb len */ -+ if (!pskb_may_pull(rx->skb, -+ hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr))) -+ return RX_DROP_MONITOR; ++ if (unlikely(abs_offset >= st->upper_offset)) { ++ if (st->frag_data) { ++ kunmap_atomic(st->frag_data); ++ st->frag_data = NULL; ++ } ++ return 0; ++ } + -+ /* reload pointers */ -+ hdr = (struct ieee80211_hdr *) skb->data; -+ mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); ++next_skb: ++ block_limit = skb_headlen(st->cur_skb) + st->stepped_offset; + -+ if (ieee80211_drop_unencrypted(rx, hdr->frame_control)) -+ return RX_DROP_MONITOR; ++ if (abs_offset < block_limit && !st->frag_data) { ++ *data = st->cur_skb->data + (abs_offset - st->stepped_offset); ++ return block_limit - abs_offset; ++ } + -+ /* frame is in RMC, don't forward */ -+ if (ieee80211_is_data(hdr->frame_control) && -+ is_multicast_ether_addr(hdr->addr1) && -+ mesh_rmc_check(rx->sdata, hdr->addr3, mesh_hdr)) -+ return RX_DROP_MONITOR; ++ if (st->frag_idx == 0 && !st->frag_data) ++ st->stepped_offset += skb_headlen(st->cur_skb); + -+ if (!ieee80211_is_data(hdr->frame_control) || -+ !(status->rx_flags & IEEE80211_RX_RA_MATCH)) -+ return RX_CONTINUE; ++ while (st->frag_idx < skb_shinfo(st->cur_skb)->nr_frags) { ++ frag = &skb_shinfo(st->cur_skb)->frags[st->frag_idx]; ++ block_limit = skb_frag_size(frag) + st->stepped_offset; + -+ if (!mesh_hdr->ttl) -+ return RX_DROP_MONITOR; ++ if (abs_offset < block_limit) { ++ if (!st->frag_data) ++ st->frag_data = kmap_atomic(skb_frag_page(frag)); + -+ if (mesh_hdr->flags & MESH_FLAGS_AE) { -+ struct mesh_path *mppath; -+ char *proxied_addr; -+ char *mpp_addr; ++ *data = (u8 *) st->frag_data + frag->page_offset + ++ (abs_offset - st->stepped_offset); + -+ if (is_multicast_ether_addr(hdr->addr1)) { -+ mpp_addr = hdr->addr3; -+ proxied_addr = mesh_hdr->eaddr1; -+ } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) { -+ /* has_a4 already checked in ieee80211_rx_mesh_check */ -+ mpp_addr = hdr->addr4; -+ proxied_addr = mesh_hdr->eaddr2; -+ } else { -+ return RX_DROP_MONITOR; ++ return block_limit - abs_offset; + } + -+ rcu_read_lock(); -+ mppath = mpp_path_lookup(sdata, proxied_addr); -+ if (!mppath) { -+ mpp_path_add(sdata, proxied_addr, mpp_addr); -+ } else { -+ spin_lock_bh(&mppath->state_lock); -+ if (!ether_addr_equal(mppath->mpp, mpp_addr)) -+ memcpy(mppath->mpp, mpp_addr, ETH_ALEN); -+ spin_unlock_bh(&mppath->state_lock); ++ if (st->frag_data) { ++ kunmap_atomic(st->frag_data); ++ st->frag_data = NULL; + } -+ rcu_read_unlock(); -+ } + -+ /* Frame has reached destination. Don't forward */ -+ if (!is_multicast_ether_addr(hdr->addr1) && -+ ether_addr_equal(sdata->vif.addr, hdr->addr3)) -+ return RX_CONTINUE; ++ st->frag_idx++; ++ st->stepped_offset += skb_frag_size(frag); ++ } + -+ q = ieee80211_select_queue_80211(sdata, skb, hdr); -+ if (ieee80211_queue_stopped(&local->hw, q)) { -+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_congestion); -+ return RX_DROP_MONITOR; ++ if (st->frag_data) { ++ kunmap_atomic(st->frag_data); ++ st->frag_data = NULL; + } -+ skb_set_queue_mapping(skb, q); + -+ if (!--mesh_hdr->ttl) { -+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); -+ goto out; ++ if (st->root_skb == st->cur_skb && skb_has_frag_list(st->root_skb)) { ++ st->cur_skb = skb_shinfo(st->root_skb)->frag_list; ++ st->frag_idx = 0; ++ goto next_skb; ++ } else if (st->cur_skb->next) { ++ st->cur_skb = st->cur_skb->next; ++ st->frag_idx = 0; ++ goto next_skb; + } + -+ if (!ifmsh->mshcfg.dot11MeshForwarding) -+ goto out; ++ return 0; ++} ++EXPORT_SYMBOL(skb_seq_read); + -+ fwd_skb = skb_copy(skb, GFP_ATOMIC); -+ if (!fwd_skb) { -+ net_info_ratelimited("%s: failed to clone mesh frame\n", -+ sdata->name); -+ goto out; -+ } ++/** ++ * skb_abort_seq_read - Abort a sequential read of skb data ++ * @st: state variable ++ * ++ * Must be called if skb_seq_read() was not called until it ++ * returned 0. ++ */ ++void skb_abort_seq_read(struct skb_seq_state *st) ++{ ++ if (st->frag_data) ++ kunmap_atomic(st->frag_data); ++} ++EXPORT_SYMBOL(skb_abort_seq_read); + -+ fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; -+ fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY); -+ info = IEEE80211_SKB_CB(fwd_skb); -+ memset(info, 0, sizeof(*info)); -+ info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; -+ info->control.vif = &rx->sdata->vif; -+ info->control.jiffies = jiffies; -+ if (is_multicast_ether_addr(fwd_hdr->addr1)) { -+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast); -+ memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); -+ /* update power mode indication when forwarding */ -+ ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr); -+ } else if (!mesh_nexthop_lookup(sdata, fwd_skb)) { -+ /* mesh power mode flags updated in mesh_nexthop_lookup */ -+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast); -+ } else { -+ /* unable to resolve next hop */ -+ mesh_path_error_tx(sdata, ifmsh->mshcfg.element_ttl, -+ fwd_hdr->addr3, 0, -+ WLAN_REASON_MESH_PATH_NOFORWARD, -+ fwd_hdr->addr2); -+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_no_route); -+ kfree_skb(fwd_skb); -+ return RX_DROP_MONITOR; -+ } -+ -+ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames); -+ ieee80211_add_pending_skb(local, fwd_skb); -+ out: -+ if (is_multicast_ether_addr(hdr->addr1) || -+ sdata->dev->flags & IFF_PROMISC) -+ return RX_CONTINUE; -+ else -+ return RX_DROP_MONITOR; ++#define TS_SKB_CB(state) ((struct skb_seq_state *) &((state)->cb)) ++ ++static unsigned int skb_ts_get_next_block(unsigned int offset, const u8 **text, ++ struct ts_config *conf, ++ struct ts_state *state) ++{ ++ return skb_seq_read(offset, text, TS_SKB_CB(state)); +} -+#endif + -+static ieee80211_rx_result debug_noinline -+ieee80211_rx_h_data(struct ieee80211_rx_data *rx) ++static void skb_ts_finish(struct ts_config *conf, struct ts_state *state) +{ -+ struct ieee80211_sub_if_data *sdata = rx->sdata; -+ struct ieee80211_local *local = rx->local; -+ struct net_device *dev = sdata->dev; -+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; -+ __le16 fc = hdr->frame_control; -+ bool port_control; -+ int err; ++ skb_abort_seq_read(TS_SKB_CB(state)); ++} ++ ++/** ++ * skb_find_text - Find a text pattern in skb data ++ * @skb: the buffer to look in ++ * @from: search offset ++ * @to: search limit ++ * @config: textsearch configuration ++ * @state: uninitialized textsearch state variable ++ * ++ * Finds a pattern in the skb data according to the specified ++ * textsearch configuration. Use textsearch_next() to retrieve ++ * subsequent occurrences of the pattern. Returns the offset ++ * to the first occurrence or UINT_MAX if no match was found. ++ */ ++unsigned int skb_find_text(struct sk_buff *skb, unsigned int from, ++ unsigned int to, struct ts_config *config, ++ struct ts_state *state) ++{ ++ unsigned int ret; + -+ if (unlikely(!ieee80211_is_data(hdr->frame_control))) -+ return RX_CONTINUE; ++ config->get_next_block = skb_ts_get_next_block; ++ config->finish = skb_ts_finish; + -+ if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) -+ return RX_DROP_MONITOR; ++ skb_prepare_seq_read(skb, from, to, TS_SKB_CB(state)); + -+ /* -+ * Send unexpected-4addr-frame event to hostapd. For older versions, -+ * also drop the frame to cooked monitor interfaces. -+ */ -+ if (ieee80211_has_a4(hdr->frame_control) && -+ sdata->vif.type == NL80211_IFTYPE_AP) { -+ if (rx->sta && -+ !test_and_set_sta_flag(rx->sta, WLAN_STA_4ADDR_EVENT)) -+ cfg80211_rx_unexpected_4addr_frame( -+ rx->sdata->dev, rx->sta->sta.addr, GFP_ATOMIC); -+ return RX_DROP_MONITOR; -+ } ++ ret = textsearch_find(config, state); ++ return (ret <= to - from ? ret : UINT_MAX); ++} ++EXPORT_SYMBOL(skb_find_text); + -+ err = __ieee80211_data_to_8023(rx, &port_control); -+ if (unlikely(err)) -+ return RX_DROP_UNUSABLE; ++/** ++ * skb_append_datato_frags - append the user data to a skb ++ * @sk: sock structure ++ * @skb: skb structure to be appended with user data. ++ * @getfrag: call back function to be used for getting the user data ++ * @from: pointer to user message iov ++ * @length: length of the iov message ++ * ++ * Description: This procedure append the user data in the fragment part ++ * of the skb if any page alloc fails user this procedure returns -ENOMEM ++ */ ++int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, ++ int (*getfrag)(void *from, char *to, int offset, ++ int len, int odd, struct sk_buff *skb), ++ void *from, int length) ++{ ++ int frg_cnt = skb_shinfo(skb)->nr_frags; ++ int copy; ++ int offset = 0; ++ int ret; ++ struct page_frag *pfrag = ¤t->task_frag; + -+ if (!ieee80211_frame_allowed(rx, fc)) -+ return RX_DROP_MONITOR; ++ do { ++ /* Return error if we don't have space for new frag */ ++ if (frg_cnt >= MAX_SKB_FRAGS) ++ return -EMSGSIZE; + -+ if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && -+ unlikely(port_control) && sdata->bss) { -+ sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, -+ u.ap); -+ dev = sdata->dev; -+ rx->sdata = sdata; -+ } ++ if (!sk_page_frag_refill(sk, pfrag)) ++ return -ENOMEM; ++ ++ /* copy the user data to page */ ++ copy = min_t(int, length, pfrag->size - pfrag->offset); + -+ rx->skb->dev = dev; ++ ret = getfrag(from, page_address(pfrag->page) + pfrag->offset, ++ offset, copy, 0, skb); ++ if (ret < 0) ++ return -EFAULT; + -+ dev->stats.rx_packets++; -+ dev->stats.rx_bytes += rx->skb->len; ++ /* copy was successful so update the size parameters */ ++ skb_fill_page_desc(skb, frg_cnt, pfrag->page, pfrag->offset, ++ copy); ++ frg_cnt++; ++ pfrag->offset += copy; ++ get_page(pfrag->page); + -+ if (local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 && -+ !is_multicast_ether_addr( -+ ((struct ethhdr *)rx->skb->data)->h_dest) && -+ (!local->scanning && -+ !test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))) { -+ mod_timer(&local->dynamic_ps_timer, jiffies + -+ msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); -+ } ++ skb->truesize += copy; ++ atomic_add(copy, &sk->sk_wmem_alloc); ++ skb->len += copy; ++ skb->data_len += copy; ++ offset += copy; ++ length -= copy; + -+ ieee80211_deliver_skb(rx); ++ } while (length > 0); + -+ return RX_QUEUED; ++ return 0; +} ++EXPORT_SYMBOL(skb_append_datato_frags); + -+static ieee80211_rx_result debug_noinline -+ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) ++/** ++ * skb_pull_rcsum - pull skb and update receive checksum ++ * @skb: buffer to update ++ * @len: length of data pulled ++ * ++ * This function performs an skb_pull on the packet and updates ++ * the CHECKSUM_COMPLETE checksum. It should be used on ++ * receive path processing instead of skb_pull unless you know ++ * that the checksum difference is zero (e.g., a valid IP header) ++ * or you are setting ip_summed to CHECKSUM_NONE. ++ */ ++unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) +{ -+ struct sk_buff *skb = rx->skb; -+ struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data; -+ struct tid_ampdu_rx *tid_agg_rx; -+ u16 start_seq_num; -+ u16 tid; ++ BUG_ON(len > skb->len); ++ skb->len -= len; ++ BUG_ON(skb->len < skb->data_len); ++ skb_postpull_rcsum(skb, skb->data, len); ++ return skb->data += len; ++} ++EXPORT_SYMBOL_GPL(skb_pull_rcsum); + -+ if (likely(!ieee80211_is_ctl(bar->frame_control))) -+ return RX_CONTINUE; ++/** ++ * skb_segment - Perform protocol segmentation on skb. ++ * @head_skb: buffer to segment ++ * @features: features for the output path (see dev->features) ++ * ++ * This function performs segmentation on the given skb. It returns ++ * a pointer to the first in a list of new skbs for the segments. ++ * In case of error it returns ERR_PTR(err). ++ */ ++struct sk_buff *skb_segment(struct sk_buff *head_skb, ++ netdev_features_t features) ++{ ++ struct sk_buff *segs = NULL; ++ struct sk_buff *tail = NULL; ++ struct sk_buff *list_skb = skb_shinfo(head_skb)->frag_list; ++ skb_frag_t *frag = skb_shinfo(head_skb)->frags; ++ unsigned int mss = skb_shinfo(head_skb)->gso_size; ++ unsigned int doffset = head_skb->data - skb_mac_header(head_skb); ++ struct sk_buff *frag_skb = head_skb; ++ unsigned int offset = doffset; ++ unsigned int tnl_hlen = skb_tnl_header_len(head_skb); ++ unsigned int headroom; ++ unsigned int len; ++ __be16 proto; ++ bool csum; ++ int sg = !!(features & NETIF_F_SG); ++ int nfrags = skb_shinfo(head_skb)->nr_frags; ++ int err = -ENOMEM; ++ int i = 0; ++ int pos; ++ int dummy; + -+ if (ieee80211_is_back_req(bar->frame_control)) { -+ struct { -+ __le16 control, start_seq_num; -+ } __packed bar_data; ++ __skb_push(head_skb, doffset); ++ proto = skb_network_protocol(head_skb, &dummy); ++ if (unlikely(!proto)) ++ return ERR_PTR(-EINVAL); + -+ if (!rx->sta) -+ return RX_DROP_MONITOR; ++ csum = !head_skb->encap_hdr_csum && ++ !!can_checksum_protocol(features, proto); + -+ if (skb_copy_bits(skb, offsetof(struct ieee80211_bar, control), -+ &bar_data, sizeof(bar_data))) -+ return RX_DROP_MONITOR; ++ headroom = skb_headroom(head_skb); ++ pos = skb_headlen(head_skb); + -+ tid = le16_to_cpu(bar_data.control) >> 12; ++ do { ++ struct sk_buff *nskb; ++ skb_frag_t *nskb_frag; ++ int hsize; ++ int size; ++ ++ len = head_skb->len - offset; ++ if (len > mss) ++ len = mss; ++ ++ hsize = skb_headlen(head_skb) - offset; ++ if (hsize < 0) ++ hsize = 0; ++ if (hsize > len || !sg) ++ hsize = len; ++ ++ if (!hsize && i >= nfrags && skb_headlen(list_skb) && ++ (skb_headlen(list_skb) == len || sg)) { ++ BUG_ON(skb_headlen(list_skb) > len); ++ ++ i = 0; ++ nfrags = skb_shinfo(list_skb)->nr_frags; ++ frag = skb_shinfo(list_skb)->frags; ++ frag_skb = list_skb; ++ pos += skb_headlen(list_skb); ++ ++ while (pos < offset + len) { ++ BUG_ON(i >= nfrags); ++ ++ size = skb_frag_size(frag); ++ if (pos + size > offset + len) ++ break; ++ ++ i++; ++ pos += size; ++ frag++; ++ } + -+ tid_agg_rx = rcu_dereference(rx->sta->ampdu_mlme.tid_rx[tid]); -+ if (!tid_agg_rx) -+ return RX_DROP_MONITOR; ++ nskb = skb_clone(list_skb, GFP_ATOMIC); ++ list_skb = list_skb->next; + -+ start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4; ++ if (unlikely(!nskb)) ++ goto err; + -+ /* reset session timer */ -+ if (tid_agg_rx->timeout) -+ mod_timer(&tid_agg_rx->session_timer, -+ TU_TO_EXP_TIME(tid_agg_rx->timeout)); ++ if (unlikely(pskb_trim(nskb, len))) { ++ kfree_skb(nskb); ++ goto err; ++ } + -+ spin_lock(&tid_agg_rx->reorder_lock); -+ /* release stored frames up to start of BAR */ -+ ieee80211_release_reorder_frames(rx->sdata, tid_agg_rx, -+ start_seq_num, frames); -+ spin_unlock(&tid_agg_rx->reorder_lock); ++ hsize = skb_end_offset(nskb); ++ if (skb_cow_head(nskb, doffset + headroom)) { ++ kfree_skb(nskb); ++ goto err; ++ } + -+ kfree_skb(skb); -+ return RX_QUEUED; -+ } ++ nskb->truesize += skb_end_offset(nskb) - hsize; ++ skb_release_head_state(nskb); ++ __skb_push(nskb, doffset); ++ } else { ++ nskb = __alloc_skb(hsize + doffset + headroom, ++ GFP_ATOMIC, skb_alloc_rx_flag(head_skb), ++ NUMA_NO_NODE); + -+ /* -+ * After this point, we only want management frames, -+ * so we can drop all remaining control frames to -+ * cooked monitor interfaces. -+ */ -+ return RX_DROP_MONITOR; -+} ++ if (unlikely(!nskb)) ++ goto err; + -+static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, -+ struct ieee80211_mgmt *mgmt, -+ size_t len) -+{ -+ struct ieee80211_local *local = sdata->local; -+ struct sk_buff *skb; -+ struct ieee80211_mgmt *resp; ++ skb_reserve(nskb, headroom); ++ __skb_put(nskb, doffset); ++ } + -+ if (!ether_addr_equal(mgmt->da, sdata->vif.addr)) { -+ /* Not to own unicast address */ -+ return; -+ } ++ if (segs) ++ tail->next = nskb; ++ else ++ segs = nskb; ++ tail = nskb; + -+ if (!ether_addr_equal(mgmt->sa, sdata->u.mgd.bssid) || -+ !ether_addr_equal(mgmt->bssid, sdata->u.mgd.bssid)) { -+ /* Not from the current AP or not associated yet. */ -+ return; -+ } ++ __copy_skb_header(nskb, head_skb); + -+ if (len < 24 + 1 + sizeof(resp->u.action.u.sa_query)) { -+ /* Too short SA Query request frame */ -+ return; -+ } ++ skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom); ++ skb_reset_mac_len(nskb); + -+ skb = dev_alloc_skb(sizeof(*resp) + local->hw.extra_tx_headroom); -+ if (skb == NULL) -+ return; ++ skb_copy_from_linear_data_offset(head_skb, -tnl_hlen, ++ nskb->data - tnl_hlen, ++ doffset + tnl_hlen); + -+ skb_reserve(skb, local->hw.extra_tx_headroom); -+ resp = (struct ieee80211_mgmt *) skb_put(skb, 24); -+ memset(resp, 0, 24); -+ memcpy(resp->da, mgmt->sa, ETH_ALEN); -+ memcpy(resp->sa, sdata->vif.addr, ETH_ALEN); -+ memcpy(resp->bssid, sdata->u.mgd.bssid, ETH_ALEN); -+ resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | -+ IEEE80211_STYPE_ACTION); -+ skb_put(skb, 1 + sizeof(resp->u.action.u.sa_query)); -+ resp->u.action.category = WLAN_CATEGORY_SA_QUERY; -+ resp->u.action.u.sa_query.action = WLAN_ACTION_SA_QUERY_RESPONSE; -+ memcpy(resp->u.action.u.sa_query.trans_id, -+ mgmt->u.action.u.sa_query.trans_id, -+ WLAN_SA_QUERY_TR_ID_LEN); ++ if (nskb->len == len + doffset) ++ goto perform_csum_check; + -+ ieee80211_tx_skb(sdata, skb); -+} ++ if (!sg) { ++ nskb->ip_summed = CHECKSUM_NONE; ++ nskb->csum = skb_copy_and_csum_bits(head_skb, offset, ++ skb_put(nskb, len), ++ len, 0); ++ SKB_GSO_CB(nskb)->csum_start = ++ skb_headroom(nskb) + doffset; ++ continue; ++ } + -+static ieee80211_rx_result debug_noinline -+ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) -+{ -+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); ++ nskb_frag = skb_shinfo(nskb)->frags; + -+ /* -+ * From here on, look only at management frames. -+ * Data and control frames are already handled, -+ * and unknown (reserved) frames are useless. -+ */ -+ if (rx->skb->len < 24) -+ return RX_DROP_MONITOR; ++ skb_copy_from_linear_data_offset(head_skb, offset, ++ skb_put(nskb, hsize), hsize); + -+ if (!ieee80211_is_mgmt(mgmt->frame_control)) -+ return RX_DROP_MONITOR; ++ skb_shinfo(nskb)->tx_flags = skb_shinfo(head_skb)->tx_flags & ++ SKBTX_SHARED_FRAG; + -+ if (rx->sdata->vif.type == NL80211_IFTYPE_AP && -+ ieee80211_is_beacon(mgmt->frame_control) && -+ !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) { -+ int sig = 0; ++ while (pos < offset + len) { ++ if (i >= nfrags) { ++ BUG_ON(skb_headlen(list_skb)); + -+ if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) -+ sig = status->signal; ++ i = 0; ++ nfrags = skb_shinfo(list_skb)->nr_frags; ++ frag = skb_shinfo(list_skb)->frags; ++ frag_skb = list_skb; + -+ cfg80211_report_obss_beacon(rx->local->hw.wiphy, -+ rx->skb->data, rx->skb->len, -+ status->freq, sig); -+ rx->flags |= IEEE80211_RX_BEACON_REPORTED; -+ } ++ BUG_ON(!nfrags); ++ ++ list_skb = list_skb->next; ++ } + -+ if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) -+ return RX_DROP_MONITOR; ++ if (unlikely(skb_shinfo(nskb)->nr_frags >= ++ MAX_SKB_FRAGS)) { ++ net_warn_ratelimited( ++ "skb_segment: too many frags: %u %u\n", ++ pos, mss); ++ goto err; ++ } ++ ++ if (unlikely(skb_orphan_frags(frag_skb, GFP_ATOMIC))) ++ goto err; ++ ++ *nskb_frag = *frag; ++ __skb_frag_ref(nskb_frag); ++ size = skb_frag_size(nskb_frag); ++ ++ if (pos < offset) { ++ nskb_frag->page_offset += offset - pos; ++ skb_frag_size_sub(nskb_frag, offset - pos); ++ } ++ ++ skb_shinfo(nskb)->nr_frags++; ++ ++ if (pos + size <= offset + len) { ++ i++; ++ frag++; ++ pos += size; ++ } else { ++ skb_frag_size_sub(nskb_frag, pos + size - (offset + len)); ++ goto skip_fraglist; ++ } ++ ++ nskb_frag++; ++ } ++ ++skip_fraglist: ++ nskb->data_len = len - hsize; ++ nskb->len += nskb->data_len; ++ nskb->truesize += nskb->data_len; ++ ++perform_csum_check: ++ if (!csum) { ++ nskb->csum = skb_checksum(nskb, doffset, ++ nskb->len - doffset, 0); ++ nskb->ip_summed = CHECKSUM_NONE; ++ SKB_GSO_CB(nskb)->csum_start = ++ skb_headroom(nskb) + doffset; ++ } ++ } while ((offset += len) < head_skb->len); + -+ if (ieee80211_drop_unencrypted_mgmt(rx)) -+ return RX_DROP_UNUSABLE; ++ /* Some callers want to get the end of the list. ++ * Put it in segs->prev to avoid walking the list. ++ * (see validate_xmit_skb_list() for example) ++ */ ++ segs->prev = tail; ++ return segs; + -+ return RX_CONTINUE; ++err: ++ kfree_skb_list(segs); ++ return ERR_PTR(err); +} ++EXPORT_SYMBOL_GPL(skb_segment); + -+static ieee80211_rx_result debug_noinline -+ieee80211_rx_h_action(struct ieee80211_rx_data *rx) ++int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) +{ -+ struct ieee80211_local *local = rx->local; -+ struct ieee80211_sub_if_data *sdata = rx->sdata; -+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); -+ int len = rx->skb->len; ++ struct skb_shared_info *pinfo, *skbinfo = skb_shinfo(skb); ++ unsigned int offset = skb_gro_offset(skb); ++ unsigned int headlen = skb_headlen(skb); ++ struct sk_buff *nskb, *lp, *p = *head; ++ unsigned int len = skb_gro_len(skb); ++ unsigned int delta_truesize; ++ unsigned int headroom; + -+ if (!ieee80211_is_action(mgmt->frame_control)) -+ return RX_CONTINUE; ++ if (unlikely(p->len + len >= 65536)) ++ return -E2BIG; + -+ /* drop too small frames */ -+ if (len < IEEE80211_MIN_ACTION_SIZE) -+ return RX_DROP_UNUSABLE; ++ lp = NAPI_GRO_CB(p)->last; ++ pinfo = skb_shinfo(lp); + -+ if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC && -+ mgmt->u.action.category != WLAN_CATEGORY_SELF_PROTECTED && -+ mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT) -+ return RX_DROP_UNUSABLE; ++ if (headlen <= offset) { ++ skb_frag_t *frag; ++ skb_frag_t *frag2; ++ int i = skbinfo->nr_frags; ++ int nr_frags = pinfo->nr_frags + i; + -+ if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) -+ return RX_DROP_UNUSABLE; ++ if (nr_frags > MAX_SKB_FRAGS) ++ goto merge; + -+ switch (mgmt->u.action.category) { -+ case WLAN_CATEGORY_HT: -+ /* reject HT action frames from stations not supporting HT */ -+ if (!rx->sta->sta.ht_cap.ht_supported) -+ goto invalid; ++ offset -= headlen; ++ pinfo->nr_frags = nr_frags; ++ skbinfo->nr_frags = 0; + -+ if (sdata->vif.type != NL80211_IFTYPE_STATION && -+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT && -+ sdata->vif.type != NL80211_IFTYPE_AP_VLAN && -+ sdata->vif.type != NL80211_IFTYPE_AP && -+ sdata->vif.type != NL80211_IFTYPE_ADHOC) -+ break; ++ frag = pinfo->frags + nr_frags; ++ frag2 = skbinfo->frags + i; ++ do { ++ *--frag = *--frag2; ++ } while (--i); + -+ /* verify action & smps_control/chanwidth are present */ -+ if (len < IEEE80211_MIN_ACTION_SIZE + 2) -+ goto invalid; ++ frag->page_offset += offset; ++ skb_frag_size_sub(frag, offset); + -+ switch (mgmt->u.action.u.ht_smps.action) { -+ case WLAN_HT_ACTION_SMPS: { -+ struct ieee80211_supported_band *sband; -+ enum ieee80211_smps_mode smps_mode; ++ /* all fragments truesize : remove (head size + sk_buff) */ ++ delta_truesize = skb->truesize - ++ SKB_TRUESIZE(skb_end_offset(skb)); + -+ /* convert to HT capability */ -+ switch (mgmt->u.action.u.ht_smps.smps_control) { -+ case WLAN_HT_SMPS_CONTROL_DISABLED: -+ smps_mode = IEEE80211_SMPS_OFF; -+ break; -+ case WLAN_HT_SMPS_CONTROL_STATIC: -+ smps_mode = IEEE80211_SMPS_STATIC; -+ break; -+ case WLAN_HT_SMPS_CONTROL_DYNAMIC: -+ smps_mode = IEEE80211_SMPS_DYNAMIC; -+ break; -+ default: -+ goto invalid; -+ } ++ skb->truesize -= skb->data_len; ++ skb->len -= skb->data_len; ++ skb->data_len = 0; + -+ /* if no change do nothing */ -+ if (rx->sta->sta.smps_mode == smps_mode) -+ goto handled; -+ rx->sta->sta.smps_mode = smps_mode; ++ NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE; ++ goto done; ++ } else if (skb->head_frag) { ++ int nr_frags = pinfo->nr_frags; ++ skb_frag_t *frag = pinfo->frags + nr_frags; ++ struct page *page = virt_to_head_page(skb->head); ++ unsigned int first_size = headlen - offset; ++ unsigned int first_offset; + -+ sband = rx->local->hw.wiphy->bands[status->band]; ++ if (nr_frags + 1 + skbinfo->nr_frags > MAX_SKB_FRAGS) ++ goto merge; + -+ rate_control_rate_update(local, sband, rx->sta, -+ IEEE80211_RC_SMPS_CHANGED); -+ goto handled; -+ } -+ case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: { -+ struct ieee80211_supported_band *sband; -+ u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth; -+ enum ieee80211_sta_rx_bandwidth new_bw; -+ -+ /* If it doesn't support 40 MHz it can't change ... */ -+ if (!(rx->sta->sta.ht_cap.cap & -+ IEEE80211_HT_CAP_SUP_WIDTH_20_40)) -+ goto handled; -+ -+ if (chanwidth == IEEE80211_HT_CHANWIDTH_20MHZ) -+ new_bw = IEEE80211_STA_RX_BW_20; -+ else -+ new_bw = ieee80211_sta_cur_vht_bw(rx->sta); ++ first_offset = skb->data - ++ (unsigned char *)page_address(page) + ++ offset; + -+ if (rx->sta->sta.bandwidth == new_bw) -+ goto handled; ++ pinfo->nr_frags = nr_frags + 1 + skbinfo->nr_frags; + -+ sband = rx->local->hw.wiphy->bands[status->band]; ++ frag->page.p = page; ++ frag->page_offset = first_offset; ++ skb_frag_size_set(frag, first_size); + -+ rate_control_rate_update(local, sband, rx->sta, -+ IEEE80211_RC_BW_CHANGED); -+ goto handled; -+ } -+ default: -+ goto invalid; -+ } ++ memcpy(frag + 1, skbinfo->frags, sizeof(*frag) * skbinfo->nr_frags); ++ /* We dont need to clear skbinfo->nr_frags here */ + -+ break; -+ case WLAN_CATEGORY_PUBLIC: -+ if (len < IEEE80211_MIN_ACTION_SIZE + 1) -+ goto invalid; -+ if (sdata->vif.type != NL80211_IFTYPE_STATION) -+ break; -+ if (!rx->sta) -+ break; -+ if (!ether_addr_equal(mgmt->bssid, sdata->u.mgd.bssid)) -+ break; -+ if (mgmt->u.action.u.ext_chan_switch.action_code != -+ WLAN_PUB_ACTION_EXT_CHANSW_ANN) -+ break; -+ if (len < offsetof(struct ieee80211_mgmt, -+ u.action.u.ext_chan_switch.variable)) -+ goto invalid; -+ goto queue; -+ case WLAN_CATEGORY_VHT: -+ if (sdata->vif.type != NL80211_IFTYPE_STATION && -+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT && -+ sdata->vif.type != NL80211_IFTYPE_AP_VLAN && -+ sdata->vif.type != NL80211_IFTYPE_AP && -+ sdata->vif.type != NL80211_IFTYPE_ADHOC) -+ break; ++ delta_truesize = skb->truesize - SKB_DATA_ALIGN(sizeof(struct sk_buff)); ++ NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE_STOLEN_HEAD; ++ goto done; ++ } ++ /* switch back to head shinfo */ ++ pinfo = skb_shinfo(p); + -+ /* verify action code is present */ -+ if (len < IEEE80211_MIN_ACTION_SIZE + 1) -+ goto invalid; ++ if (pinfo->frag_list) ++ goto merge; ++ if (skb_gro_len(p) != pinfo->gso_size) ++ return -E2BIG; + -+ switch (mgmt->u.action.u.vht_opmode_notif.action_code) { -+ case WLAN_VHT_ACTION_OPMODE_NOTIF: { -+ u8 opmode; ++ headroom = skb_headroom(p); ++ nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC); ++ if (unlikely(!nskb)) ++ return -ENOMEM; + -+ /* verify opmode is present */ -+ if (len < IEEE80211_MIN_ACTION_SIZE + 2) -+ goto invalid; ++ __copy_skb_header(nskb, p); ++ nskb->mac_len = p->mac_len; + -+ opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode; ++ skb_reserve(nskb, headroom); ++ __skb_put(nskb, skb_gro_offset(p)); + -+ ieee80211_vht_handle_opmode(rx->sdata, rx->sta, -+ opmode, status->band, -+ false); -+ goto handled; -+ } -+ default: -+ break; -+ } -+ break; -+ case WLAN_CATEGORY_BACK: -+ if (sdata->vif.type != NL80211_IFTYPE_STATION && -+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT && -+ sdata->vif.type != NL80211_IFTYPE_AP_VLAN && -+ sdata->vif.type != NL80211_IFTYPE_AP && -+ sdata->vif.type != NL80211_IFTYPE_ADHOC) -+ break; ++ skb_set_mac_header(nskb, skb_mac_header(p) - p->data); ++ skb_set_network_header(nskb, skb_network_offset(p)); ++ skb_set_transport_header(nskb, skb_transport_offset(p)); + -+ /* verify action_code is present */ -+ if (len < IEEE80211_MIN_ACTION_SIZE + 1) -+ break; ++ __skb_pull(p, skb_gro_offset(p)); ++ memcpy(skb_mac_header(nskb), skb_mac_header(p), ++ p->data - skb_mac_header(p)); + -+ switch (mgmt->u.action.u.addba_req.action_code) { -+ case WLAN_ACTION_ADDBA_REQ: -+ if (len < (IEEE80211_MIN_ACTION_SIZE + -+ sizeof(mgmt->u.action.u.addba_req))) -+ goto invalid; -+ break; -+ case WLAN_ACTION_ADDBA_RESP: -+ if (len < (IEEE80211_MIN_ACTION_SIZE + -+ sizeof(mgmt->u.action.u.addba_resp))) -+ goto invalid; -+ break; -+ case WLAN_ACTION_DELBA: -+ if (len < (IEEE80211_MIN_ACTION_SIZE + -+ sizeof(mgmt->u.action.u.delba))) -+ goto invalid; -+ break; -+ default: -+ goto invalid; -+ } ++ skb_shinfo(nskb)->frag_list = p; ++ skb_shinfo(nskb)->gso_size = pinfo->gso_size; ++ pinfo->gso_size = 0; ++ __skb_header_release(p); ++ NAPI_GRO_CB(nskb)->last = p; + -+ goto queue; -+ case WLAN_CATEGORY_SPECTRUM_MGMT: -+ /* verify action_code is present */ -+ if (len < IEEE80211_MIN_ACTION_SIZE + 1) -+ break; ++ nskb->data_len += p->len; ++ nskb->truesize += p->truesize; ++ nskb->len += p->len; + -+ switch (mgmt->u.action.u.measurement.action_code) { -+ case WLAN_ACTION_SPCT_MSR_REQ: -+ if (status->band != IEEE80211_BAND_5GHZ) -+ break; ++ *head = nskb; ++ nskb->next = p->next; ++ p->next = NULL; + -+ if (len < (IEEE80211_MIN_ACTION_SIZE + -+ sizeof(mgmt->u.action.u.measurement))) -+ break; ++ p = nskb; + -+ if (sdata->vif.type != NL80211_IFTYPE_STATION) -+ break; ++merge: ++ delta_truesize = skb->truesize; ++ if (offset > headlen) { ++ unsigned int eat = offset - headlen; + -+ ieee80211_process_measurement_req(sdata, mgmt, len); -+ goto handled; -+ case WLAN_ACTION_SPCT_CHL_SWITCH: { -+ u8 *bssid; -+ if (len < (IEEE80211_MIN_ACTION_SIZE + -+ sizeof(mgmt->u.action.u.chan_switch))) -+ break; ++ skbinfo->frags[0].page_offset += eat; ++ skb_frag_size_sub(&skbinfo->frags[0], eat); ++ skb->data_len -= eat; ++ skb->len -= eat; ++ offset = headlen; ++ } + -+ if (sdata->vif.type != NL80211_IFTYPE_STATION && -+ sdata->vif.type != NL80211_IFTYPE_ADHOC && -+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT) -+ break; ++ __skb_pull(skb, offset); + -+ if (sdata->vif.type == NL80211_IFTYPE_STATION) -+ bssid = sdata->u.mgd.bssid; -+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) -+ bssid = sdata->u.ibss.bssid; -+ else if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) -+ bssid = mgmt->sa; -+ else -+ break; ++ if (NAPI_GRO_CB(p)->last == p) ++ skb_shinfo(p)->frag_list = skb; ++ else ++ NAPI_GRO_CB(p)->last->next = skb; ++ NAPI_GRO_CB(p)->last = skb; ++ __skb_header_release(skb); ++ lp = p; + -+ if (!ether_addr_equal(mgmt->bssid, bssid)) -+ break; ++done: ++ NAPI_GRO_CB(p)->count++; ++ p->data_len += len; ++ p->truesize += delta_truesize; ++ p->len += len; ++ if (lp != p) { ++ lp->data_len += len; ++ lp->truesize += delta_truesize; ++ lp->len += len; ++ } ++ NAPI_GRO_CB(skb)->same_flow = 1; ++ return 0; ++} + -+ goto queue; -+ } -+ } -+ break; -+ case WLAN_CATEGORY_SA_QUERY: -+ if (len < (IEEE80211_MIN_ACTION_SIZE + -+ sizeof(mgmt->u.action.u.sa_query))) -+ break; ++void __init skb_init(void) ++{ ++ skbuff_head_cache = kmem_cache_create("skbuff_head_cache", ++ sizeof(struct sk_buff), ++ 0, ++ SLAB_HWCACHE_ALIGN|SLAB_PANIC, ++ NULL); ++ skbuff_fclone_cache = kmem_cache_create("skbuff_fclone_cache", ++ sizeof(struct sk_buff_fclones), ++ 0, ++ SLAB_HWCACHE_ALIGN|SLAB_PANIC, ++ NULL); ++} + -+ switch (mgmt->u.action.u.sa_query.action) { -+ case WLAN_ACTION_SA_QUERY_REQUEST: -+ if (sdata->vif.type != NL80211_IFTYPE_STATION) -+ break; -+ ieee80211_process_sa_query_req(sdata, mgmt, len); -+ goto handled; ++/** ++ * skb_to_sgvec - Fill a scatter-gather list from a socket buffer ++ * @skb: Socket buffer containing the buffers to be mapped ++ * @sg: The scatter-gather list to map into ++ * @offset: The offset into the buffer's contents to start mapping ++ * @len: Length of buffer space to be mapped ++ * ++ * Fill the specified scatter-gather list with mappings/pointers into a ++ * region of the buffer space attached to a socket buffer. ++ */ ++static int ++__skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) ++{ ++ int start = skb_headlen(skb); ++ int i, copy = start - offset; ++ struct sk_buff *frag_iter; ++ int elt = 0; ++ ++ if (copy > 0) { ++ if (copy > len) ++ copy = len; ++ sg_set_buf(sg, skb->data + offset, copy); ++ elt++; ++ if ((len -= copy) == 0) ++ return elt; ++ offset += copy; ++ } ++ ++ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { ++ int end; ++ ++ WARN_ON(start > offset + len); ++ ++ end = start + skb_frag_size(&skb_shinfo(skb)->frags[i]); ++ if ((copy = end - offset) > 0) { ++ skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; ++ ++ if (copy > len) ++ copy = len; ++ sg_set_page(&sg[elt], skb_frag_page(frag), copy, ++ frag->page_offset+offset-start); ++ elt++; ++ if (!(len -= copy)) ++ return elt; ++ offset += copy; + } -+ break; -+ case WLAN_CATEGORY_SELF_PROTECTED: -+ if (len < (IEEE80211_MIN_ACTION_SIZE + -+ sizeof(mgmt->u.action.u.self_prot.action_code))) -+ break; ++ start = end; ++ } + -+ switch (mgmt->u.action.u.self_prot.action_code) { -+ case WLAN_SP_MESH_PEERING_OPEN: -+ case WLAN_SP_MESH_PEERING_CLOSE: -+ case WLAN_SP_MESH_PEERING_CONFIRM: -+ if (!ieee80211_vif_is_mesh(&sdata->vif)) -+ goto invalid; -+ if (sdata->u.mesh.user_mpm) -+ /* userspace handles this frame */ -+ break; -+ goto queue; -+ case WLAN_SP_MGK_INFORM: -+ case WLAN_SP_MGK_ACK: -+ if (!ieee80211_vif_is_mesh(&sdata->vif)) -+ goto invalid; -+ break; -+ } -+ break; -+ case WLAN_CATEGORY_MESH_ACTION: -+ if (len < (IEEE80211_MIN_ACTION_SIZE + -+ sizeof(mgmt->u.action.u.mesh_action.action_code))) -+ break; ++ skb_walk_frags(skb, frag_iter) { ++ int end; + -+ if (!ieee80211_vif_is_mesh(&sdata->vif)) -+ break; -+ if (mesh_action_is_path_sel(mgmt) && -+ !mesh_path_sel_is_hwmp(sdata)) -+ break; -+ goto queue; ++ WARN_ON(start > offset + len); ++ ++ end = start + frag_iter->len; ++ if ((copy = end - offset) > 0) { ++ if (copy > len) ++ copy = len; ++ elt += __skb_to_sgvec(frag_iter, sg+elt, offset - start, ++ copy); ++ if ((len -= copy) == 0) ++ return elt; ++ offset += copy; ++ } ++ start = end; + } ++ BUG_ON(len); ++ return elt; ++} + -+ return RX_CONTINUE; ++/* As compared with skb_to_sgvec, skb_to_sgvec_nomark only map skb to given ++ * sglist without mark the sg which contain last skb data as the end. ++ * So the caller can mannipulate sg list as will when padding new data after ++ * the first call without calling sg_unmark_end to expend sg list. ++ * ++ * Scenario to use skb_to_sgvec_nomark: ++ * 1. sg_init_table ++ * 2. skb_to_sgvec_nomark(payload1) ++ * 3. skb_to_sgvec_nomark(payload2) ++ * ++ * This is equivalent to: ++ * 1. sg_init_table ++ * 2. skb_to_sgvec(payload1) ++ * 3. sg_unmark_end ++ * 4. skb_to_sgvec(payload2) ++ * ++ * When mapping mutilple payload conditionally, skb_to_sgvec_nomark ++ * is more preferable. ++ */ ++int skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg, ++ int offset, int len) ++{ ++ return __skb_to_sgvec(skb, sg, offset, len); ++} ++EXPORT_SYMBOL_GPL(skb_to_sgvec_nomark); + -+ invalid: -+ status->rx_flags |= IEEE80211_RX_MALFORMED_ACTION_FRM; -+ /* will return in the next handlers */ -+ return RX_CONTINUE; ++int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) ++{ ++ int nsg = __skb_to_sgvec(skb, sg, offset, len); + -+ handled: -+ if (rx->sta) -+ rx->sta->rx_packets++; -+ dev_kfree_skb(rx->skb); -+ return RX_QUEUED; ++ sg_mark_end(&sg[nsg - 1]); + -+ queue: -+ rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; -+ skb_queue_tail(&sdata->skb_queue, rx->skb); -+ ieee80211_queue_work(&local->hw, &sdata->work); -+ if (rx->sta) -+ rx->sta->rx_packets++; -+ return RX_QUEUED; ++ return nsg; +} ++EXPORT_SYMBOL_GPL(skb_to_sgvec); + -+static ieee80211_rx_result debug_noinline -+ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx) ++/** ++ * skb_cow_data - Check that a socket buffer's data buffers are writable ++ * @skb: The socket buffer to check. ++ * @tailbits: Amount of trailing space to be added ++ * @trailer: Returned pointer to the skb where the @tailbits space begins ++ * ++ * Make sure that the data buffers attached to a socket buffer are ++ * writable. If they are not, private copies are made of the data buffers ++ * and the socket buffer is set to use these instead. ++ * ++ * If @tailbits is given, make sure that there is space to write @tailbits ++ * bytes of data beyond current end of socket buffer. @trailer will be ++ * set to point to the skb in which this space begins. ++ * ++ * The number of scatterlist elements required to completely map the ++ * COW'd and extended socket buffer will be returned. ++ */ ++int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) +{ -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); -+ int sig = 0; ++ int copyflag; ++ int elt; ++ struct sk_buff *skb1, **skb_p; + -+ /* skip known-bad action frames and return them in the next handler */ -+ if (status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM) -+ return RX_CONTINUE; -+ -+ /* -+ * Getting here means the kernel doesn't know how to handle -+ * it, but maybe userspace does ... include returned frames -+ * so userspace can register for those to know whether ones -+ * it transmitted were processed or returned. ++ /* If skb is cloned or its head is paged, reallocate ++ * head pulling out all the pages (pages are considered not writable ++ * at the moment even if they are anonymous). + */ ++ if ((skb_cloned(skb) || skb_shinfo(skb)->nr_frags) && ++ __pskb_pull_tail(skb, skb_pagelen(skb)-skb_headlen(skb)) == NULL) ++ return -ENOMEM; ++ ++ /* Easy case. Most of packets will go this way. */ ++ if (!skb_has_frag_list(skb)) { ++ /* A little of trouble, not enough of space for trailer. ++ * This should not happen, when stack is tuned to generate ++ * good frames. OK, on miss we reallocate and reserve even more ++ * space, 128 bytes is fair. */ + -+ if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) -+ sig = status->signal; ++ if (skb_tailroom(skb) < tailbits && ++ pskb_expand_head(skb, 0, tailbits-skb_tailroom(skb)+128, GFP_ATOMIC)) ++ return -ENOMEM; + -+ if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig, -+ rx->skb->data, rx->skb->len, 0)) { -+ if (rx->sta) -+ rx->sta->rx_packets++; -+ dev_kfree_skb(rx->skb); -+ return RX_QUEUED; ++ /* Voila! */ ++ *trailer = skb; ++ return 1; + } + -+ return RX_CONTINUE; -+} ++ /* Misery. We are in troubles, going to mincer fragments... */ + -+static ieee80211_rx_result debug_noinline -+ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) -+{ -+ struct ieee80211_local *local = rx->local; -+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; -+ struct sk_buff *nskb; -+ struct ieee80211_sub_if_data *sdata = rx->sdata; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); ++ elt = 1; ++ skb_p = &skb_shinfo(skb)->frag_list; ++ copyflag = 0; + -+ if (!ieee80211_is_action(mgmt->frame_control)) -+ return RX_CONTINUE; ++ while ((skb1 = *skb_p) != NULL) { ++ int ntail = 0; + -+ /* -+ * For AP mode, hostapd is responsible for handling any action -+ * frames that we didn't handle, including returning unknown -+ * ones. For all other modes we will return them to the sender, -+ * setting the 0x80 bit in the action category, as required by -+ * 802.11-2012 9.24.4. -+ * Newer versions of hostapd shall also use the management frame -+ * registration mechanisms, but older ones still use cooked -+ * monitor interfaces so push all frames there. -+ */ -+ if (!(status->rx_flags & IEEE80211_RX_MALFORMED_ACTION_FRM) && -+ (sdata->vif.type == NL80211_IFTYPE_AP || -+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) -+ return RX_DROP_MONITOR; -+ -+ if (is_multicast_ether_addr(mgmt->da)) -+ return RX_DROP_MONITOR; -+ -+ /* do not return rejected action frames */ -+ if (mgmt->u.action.category & 0x80) -+ return RX_DROP_UNUSABLE; -+ -+ nskb = skb_copy_expand(rx->skb, local->hw.extra_tx_headroom, 0, -+ GFP_ATOMIC); -+ if (nskb) { -+ struct ieee80211_mgmt *nmgmt = (void *)nskb->data; -+ -+ nmgmt->u.action.category |= 0x80; -+ memcpy(nmgmt->da, nmgmt->sa, ETH_ALEN); -+ memcpy(nmgmt->sa, rx->sdata->vif.addr, ETH_ALEN); -+ -+ memset(nskb->cb, 0, sizeof(nskb->cb)); -+ -+ if (rx->sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) { -+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(nskb); -+ -+ info->flags = IEEE80211_TX_CTL_TX_OFFCHAN | -+ IEEE80211_TX_INTFL_OFFCHAN_TX_OK | -+ IEEE80211_TX_CTL_NO_CCK_RATE; -+ if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) -+ info->hw_queue = -+ local->hw.offchannel_tx_hw_queue; ++ /* The fragment is partially pulled by someone, ++ * this can happen on input. Copy it and everything ++ * after it. */ ++ ++ if (skb_shared(skb1)) ++ copyflag = 1; ++ ++ /* If the skb is the last, worry about trailer. */ ++ ++ if (skb1->next == NULL && tailbits) { ++ if (skb_shinfo(skb1)->nr_frags || ++ skb_has_frag_list(skb1) || ++ skb_tailroom(skb1) < tailbits) ++ ntail = tailbits + 128; + } + -+ __ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7, -+ status->band); ++ if (copyflag || ++ skb_cloned(skb1) || ++ ntail || ++ skb_shinfo(skb1)->nr_frags || ++ skb_has_frag_list(skb1)) { ++ struct sk_buff *skb2; ++ ++ /* Fuck, we are miserable poor guys... */ ++ if (ntail == 0) ++ skb2 = skb_copy(skb1, GFP_ATOMIC); ++ else ++ skb2 = skb_copy_expand(skb1, ++ skb_headroom(skb1), ++ ntail, ++ GFP_ATOMIC); ++ if (unlikely(skb2 == NULL)) ++ return -ENOMEM; ++ ++ if (skb1->sk) ++ skb_set_owner_w(skb2, skb1->sk); ++ ++ /* Looking around. Are we still alive? ++ * OK, link new skb, drop old one */ ++ ++ skb2->next = skb1->next; ++ *skb_p = skb2; ++ kfree_skb(skb1); ++ skb1 = skb2; ++ } ++ elt++; ++ *trailer = skb1; ++ skb_p = &skb1->next; + } -+ dev_kfree_skb(rx->skb); -+ return RX_QUEUED; ++ ++ return elt; +} ++EXPORT_SYMBOL_GPL(skb_cow_data); + -+static ieee80211_rx_result debug_noinline -+ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) ++static void sock_rmem_free(struct sk_buff *skb) +{ -+ struct ieee80211_sub_if_data *sdata = rx->sdata; -+ struct ieee80211_mgmt *mgmt = (void *)rx->skb->data; -+ __le16 stype; ++ struct sock *sk = skb->sk; + -+ stype = mgmt->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE); ++ atomic_sub(skb->truesize, &sk->sk_rmem_alloc); ++} + -+ if (!ieee80211_vif_is_mesh(&sdata->vif) && -+ sdata->vif.type != NL80211_IFTYPE_ADHOC && -+ sdata->vif.type != NL80211_IFTYPE_STATION) -+ return RX_DROP_MONITOR; ++/* ++ * Note: We dont mem charge error packets (no sk_forward_alloc changes) ++ */ ++int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) ++{ ++ if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= ++ (unsigned int)sk->sk_rcvbuf) ++ return -ENOMEM; + -+ switch (stype) { -+ case cpu_to_le16(IEEE80211_STYPE_AUTH): -+ case cpu_to_le16(IEEE80211_STYPE_BEACON): -+ case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): -+ /* process for all: mesh, mlme, ibss */ -+ break; -+ case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): -+ case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): -+ case cpu_to_le16(IEEE80211_STYPE_DEAUTH): -+ case cpu_to_le16(IEEE80211_STYPE_DISASSOC): -+ if (is_multicast_ether_addr(mgmt->da) && -+ !is_broadcast_ether_addr(mgmt->da)) -+ return RX_DROP_MONITOR; -+ -+ /* process only for station */ -+ if (sdata->vif.type != NL80211_IFTYPE_STATION) -+ return RX_DROP_MONITOR; -+ break; -+ case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): -+ /* process only for ibss and mesh */ -+ if (sdata->vif.type != NL80211_IFTYPE_ADHOC && -+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT) -+ return RX_DROP_MONITOR; -+ break; -+ default: -+ return RX_DROP_MONITOR; -+ } ++ skb_orphan(skb); ++ skb->sk = sk; ++ skb->destructor = sock_rmem_free; ++ atomic_add(skb->truesize, &sk->sk_rmem_alloc); + -+ /* queue up frame and kick off work to process it */ -+ rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME; -+ skb_queue_tail(&sdata->skb_queue, rx->skb); -+ ieee80211_queue_work(&rx->local->hw, &sdata->work); -+ if (rx->sta) -+ rx->sta->rx_packets++; ++ /* before exiting rcu section, make sure dst is refcounted */ ++ skb_dst_force(skb); + -+ return RX_QUEUED; ++ skb_queue_tail(&sk->sk_error_queue, skb); ++ if (!sock_flag(sk, SOCK_DEAD)) ++ sk->sk_data_ready(sk); ++ return 0; +} ++EXPORT_SYMBOL(sock_queue_err_skb); + -+/* TODO: use IEEE80211_RX_FRAGMENTED */ -+static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, -+ struct ieee80211_rate *rate) ++struct sk_buff *sock_dequeue_err_skb(struct sock *sk) +{ -+ struct ieee80211_sub_if_data *sdata; -+ struct ieee80211_local *local = rx->local; -+ struct sk_buff *skb = rx->skb, *skb2; -+ struct net_device *prev_dev = NULL; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); -+ int needed_headroom; ++ struct sk_buff_head *q = &sk->sk_error_queue; ++ struct sk_buff *skb, *skb_next; ++ unsigned long flags; ++ int err = 0; + -+ /* -+ * If cooked monitor has been processed already, then -+ * don't do it again. If not, set the flag. -+ */ -+ if (rx->flags & IEEE80211_RX_CMNTR) -+ goto out_free_skb; -+ rx->flags |= IEEE80211_RX_CMNTR; ++ spin_lock_irqsave(&q->lock, flags); ++ skb = __skb_dequeue(q); ++ if (skb && (skb_next = skb_peek(q))) ++ err = SKB_EXT_ERR(skb_next)->ee.ee_errno; ++ spin_unlock_irqrestore(&q->lock, flags); + -+ /* If there are no cooked monitor interfaces, just free the SKB */ -+ if (!local->cooked_mntrs) -+ goto out_free_skb; ++ sk->sk_err = err; ++ if (err) ++ sk->sk_error_report(sk); + -+ /* room for the radiotap header based on driver features */ -+ needed_headroom = ieee80211_rx_radiotap_space(local, status); ++ return skb; ++} ++EXPORT_SYMBOL(sock_dequeue_err_skb); + -+ if (skb_headroom(skb) < needed_headroom && -+ pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC)) -+ goto out_free_skb; ++/** ++ * skb_clone_sk - create clone of skb, and take reference to socket ++ * @skb: the skb to clone ++ * ++ * This function creates a clone of a buffer that holds a reference on ++ * sk_refcnt. Buffers created via this function are meant to be ++ * returned using sock_queue_err_skb, or free via kfree_skb. ++ * ++ * When passing buffers allocated with this function to sock_queue_err_skb ++ * it is necessary to wrap the call with sock_hold/sock_put in order to ++ * prevent the socket from being released prior to being enqueued on ++ * the sk_error_queue. ++ */ ++struct sk_buff *skb_clone_sk(struct sk_buff *skb) ++{ ++ struct sock *sk = skb->sk; ++ struct sk_buff *clone; + -+ /* prepend radiotap information */ -+ ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom, -+ false); ++ if (!sk || !atomic_inc_not_zero(&sk->sk_refcnt)) ++ return NULL; + -+ skb_set_mac_header(skb, 0); -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ skb->pkt_type = PACKET_OTHERHOST; -+ skb->protocol = htons(ETH_P_802_2); ++ clone = skb_clone(skb, GFP_ATOMIC); ++ if (!clone) { ++ sock_put(sk); ++ return NULL; ++ } + -+ list_for_each_entry_rcu(sdata, &local->interfaces, list) { -+ if (!ieee80211_sdata_running(sdata)) -+ continue; ++ clone->sk = sk; ++ clone->destructor = sock_efree; + -+ if (sdata->vif.type != NL80211_IFTYPE_MONITOR || -+ !(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)) -+ continue; ++ return clone; ++} ++EXPORT_SYMBOL(skb_clone_sk); + -+ if (prev_dev) { -+ skb2 = skb_clone(skb, GFP_ATOMIC); -+ if (skb2) { -+ skb2->dev = prev_dev; -+ netif_receive_skb(skb2); -+ } -+ } ++static void __skb_complete_tx_timestamp(struct sk_buff *skb, ++ struct sock *sk, ++ int tstype) ++{ ++ struct sock_exterr_skb *serr; ++ int err; + -+ prev_dev = sdata->dev; -+ sdata->dev->stats.rx_packets++; -+ sdata->dev->stats.rx_bytes += skb->len; ++ serr = SKB_EXT_ERR(skb); ++ memset(serr, 0, sizeof(*serr)); ++ serr->ee.ee_errno = ENOMSG; ++ serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; ++ serr->ee.ee_info = tstype; ++ if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) { ++ serr->ee.ee_data = skb_shinfo(skb)->tskey; ++ if (sk->sk_protocol == IPPROTO_TCP) ++ serr->ee.ee_data -= sk->sk_tskey; + } + -+ if (prev_dev) { -+ skb->dev = prev_dev; -+ netif_receive_skb(skb); -+ return; -+ } ++ err = sock_queue_err_skb(sk, skb); + -+ out_free_skb: -+ dev_kfree_skb(skb); ++ if (err) ++ kfree_skb(skb); +} + -+static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, -+ ieee80211_rx_result res) ++void skb_complete_tx_timestamp(struct sk_buff *skb, ++ struct skb_shared_hwtstamps *hwtstamps) +{ -+ switch (res) { -+ case RX_DROP_MONITOR: -+ I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); -+ if (rx->sta) -+ rx->sta->rx_dropped++; -+ /* fall through */ -+ case RX_CONTINUE: { -+ struct ieee80211_rate *rate = NULL; -+ struct ieee80211_supported_band *sband; -+ struct ieee80211_rx_status *status; ++ struct sock *sk = skb->sk; + -+ status = IEEE80211_SKB_RXCB((rx->skb)); ++ /* take a reference to prevent skb_orphan() from freeing the socket */ ++ sock_hold(sk); + -+ sband = rx->local->hw.wiphy->bands[status->band]; -+ if (!(status->flag & RX_FLAG_HT) && -+ !(status->flag & RX_FLAG_VHT)) -+ rate = &sband->bitrates[status->rate_idx]; ++ *skb_hwtstamps(skb) = *hwtstamps; ++ __skb_complete_tx_timestamp(skb, sk, SCM_TSTAMP_SND); + -+ ieee80211_rx_cooked_monitor(rx, rate); -+ break; -+ } -+ case RX_DROP_UNUSABLE: -+ I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop); -+ if (rx->sta) -+ rx->sta->rx_dropped++; -+ dev_kfree_skb(rx->skb); -+ break; -+ case RX_QUEUED: -+ I802_DEBUG_INC(rx->sdata->local->rx_handlers_queued); -+ break; -+ } ++ sock_put(sk); +} ++EXPORT_SYMBOL_GPL(skb_complete_tx_timestamp); + -+static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, -+ struct sk_buff_head *frames) ++void __skb_tstamp_tx(struct sk_buff *orig_skb, ++ struct skb_shared_hwtstamps *hwtstamps, ++ struct sock *sk, int tstype) +{ -+ ieee80211_rx_result res = RX_DROP_MONITOR; + struct sk_buff *skb; + -+#define CALL_RXH(rxh) \ -+ do { \ -+ res = rxh(rx); \ -+ if (res != RX_CONTINUE) \ -+ goto rxh_next; \ -+ } while (0); ++ if (!sk) ++ return; + -+ spin_lock_bh(&rx->local->rx_path_lock); ++ if (hwtstamps) ++ *skb_hwtstamps(orig_skb) = *hwtstamps; ++ else ++ orig_skb->tstamp = ktime_get_real(); + -+ while ((skb = __skb_dequeue(frames))) { -+ /* -+ * all the other fields are valid across frames -+ * that belong to an aMPDU since they are on the -+ * same TID from the same station -+ */ -+ rx->skb = skb; ++ skb = skb_clone(orig_skb, GFP_ATOMIC); ++ if (!skb) ++ return; + -+ CALL_RXH(ieee80211_rx_h_check_more_data) -+ CALL_RXH(ieee80211_rx_h_uapsd_and_pspoll) -+ CALL_RXH(ieee80211_rx_h_sta_process) -+ CALL_RXH(ieee80211_rx_h_decrypt) -+ CALL_RXH(ieee80211_rx_h_defragment) -+ CALL_RXH(ieee80211_rx_h_michael_mic_verify) -+ /* must be after MMIC verify so header is counted in MPDU mic */ -+#ifdef CONFIG_MAC80211_MESH -+ if (ieee80211_vif_is_mesh(&rx->sdata->vif)) -+ CALL_RXH(ieee80211_rx_h_mesh_fwding); -+#endif -+ CALL_RXH(ieee80211_rx_h_amsdu) -+ CALL_RXH(ieee80211_rx_h_data) ++ __skb_complete_tx_timestamp(skb, sk, tstype); ++} ++EXPORT_SYMBOL_GPL(__skb_tstamp_tx); ++ ++void skb_tstamp_tx(struct sk_buff *orig_skb, ++ struct skb_shared_hwtstamps *hwtstamps) ++{ ++ return __skb_tstamp_tx(orig_skb, hwtstamps, orig_skb->sk, ++ SCM_TSTAMP_SND); ++} ++EXPORT_SYMBOL_GPL(skb_tstamp_tx); ++ ++void skb_complete_wifi_ack(struct sk_buff *skb, bool acked) ++{ ++ struct sock *sk = skb->sk; ++ struct sock_exterr_skb *serr; ++ int err; + -+ /* special treatment -- needs the queue */ -+ res = ieee80211_rx_h_ctrl(rx, frames); -+ if (res != RX_CONTINUE) -+ goto rxh_next; ++ skb->wifi_acked_valid = 1; ++ skb->wifi_acked = acked; + -+ CALL_RXH(ieee80211_rx_h_mgmt_check) -+ CALL_RXH(ieee80211_rx_h_action) -+ CALL_RXH(ieee80211_rx_h_userspace_mgmt) -+ CALL_RXH(ieee80211_rx_h_action_return) -+ CALL_RXH(ieee80211_rx_h_mgmt) ++ serr = SKB_EXT_ERR(skb); ++ memset(serr, 0, sizeof(*serr)); ++ serr->ee.ee_errno = ENOMSG; ++ serr->ee.ee_origin = SO_EE_ORIGIN_TXSTATUS; + -+ rxh_next: -+ ieee80211_rx_handlers_result(rx, res); ++ /* take a reference to prevent skb_orphan() from freeing the socket */ ++ sock_hold(sk); ++ ++ err = sock_queue_err_skb(sk, skb); ++ if (err) ++ kfree_skb(skb); ++ ++ sock_put(sk); ++} ++EXPORT_SYMBOL_GPL(skb_complete_wifi_ack); + -+#undef CALL_RXH -+ } + -+ spin_unlock_bh(&rx->local->rx_path_lock); ++/** ++ * skb_partial_csum_set - set up and verify partial csum values for packet ++ * @skb: the skb to set ++ * @start: the number of bytes after skb->data to start checksumming. ++ * @off: the offset from start to place the checksum. ++ * ++ * For untrusted partially-checksummed packets, we need to make sure the values ++ * for skb->csum_start and skb->csum_offset are valid so we don't oops. ++ * ++ * This function checks and sets those values and skb->ip_summed: if this ++ * returns false you should drop the packet. ++ */ ++bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off) ++{ ++ if (unlikely(start > skb_headlen(skb)) || ++ unlikely((int)start + off > skb_headlen(skb) - 2)) { ++ net_warn_ratelimited("bad partial csum: csum=%u/%u len=%u\n", ++ start, off, skb_headlen(skb)); ++ return false; ++ } ++ skb->ip_summed = CHECKSUM_PARTIAL; ++ skb->csum_start = skb_headroom(skb) + start; ++ skb->csum_offset = off; ++ skb_set_transport_header(skb, start); ++ return true; +} ++EXPORT_SYMBOL_GPL(skb_partial_csum_set); + -+static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) ++static int skb_maybe_pull_tail(struct sk_buff *skb, unsigned int len, ++ unsigned int max) +{ -+ struct sk_buff_head reorder_release; -+ ieee80211_rx_result res = RX_DROP_MONITOR; ++ if (skb_headlen(skb) >= len) ++ return 0; ++ ++ /* If we need to pullup then pullup to the max, so we ++ * won't need to do it again. ++ */ ++ if (max > skb->len) ++ max = skb->len; + -+ __skb_queue_head_init(&reorder_release); ++ if (__pskb_pull_tail(skb, max - skb_headlen(skb)) == NULL) ++ return -ENOMEM; + -+#define CALL_RXH(rxh) \ -+ do { \ -+ res = rxh(rx); \ -+ if (res != RX_CONTINUE) \ -+ goto rxh_next; \ -+ } while (0); ++ if (skb_headlen(skb) < len) ++ return -EPROTO; + -+ CALL_RXH(ieee80211_rx_h_check) ++ return 0; ++} + -+ ieee80211_rx_reorder_ampdu(rx, &reorder_release); ++#define MAX_TCP_HDR_LEN (15 * 4) + -+ ieee80211_rx_handlers(rx, &reorder_release); -+ return; ++static __sum16 *skb_checksum_setup_ip(struct sk_buff *skb, ++ typeof(IPPROTO_IP) proto, ++ unsigned int off) ++{ ++ switch (proto) { ++ int err; ++ ++ case IPPROTO_TCP: ++ err = skb_maybe_pull_tail(skb, off + sizeof(struct tcphdr), ++ off + MAX_TCP_HDR_LEN); ++ if (!err && !skb_partial_csum_set(skb, off, ++ offsetof(struct tcphdr, ++ check))) ++ err = -EPROTO; ++ return err ? ERR_PTR(err) : &tcp_hdr(skb)->check; + -+ rxh_next: -+ ieee80211_rx_handlers_result(rx, res); ++ case IPPROTO_UDP: ++ err = skb_maybe_pull_tail(skb, off + sizeof(struct udphdr), ++ off + sizeof(struct udphdr)); ++ if (!err && !skb_partial_csum_set(skb, off, ++ offsetof(struct udphdr, ++ check))) ++ err = -EPROTO; ++ return err ? ERR_PTR(err) : &udp_hdr(skb)->check; ++ } + -+#undef CALL_RXH ++ return ERR_PTR(-EPROTO); +} + -+/* -+ * This function makes calls into the RX path, therefore -+ * it has to be invoked under RCU read lock. -+ */ -+void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) -+{ -+ struct sk_buff_head frames; -+ struct ieee80211_rx_data rx = { -+ .sta = sta, -+ .sdata = sta->sdata, -+ .local = sta->local, -+ /* This is OK -- must be QoS data frame */ -+ .security_idx = tid, -+ .seqno_idx = tid, -+ .flags = 0, -+ }; -+ struct tid_ampdu_rx *tid_agg_rx; ++/* This value should be large enough to cover a tagged ethernet header plus ++ * maximally sized IP and TCP or UDP headers. ++ */ ++#define MAX_IP_HDR_LEN 128 + -+ tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]); -+ if (!tid_agg_rx) -+ return; ++static int skb_checksum_setup_ipv4(struct sk_buff *skb, bool recalculate) ++{ ++ unsigned int off; ++ bool fragment; ++ __sum16 *csum; ++ int err; ++ ++ fragment = false; ++ ++ err = skb_maybe_pull_tail(skb, ++ sizeof(struct iphdr), ++ MAX_IP_HDR_LEN); ++ if (err < 0) ++ goto out; ++ ++ if (ip_hdr(skb)->frag_off & htons(IP_OFFSET | IP_MF)) ++ fragment = true; + -+ __skb_queue_head_init(&frames); ++ off = ip_hdrlen(skb); + -+ spin_lock(&tid_agg_rx->reorder_lock); -+ ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx, &frames); -+ spin_unlock(&tid_agg_rx->reorder_lock); ++ err = -EPROTO; ++ ++ if (fragment) ++ goto out; + -+ ieee80211_rx_handlers(&rx, &frames); ++ csum = skb_checksum_setup_ip(skb, ip_hdr(skb)->protocol, off); ++ if (IS_ERR(csum)) ++ return PTR_ERR(csum); ++ ++ if (recalculate) ++ *csum = ~csum_tcpudp_magic(ip_hdr(skb)->saddr, ++ ip_hdr(skb)->daddr, ++ skb->len - off, ++ ip_hdr(skb)->protocol, 0); ++ err = 0; ++ ++out: ++ return err; +} + -+/* main receive path */ ++/* This value should be large enough to cover a tagged ethernet header plus ++ * an IPv6 header, all options, and a maximal TCP or UDP header. ++ */ ++#define MAX_IPV6_HDR_LEN 256 + -+static bool prepare_for_handlers(struct ieee80211_rx_data *rx, -+ struct ieee80211_hdr *hdr) ++#define OPT_HDR(type, skb, off) \ ++ (type *)(skb_network_header(skb) + (off)) ++ ++static int skb_checksum_setup_ipv6(struct sk_buff *skb, bool recalculate) +{ -+ struct ieee80211_sub_if_data *sdata = rx->sdata; -+ struct sk_buff *skb = rx->skb; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); -+ u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type); -+ int multicast = is_multicast_ether_addr(hdr->addr1); ++ int err; ++ u8 nexthdr; ++ unsigned int off; ++ unsigned int len; ++ bool fragment; ++ bool done; ++ __sum16 *csum; + -+ switch (sdata->vif.type) { -+ case NL80211_IFTYPE_STATION: -+ if (!bssid && !sdata->u.mgd.use_4addr) -+ return false; -+ if (!multicast && -+ !ether_addr_equal(sdata->vif.addr, hdr->addr1)) { -+ if (!(sdata->dev->flags & IFF_PROMISC) || -+ sdata->u.mgd.use_4addr) -+ return false; -+ status->rx_flags &= ~IEEE80211_RX_RA_MATCH; ++ fragment = false; ++ done = false; ++ ++ off = sizeof(struct ipv6hdr); ++ ++ err = skb_maybe_pull_tail(skb, off, MAX_IPV6_HDR_LEN); ++ if (err < 0) ++ goto out; ++ ++ nexthdr = ipv6_hdr(skb)->nexthdr; ++ ++ len = sizeof(struct ipv6hdr) + ntohs(ipv6_hdr(skb)->payload_len); ++ while (off <= len && !done) { ++ switch (nexthdr) { ++ case IPPROTO_DSTOPTS: ++ case IPPROTO_HOPOPTS: ++ case IPPROTO_ROUTING: { ++ struct ipv6_opt_hdr *hp; ++ ++ err = skb_maybe_pull_tail(skb, ++ off + ++ sizeof(struct ipv6_opt_hdr), ++ MAX_IPV6_HDR_LEN); ++ if (err < 0) ++ goto out; ++ ++ hp = OPT_HDR(struct ipv6_opt_hdr, skb, off); ++ nexthdr = hp->nexthdr; ++ off += ipv6_optlen(hp); ++ break; + } -+ break; -+ case NL80211_IFTYPE_ADHOC: -+ if (!bssid) -+ return false; -+ if (ether_addr_equal(sdata->vif.addr, hdr->addr2) || -+ ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2)) -+ return false; -+ if (ieee80211_is_beacon(hdr->frame_control)) { -+ return true; -+ } else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) { -+ return false; -+ } else if (!multicast && -+ !ether_addr_equal(sdata->vif.addr, hdr->addr1)) { -+ if (!(sdata->dev->flags & IFF_PROMISC)) -+ return false; -+ status->rx_flags &= ~IEEE80211_RX_RA_MATCH; -+ } else if (!rx->sta) { -+ int rate_idx; -+ if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) -+ rate_idx = 0; /* TODO: HT/VHT rates */ -+ else -+ rate_idx = status->rate_idx; -+ ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2, -+ BIT(rate_idx)); ++ case IPPROTO_AH: { ++ struct ip_auth_hdr *hp; ++ ++ err = skb_maybe_pull_tail(skb, ++ off + ++ sizeof(struct ip_auth_hdr), ++ MAX_IPV6_HDR_LEN); ++ if (err < 0) ++ goto out; ++ ++ hp = OPT_HDR(struct ip_auth_hdr, skb, off); ++ nexthdr = hp->nexthdr; ++ off += ipv6_authlen(hp); ++ break; + } -+ break; -+ case NL80211_IFTYPE_MESH_POINT: -+ if (!multicast && -+ !ether_addr_equal(sdata->vif.addr, hdr->addr1)) { -+ if (!(sdata->dev->flags & IFF_PROMISC)) -+ return false; ++ case IPPROTO_FRAGMENT: { ++ struct frag_hdr *hp; ++ ++ err = skb_maybe_pull_tail(skb, ++ off + ++ sizeof(struct frag_hdr), ++ MAX_IPV6_HDR_LEN); ++ if (err < 0) ++ goto out; ++ ++ hp = OPT_HDR(struct frag_hdr, skb, off); ++ ++ if (hp->frag_off & htons(IP6_OFFSET | IP6_MF)) ++ fragment = true; + -+ status->rx_flags &= ~IEEE80211_RX_RA_MATCH; ++ nexthdr = hp->nexthdr; ++ off += sizeof(struct frag_hdr); ++ break; + } -+ break; -+ case NL80211_IFTYPE_AP_VLAN: -+ case NL80211_IFTYPE_AP: -+ if (!bssid) { -+ if (!ether_addr_equal(sdata->vif.addr, hdr->addr1)) -+ return false; -+ } else if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) { -+ /* -+ * Accept public action frames even when the -+ * BSSID doesn't match, this is used for P2P -+ * and location updates. Note that mac80211 -+ * itself never looks at these frames. -+ */ -+ if (!multicast && -+ !ether_addr_equal(sdata->vif.addr, hdr->addr1)) -+ return false; -+ if (ieee80211_is_public_action(hdr, skb->len)) -+ return true; -+ if (!ieee80211_is_beacon(hdr->frame_control)) -+ return false; -+ status->rx_flags &= ~IEEE80211_RX_RA_MATCH; -+ } else if (!ieee80211_has_tods(hdr->frame_control)) { -+ /* ignore data frames to TDLS-peers */ -+ if (ieee80211_is_data(hdr->frame_control)) -+ return false; -+ /* ignore action frames to TDLS-peers */ -+ if (ieee80211_is_action(hdr->frame_control) && -+ !ether_addr_equal(bssid, hdr->addr1)) -+ return false; ++ default: ++ done = true; ++ break; + } -+ break; -+ case NL80211_IFTYPE_WDS: -+ if (bssid || !ieee80211_is_data(hdr->frame_control)) -+ return false; -+ if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2)) -+ return false; -+ break; -+ case NL80211_IFTYPE_P2P_DEVICE: -+ if (!ieee80211_is_public_action(hdr, skb->len) && -+ !ieee80211_is_probe_req(hdr->frame_control) && -+ !ieee80211_is_probe_resp(hdr->frame_control) && -+ !ieee80211_is_beacon(hdr->frame_control)) -+ return false; -+ if (!ether_addr_equal(sdata->vif.addr, hdr->addr1) && -+ !multicast) -+ status->rx_flags &= ~IEEE80211_RX_RA_MATCH; -+ break; -+ default: -+ /* should never get here */ -+ WARN_ON_ONCE(1); -+ break; + } + -+ return true; ++ err = -EPROTO; ++ ++ if (!done || fragment) ++ goto out; ++ ++ csum = skb_checksum_setup_ip(skb, nexthdr, off); ++ if (IS_ERR(csum)) ++ return PTR_ERR(csum); ++ ++ if (recalculate) ++ *csum = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, ++ &ipv6_hdr(skb)->daddr, ++ skb->len - off, nexthdr, 0); ++ err = 0; ++ ++out: ++ return err; +} + -+/* -+ * This function returns whether or not the SKB -+ * was destined for RX processing or not, which, -+ * if consume is true, is equivalent to whether -+ * or not the skb was consumed. ++/** ++ * skb_checksum_setup - set up partial checksum offset ++ * @skb: the skb to set up ++ * @recalculate: if true the pseudo-header checksum will be recalculated + */ -+static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx, -+ struct sk_buff *skb, bool consume) ++int skb_checksum_setup(struct sk_buff *skb, bool recalculate) +{ -+ struct ieee80211_local *local = rx->local; -+ struct ieee80211_sub_if_data *sdata = rx->sdata; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); -+ struct ieee80211_hdr *hdr = (void *)skb->data; -+ -+ rx->skb = skb; -+ status->rx_flags |= IEEE80211_RX_RA_MATCH; ++ int err; + -+ if (!prepare_for_handlers(rx, hdr)) -+ return false; ++ switch (skb->protocol) { ++ case htons(ETH_P_IP): ++ err = skb_checksum_setup_ipv4(skb, recalculate); ++ break; + -+ if (!consume) { -+ skb = skb_copy(skb, GFP_ATOMIC); -+ if (!skb) { -+ if (net_ratelimit()) -+ wiphy_debug(local->hw.wiphy, -+ "failed to copy skb for %s\n", -+ sdata->name); -+ return true; -+ } ++ case htons(ETH_P_IPV6): ++ err = skb_checksum_setup_ipv6(skb, recalculate); ++ break; + -+ rx->skb = skb; ++ default: ++ err = -EPROTO; ++ break; + } + -+ ieee80211_invoke_rx_handlers(rx); -+ return true; ++ return err; +} ++EXPORT_SYMBOL(skb_checksum_setup); + -+/* -+ * This is the actual Rx frames handler. as it belongs to Rx path it must -+ * be called with rcu_read_lock protection. -+ */ -+static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, -+ struct sk_buff *skb) -+{ -+ struct ieee80211_local *local = hw_to_local(hw); -+ struct ieee80211_sub_if_data *sdata; -+ struct ieee80211_hdr *hdr; -+ __le16 fc; -+ struct ieee80211_rx_data rx; -+ struct ieee80211_sub_if_data *prev; -+ struct sta_info *sta, *tmp, *prev_sta; -+ int err = 0; -+ -+ fc = ((struct ieee80211_hdr *)skb->data)->frame_control; -+ memset(&rx, 0, sizeof(rx)); -+ rx.skb = skb; -+ rx.local = local; -+ -+ if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) -+ local->dot11ReceivedFragmentCount++; ++void __skb_warn_lro_forwarding(const struct sk_buff *skb) ++{ ++ net_warn_ratelimited("%s: received packets cannot be forwarded while LRO is enabled\n", ++ skb->dev->name); ++} ++EXPORT_SYMBOL(__skb_warn_lro_forwarding); + -+ if (ieee80211_is_mgmt(fc)) { -+ /* drop frame if too short for header */ -+ if (skb->len < ieee80211_hdrlen(fc)) -+ err = -ENOBUFS; -+ else -+ err = skb_linearize(skb); ++void kfree_skb_partial(struct sk_buff *skb, bool head_stolen) ++{ ++ if (head_stolen) { ++ skb_release_head_state(skb); ++ kmem_cache_free(skbuff_head_cache, skb); + } else { -+ err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); ++ __kfree_skb(skb); + } ++} ++EXPORT_SYMBOL(kfree_skb_partial); + -+ if (err) { -+ dev_kfree_skb(skb); -+ return; ++/** ++ * skb_try_coalesce - try to merge skb to prior one ++ * @to: prior buffer ++ * @from: buffer to add ++ * @fragstolen: pointer to boolean ++ * @delta_truesize: how much more was allocated than was requested ++ */ ++bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from, ++ bool *fragstolen, int *delta_truesize) ++{ ++ int i, delta, len = from->len; ++ ++ *fragstolen = false; ++ ++ if (skb_cloned(to)) ++ return false; ++ ++ if (len <= skb_tailroom(to)) { ++ if (len) ++ BUG_ON(skb_copy_bits(from, 0, skb_put(to, len), len)); ++ *delta_truesize = 0; ++ return true; + } + -+ hdr = (struct ieee80211_hdr *)skb->data; -+ ieee80211_parse_qos(&rx); -+ ieee80211_verify_alignment(&rx); ++ if (skb_has_frag_list(to) || skb_has_frag_list(from)) ++ return false; + -+ if (unlikely(ieee80211_is_probe_resp(hdr->frame_control) || -+ ieee80211_is_beacon(hdr->frame_control))) -+ ieee80211_scan_rx(local, skb); ++ if (skb_headlen(from) != 0) { ++ struct page *page; ++ unsigned int offset; + -+ if (ieee80211_is_data(fc)) { -+ prev_sta = NULL; ++ if (skb_shinfo(to)->nr_frags + ++ skb_shinfo(from)->nr_frags >= MAX_SKB_FRAGS) ++ return false; + -+ for_each_sta_info(local, hdr->addr2, sta, tmp) { -+ if (!prev_sta) { -+ prev_sta = sta; -+ continue; -+ } ++ if (skb_head_is_locked(from)) ++ return false; + -+ rx.sta = prev_sta; -+ rx.sdata = prev_sta->sdata; -+ ieee80211_prepare_and_rx_handle(&rx, skb, false); ++ delta = from->truesize - SKB_DATA_ALIGN(sizeof(struct sk_buff)); + -+ prev_sta = sta; -+ } ++ page = virt_to_head_page(from->head); ++ offset = from->data - (unsigned char *)page_address(page); + -+ if (prev_sta) { -+ rx.sta = prev_sta; -+ rx.sdata = prev_sta->sdata; ++ skb_fill_page_desc(to, skb_shinfo(to)->nr_frags, ++ page, offset, skb_headlen(from)); ++ *fragstolen = true; ++ } else { ++ if (skb_shinfo(to)->nr_frags + ++ skb_shinfo(from)->nr_frags > MAX_SKB_FRAGS) ++ return false; + -+ if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) -+ return; -+ goto out; -+ } ++ delta = from->truesize - SKB_TRUESIZE(skb_end_offset(from)); + } + -+ prev = NULL; ++ WARN_ON_ONCE(delta < len); + -+ list_for_each_entry_rcu(sdata, &local->interfaces, list) { -+ if (!ieee80211_sdata_running(sdata)) -+ continue; ++ memcpy(skb_shinfo(to)->frags + skb_shinfo(to)->nr_frags, ++ skb_shinfo(from)->frags, ++ skb_shinfo(from)->nr_frags * sizeof(skb_frag_t)); ++ skb_shinfo(to)->nr_frags += skb_shinfo(from)->nr_frags; + -+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR || -+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN) -+ continue; ++ if (!skb_cloned(from)) ++ skb_shinfo(from)->nr_frags = 0; + -+ /* -+ * frame is destined for this interface, but if it's -+ * not also for the previous one we handle that after -+ * the loop to avoid copying the SKB once too much -+ */ ++ /* if the skb is not cloned this does nothing ++ * since we set nr_frags to 0. ++ */ ++ for (i = 0; i < skb_shinfo(from)->nr_frags; i++) ++ skb_frag_ref(from, i); + -+ if (!prev) { -+ prev = sdata; -+ continue; -+ } ++ to->truesize += delta; ++ to->len += len; ++ to->data_len += len; + -+ rx.sta = sta_info_get_bss(prev, hdr->addr2); -+ rx.sdata = prev; -+ ieee80211_prepare_and_rx_handle(&rx, skb, false); ++ *delta_truesize = delta; ++ return true; ++} ++EXPORT_SYMBOL(skb_try_coalesce); + -+ prev = sdata; -+ } ++/** ++ * skb_scrub_packet - scrub an skb ++ * ++ * @skb: buffer to clean ++ * @xnet: packet is crossing netns ++ * ++ * skb_scrub_packet can be used after encapsulating or decapsulting a packet ++ * into/from a tunnel. Some information have to be cleared during these ++ * operations. ++ * skb_scrub_packet can also be used to clean a skb before injecting it in ++ * another namespace (@xnet == true). We have to clear all information in the ++ * skb that could impact namespace isolation. ++ */ ++void skb_scrub_packet(struct sk_buff *skb, bool xnet) ++{ ++ skb->tstamp.tv64 = 0; ++ skb->pkt_type = PACKET_HOST; ++ skb->skb_iif = 0; ++ skb->ignore_df = 0; ++ skb_dst_drop(skb); ++ secpath_reset(skb); ++ nf_reset(skb); ++ nf_reset_trace(skb); ++ ++ if (!xnet) ++ return; + -+ if (prev) { -+ rx.sta = sta_info_get_bss(prev, hdr->addr2); -+ rx.sdata = prev; ++ skb_orphan(skb); ++ skb->mark = 0; ++} ++EXPORT_SYMBOL_GPL(skb_scrub_packet); + -+ if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) -+ return; ++/** ++ * skb_gso_transport_seglen - Return length of individual segments of a gso packet ++ * ++ * @skb: GSO skb ++ * ++ * skb_gso_transport_seglen is used to determine the real size of the ++ * individual segments, including Layer4 headers (TCP/UDP). ++ * ++ * The MAC/L2 or network (IP, IPv6) headers are not accounted for. ++ */ ++unsigned int skb_gso_transport_seglen(const struct sk_buff *skb) ++{ ++ const struct skb_shared_info *shinfo = skb_shinfo(skb); ++ unsigned int thlen = 0; ++ ++ if (skb->encapsulation) { ++ thlen = skb_inner_transport_header(skb) - ++ skb_transport_header(skb); ++ ++ if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) ++ thlen += inner_tcp_hdrlen(skb); ++ } else if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) { ++ thlen = tcp_hdrlen(skb); ++ } ++ /* UFO sets gso_size to the size of the fragmentation ++ * payload, i.e. the size of the L4 (UDP) header is already ++ * accounted for. ++ */ ++ return thlen + shinfo->gso_size; ++} ++EXPORT_SYMBOL_GPL(skb_gso_transport_seglen); ++ ++static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb) ++{ ++ if (skb_cow(skb, skb_headroom(skb)) < 0) { ++ kfree_skb(skb); ++ return NULL; + } + -+ out: -+ dev_kfree_skb(skb); ++ memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN); ++ skb->mac_header += VLAN_HLEN; ++ return skb; +} + -+/* -+ * This is the receive path handler. It is called by a low level driver when an -+ * 802.11 MPDU is received from the hardware. -+ */ -+void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) ++struct sk_buff *skb_vlan_untag(struct sk_buff *skb) +{ -+ struct ieee80211_local *local = hw_to_local(hw); -+ struct ieee80211_rate *rate = NULL; -+ struct ieee80211_supported_band *sband; -+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); ++ struct vlan_hdr *vhdr; ++ u16 vlan_tci; + -+ WARN_ON_ONCE(softirq_count() == 0); ++ if (unlikely(vlan_tx_tag_present(skb))) { ++ /* vlan_tci is already set-up so leave this for another time */ ++ return skb; ++ } + -+ if (WARN_ON(status->band >= IEEE80211_NUM_BANDS)) -+ goto drop; ++ skb = skb_share_check(skb, GFP_ATOMIC); ++ if (unlikely(!skb)) ++ goto err_free; + -+ sband = local->hw.wiphy->bands[status->band]; -+ if (WARN_ON(!sband)) -+ goto drop; ++ if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) ++ goto err_free; + -+ /* -+ * If we're suspending, it is possible although not too likely -+ * that we'd be receiving frames after having already partially -+ * quiesced the stack. We can't process such frames then since -+ * that might, for example, cause stations to be added or other -+ * driver callbacks be invoked. -+ */ -+ if (unlikely(local->quiescing || local->suspended)) -+ goto drop; ++ vhdr = (struct vlan_hdr *)skb->data; ++ vlan_tci = ntohs(vhdr->h_vlan_TCI); ++ __vlan_hwaccel_put_tag(skb, skb->protocol, vlan_tci); + -+ /* We might be during a HW reconfig, prevent Rx for the same reason */ -+ if (unlikely(local->in_reconfig)) -+ goto drop; ++ skb_pull_rcsum(skb, VLAN_HLEN); ++ vlan_set_encap_proto(skb, vhdr); + -+ /* -+ * The same happens when we're not even started, -+ * but that's worth a warning. -+ */ -+ if (WARN_ON(!local->started)) -+ goto drop; ++ skb = skb_reorder_vlan_header(skb); ++ if (unlikely(!skb)) ++ goto err_free; + -+ if (likely(!(status->flag & RX_FLAG_FAILED_PLCP_CRC))) { -+ /* -+ * Validate the rate, unless a PLCP error means that -+ * we probably can't have a valid rate here anyway. -+ */ ++ skb_reset_network_header(skb); ++ skb_reset_transport_header(skb); ++ skb_reset_mac_len(skb); + -+ if (status->flag & RX_FLAG_HT) { -+ /* -+ * rate_idx is MCS index, which can be [0-76] -+ * as documented on: -+ * -+ * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n -+ * -+ * Anything else would be some sort of driver or -+ * hardware error. The driver should catch hardware -+ * errors. -+ */ -+ if (WARN(status->rate_idx > 76, -+ "Rate marked as an HT rate but passed " -+ "status->rate_idx is not " -+ "an MCS index [0-76]: %d (0x%02x)\n", -+ status->rate_idx, -+ status->rate_idx)) -+ goto drop; -+ } else if (status->flag & RX_FLAG_VHT) { -+ if (WARN_ONCE(status->rate_idx > 9 || -+ !status->vht_nss || -+ status->vht_nss > 8, -+ "Rate marked as a VHT rate but data is invalid: MCS: %d, NSS: %d\n", -+ status->rate_idx, status->vht_nss)) -+ goto drop; -+ } else { -+ if (WARN_ON(status->rate_idx >= sband->n_bitrates)) -+ goto drop; -+ rate = &sband->bitrates[status->rate_idx]; -+ } -+ } ++ return skb; + -+ status->rx_flags = 0; ++err_free: ++ kfree_skb(skb); ++ return NULL; ++} ++EXPORT_SYMBOL(skb_vlan_untag); + -+ /* -+ * key references and virtual interfaces are protected using RCU -+ * and this requires that we are in a read-side RCU section during -+ * receive processing -+ */ -+ rcu_read_lock(); ++/** ++ * alloc_skb_with_frags - allocate skb with page frags ++ * ++ * @header_len: size of linear part ++ * @data_len: needed length in frags ++ * @max_page_order: max page order desired. ++ * @errcode: pointer to error code if any ++ * @gfp_mask: allocation mask ++ * ++ * This can be used to allocate a paged skb, given a maximal order for frags. ++ */ ++struct sk_buff *alloc_skb_with_frags(unsigned long header_len, ++ unsigned long data_len, ++ int max_page_order, ++ int *errcode, ++ gfp_t gfp_mask) ++{ ++ int npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT; ++ unsigned long chunk; ++ struct sk_buff *skb; ++ struct page *page; ++ gfp_t gfp_head; ++ int i; + -+ /* -+ * Frames with failed FCS/PLCP checksum are not returned, -+ * all other frames are returned without radiotap header -+ * if it was previously present. -+ * Also, frames with less than 16 bytes are dropped. ++ *errcode = -EMSGSIZE; ++ /* Note this test could be relaxed, if we succeed to allocate ++ * high order pages... + */ -+ skb = ieee80211_rx_monitor(local, skb, rate); -+ if (!skb) { -+ rcu_read_unlock(); -+ return; -+ } ++ if (npages > MAX_SKB_FRAGS) ++ return NULL; + -+ ieee80211_tpt_led_trig_rx(local, -+ ((struct ieee80211_hdr *)skb->data)->frame_control, -+ skb->len); -+ __ieee80211_rx_handle_packet(hw, skb); ++ gfp_head = gfp_mask; ++ if (gfp_head & __GFP_WAIT) ++ gfp_head |= __GFP_REPEAT; + -+ rcu_read_unlock(); ++ *errcode = -ENOBUFS; ++ skb = alloc_skb(header_len, gfp_head); ++ if (!skb) ++ return NULL; + -+ return; -+ drop: ++ skb->truesize += npages << PAGE_SHIFT; ++ ++ for (i = 0; npages > 0; i++) { ++ int order = max_page_order; ++ ++ while (order) { ++ if (npages >= 1 << order) { ++ page = alloc_pages(gfp_mask | ++ __GFP_COMP | ++ __GFP_NOWARN | ++ __GFP_NORETRY, ++ order); ++ if (page) ++ goto fill_page; ++ /* Do not retry other high order allocations */ ++ order = 1; ++ max_page_order = 0; ++ } ++ order--; ++ } ++ page = alloc_page(gfp_mask); ++ if (!page) ++ goto failure; ++fill_page: ++ chunk = min_t(unsigned long, data_len, ++ PAGE_SIZE << order); ++ skb_fill_page_desc(skb, i, page, 0, chunk); ++ data_len -= chunk; ++ npages -= 1 << order; ++ } ++ return skb; ++ ++failure: + kfree_skb(skb); ++ return NULL; +} -+EXPORT_SYMBOL(ieee80211_rx); ++EXPORT_SYMBOL(alloc_skb_with_frags); +diff -Nur linux-3.18.14.orig/net/core/sock.c linux-3.18.14-rt/net/core/sock.c +--- linux-3.18.14.orig/net/core/sock.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/net/core/sock.c 2015-05-31 15:32:49.433635358 -0500 +@@ -2345,12 +2345,11 @@ + if (sk->sk_lock.owned) + __lock_sock(sk); + sk->sk_lock.owned = 1; +- spin_unlock(&sk->sk_lock.slock); ++ spin_unlock_bh(&sk->sk_lock.slock); + /* + * The sk_lock has mutex_lock() semantics here: + */ + mutex_acquire(&sk->sk_lock.dep_map, subclass, 0, _RET_IP_); +- local_bh_enable(); + } + EXPORT_SYMBOL(lock_sock_nested); + +diff -Nur linux-3.18.14.orig/net/ipv4/icmp.c linux-3.18.14-rt/net/ipv4/icmp.c +--- linux-3.18.14.orig/net/ipv4/icmp.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/net/ipv4/icmp.c 2015-05-31 15:32:49.457635357 -0500 +@@ -69,6 +69,7 @@ + #include <linux/jiffies.h> + #include <linux/kernel.h> + #include <linux/fcntl.h> ++#include <linux/sysrq.h> + #include <linux/socket.h> + #include <linux/in.h> + #include <linux/inet.h> +@@ -864,6 +865,30 @@ + } + + /* ++ * 32bit and 64bit have different timestamp length, so we check for ++ * the cookie at offset 20 and verify it is repeated at offset 50 ++ */ ++#define CO_POS0 20 ++#define CO_POS1 50 ++#define CO_SIZE sizeof(int) ++#define ICMP_SYSRQ_SIZE 57 + -+/* This is a version of the rx handler that can be called from hard irq -+ * context. Post the skb on the queue and schedule the tasklet */ -+void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb) ++/* ++ * We got a ICMP_SYSRQ_SIZE sized ping request. Check for the cookie ++ * pattern and if it matches send the next byte as a trigger to sysrq. ++ */ ++static void icmp_check_sysrq(struct net *net, struct sk_buff *skb) +{ -+ struct ieee80211_local *local = hw_to_local(hw); -+ -+ BUILD_BUG_ON(sizeof(struct ieee80211_rx_status) > sizeof(skb->cb)); ++ int cookie = htonl(net->ipv4.sysctl_icmp_echo_sysrq); ++ char *p = skb->data; + -+ skb->pkt_type = IEEE80211_RX_MSG; -+ skb_queue_tail(&local->skb_queue, skb); -+ tasklet_schedule(&local->tasklet); ++ if (!memcmp(&cookie, p + CO_POS0, CO_SIZE) && ++ !memcmp(&cookie, p + CO_POS1, CO_SIZE) && ++ p[CO_POS0 + CO_SIZE] == p[CO_POS1 + CO_SIZE]) ++ handle_sysrq(p[CO_POS0 + CO_SIZE]); +} -+EXPORT_SYMBOL(ieee80211_rx_irqsafe); -diff -Nur linux-3.18.12.orig/net/netfilter/core.c linux-3.18.12/net/netfilter/core.c ---- linux-3.18.12.orig/net/netfilter/core.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/net/netfilter/core.c 2015-04-26 13:32:22.471684003 -0500 ++ ++/* + * Handle ICMP_ECHO ("ping") requests. + * + * RFC 1122: 3.2.2.6 MUST have an echo server that answers ICMP echo +@@ -890,6 +915,11 @@ + icmp_param.data_len = skb->len; + icmp_param.head_len = sizeof(struct icmphdr); + icmp_reply(&icmp_param, skb); ++ ++ if (skb->len == ICMP_SYSRQ_SIZE && ++ net->ipv4.sysctl_icmp_echo_sysrq) { ++ icmp_check_sysrq(net, skb); ++ } + } + } + +diff -Nur linux-3.18.14.orig/net/ipv4/sysctl_net_ipv4.c linux-3.18.14-rt/net/ipv4/sysctl_net_ipv4.c +--- linux-3.18.14.orig/net/ipv4/sysctl_net_ipv4.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/net/ipv4/sysctl_net_ipv4.c 2015-05-31 15:32:49.485635357 -0500 +@@ -779,6 +779,13 @@ + .proc_handler = proc_dointvec + }, + { ++ .procname = "icmp_echo_sysrq", ++ .data = &init_net.ipv4.sysctl_icmp_echo_sysrq, ++ .maxlen = sizeof(int), ++ .mode = 0644, ++ .proc_handler = proc_dointvec ++ }, ++ { + .procname = "icmp_ignore_bogus_error_responses", + .data = &init_net.ipv4.sysctl_icmp_ignore_bogus_error_responses, + .maxlen = sizeof(int), +diff -Nur linux-3.18.14.orig/net/mac80211/rx.c linux-3.18.14-rt/net/mac80211/rx.c +--- linux-3.18.14.orig/net/mac80211/rx.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/net/mac80211/rx.c 2015-05-31 15:32:49.501635357 -0500 +@@ -3360,7 +3360,7 @@ + struct ieee80211_supported_band *sband; + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + +- WARN_ON_ONCE(softirq_count() == 0); ++ WARN_ON_ONCE_NONRT(softirq_count() == 0); + + if (WARN_ON(status->band >= IEEE80211_NUM_BANDS)) + goto drop; +diff -Nur linux-3.18.14.orig/net/netfilter/core.c linux-3.18.14-rt/net/netfilter/core.c +--- linux-3.18.14.orig/net/netfilter/core.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/net/netfilter/core.c 2015-05-31 15:32:49.549635357 -0500 @@ -21,11 +21,17 @@ #include <linux/proc_fs.h> #include <linux/mutex.h> @@ -36114,9 +36630,9 @@ diff -Nur linux-3.18.12.orig/net/netfilter/core.c linux-3.18.12/net/netfilter/co static DEFINE_MUTEX(afinfo_mutex); const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO] __read_mostly; -diff -Nur linux-3.18.12.orig/net/packet/af_packet.c linux-3.18.12/net/packet/af_packet.c ---- linux-3.18.12.orig/net/packet/af_packet.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/net/packet/af_packet.c 2015-04-26 13:32:22.471684003 -0500 +diff -Nur linux-3.18.14.orig/net/packet/af_packet.c linux-3.18.14-rt/net/packet/af_packet.c +--- linux-3.18.14.orig/net/packet/af_packet.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/net/packet/af_packet.c 2015-05-31 15:32:49.557635357 -0500 @@ -63,6 +63,7 @@ #include <linux/if_packet.h> #include <linux/wireless.h> @@ -36143,9 +36659,9 @@ diff -Nur linux-3.18.12.orig/net/packet/af_packet.c linux-3.18.12/net/packet/af_ } } prb_close_block(pkc, pbd, po, status); -diff -Nur linux-3.18.12.orig/net/rds/ib_rdma.c linux-3.18.12/net/rds/ib_rdma.c ---- linux-3.18.12.orig/net/rds/ib_rdma.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/net/rds/ib_rdma.c 2015-04-26 13:32:22.471684003 -0500 +diff -Nur linux-3.18.14.orig/net/rds/ib_rdma.c linux-3.18.14-rt/net/rds/ib_rdma.c +--- linux-3.18.14.orig/net/rds/ib_rdma.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/net/rds/ib_rdma.c 2015-05-31 15:32:49.573635357 -0500 @@ -34,6 +34,7 @@ #include <linux/slab.h> #include <linux/rculist.h> @@ -36163,9 +36679,9 @@ diff -Nur linux-3.18.12.orig/net/rds/ib_rdma.c linux-3.18.12/net/rds/ib_rdma.c } } -diff -Nur linux-3.18.12.orig/net/sched/sch_generic.c linux-3.18.12/net/sched/sch_generic.c ---- linux-3.18.12.orig/net/sched/sch_generic.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/net/sched/sch_generic.c 2015-04-26 13:32:22.471684003 -0500 +diff -Nur linux-3.18.14.orig/net/sched/sch_generic.c linux-3.18.14-rt/net/sched/sch_generic.c +--- linux-3.18.14.orig/net/sched/sch_generic.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/net/sched/sch_generic.c 2015-05-31 15:32:49.593635356 -0500 @@ -894,7 +894,7 @@ /* Wait for outstanding qdisc_run calls. */ list_for_each_entry(dev, head, close_list) @@ -36175,9 +36691,9 @@ diff -Nur linux-3.18.12.orig/net/sched/sch_generic.c linux-3.18.12/net/sched/sch } void dev_deactivate(struct net_device *dev) -diff -Nur linux-3.18.12.orig/net/sunrpc/svc_xprt.c linux-3.18.12/net/sunrpc/svc_xprt.c ---- linux-3.18.12.orig/net/sunrpc/svc_xprt.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/net/sunrpc/svc_xprt.c 2015-04-26 13:32:22.475684003 -0500 +diff -Nur linux-3.18.14.orig/net/sunrpc/svc_xprt.c linux-3.18.14-rt/net/sunrpc/svc_xprt.c +--- linux-3.18.14.orig/net/sunrpc/svc_xprt.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/net/sunrpc/svc_xprt.c 2015-05-31 15:32:49.617635356 -0500 @@ -357,7 +357,7 @@ return; } @@ -36196,9 +36712,9 @@ diff -Nur linux-3.18.12.orig/net/sunrpc/svc_xprt.c linux-3.18.12/net/sunrpc/svc_ } /* -diff -Nur linux-3.18.12.orig/scripts/mkcompile_h linux-3.18.12/scripts/mkcompile_h ---- linux-3.18.12.orig/scripts/mkcompile_h 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/scripts/mkcompile_h 2015-04-26 13:32:22.475684003 -0500 +diff -Nur linux-3.18.14.orig/scripts/mkcompile_h linux-3.18.14-rt/scripts/mkcompile_h +--- linux-3.18.14.orig/scripts/mkcompile_h 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/scripts/mkcompile_h 2015-05-31 15:32:49.641635356 -0500 @@ -4,7 +4,8 @@ ARCH=$2 SMP=$3 @@ -36217,9 +36733,9 @@ diff -Nur linux-3.18.12.orig/scripts/mkcompile_h linux-3.18.12/scripts/mkcompile UTS_VERSION="$UTS_VERSION $CONFIG_FLAGS $TIMESTAMP" # Truncate to maximum length -diff -Nur linux-3.18.12.orig/sound/core/pcm_native.c linux-3.18.12/sound/core/pcm_native.c ---- linux-3.18.12.orig/sound/core/pcm_native.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/sound/core/pcm_native.c 2015-04-26 13:32:22.475684003 -0500 +diff -Nur linux-3.18.14.orig/sound/core/pcm_native.c linux-3.18.14-rt/sound/core/pcm_native.c +--- linux-3.18.14.orig/sound/core/pcm_native.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/sound/core/pcm_native.c 2015-05-31 15:32:49.661635356 -0500 @@ -104,7 +104,7 @@ void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream) { @@ -36256,9 +36772,9 @@ diff -Nur linux-3.18.12.orig/sound/core/pcm_native.c linux-3.18.12/sound/core/pc } EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore); -diff -Nur linux-3.18.12.orig/virt/kvm/async_pf.c linux-3.18.12/virt/kvm/async_pf.c ---- linux-3.18.12.orig/virt/kvm/async_pf.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/virt/kvm/async_pf.c 2015-04-26 13:32:22.475684003 -0500 +diff -Nur linux-3.18.14.orig/virt/kvm/async_pf.c linux-3.18.14-rt/virt/kvm/async_pf.c +--- linux-3.18.14.orig/virt/kvm/async_pf.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/virt/kvm/async_pf.c 2015-05-31 15:32:49.661635356 -0500 @@ -94,8 +94,8 @@ trace_kvm_async_pf_completed(addr, gva); @@ -36270,9 +36786,9 @@ diff -Nur linux-3.18.12.orig/virt/kvm/async_pf.c linux-3.18.12/virt/kvm/async_pf mmput(mm); kvm_put_kvm(vcpu->kvm); -diff -Nur linux-3.18.12.orig/virt/kvm/kvm_main.c linux-3.18.12/virt/kvm/kvm_main.c ---- linux-3.18.12.orig/virt/kvm/kvm_main.c 2015-04-20 14:48:02.000000000 -0500 -+++ linux-3.18.12/virt/kvm/kvm_main.c 2015-04-26 13:32:22.475684003 -0500 +diff -Nur linux-3.18.14.orig/virt/kvm/kvm_main.c linux-3.18.14-rt/virt/kvm/kvm_main.c +--- linux-3.18.14.orig/virt/kvm/kvm_main.c 2015-05-20 10:04:50.000000000 -0500 ++++ linux-3.18.14-rt/virt/kvm/kvm_main.c 2015-05-31 15:32:49.697635356 -0500 @@ -221,7 +221,7 @@ vcpu->kvm = kvm; vcpu->vcpu_id = id; @@ -36282,7 +36798,7 @@ diff -Nur linux-3.18.12.orig/virt/kvm/kvm_main.c linux-3.18.12/virt/kvm/kvm_main kvm_async_pf_vcpu_init(vcpu); page = alloc_page(GFP_KERNEL | __GFP_ZERO); -@@ -1740,10 +1740,10 @@ +@@ -1741,10 +1741,10 @@ */ void kvm_vcpu_block(struct kvm_vcpu *vcpu) { @@ -36295,7 +36811,7 @@ diff -Nur linux-3.18.12.orig/virt/kvm/kvm_main.c linux-3.18.12/virt/kvm/kvm_main if (kvm_arch_vcpu_runnable(vcpu)) { kvm_make_request(KVM_REQ_UNHALT, vcpu); -@@ -1757,7 +1757,7 @@ +@@ -1758,7 +1758,7 @@ schedule(); } @@ -36304,7 +36820,7 @@ diff -Nur linux-3.18.12.orig/virt/kvm/kvm_main.c linux-3.18.12/virt/kvm/kvm_main } EXPORT_SYMBOL_GPL(kvm_vcpu_block); -@@ -1769,11 +1769,11 @@ +@@ -1770,11 +1770,11 @@ { int me; int cpu = vcpu->cpu; @@ -36319,7 +36835,7 @@ diff -Nur linux-3.18.12.orig/virt/kvm/kvm_main.c linux-3.18.12/virt/kvm/kvm_main ++vcpu->stat.halt_wakeup; } -@@ -1878,7 +1878,7 @@ +@@ -1879,7 +1879,7 @@ continue; if (vcpu == me) continue; diff --git a/target/linux/patches/3.18.12/regmap-bool.patch b/target/linux/patches/3.18.14/regmap-bool.patch index 5c0ff5e2c..5c0ff5e2c 100644 --- a/target/linux/patches/3.18.12/regmap-bool.patch +++ b/target/linux/patches/3.18.14/regmap-bool.patch diff --git a/target/linux/patches/3.18.12/relocs.patch b/target/linux/patches/3.18.14/relocs.patch index 69a7c88a9..69a7c88a9 100644 --- a/target/linux/patches/3.18.12/relocs.patch +++ b/target/linux/patches/3.18.14/relocs.patch diff --git a/target/linux/patches/3.18.12/sgidefs.patch b/target/linux/patches/3.18.14/sgidefs.patch index f00a284d9..f00a284d9 100644 --- a/target/linux/patches/3.18.12/sgidefs.patch +++ b/target/linux/patches/3.18.14/sgidefs.patch diff --git a/target/linux/patches/3.18.12/sortext.patch b/target/linux/patches/3.18.14/sortext.patch index 8fd4e1d6b..8fd4e1d6b 100644 --- a/target/linux/patches/3.18.12/sortext.patch +++ b/target/linux/patches/3.18.14/sortext.patch diff --git a/target/linux/patches/3.18.12/startup.patch b/target/linux/patches/3.18.14/startup.patch index d396b75e4..d396b75e4 100644 --- a/target/linux/patches/3.18.12/startup.patch +++ b/target/linux/patches/3.18.14/startup.patch diff --git a/target/linux/patches/3.18.12/wlan-cf.patch b/target/linux/patches/3.18.14/wlan-cf.patch index fc20759e2..fc20759e2 100644 --- a/target/linux/patches/3.18.12/wlan-cf.patch +++ b/target/linux/patches/3.18.14/wlan-cf.patch diff --git a/target/linux/patches/3.18.12/xargs.patch b/target/linux/patches/3.18.14/xargs.patch index 2c7b3df59..2c7b3df59 100644 --- a/target/linux/patches/3.18.12/xargs.patch +++ b/target/linux/patches/3.18.14/xargs.patch diff --git a/target/linux/patches/3.18.12/yaffs2.patch b/target/linux/patches/3.18.14/yaffs2.patch index bb244c7ca..bb244c7ca 100644 --- a/target/linux/patches/3.18.12/yaffs2.patch +++ b/target/linux/patches/3.18.14/yaffs2.patch |