[kernel/f16] Linux 3.5

Dave Jones davej at fedoraproject.org
Tue Oct 16 18:00:31 UTC 2012


commit f692e37cf5b02cc4341a78f65f49589747bae80a
Author: Dave Jones <davej at redhat.com>
Date:   Tue Oct 16 14:00:18 2012 -0400

    Linux 3.5

 atl1c_net_next_update-3.4.patch                    | 3657 ----------
 config-generic                                     |   87 +-
 config-powerpc-generic                             |    4 +
 config-powerpc64                                   |    5 +
 config-s390x                                       |    1 +
 config-sparc64-generic                             |    3 +
 config-x86-32-generic                              |    4 +
 config-x86-generic                                 |    5 +
 drm-i915-fbc-stfu.patch                            |  102 -
 ...lidate-sb-s_first-in-journal_get_superblo.patch |   95 -
 kernel.spec                                        |   32 +-
 linux-2.6-input-kill-stupid-messages.patch         |   20 +-
 linux-2.6-makefile-after_link.patch                |   82 +-
 ...sd_revalidate_disk-prevent-NULL-ptr-deref.patch |    2 +-
 sources                                            |    3 +-
 uprobes-3.4-backport.patch                         | 6983 --------------------
 uprobes-3.4-tip.patch                              |  915 ---
 uprobes-backport.patch                             | 1742 +++++
 18 files changed, 1899 insertions(+), 11843 deletions(-)
---
diff --git a/config-generic b/config-generic
index 7427c2d..dc9441e 100644
--- a/config-generic
+++ b/config-generic
@@ -169,6 +169,7 @@ CONFIG_MLX4_INFINIBAND=m
 CONFIG_INFINIBAND_NES=m
 # CONFIG_INFINIBAND_NES_DEBUG is not set
 CONFIG_INFINIBAND_QIB=m
+# CONFIG_INFINIBAND_OCRDMA is not set
 
 #
 # Executable file formats
@@ -189,6 +190,8 @@ CONFIG_FW_LOADER=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 CONFIG_EXTRA_FIRMWARE=""
 
+# CONFIG_CMA is not set
+
 # CONFIG_SPI is not set
 
 #
@@ -446,6 +449,7 @@ CONFIG_VIRTIO_BLK=m
 CONFIG_VIRTIO_PCI=y
 CONFIG_VIRTIO_BALLOON=m
 CONFIG_VIRTIO_MMIO=m
+# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set
 CONFIG_VIRTIO_NET=m
 CONFIG_VMXNET3=m
 CONFIG_HW_RANDOM_VIRTIO=m
@@ -589,6 +593,7 @@ CONFIG_SCSI_DC395x=m
 CONFIG_SCSI_DEBUG=m
 CONFIG_SCSI_DC390T=m
 CONFIG_SCSI_QLA_FC=m
+CONFIG_TCM_QLA2XXX=m
 CONFIG_SCSI_QLA_ISCSI=m
 # CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_DPT_I2O is not set
@@ -914,6 +919,7 @@ CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
 CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
 CONFIG_NETFILTER_XT_TARGET_CT=m
 CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
 CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
 CONFIG_NETFILTER_XT_TARGET_LED=m
 CONFIG_NETFILTER_XT_TARGET_LOG=m
@@ -1168,6 +1174,8 @@ CONFIG_NET_SCH_MQPRIO=m
 CONFIG_NET_SCH_MULTIQ=m
 CONFIG_NET_SCH_CHOKE=m
 CONFIG_NET_SCH_QFQ=m
+CONFIG_NET_SCH_CODEL=m
+CONFIG_NET_SCH_FQ_CODEL=m
 CONFIG_NET_SCH_PLUG=m
 CONFIG_NET_CLS=y
 CONFIG_NET_CLS_ACT=y
@@ -1225,6 +1233,7 @@ CONFIG_IFB=m
 CONFIG_NET_TEAM=m
 CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
 CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
 CONFIG_MACVLAN=m
@@ -1371,12 +1380,15 @@ CONFIG_E1000=m
 CONFIG_E1000E=m
 CONFIG_IGB=m
 CONFIG_IGB_DCA=y
+CONFIG_IGB_PTP=y
 CONFIG_IGBVF=m
 CONFIG_IXGB=m
 CONFIG_IXGBEVF=m
 CONFIG_IXGBE=m
 CONFIG_IXGBE_DCA=y
 CONFIG_IXGBE_DCB=y
+CONFIG_IXGBE_HWMON=y
+CONFIG_IXGBE_PTP=y
 
 # CONFIG_NET_VENDOR_I825XX is not set
 CONFIG_NET_VENDOR_MARVELL=y
@@ -1477,6 +1489,10 @@ CONFIG_VIA_RHINE=m
 CONFIG_VIA_RHINE_MMIO=y
 CONFIG_VIA_VELOCITY=m
 
+CONFIG_NET_VENDOR_WIZNET=y
+CONFIG_WIZNET_W5100=m
+CONFIG_WIZNET_W5300=m
+
 CONFIG_NET_VENDOR_XIRCOM=y
 CONFIG_PCMCIA_XIRC2PS=m
 
@@ -1529,6 +1545,7 @@ CONFIG_JME=m
 #
 CONFIG_IP1000=m
 CONFIG_MLX4_EN=m
+CONFIG_MLX4_EN_DCB=y
 # CONFIG_MLX4_DEBUG is not set
 CONFIG_SFC=m
 CONFIG_SFC_MCDI_MON=y
@@ -1645,6 +1662,7 @@ CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y
 CONFIG_BRCMSMAC=m
 CONFIG_BRCMFMAC=m
 CONFIG_BRCMFMAC_SDIO=y
+CONFIG_BRCMFMAC_SDIO_OOB=y
 CONFIG_BRCMFMAC_USB=y
 # CONFIG_BRCMDBG is not set
 CONFIG_HERMES=m
@@ -1727,6 +1745,7 @@ CONFIG_USB_NET_RNDIS_WLAN=m
 CONFIG_USB_NET_KALMIA=m
 CONFIG_USB_NET_QMI_WWAN=m
 CONFIG_USB_NET_SMSC75XX=m
+# CONFIG_WL_TI is not set
 CONFIG_ZD1211RW=m
 # CONFIG_ZD1211RW_DEBUG is not set
 
@@ -1749,6 +1768,7 @@ CONFIG_RTL8192DE=m
 CONFIG_MWIFIEX=m
 CONFIG_MWIFIEX_SDIO=m
 CONFIG_MWIFIEX_PCIE=m
+CONFIG_MWIFIEX_USB=m
 
 #
 # Token Ring devices
@@ -2012,6 +2032,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 CONFIG_INPUT_JOYDEV=m
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
 
 CONFIG_INPUT_TABLET=y
 CONFIG_TABLET_USB_ACECAD=m
@@ -2062,6 +2083,7 @@ CONFIG_KEYBOARD_ATKBD=y
 # CONFIG_KEYBOARD_STOWAWAY is not set
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_LM8323 is not set
+# CONFIG_KEYBOARD_LM8333 is not set
 # CONFIG_KEYBOARD_ADP5588 is not set
 # CONFIG_KEYBOARD_MAX7359 is not set
 # CONFIG_KEYBOARD_ADP5589 is not set
@@ -2145,6 +2167,7 @@ CONFIG_TOUCHSCREEN_TOUCHWIN=m
 CONFIG_TOUCHSCREEN_PIXCIR=m
 CONFIG_TOUCHSCREEN_UCB1400=m
 CONFIG_TOUCHSCREEN_WACOM_W8001=m
+CONFIG_TOUCHSCREEN_WACOM_I2C=m
 CONFIG_TOUCHSCREEN_USB_E2I=y
 CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
 # CONFIG_TOUCHSCREEN_WM97XX is not set
@@ -2401,6 +2424,7 @@ CONFIG_SENSORS_WM8350=m
 CONFIG_SENSORS_WM831X=m
 CONFIG_SENSORS_LM73=m
 CONFIG_SENSORS_AMC6821=m
+CONFIG_SENSORS_INA2XX=m
 CONFIG_SENSORS_ADT7411=m
 CONFIG_SENSORS_ASC7621=m
 CONFIG_SENSORS_EMC1403=m
@@ -2440,6 +2464,7 @@ CONFIG_SENSORS_MAX1668=m
 
 # CONFIG_HMC6352 is not set
 # CONFIG_BMP085 is not set
+# CONFIG_BMP085_I2C is not set
 # CONFIG_PCH_PHUB is not set
 # CONFIG_SERIAL_PCH_UART is not set
 # CONFIG_USB_SWITCH_FSA9480 is not set
@@ -2583,10 +2608,13 @@ CONFIG_DRM=m
 # CONFIG_DRM_LOAD_EDID_FIRMWARE is not set
 CONFIG_DRM_TDFX=m
 CONFIG_DRM_R128=m
+# CONFIG_DRM_AST is not set
+# CONFIG_DRM_CIRRUS_QEMU is not set
 CONFIG_DRM_RADEON=m
 CONFIG_DRM_RADEON_KMS=y
 CONFIG_DRM_I810=m
 CONFIG_DRM_MGA=m
+# CONFIG_DRM_MGAG200 is not set
 CONFIG_DRM_SIS=m
 CONFIG_DRM_SAVAGE=m
 CONFIG_DRM_I915=m
@@ -2866,6 +2894,7 @@ CONFIG_FB=y
 # CONFIG_FB_ATY_CT is not set
 # CONFIG_FB_ATY_GX is not set
 # CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_AUO_K190X is not set
 # CONFIG_FB_CARMINE is not set
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_CYBER2000 is not set
@@ -3192,7 +3221,8 @@ CONFIG_USB_HID=y
 
 CONFIG_HID_SUPPORT=y
 
-CONFIG_HID=m
+CONFIG_HID=ym
+CONFIG_HID_BATTERY_STRENGTH=y
 # debugging default is y upstream now
 CONFIG_HIDRAW=y
 CONFIG_HID_PID=y
@@ -3257,6 +3287,9 @@ CONFIG_HID_WIIMOTE_EXT=y
 CONFIG_HID_KYE=m
 CONFIG_HID_SAITEK=m
 CONFIG_HID_TIVO=m
+CONFIG_HID_GENERIC=y
+CONFIG_HID_AUREAL=m
+
 
 #
 # USB Imaging devices
@@ -3368,6 +3401,7 @@ CONFIG_USB_EPSON2888=y
 CONFIG_USB_KC2190=y
 
 # CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_CHIPIDEA is not set
 
 #
 # USB port drivers
@@ -3444,6 +3478,7 @@ CONFIG_USB_SERIAL_QCAUX=m
 CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
 CONFIG_USB_SERIAL_DEBUG=m
 CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_QT2=m
 
 CONFIG_USB_SERIAL_CONSOLE=y
 
@@ -3505,6 +3540,8 @@ CONFIG_USB_ZERO=m
 
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 
+# CONFIG_USB_ISP1301 is not set
+
 # CONFIG_USB_OTG is not set
 
 #
@@ -3543,6 +3580,7 @@ CONFIG_MFD_WM8400=m
 # CONFIG_MFD_WM8994 is not set
 # CONFIG_MFD_88PM860X is not set
 # CONFIG_LPC_SCH is not set
+# CONFIG_LPC_ICH is not set
 # CONFIG_HTC_I2CPLD is not set
 # CONFIG_MFD_MAX8925 is not set
 # CONFIG_MFD_ASIC3 is not set
@@ -3559,6 +3597,8 @@ CONFIG_MFD_WM8400=m
 # CONFIG_MFD_TC3589X is not set
 # CONFIG_MFD_WL1273_CORE is not set
 # CONFIG_MFD_TPS65217 is not set
+# CONFIG_MFD_LM3533 is not set
+# CONFIG_MFD_MC13XXX_I2C is not set
 
 #
 # File systems
@@ -3695,6 +3735,7 @@ CONFIG_CUSE=m
 #
 CONFIG_NETWORK_FILESYSTEMS=y
 CONFIG_NFS_FS=m
+CONFIG_NFS_V2=y
 CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
@@ -3827,6 +3868,17 @@ CONFIG_NLS_ISO8859_14=m
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_KOI8_R=m
 CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
 CONFIG_NLS_UTF8=m
 CONFIG_NLS_ASCII=y
 
@@ -3849,6 +3901,7 @@ CONFIG_FRAME_POINTER=y
 # CONFIG_DEBUG_DRIVER is not set
 CONFIG_HEADERS_CHECK=y
 # CONFIG_LKDTM is not set
+# CONFIG_READABLE_ASM is not set
 
 # CONFIG_RT_MUTEX_TESTER is not set
 # CONFIG_DEBUG_LOCKDEP is not set
@@ -3884,6 +3937,7 @@ CONFIG_LOCKUP_DETECTOR=y
 CONFIG_ATOMIC64_SELFTEST=y
 CONFIG_MEMORY_FAILURE=y
 CONFIG_HWPOISON_INJECT=m
+CONFIG_CROSS_MEMORY_ATTACH=y
 # CONFIG_DEBUG_SECTION_MISMATCH is not set
 # CONFIG_BACKTRACE_SELF_TEST is not set
 CONFIG_LATENCYTOP=y
@@ -4016,6 +4070,7 @@ CONFIG_CRC_T10DIF=m
 CONFIG_CRC8=m
 # CONFIG_CRC7 is not set
 CONFIG_CORDIC=m
+# CONFIG_DDR is not set
 
 CONFIG_CRYPTO_ZLIB=m
 CONFIG_ZLIB_INFLATE=y
@@ -4102,6 +4157,8 @@ CONFIG_PM_TRACE_RTC=y
 # CONFIG_PM_TEST_SUSPEND is not set
 CONFIG_PM_RUNTIME=y
 # CONFIG_PM_OPP is not set
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
 
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
@@ -4250,6 +4307,7 @@ CONFIG_LEDS_TRIGGER_IDE_DISK=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=m
 CONFIG_LEDS_TRIGGER_BACKLIGHT=m
 CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
+CONFIG_LEDS_TRIGGER_TRANSIENT=m
 CONFIG_LEDS_ALIX2=m
 CONFIG_LEDS_CLEVO_MAIL=m
 CONFIG_LEDS_INTEL_SS4200=m
@@ -4310,7 +4368,7 @@ CONFIG_CFAG12864B_RATE=20
 # CONFIG_PHANTOM is not set
 # CONFIG_INTEL_MID_PTI is not set
 
-CONFIG_POWER_SUPPLY=m
+CONFIG_POWER_SUPPLY=y
 # CONFIG_POWER_SUPPLY_DEBUG is not set
 
 # CONFIG_TEST_POWER is not set
@@ -4401,10 +4459,10 @@ CONFIG_OPTIMIZE_INLINING=y
 # CONFIG_GPIOLIB is not set
 # CONFIG_PINCTRL is not set
 
-CONFIG_NET_DSA=y
-CONFIG_NET_DSA_MV88E6060=y
-CONFIG_NET_DSA_MV88E6131=y
-CONFIG_NET_DSA_MV88E6123_61_65=y
+CONFIG_NET_DSA=m
+CONFIG_NET_DSA_MV88E6060=m
+CONFIG_NET_DSA_MV88E6131=m
+CONFIG_NET_DSA_MV88E6123_61_65=m
 
 # Used by Maemo, we don't care.
 # CONFIG_PHONET is not set
@@ -4425,6 +4483,8 @@ CONFIG_USB_WUSB_CBAF=m
 # CONFIG_USB_WUSB_CBAF_DEBUG is not set
 CONFIG_USB_WHCI_HCD=m
 CONFIG_USB_HWA_HCD=m
+# CONFIG_USB_HCD_BCMA is not set
+# CONFIG_USB_HCD_SSB is not set
 
 CONFIG_UWB=m
 CONFIG_UWB_HWA=m
@@ -4473,7 +4533,8 @@ CONFIG_USB_ATMEL=m
 # CONFIG_EASYCAP is not set
 # CONFIG_SOLO6X10 is not set
 # CONFIG_ACPI_QUICKSTART is not set
-# CONFIG_R8712U is not set
+CONFIG_R8712U=m # Larry Finger maintains this (rhbz 699618)
+# CONFIG_R8712_AP is not set
 # CONFIG_ATH6K_LEGACY is not set
 # CONFIG_USB_ENESTORAGE is not set
 # CONFIG_BCM_WIMAX is not set
@@ -4494,6 +4555,8 @@ CONFIG_ALTERA_STAPL=m
 # CONFIG_ZSMALLOC is not set
 # CONFIG_RAMSTER is not set
 # CONFIG_USB_WPAN_HCD is not set
+# CONFIG_WIMAX_GDM72XX is not set 
+# CONFIG_IPACK_BUS is not set
 #
 # END OF STAGING
 
@@ -4534,6 +4597,12 @@ CONFIG_IEEE802154=m
 CONFIG_IEEE802154_6LOWPAN=m
 CONFIG_IEEE802154_DRIVERS=m
 CONFIG_IEEE802154_FAKEHARD=m
+CONFIG_IEEE802154_FAKELB=m
+
+CONFIG_MAC802154=m
+
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
 
 CONFIG_PPS=m
 # CONFIG_PPS_CLIENT_KTIMER is not set
@@ -4548,6 +4617,7 @@ CONFIG_PTP_1588_CLOCK=m
 CONFIG_PTP_1588_CLOCK_PCH=m
 
 CONFIG_CLEANCACHE=y
+CONFIG_FRONTSWAP=y
 
 # CONFIG_MDIO_GPIO is not set
 # CONFIG_KEYBOARD_GPIO is not set
@@ -4589,6 +4659,7 @@ CONFIG_TEST_KSTRTOX=y
 CONFIG_TARGET_CORE=m
 CONFIG_ISCSI_TARGET=m
 CONFIG_LOOPBACK_TARGET=m
+CONFIG_SBP_TARGET=m
 CONFIG_TCM_IBLOCK=m
 CONFIG_TCM_FILEIO=m
 CONFIG_TCM_PSCSI=m
@@ -4597,6 +4668,7 @@ CONFIG_TCM_FC=m
 CONFIG_HWSPINLOCK=m
 
 CONFIG_PSTORE=y
+CONFIG_PSTORE_RAM=m
 
 # CONFIG_AVERAGE is not set
 
@@ -4616,3 +4688,4 @@ CONFIG_IOMMU_SUPPORT=y
 # CONFIG_HSI is not set
 
 # CONFIG_PM_DEVFREQ is not set
+
diff --git a/config-powerpc-generic b/config-powerpc-generic
index 59e7d5c..1b82cf4 100644
--- a/config-powerpc-generic
+++ b/config-powerpc-generic
@@ -359,7 +359,11 @@ CONFIG_RFKILL_GPIO=m
 # CONFIG_INPUT_GPIO_TILT_POLLED is not set
 # CONFIG_CPU_IDLE is not set
 CONFIG_STRICT_DEVMEM=y
+
+CONFIG_RCU_FANOUT_LEAF=16
+
 # CONFIG_V4L_RADIO_ISA_DRIVERS is not set
 # CONFIG_IRQ_DOMAIN_DEBUG is not set
 # CONFIG_MPIC_MSGR is not set
 # CONFIG_FA_DUMP is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
diff --git a/config-powerpc64 b/config-powerpc64
index 3057191..708e311 100644
--- a/config-powerpc64
+++ b/config-powerpc64
@@ -1,6 +1,8 @@
+CONFIG_WINDFARM_PM72=y
 CONFIG_WINDFARM_PM81=y
 CONFIG_WINDFARM_PM91=y
 CONFIG_WINDFARM_PM121=y
+CONFIG_WINDFARM_RM31=y
 CONFIG_PPC_PMAC64=y
 CONFIG_PPC_MAPLE=y
 # CONFIG_PPC_CELL is not set
@@ -158,6 +160,9 @@ CONFIG_PPC_ICSWX=y
 CONFIG_IO_EVENT_IRQ=y
 CONFIG_HW_RANDOM_AMD=m
 
+CONFIG_HW_RANDOM_PSERIES=m
+CONFIG_CRYPTO_DEV_NX=m
+
 CONFIG_BPF_JIT=y
 
 # CONFIG_PPC_ICSWX_PID is not set
diff --git a/config-s390x b/config-s390x
index 848709d..e68ad47 100644
--- a/config-s390x
+++ b/config-s390x
@@ -211,6 +211,7 @@ CONFIG_CHSC_SCH=m
 CONFIG_HVC_IUCV=y
 
 CONFIG_RCU_FANOUT=64
+CONFIG_RCU_FANOUT_LEAF=8
 
 CONFIG_SECCOMP=y
 
diff --git a/config-sparc64-generic b/config-sparc64-generic
index 2b29f9b..a2b72df 100644
--- a/config-sparc64-generic
+++ b/config-sparc64-generic
@@ -173,6 +173,7 @@ CONFIG_LEDS_SUNFIRE=m
 CONFIG_TADPOLE_TS102_UCTRL=m
 
 CONFIG_RCU_FANOUT=64
+CONFIG_RCU_FANOUT_LEAF=16
 
 CONFIG_LIRC_ENE0100=m
 # CONFIG_BATTERY_DS2782 is not set
@@ -196,3 +197,5 @@ CONFIG_CRYPTO_DEV_NIAGARA2=y
 # CONFIG_MTD_PHYSMAP_OF is not set
 # CONFIG_MMC_SDHCI_OF is not set
 # CONFIG_OF_SELFTEST is not set
+
+CONFIG_BPF_JIT=y
diff --git a/config-x86-32-generic b/config-x86-32-generic
index b008344..5b9805a 100644
--- a/config-x86-32-generic
+++ b/config-x86-32-generic
@@ -211,5 +211,9 @@ CONFIG_I2O_BUS=m
 # CONFIG_INPUT_GPIO_TILT_POLLED is not set
 # CONFIG_GEOS is not set
 # CONFIG_NET5501 is not set
+# CONFIG_MDIO_BUS_MUX_GPIO is not set
 # CONFIG_GPIO_SODAVILLE is not set
 # CONFIG_BACKLIGHT_OT200 is not set
+
+# CONFIG_STA2X11 is not set
+
diff --git a/config-x86-generic b/config-x86-generic
index 181e3e9..c5fb4d8 100644
--- a/config-x86-generic
+++ b/config-x86-generic
@@ -218,6 +218,7 @@ CONFIG_XO15_EBOOK=m
 # CONFIG_SMSC37B787_WDT is not set
 CONFIG_W83697HF_WDT=m
 CONFIG_VIA_WDT=m
+CONFIG_IE6XX_WDT=m
 
 CONFIG_CRASH_DUMP=y
 CONFIG_PROC_VMCORE=y
@@ -351,6 +352,8 @@ CONFIG_TOSHIBA_BT_RFKILL=m
 CONFIG_VGA_SWITCHEROO=y
 CONFIG_LPC_SCH=m
 
+CONFIG_GPIO_ICH=m
+
 CONFIG_PCI_CNB20LE_QUIRK=y
 
 CONFIG_ACPI_EC_DEBUGFS=m
@@ -405,6 +408,8 @@ CONFIG_DRM_GMA500=m
 # CONFIG_DRM_GMA600 is not set
 # CONFIG_DRM_GMA3600 is not set
 
+CONFIG_RCU_FANOUT_LEAF=16
+
 # Maybe enable in debug kernels?
 # CONFIG_DEBUG_NMI_SELFTEST is not set
 
diff --git a/kernel.spec b/kernel.spec
index d37818b..31b1fc8 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -60,13 +60,13 @@ Summary: The Linux kernel
 # base_sublevel is the kernel version we're starting with and patching
 # on top of -- for example, 2.6.22-rc7-git1 starts with a 2.6.21 base,
 # which yields a base_sublevel of 21.
-%define base_sublevel 4
+%define base_sublevel 5
 
 ## If this is a released kernel ##
 %if 0%{?released_kernel}
 
 # Do we have a -stable update to apply?
-%define stable_update 14
+%define stable_update 0
 # Is it a -stable RC?
 %define stable_rc 0
 # Set rpm version accordingly
@@ -643,9 +643,6 @@ Patch800: linux-2.6-crash-driver.patch
 Patch1824: drm-intel-next.patch
 Patch1825: drm-i915-dp-stfu.patch
 
-# hush the i915 fbc noise
-Patch1826: drm-i915-fbc-stfu.patch
-
 Patch1900: linux-2.6-intel-iommu-igfx.patch
 
 # Quiet boot fixes
@@ -657,9 +654,6 @@ Patch2901: drivers-media-update.patch
 
 # fs fixes
 
-#rhbz 753346
-Patch3500: jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch
-
 # NFSv4
 
 # patches headed upstream
@@ -675,9 +669,7 @@ Patch14010: lis3-improve-handling-of-null-rate.patch
 Patch19000: ips-noirq.patch
 
 # Uprobes (rhbz 832083)
-Patch20000: uprobes-3.4-backport.patch
-Patch20001: uprobes-3.4-tip.patch
-Patch20002: uprobes-task_work_add-generic-process-context-callbacks.patch
+Patch20000: uprobes-backport.patch
 
 #rhbz 769766
 Patch21072: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch
@@ -696,9 +688,6 @@ Patch21306: shlib_base_randomize.patch
 Patch30000: weird-root-dentry-name-debug.patch
 Patch30010: debug-808990.patch
 
-#rhbz 749276
-Patch22018: atl1c_net_next_update-3.4.patch
-
 #Fix FIPS for aesni hardare
 Patch22055: crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch
 Patch22056: crypto-aesni-intel-fix-wrong-kfree-pointer.patch
@@ -1199,10 +1188,6 @@ ApplyPatch taint-vbox.patch
 # bugfixes to drivers and filesystems
 #
 
-# ext4
-#rhbz 753346
-ApplyPatch jbd-jbd2-validate-sb-s_first-in-journal_get_superblo.patch
-
 # xfs
 
 # btrfs
@@ -1274,7 +1259,6 @@ ApplyPatch linux-2.6-e1000-ich9-montevina.patch
 # Intel DRM
 ApplyOptionalPatch drm-intel-next.patch
 ApplyPatch drm-i915-dp-stfu.patch
-ApplyPatch drm-i915-fbc-stfu.patch
 
 ApplyPatch linux-2.6-intel-iommu-igfx.patch
 
@@ -1302,9 +1286,7 @@ ApplyPatch ips-noirq.patch
 #ApplyPatch pci-crs-blacklist.patch
 
 # Uprobes (rhbz 832083)
-ApplyPatch uprobes-3.4-backport.patch
-ApplyPatch uprobes-3.4-tip.patch
-ApplyPatch uprobes-task_work_add-generic-process-context-callbacks.patch
+ApplyPatch uprobes-backport.patch
 
 #rhbz 754518
 #ApplyPatch scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch
@@ -1315,9 +1297,6 @@ ApplyPatch unhandled-irqs-switch-to-polling.patch
 ApplyPatch weird-root-dentry-name-debug.patch
 ApplyPatch debug-808990.patch
 
-#rhbz 749276
-ApplyPatch atl1c_net_next_update-3.4.patch
-
 #Fix FIPS for aesni hardare
 ApplyPatch crypto-testmgr-allow-aesni-intel-and-ghash_clmulni-intel.patch
 ApplyPatch crypto-aesni-intel-fix-wrong-kfree-pointer.patch
@@ -2022,6 +2001,9 @@ fi
 # and build.
 
 %changelog
+* Tue Oct 16 2012 Dave Jones <davej at redhat.com> 3.5.0-1
+- Linux 3.5
+
 * Tue Oct 16 2012 Dave Jones <davej at redhat.com> 3.4.14-1
 - Linux 3.4.14
 
diff --git a/linux-2.6-input-kill-stupid-messages.patch b/linux-2.6-input-kill-stupid-messages.patch
index cc1dd74..ff7023f 100644
--- a/linux-2.6-input-kill-stupid-messages.patch
+++ b/linux-2.6-input-kill-stupid-messages.patch
@@ -1,32 +1,20 @@
-From b2c6d55b2351152696aafb8c9bf3ec8968acf77c Mon Sep 17 00:00:00 2001
-From: Kyle McMartin <kyle at phobos.i.jkkm.org>
-Date: Mon, 29 Mar 2010 23:59:58 -0400
-Subject: linux-2.6-input-kill-stupid-messages
-
----
- drivers/input/keyboard/atkbd.c |    5 +++++
- 1 files changed, 5 insertions(+), 0 deletions(-)
-
 diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
-index d358ef8..38db098 100644
+index add5ffd..5eb2f03 100644
 --- a/drivers/input/keyboard/atkbd.c
 +++ b/drivers/input/keyboard/atkbd.c
-@@ -425,11 +426,15 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
+@@ -430,11 +430,15 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
  		goto out;
  	case ATKBD_RET_ACK:
  	case ATKBD_RET_NAK:
-+#if 0
++# if 0
 +		/* Quite a few key switchers and other tools trigger this
 +		 * and it confuses people who can do nothing about it */
  		if (printk_ratelimit())
  			dev_warn(&serio->dev,
  				 "Spurious %s on %s. "
- 				 "Some program might be trying access hardware directly.\n",
+ 				 "Some program might be trying to access hardware directly.\n",
  				 data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys);
 +#endif
  		goto out;
  	case ATKBD_RET_ERR:
  		atkbd->err_count++;
--- 
-1.7.0.1
-
diff --git a/linux-2.6-makefile-after_link.patch b/linux-2.6-makefile-after_link.patch
index c2541b1..b520b19 100644
--- a/linux-2.6-makefile-after_link.patch
+++ b/linux-2.6-makefile-after_link.patch
@@ -1,4 +1,4 @@
-From f072f7db2194c8255c003d985b61ad2f97ebbee0 Mon Sep 17 00:00:00 2001
+From b707aea6a4947c3806ced2c23e889943a0f36876 Mon Sep 17 00:00:00 2001
 From: Roland McGrath <roland at redhat.com>
 Date: Mon, 6 Oct 2008 23:03:03 -0700
 Subject: [PATCH] kbuild: AFTER_LINK
@@ -7,24 +7,9 @@ If the make variable AFTER_LINK is set, it is a command line to run
 after each final link.  This includes vmlinux itself and vDSO images.
 
 Signed-off-by: Roland McGrath <roland at redhat.com>
----
-diff --git a/Makefile b/Makefile
-index f908acc..960ff6f 100644
---- a/Makefile
-+++ b/Makefile
-@@ -746,6 +746,10 @@ quiet_cmd_vmlinux__ ?= LD      $@
-       --start-group $(vmlinux-main) --end-group                  \
-       $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) vmlinux.o FORCE ,$^)
- 
-+ifdef AFTER_LINK
-+cmd_vmlinux__ += ; $(AFTER_LINK)
-+endif
-+
- # Generate new vmlinux version
- quiet_cmd_vmlinux_version = GEN     .version
-       cmd_vmlinux_version = set -e;                     \
+
 diff --git a/arch/powerpc/kernel/vdso32/Makefile b/arch/powerpc/kernel/vdso32/Makefile
-index 51ead52..ad21273 100644
+index 9a7946c..28d6765 100644
 --- a/arch/powerpc/kernel/vdso32/Makefile
 +++ b/arch/powerpc/kernel/vdso32/Makefile
 @@ -41,7 +41,8 @@ $(obj-vdso32): %.o: %.S
@@ -38,7 +23,7 @@ index 51ead52..ad21273 100644
        cmd_vdso32as = $(CROSS32CC) $(a_flags) -c -o $@ $<
  
 diff --git a/arch/powerpc/kernel/vdso64/Makefile b/arch/powerpc/kernel/vdso64/Makefile
-index 79da65d..f11c21b 100644
+index 8c500d8..d27737b 100644
 --- a/arch/powerpc/kernel/vdso64/Makefile
 +++ b/arch/powerpc/kernel/vdso64/Makefile
 @@ -36,7 +36,8 @@ $(obj-vdso64): %.o: %.S
@@ -51,28 +36,11 @@ index 79da65d..f11c21b 100644
  quiet_cmd_vdso64as = VDSO64A $@
        cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $<
  
-diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile
-index 4a2afa1..12ad9f7 100644
---- a/arch/x86/vdso/Makefile
-+++ b/arch/x86/vdso/Makefile
-@@ -120,8 +120,9 @@ $(obj)/vdso32-syms.lds: $(vdso32.so-y:%=$(obj)/vdso32-%-syms.lds) FORCE
- quiet_cmd_vdso = VDSO    $@
-       cmd_vdso = $(CC) -nostdlib -o $@ \
- 		       $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
--		       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
--		 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
-+		       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) \
-+		$(if $(AFTER_LINK),; $(AFTER_LINK)) && \
-+		sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
- 
- VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
- GCOV_PROFILE := n
-
 diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile
-index d13e875..28a3e1ad 100644
+index 8ad2b34..e153572 100644
 --- a/arch/s390/kernel/vdso32/Makefile
 +++ b/arch/s390/kernel/vdso32/Makefile
-@@ -40,7 +40,8 @@ $(obj-vdso32): %.o: %.S
+@@ -43,7 +43,8 @@ $(obj-vdso32): %.o: %.S
  
  # actual build commands
  quiet_cmd_vdso32ld = VDSO32L $@
@@ -83,10 +51,10 @@ index d13e875..28a3e1ad 100644
        cmd_vdso32as = $(CC) $(a_flags) -c -o $@ $<
  
 diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile
-index 449352d..e90e656 100644
+index 2a8ddfd..452ca53 100644
 --- a/arch/s390/kernel/vdso64/Makefile
 +++ b/arch/s390/kernel/vdso64/Makefile
-@@ -40,7 +40,8 @@ $(obj-vdso64): %.o: %.S
+@@ -43,7 +43,8 @@ $(obj-vdso64): %.o: %.S
  
  # actual build commands
  quiet_cmd_vdso64ld = VDSO64L $@
@@ -96,3 +64,37 @@ index 449352d..e90e656 100644
  quiet_cmd_vdso64as = VDSO64A $@
        cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $<
  
+diff --git a/arch/x86/vdso/Makefile b/arch/x86/vdso/Makefile
+index fd14be1..1f3eb19 100644
+--- a/arch/x86/vdso/Makefile
++++ b/arch/x86/vdso/Makefile
+@@ -178,8 +178,9 @@ $(obj)/vdso32-syms.lds: $(vdso32.so-y:%=$(obj)/vdso32-%-syms.lds) FORCE
+ quiet_cmd_vdso = VDSO    $@
+       cmd_vdso = $(CC) -nostdlib -o $@ \
+ 		       $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
+-		       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
+-		 sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
++		       -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) \
++		$(if $(AFTER_LINK),; $(AFTER_LINK)) && \
++		sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
+ 
+ VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
+ GCOV_PROFILE := n
+diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
+index cd9c6c6..3edf048 100644
+--- a/scripts/link-vmlinux.sh
++++ b/scripts/link-vmlinux.sh
+@@ -65,6 +65,10 @@ vmlinux_link()
+ 			-lutil ${1}
+ 		rm -f linux
+ 	fi
++	if [ -n "${AFTER_LINK}" ]; then
++		/usr/lib/rpm/debugedit -b ${RPM_BUILD_DIR} -d /usr/src/debug -i ${2} \
++			> ${2}.id
++	fi
+ }
+ 
+ 
+-- 
+1.7.7.6
+
diff --git a/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch b/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch
index 492376d..48db133 100644
--- a/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch
+++ b/scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch
@@ -12,7 +12,7 @@
  	SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp,
  				      "sd_revalidate_disk\n"));
  
-+	if (!sdkp)
++	if (WARN_ONCE((!sdkp), "Invalid scsi_disk from %p\n", disk))
 +		goto out;
 +
 +	sdp = sdkp->device;
diff --git a/sources b/sources
index 40daba2..d239339 100644
--- a/sources
+++ b/sources
@@ -1,2 +1 @@
-967f72983655e2479f951195953e8480  linux-3.4.tar.xz
-c3225a0538db8486d991c1af70f5f0a4  patch-3.4.14.xz
+24153eaaa81dedc9481ada8cd9c3b83d  linux-3.5.tar.xz
diff --git a/uprobes-backport.patch b/uprobes-backport.patch
new file mode 100644
index 0000000..5f2bacf
--- /dev/null
+++ b/uprobes-backport.patch
@@ -0,0 +1,1742 @@
+Hello,
+
+Test build: http://koji.fedoraproject.org/koji/taskinfo?taskID=4490824
+This also fixes: https://bugzilla.redhat.com/show_bug.cgi?id=849364
+
+The split-out series is available in the git repository at:
+  http://fedorapeople.org/cgit/aarapov/public_git/kernel-uprobes.git/log/?h=f17_uprobes_out
+  (Just @jistone's patch is not upstream that exports functions.)
+
+Ananth N Mavinakayanahalli (1):
+      uprobes: Pass probed vaddr to arch_uprobe_analyze_insn()
+
+Josh Stone (1):
+      uprobes: add exports necessary for uprobes use by modules
+
+Oleg Nesterov (52):
+      uprobes: Optimize is_swbp_at_addr() for current->mm
+      uprobes: Change read_opcode() to use FOLL_FORCE
+      uprobes: Introduce find_active_uprobe() helper
+      uprobes: Teach find_active_uprobe() to provide the "is_swbp" info
+      uprobes: Change register_for_each_vma() to take mm->mmap_sem for writing
+      uprobes: Teach handle_swbp() to rely on "is_swbp" rather than uprobes_srcu
+      uprobes: Kill uprobes_srcu/uprobe_srcu_id
+      uprobes: Valid_vma() should reject VM_HUGETLB
+      uprobes: __copy_insn() should ensure a_ops->readpage != NULL
+      uprobes: Write_opcode()->__replace_page() can race with try_to_unmap()
+      uprobes: Install_breakpoint() should fail if is_swbp_insn() == T
+      uprobes: Rework register_for_each_vma() to make it O(n)
+      uprobes: Change build_map_info() to try kmalloc(GFP_NOWAIT) first
+      uprobes: Copy_insn() shouldn't depend on mm/vma/vaddr
+      uprobes: Copy_insn() should not return -ENOMEM if __copy_insn() fails
+      uprobes: No need to re-check vma_address() in write_opcode()
+      uprobes: Move BUG_ON(UPROBE_SWBP_INSN_SIZE) from write_opcode() to install_breakpoint()
+      uprobes: Simplify the usage of uprobe->pending_list
+      uprobes: Don't use loff_t for the valid virtual address
+      uprobes: __copy_insn() needs "loff_t offset"
+      uprobes: Remove the unnecessary initialization in add_utask()
+      uprobes: Don't recheck vma/f_mapping in write_opcode()
+      uprobes: __replace_page() should not use page_address_in_vma()
+      uprobes: Kill write_opcode()->lock_page(new_page)
+      uprobes: Clean up and document write_opcode()->lock_page(old_page)
+      uprobes: Uprobe_mmap/munmap needs list_for_each_entry_safe()
+      uprobes: Suppress uprobe_munmap() from mmput()
+      uprobes: Fix overflow in vma_address()/find_active_uprobe()
+      uprobes: Remove copy_vma()->uprobe_mmap()
+      uprobes: Remove insert_vm_struct()->uprobe_mmap()
+      uprobes: Teach build_probe_list() to consider the range
+      uprobes: Introduce vaddr_to_offset(vma, vaddr)
+      uprobes: Fix register_for_each_vma()->vma_address() check
+      uprobes: Rename vma_address() and make it return "unsigned long"
+      uprobes: __replace_page() needs munlock_vma_page()
+      uprobes: Fix mmap_region()'s mm->mm_rb corruption if uprobe_mmap() fails
+      uprobes: Kill uprobes_state->count
+      uprobes: Kill dup_mmap()->uprobe_mmap(), simplify uprobe_mmap/munmap
+      uprobes: Change uprobe_mmap() to ignore the errors but check fatal_signal_pending()
+      uprobes: Do not use -EEXIST in install_breakpoint() paths
+      uprobes: Introduce MMF_HAS_UPROBES
+      uprobes: Fold uprobe_reset_state() into uprobe_dup_mmap()
+      uprobes: Remove "verify" argument from set_orig_insn()
+      uprobes: uprobes_treelock should not disable irqs
+      uprobes: Introduce MMF_RECALC_UPROBES
+      uprobes: Teach find_active_uprobe() to clear MMF_HAS_UPROBES
+      ptrace/x86: Introduce set_task_blockstep() helper
+      ptrace/x86: Partly fix set_task_blockstep()->update_debugctlmsr() logic
+      uprobes/x86: Do not (ab)use TIF_SINGLESTEP/user_*_single_step() for single-stepping
+      uprobes/x86: Xol should send SIGTRAP if X86_EFLAGS_TF was set
+      uprobes/x86: Fix arch_uprobe_disable_step() && UTASK_SSTEP_TRAPPED interaction
+      uprobes: Make arch_uprobe_task->saved_trap_nr "unsigned int"
+
+Peter Zijlstra (1):
+      uprobes: Document uprobe_register() vs uprobe_mmap() race
+
+Sebastian Andrzej Siewior (4):
+      uprobes: Remove check for uprobe variable in handle_swbp()
+      uprobes: Don't put NULL pointer in uprobe_register()
+      uprobes: Introduce arch_uprobe_enable/disable_step()
+      uprobes/x86: Implement x86 specific arch_uprobe_*_step
+
+Srikar Dronamraju (1):
+      uprobes: Remove redundant lock_page/unlock_page
+
+Signed-off-by: Anton Arapov <anton at redhat.com>
+---
+ arch/x86/include/asm/processor.h |   2 +
+ arch/x86/include/asm/uprobes.h   |   5 +-
+ arch/x86/kernel/step.c           |  53 ++-
+ arch/x86/kernel/uprobes.c        |  55 ++-
+ include/linux/sched.h            |   4 +-
+ include/linux/uprobes.h          |  15 +-
+ kernel/events/uprobes.c          | 819 +++++++++++++++++++--------------------
+ kernel/fork.c                    |   6 +-
+ kernel/ptrace.c                  |   6 +
+ mm/mmap.c                        |  11 +-
+ 10 files changed, 505 insertions(+), 471 deletions(-)
+
+diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
+index 39bc577..2f9f8ca 100644
+--- a/arch/x86/include/asm/processor.h
++++ b/arch/x86/include/asm/processor.h
+@@ -746,6 +746,8 @@ static inline void update_debugctlmsr(unsigned long debugctlmsr)
+ 	wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctlmsr);
+ }
+ 
++extern void set_task_blockstep(struct task_struct *task, bool on);
++
+ /*
+  * from system description table in BIOS. Mostly for MCA use, but
+  * others may find it useful:
+diff --git a/arch/x86/include/asm/uprobes.h b/arch/x86/include/asm/uprobes.h
+index 1e9bed1..8ff8be7 100644
+--- a/arch/x86/include/asm/uprobes.h
++++ b/arch/x86/include/asm/uprobes.h
+@@ -42,13 +42,14 @@ struct arch_uprobe {
+ };
+ 
+ struct arch_uprobe_task {
+-	unsigned long			saved_trap_nr;
+ #ifdef CONFIG_X86_64
+ 	unsigned long			saved_scratch_register;
+ #endif
++	unsigned int			saved_trap_nr;
++	unsigned int			saved_tf;
+ };
+ 
+-extern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm);
++extern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
+ extern int  arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+ extern int  arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
+ extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
+diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c
+index c346d11..cd3b243 100644
+--- a/arch/x86/kernel/step.c
++++ b/arch/x86/kernel/step.c
+@@ -157,6 +157,33 @@ static int enable_single_step(struct task_struct *child)
+ 	return 1;
+ }
+ 
++void set_task_blockstep(struct task_struct *task, bool on)
++{
++	unsigned long debugctl;
++
++	/*
++	 * Ensure irq/preemption can't change debugctl in between.
++	 * Note also that both TIF_BLOCKSTEP and debugctl should
++	 * be changed atomically wrt preemption.
++	 * FIXME: this means that set/clear TIF_BLOCKSTEP is simply
++	 * wrong if task != current, SIGKILL can wakeup the stopped
++	 * tracee and set/clear can play with the running task, this
++	 * can confuse the next __switch_to_xtra().
++	 */
++	local_irq_disable();
++	debugctl = get_debugctlmsr();
++	if (on) {
++		debugctl |= DEBUGCTLMSR_BTF;
++		set_tsk_thread_flag(task, TIF_BLOCKSTEP);
++	} else {
++		debugctl &= ~DEBUGCTLMSR_BTF;
++		clear_tsk_thread_flag(task, TIF_BLOCKSTEP);
++	}
++	if (task == current)
++		update_debugctlmsr(debugctl);
++	local_irq_enable();
++}
++
+ /*
+  * Enable single or block step.
+  */
+@@ -169,19 +196,10 @@ static void enable_step(struct task_struct *child, bool block)
+ 	 * So no one should try to use debugger block stepping in a program
+ 	 * that uses user-mode single stepping itself.
+ 	 */
+-	if (enable_single_step(child) && block) {
+-		unsigned long debugctl = get_debugctlmsr();
+-
+-		debugctl |= DEBUGCTLMSR_BTF;
+-		update_debugctlmsr(debugctl);
+-		set_tsk_thread_flag(child, TIF_BLOCKSTEP);
+-	} else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) {
+-		unsigned long debugctl = get_debugctlmsr();
+-
+-		debugctl &= ~DEBUGCTLMSR_BTF;
+-		update_debugctlmsr(debugctl);
+-		clear_tsk_thread_flag(child, TIF_BLOCKSTEP);
+-	}
++	if (enable_single_step(child) && block)
++		set_task_blockstep(child, true);
++	else if (test_tsk_thread_flag(child, TIF_BLOCKSTEP))
++		set_task_blockstep(child, false);
+ }
+ 
+ void user_enable_single_step(struct task_struct *child)
+@@ -199,13 +217,8 @@ void user_disable_single_step(struct task_struct *child)
+ 	/*
+ 	 * Make sure block stepping (BTF) is disabled.
+ 	 */
+-	if (test_tsk_thread_flag(child, TIF_BLOCKSTEP)) {
+-		unsigned long debugctl = get_debugctlmsr();
+-
+-		debugctl &= ~DEBUGCTLMSR_BTF;
+-		update_debugctlmsr(debugctl);
+-		clear_tsk_thread_flag(child, TIF_BLOCKSTEP);
+-	}
++	if (test_tsk_thread_flag(child, TIF_BLOCKSTEP))
++		set_task_blockstep(child, false);
+ 
+ 	/* Always clear TIF_SINGLESTEP... */
+ 	clear_tsk_thread_flag(child, TIF_SINGLESTEP);
+diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
+index dc4e910..9538f00 100644
+--- a/arch/x86/kernel/uprobes.c
++++ b/arch/x86/kernel/uprobes.c
+@@ -41,6 +41,9 @@
+ /* Adjust the return address of a call insn */
+ #define UPROBE_FIX_CALL	0x2
+ 
++/* Instruction will modify TF, don't change it */
++#define UPROBE_FIX_SETF	0x4
++
+ #define UPROBE_FIX_RIP_AX	0x8000
+ #define UPROBE_FIX_RIP_CX	0x4000
+ 
+@@ -239,6 +242,10 @@ static void prepare_fixups(struct arch_uprobe *auprobe, struct insn *insn)
+ 	insn_get_opcode(insn);	/* should be a nop */
+ 
+ 	switch (OPCODE1(insn)) {
++	case 0x9d:
++		/* popf */
++		auprobe->fixups |= UPROBE_FIX_SETF;
++		break;
+ 	case 0xc3:		/* ret/lret */
+ 	case 0xcb:
+ 	case 0xc2:
+@@ -409,9 +416,10 @@ static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm,
+  * arch_uprobe_analyze_insn - instruction analysis including validity and fixups.
+  * @mm: the probed address space.
+  * @arch_uprobe: the probepoint information.
++ * @addr: virtual address at which to install the probepoint
+  * Return 0 on success or a -ve number on error.
+  */
+-int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm)
++int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr)
+ {
+ 	int ret;
+ 	struct insn insn;
+@@ -645,7 +653,7 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
+  * Skip these instructions as per the currently known x86 ISA.
+  * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 }
+  */
+-bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
++static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
+ {
+ 	int i;
+ 
+@@ -672,3 +680,46 @@ bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
+ 	}
+ 	return false;
+ }
++
++bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
++{
++	bool ret = __skip_sstep(auprobe, regs);
++	if (ret && (regs->flags & X86_EFLAGS_TF))
++		send_sig(SIGTRAP, current, 0);
++	return ret;
++}
++
++void arch_uprobe_enable_step(struct arch_uprobe *auprobe)
++{
++	struct task_struct *task = current;
++	struct arch_uprobe_task	*autask	= &task->utask->autask;
++	struct pt_regs *regs = task_pt_regs(task);
++
++	autask->saved_tf = !!(regs->flags & X86_EFLAGS_TF);
++
++	regs->flags |= X86_EFLAGS_TF;
++	if (test_tsk_thread_flag(task, TIF_BLOCKSTEP))
++		set_task_blockstep(task, false);
++}
++
++void arch_uprobe_disable_step(struct arch_uprobe *auprobe)
++{
++	struct task_struct *task = current;
++	struct arch_uprobe_task	*autask	= &task->utask->autask;
++	bool trapped = (task->utask->state == UTASK_SSTEP_TRAPPED);
++	struct pt_regs *regs = task_pt_regs(task);
++	/*
++	 * The state of TIF_BLOCKSTEP was not saved so we can get an extra
++	 * SIGTRAP if we do not clear TF. We need to examine the opcode to
++	 * make it right.
++	 */
++	if (unlikely(trapped)) {
++		if (!autask->saved_tf)
++			regs->flags &= ~X86_EFLAGS_TF;
++	} else {
++		if (autask->saved_tf)
++			send_sig(SIGTRAP, task, 0);
++		else if (!(auprobe->fixups & UPROBE_FIX_SETF))
++			regs->flags &= ~X86_EFLAGS_TF;
++	}
++}
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index 4a1f493..864054f 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -441,6 +441,9 @@ extern int get_dumpable(struct mm_struct *mm);
+ #define MMF_VM_HUGEPAGE		17	/* set when VM_HUGEPAGE is set on vma */
+ #define MMF_EXE_FILE_CHANGED	18	/* see prctl_set_mm_exe_file() */
+ 
++#define MMF_HAS_UPROBES		19	/* has uprobes */
++#define MMF_RECALC_UPROBES	20	/* MMF_HAS_UPROBES can be wrong */
++
+ #define MMF_INIT_MASK		(MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK)
+ 
+ struct sighand_struct {
+@@ -1581,7 +1584,6 @@ struct task_struct {
+ #endif
+ #ifdef CONFIG_UPROBES
+ 	struct uprobe_task *utask;
+-	int uprobe_srcu_id;
+ #endif
+ };
+ 
+diff --git a/include/linux/uprobes.h b/include/linux/uprobes.h
+index efe4b33..e6f0331 100644
+--- a/include/linux/uprobes.h
++++ b/include/linux/uprobes.h
+@@ -99,25 +99,27 @@ struct xol_area {
+ 
+ struct uprobes_state {
+ 	struct xol_area		*xol_area;
+-	atomic_t		count;
+ };
++
+ extern int __weak set_swbp(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
+-extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm,  unsigned long vaddr, bool verify);
++extern int __weak set_orig_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long vaddr);
+ extern bool __weak is_swbp_insn(uprobe_opcode_t *insn);
+ extern int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
+ extern void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);
+ extern int uprobe_mmap(struct vm_area_struct *vma);
+ extern void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end);
++extern void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm);
+ extern void uprobe_free_utask(struct task_struct *t);
+ extern void uprobe_copy_process(struct task_struct *t);
+ extern unsigned long __weak uprobe_get_swbp_addr(struct pt_regs *regs);
++extern void __weak arch_uprobe_enable_step(struct arch_uprobe *arch);
++extern void __weak arch_uprobe_disable_step(struct arch_uprobe *arch);
+ extern int uprobe_post_sstep_notifier(struct pt_regs *regs);
+ extern int uprobe_pre_sstep_notifier(struct pt_regs *regs);
+ extern void uprobe_notify_resume(struct pt_regs *regs);
+ extern bool uprobe_deny_signal(void);
+ extern bool __weak arch_uprobe_skip_sstep(struct arch_uprobe *aup, struct pt_regs *regs);
+ extern void uprobe_clear_state(struct mm_struct *mm);
+-extern void uprobe_reset_state(struct mm_struct *mm);
+ #else /* !CONFIG_UPROBES */
+ struct uprobes_state {
+ };
+@@ -138,6 +140,10 @@ static inline void
+ uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end)
+ {
+ }
++static inline void
++uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm)
++{
++}
+ static inline void uprobe_notify_resume(struct pt_regs *regs)
+ {
+ }
+@@ -158,8 +164,5 @@ static inline void uprobe_copy_process(struct task_struct *t)
+ static inline void uprobe_clear_state(struct mm_struct *mm)
+ {
+ }
+-static inline void uprobe_reset_state(struct mm_struct *mm)
+-{
+-}
+ #endif /* !CONFIG_UPROBES */
+ #endif	/* _LINUX_UPROBES_H */
+diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
+index 985be4d..f8a97e7 100644
+--- a/kernel/events/uprobes.c
++++ b/kernel/events/uprobes.c
+@@ -27,24 +27,42 @@
+ #include <linux/pagemap.h>	/* read_mapping_page */
+ #include <linux/slab.h>
+ #include <linux/sched.h>
++#include <linux/export.h>
+ #include <linux/rmap.h>		/* anon_vma_prepare */
+ #include <linux/mmu_notifier.h>	/* set_pte_at_notify */
+ #include <linux/swap.h>		/* try_to_free_swap */
+ #include <linux/ptrace.h>	/* user_enable_single_step */
+ #include <linux/kdebug.h>	/* notifier mechanism */
++#include "../../mm/internal.h"	/* munlock_vma_page */
+ 
+ #include <linux/uprobes.h>
+ 
+ #define UINSNS_PER_PAGE			(PAGE_SIZE/UPROBE_XOL_SLOT_BYTES)
+ #define MAX_UPROBE_XOL_SLOTS		UINSNS_PER_PAGE
+ 
+-static struct srcu_struct uprobes_srcu;
+ static struct rb_root uprobes_tree = RB_ROOT;
+ 
+ static DEFINE_SPINLOCK(uprobes_treelock);	/* serialize rbtree access */
+ 
+ #define UPROBES_HASH_SZ	13
+ 
++/*
++ * We need separate register/unregister and mmap/munmap lock hashes because
++ * of mmap_sem nesting.
++ *
++ * uprobe_register() needs to install probes on (potentially) all processes
++ * and thus needs to acquire multiple mmap_sems (consequtively, not
++ * concurrently), whereas uprobe_mmap() is called while holding mmap_sem
++ * for the particular process doing the mmap.
++ *
++ * uprobe_register()->register_for_each_vma() needs to drop/acquire mmap_sem
++ * because of lock order against i_mmap_mutex. This means there's a hole in
++ * the register vma iteration where a mmap() can happen.
++ *
++ * Thus uprobe_register() can race with uprobe_mmap() and we can try and
++ * install a probe where one is already installed.
++ */
++
+ /* serialize (un)register */
+ static struct mutex uprobes_mutex[UPROBES_HASH_SZ];
+ 
+@@ -61,17 +79,6 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ];
+  */
+ static atomic_t uprobe_events = ATOMIC_INIT(0);
+ 
+-/*
+- * Maintain a temporary per vma info that can be used to search if a vma
+- * has already been handled. This structure is introduced since extending
+- * vm_area_struct wasnt recommended.
+- */
+-struct vma_info {
+-	struct list_head	probe_list;
+-	struct mm_struct	*mm;
+-	loff_t			vaddr;
+-};
+-
+ struct uprobe {
+ 	struct rb_node		rb_node;	/* node in the rb tree */
+ 	atomic_t		ref;
+@@ -100,20 +107,21 @@ static bool valid_vma(struct vm_area_struct *vma, bool is_register)
+ 	if (!is_register)
+ 		return true;
+ 
+-	if ((vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) == (VM_READ|VM_EXEC))
++	if ((vma->vm_flags & (VM_HUGETLB|VM_READ|VM_WRITE|VM_EXEC|VM_SHARED))
++				== (VM_READ|VM_EXEC))
+ 		return true;
+ 
+ 	return false;
+ }
+ 
+-static loff_t vma_address(struct vm_area_struct *vma, loff_t offset)
++static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t offset)
+ {
+-	loff_t vaddr;
+-
+-	vaddr = vma->vm_start + offset;
+-	vaddr -= vma->vm_pgoff << PAGE_SHIFT;
++	return vma->vm_start + offset - ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
++}
+ 
+-	return vaddr;
++static loff_t vaddr_to_offset(struct vm_area_struct *vma, unsigned long vaddr)
++{
++	return ((loff_t)vma->vm_pgoff << PAGE_SHIFT) + (vaddr - vma->vm_start);
+ }
+ 
+ /**
+@@ -121,41 +129,27 @@ static loff_t vma_address(struct vm_area_struct *vma, loff_t offset)
+  * based on replace_page in mm/ksm.c
+  *
+  * @vma:      vma that holds the pte pointing to page
++ * @addr:     address the old @page is mapped at
+  * @page:     the cowed page we are replacing by kpage
+  * @kpage:    the modified page we replace page by
+  *
+  * Returns 0 on success, -EFAULT on failure.
+  */
+-static int __replace_page(struct vm_area_struct *vma, struct page *page, struct page *kpage)
++static int __replace_page(struct vm_area_struct *vma, unsigned long addr,
++				struct page *page, struct page *kpage)
+ {
+ 	struct mm_struct *mm = vma->vm_mm;
+-	pgd_t *pgd;
+-	pud_t *pud;
+-	pmd_t *pmd;
+-	pte_t *ptep;
+ 	spinlock_t *ptl;
+-	unsigned long addr;
+-	int err = -EFAULT;
+-
+-	addr = page_address_in_vma(page, vma);
+-	if (addr == -EFAULT)
+-		goto out;
+-
+-	pgd = pgd_offset(mm, addr);
+-	if (!pgd_present(*pgd))
+-		goto out;
+-
+-	pud = pud_offset(pgd, addr);
+-	if (!pud_present(*pud))
+-		goto out;
++	pte_t *ptep;
++	int err;
+ 
+-	pmd = pmd_offset(pud, addr);
+-	if (!pmd_present(*pmd))
+-		goto out;
++	/* For try_to_free_swap() and munlock_vma_page() below */
++	lock_page(page);
+ 
+-	ptep = pte_offset_map_lock(mm, pmd, addr, &ptl);
++	err = -EAGAIN;
++	ptep = page_check_address(page, mm, addr, &ptl, 0);
+ 	if (!ptep)
+-		goto out;
++		goto unlock;
+ 
+ 	get_page(kpage);
+ 	page_add_new_anon_rmap(kpage, vma, addr);
+@@ -172,11 +166,15 @@ static int __replace_page(struct vm_area_struct *vma, struct page *page, struct
+ 	page_remove_rmap(page);
+ 	if (!page_mapped(page))
+ 		try_to_free_swap(page);
+-	put_page(page);
+ 	pte_unmap_unlock(ptep, ptl);
+-	err = 0;
+ 
+-out:
++	if (vma->vm_flags & VM_LOCKED)
++		munlock_vma_page(page);
++	put_page(page);
++
++	err = 0;
++ unlock:
++	unlock_page(page);
+ 	return err;
+ }
+ 
+@@ -218,79 +216,46 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
+ 			unsigned long vaddr, uprobe_opcode_t opcode)
+ {
+ 	struct page *old_page, *new_page;
+-	struct address_space *mapping;
+ 	void *vaddr_old, *vaddr_new;
+ 	struct vm_area_struct *vma;
+-	struct uprobe *uprobe;
+-	loff_t addr;
+ 	int ret;
+ 
++retry:
+ 	/* Read the page with vaddr into memory */
+ 	ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma);
+ 	if (ret <= 0)
+ 		return ret;
+ 
+-	ret = -EINVAL;
+-
+-	/*
+-	 * We are interested in text pages only. Our pages of interest
+-	 * should be mapped for read and execute only. We desist from
+-	 * adding probes in write mapped pages since the breakpoints
+-	 * might end up in the file copy.
+-	 */
+-	if (!valid_vma(vma, is_swbp_insn(&opcode)))
+-		goto put_out;
+-
+-	uprobe = container_of(auprobe, struct uprobe, arch);
+-	mapping = uprobe->inode->i_mapping;
+-	if (mapping != vma->vm_file->f_mapping)
+-		goto put_out;
+-
+-	addr = vma_address(vma, uprobe->offset);
+-	if (vaddr != (unsigned long)addr)
+-		goto put_out;
+-
+ 	ret = -ENOMEM;
+ 	new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
+ 	if (!new_page)
+-		goto put_out;
++		goto put_old;
+ 
+ 	__SetPageUptodate(new_page);
+ 
+-	/*
+-	 * lock page will serialize against do_wp_page()'s
+-	 * PageAnon() handling
+-	 */
+-	lock_page(old_page);
+ 	/* copy the page now that we've got it stable */
+ 	vaddr_old = kmap_atomic(old_page);
+ 	vaddr_new = kmap_atomic(new_page);
+ 
+ 	memcpy(vaddr_new, vaddr_old, PAGE_SIZE);
+-
+-	/* poke the new insn in, ASSUMES we don't cross page boundary */
+-	vaddr &= ~PAGE_MASK;
+-	BUG_ON(vaddr + UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
+-	memcpy(vaddr_new + vaddr, &opcode, UPROBE_SWBP_INSN_SIZE);
++	memcpy(vaddr_new + (vaddr & ~PAGE_MASK), &opcode, UPROBE_SWBP_INSN_SIZE);
+ 
+ 	kunmap_atomic(vaddr_new);
+ 	kunmap_atomic(vaddr_old);
+ 
+ 	ret = anon_vma_prepare(vma);
+ 	if (ret)
+-		goto unlock_out;
++		goto put_new;
+ 
+-	lock_page(new_page);
+-	ret = __replace_page(vma, old_page, new_page);
+-	unlock_page(new_page);
++	ret = __replace_page(vma, vaddr, old_page, new_page);
+ 
+-unlock_out:
+-	unlock_page(old_page);
++put_new:
+ 	page_cache_release(new_page);
+-
+-put_out:
++put_old:
+ 	put_page(old_page);
+ 
++	if (unlikely(ret == -EAGAIN))
++		goto retry;
+ 	return ret;
+ }
+ 
+@@ -312,16 +277,14 @@ static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_
+ 	void *vaddr_new;
+ 	int ret;
+ 
+-	ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &page, NULL);
++	ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
+ 	if (ret <= 0)
+ 		return ret;
+ 
+-	lock_page(page);
+ 	vaddr_new = kmap_atomic(page);
+ 	vaddr &= ~PAGE_MASK;
+ 	memcpy(opcode, vaddr_new + vaddr, UPROBE_SWBP_INSN_SIZE);
+ 	kunmap_atomic(vaddr_new);
+-	unlock_page(page);
+ 
+ 	put_page(page);
+ 
+@@ -333,10 +296,20 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
+ 	uprobe_opcode_t opcode;
+ 	int result;
+ 
++	if (current->mm == mm) {
++		pagefault_disable();
++		result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
++								sizeof(opcode));
++		pagefault_enable();
++
++		if (likely(result == 0))
++			goto out;
++	}
++
+ 	result = read_opcode(mm, vaddr, &opcode);
+ 	if (result)
+ 		return result;
+-
++out:
+ 	if (is_swbp_insn(&opcode))
+ 		return 1;
+ 
+@@ -355,10 +328,12 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
+ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
+ {
+ 	int result;
+-
++	/*
++	 * See the comment near uprobes_hash().
++	 */
+ 	result = is_swbp_at_addr(mm, vaddr);
+ 	if (result == 1)
+-		return -EEXIST;
++		return 0;
+ 
+ 	if (result)
+ 		return result;
+@@ -371,24 +346,22 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned
+  * @mm: the probed process address space.
+  * @auprobe: arch specific probepoint information.
+  * @vaddr: the virtual address to insert the opcode.
+- * @verify: if true, verify existance of breakpoint instruction.
+  *
+  * For mm @mm, restore the original opcode (opcode) at @vaddr.
+  * Return 0 (success) or a negative errno.
+  */
+ int __weak
+-set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr, bool verify)
++set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
+ {
+-	if (verify) {
+-		int result;
++	int result;
+ 
+-		result = is_swbp_at_addr(mm, vaddr);
+-		if (!result)
+-			return -EINVAL;
++	result = is_swbp_at_addr(mm, vaddr);
++	if (!result)
++		return -EINVAL;
++
++	if (result != 1)
++		return result;
+ 
+-		if (result != 1)
+-			return result;
+-	}
+ 	return write_opcode(auprobe, mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
+ }
+ 
+@@ -439,11 +412,10 @@ static struct uprobe *__find_uprobe(struct inode *inode, loff_t offset)
+ static struct uprobe *find_uprobe(struct inode *inode, loff_t offset)
+ {
+ 	struct uprobe *uprobe;
+-	unsigned long flags;
+ 
+-	spin_lock_irqsave(&uprobes_treelock, flags);
++	spin_lock(&uprobes_treelock);
+ 	uprobe = __find_uprobe(inode, offset);
+-	spin_unlock_irqrestore(&uprobes_treelock, flags);
++	spin_unlock(&uprobes_treelock);
+ 
+ 	return uprobe;
+ }
+@@ -490,12 +462,11 @@ static struct uprobe *__insert_uprobe(struct uprobe *uprobe)
+  */
+ static struct uprobe *insert_uprobe(struct uprobe *uprobe)
+ {
+-	unsigned long flags;
+ 	struct uprobe *u;
+ 
+-	spin_lock_irqsave(&uprobes_treelock, flags);
++	spin_lock(&uprobes_treelock);
+ 	u = __insert_uprobe(uprobe);
+-	spin_unlock_irqrestore(&uprobes_treelock, flags);
++	spin_unlock(&uprobes_treelock);
+ 
+ 	/* For now assume that the instruction need not be single-stepped */
+ 	uprobe->flags |= UPROBE_SKIP_SSTEP;
+@@ -520,7 +491,6 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset)
+ 	uprobe->inode = igrab(inode);
+ 	uprobe->offset = offset;
+ 	init_rwsem(&uprobe->consumer_rwsem);
+-	INIT_LIST_HEAD(&uprobe->pending_list);
+ 
+ 	/* add to uprobes_tree, sorted on inode:offset */
+ 	cur_uprobe = insert_uprobe(uprobe);
+@@ -588,20 +558,22 @@ static bool consumer_del(struct uprobe *uprobe, struct uprobe_consumer *uc)
+ }
+ 
+ static int
+-__copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *insn,
+-			unsigned long nbytes, unsigned long offset)
++__copy_insn(struct address_space *mapping, struct file *filp, char *insn,
++			unsigned long nbytes, loff_t offset)
+ {
+-	struct file *filp = vma->vm_file;
+ 	struct page *page;
+ 	void *vaddr;
+-	unsigned long off1;
+-	unsigned long idx;
++	unsigned long off;
++	pgoff_t idx;
+ 
+ 	if (!filp)
+ 		return -EINVAL;
+ 
+-	idx = (unsigned long)(offset >> PAGE_CACHE_SHIFT);
+-	off1 = offset &= ~PAGE_MASK;
++	if (!mapping->a_ops->readpage)
++		return -EIO;
++
++	idx = offset >> PAGE_CACHE_SHIFT;
++	off = offset & ~PAGE_MASK;
+ 
+ 	/*
+ 	 * Ensure that the page that has the original instruction is
+@@ -612,22 +584,20 @@ __copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *ins
+ 		return PTR_ERR(page);
+ 
+ 	vaddr = kmap_atomic(page);
+-	memcpy(insn, vaddr + off1, nbytes);
++	memcpy(insn, vaddr + off, nbytes);
+ 	kunmap_atomic(vaddr);
+ 	page_cache_release(page);
+ 
+ 	return 0;
+ }
+ 
+-static int
+-copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr)
++static int copy_insn(struct uprobe *uprobe, struct file *filp)
+ {
+ 	struct address_space *mapping;
+ 	unsigned long nbytes;
+ 	int bytes;
+ 
+-	addr &= ~PAGE_MASK;
+-	nbytes = PAGE_SIZE - addr;
++	nbytes = PAGE_SIZE - (uprobe->offset & ~PAGE_MASK);
+ 	mapping = uprobe->inode->i_mapping;
+ 
+ 	/* Instruction at end of binary; copy only available bytes */
+@@ -638,13 +608,13 @@ copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr)
+ 
+ 	/* Instruction at the page-boundary; copy bytes in second page */
+ 	if (nbytes < bytes) {
+-		if (__copy_insn(mapping, vma, uprobe->arch.insn + nbytes,
+-				bytes - nbytes, uprobe->offset + nbytes))
+-			return -ENOMEM;
+-
++		int err = __copy_insn(mapping, filp, uprobe->arch.insn + nbytes,
++				bytes - nbytes, uprobe->offset + nbytes);
++		if (err)
++			return err;
+ 		bytes = nbytes;
+ 	}
+-	return __copy_insn(mapping, vma, uprobe->arch.insn, bytes, uprobe->offset);
++	return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset);
+ }
+ 
+ /*
+@@ -672,9 +642,9 @@ copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr)
+  */
+ static int
+ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
+-			struct vm_area_struct *vma, loff_t vaddr)
++			struct vm_area_struct *vma, unsigned long vaddr)
+ {
+-	unsigned long addr;
++	bool first_uprobe;
+ 	int ret;
+ 
+ 	/*
+@@ -685,204 +655,194 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
+ 	 * Hence behave as if probe already existed.
+ 	 */
+ 	if (!uprobe->consumers)
+-		return -EEXIST;
+-
+-	addr = (unsigned long)vaddr;
++		return 0;
+ 
+ 	if (!(uprobe->flags & UPROBE_COPY_INSN)) {
+-		ret = copy_insn(uprobe, vma, addr);
++		ret = copy_insn(uprobe, vma->vm_file);
+ 		if (ret)
+ 			return ret;
+ 
+ 		if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn))
+-			return -EEXIST;
++			return -ENOTSUPP;
+ 
+-		ret = arch_uprobe_analyze_insn(&uprobe->arch, mm);
++		ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
+ 		if (ret)
+ 			return ret;
+ 
++		/* write_opcode() assumes we don't cross page boundary */
++		BUG_ON((uprobe->offset & ~PAGE_MASK) +
++				UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
++
+ 		uprobe->flags |= UPROBE_COPY_INSN;
+ 	}
+ 
+ 	/*
+-	 * Ideally, should be updating the probe count after the breakpoint
+-	 * has been successfully inserted. However a thread could hit the
+-	 * breakpoint we just inserted even before the probe count is
+-	 * incremented. If this is the first breakpoint placed, breakpoint
+-	 * notifier might ignore uprobes and pass the trap to the thread.
+-	 * Hence increment before and decrement on failure.
++	 * set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(),
++	 * the task can hit this breakpoint right after __replace_page().
+ 	 */
+-	atomic_inc(&mm->uprobes_state.count);
+-	ret = set_swbp(&uprobe->arch, mm, addr);
+-	if (ret)
+-		atomic_dec(&mm->uprobes_state.count);
++	first_uprobe = !test_bit(MMF_HAS_UPROBES, &mm->flags);
++	if (first_uprobe)
++		set_bit(MMF_HAS_UPROBES, &mm->flags);
++
++	ret = set_swbp(&uprobe->arch, mm, vaddr);
++	if (!ret)
++		clear_bit(MMF_RECALC_UPROBES, &mm->flags);
++	else if (first_uprobe)
++		clear_bit(MMF_HAS_UPROBES, &mm->flags);
+ 
+ 	return ret;
+ }
+ 
+ static void
+-remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, loff_t vaddr)
++remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr)
+ {
+-	if (!set_orig_insn(&uprobe->arch, mm, (unsigned long)vaddr, true))
+-		atomic_dec(&mm->uprobes_state.count);
++	/* can happen if uprobe_register() fails */
++	if (!test_bit(MMF_HAS_UPROBES, &mm->flags))
++		return;
++
++	set_bit(MMF_RECALC_UPROBES, &mm->flags);
++	set_orig_insn(&uprobe->arch, mm, vaddr);
+ }
+ 
+ /*
+- * There could be threads that have hit the breakpoint and are entering the
+- * notifier code and trying to acquire the uprobes_treelock. The thread
+- * calling delete_uprobe() that is removing the uprobe from the rb_tree can
+- * race with these threads and might acquire the uprobes_treelock compared
+- * to some of the breakpoint hit threads. In such a case, the breakpoint
+- * hit threads will not find the uprobe. The current unregistering thread
+- * waits till all other threads have hit a breakpoint, to acquire the
+- * uprobes_treelock before the uprobe is removed from the rbtree.
++ * There could be threads that have already hit the breakpoint. They
++ * will recheck the current insn and restart if find_uprobe() fails.
++ * See find_active_uprobe().
+  */
+ static void delete_uprobe(struct uprobe *uprobe)
+ {
+-	unsigned long flags;
+-
+-	synchronize_srcu(&uprobes_srcu);
+-	spin_lock_irqsave(&uprobes_treelock, flags);
++	spin_lock(&uprobes_treelock);
+ 	rb_erase(&uprobe->rb_node, &uprobes_tree);
+-	spin_unlock_irqrestore(&uprobes_treelock, flags);
++	spin_unlock(&uprobes_treelock);
+ 	iput(uprobe->inode);
+ 	put_uprobe(uprobe);
+ 	atomic_dec(&uprobe_events);
+ }
+ 
+-static struct vma_info *
+-__find_next_vma_info(struct address_space *mapping, struct list_head *head,
+-			struct vma_info *vi, loff_t offset, bool is_register)
++struct map_info {
++	struct map_info *next;
++	struct mm_struct *mm;
++	unsigned long vaddr;
++};
++
++static inline struct map_info *free_map_info(struct map_info *info)
++{
++	struct map_info *next = info->next;
++	kfree(info);
++	return next;
++}
++
++static struct map_info *
++build_map_info(struct address_space *mapping, loff_t offset, bool is_register)
+ {
++	unsigned long pgoff = offset >> PAGE_SHIFT;
+ 	struct prio_tree_iter iter;
+ 	struct vm_area_struct *vma;
+-	struct vma_info *tmpvi;
+-	unsigned long pgoff;
+-	int existing_vma;
+-	loff_t vaddr;
+-
+-	pgoff = offset >> PAGE_SHIFT;
++	struct map_info *curr = NULL;
++	struct map_info *prev = NULL;
++	struct map_info *info;
++	int more = 0;
+ 
++ again:
++	mutex_lock(&mapping->i_mmap_mutex);
+ 	vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
+ 		if (!valid_vma(vma, is_register))
+ 			continue;
+ 
+-		existing_vma = 0;
+-		vaddr = vma_address(vma, offset);
+-
+-		list_for_each_entry(tmpvi, head, probe_list) {
+-			if (tmpvi->mm == vma->vm_mm && tmpvi->vaddr == vaddr) {
+-				existing_vma = 1;
+-				break;
+-			}
++		if (!prev && !more) {
++			/*
++			 * Needs GFP_NOWAIT to avoid i_mmap_mutex recursion through
++			 * reclaim. This is optimistic, no harm done if it fails.
++			 */
++			prev = kmalloc(sizeof(struct map_info),
++					GFP_NOWAIT | __GFP_NOMEMALLOC | __GFP_NOWARN);
++			if (prev)
++				prev->next = NULL;
+ 		}
+-
+-		/*
+-		 * Another vma needs a probe to be installed. However skip
+-		 * installing the probe if the vma is about to be unlinked.
+-		 */
+-		if (!existing_vma && atomic_inc_not_zero(&vma->vm_mm->mm_users)) {
+-			vi->mm = vma->vm_mm;
+-			vi->vaddr = vaddr;
+-			list_add(&vi->probe_list, head);
+-
+-			return vi;
++		if (!prev) {
++			more++;
++			continue;
+ 		}
+-	}
+-
+-	return NULL;
+-}
+ 
+-/*
+- * Iterate in the rmap prio tree  and find a vma where a probe has not
+- * yet been inserted.
+- */
+-static struct vma_info *
+-find_next_vma_info(struct address_space *mapping, struct list_head *head,
+-		loff_t offset, bool is_register)
+-{
+-	struct vma_info *vi, *retvi;
++		if (!atomic_inc_not_zero(&vma->vm_mm->mm_users))
++			continue;
+ 
+-	vi = kzalloc(sizeof(struct vma_info), GFP_KERNEL);
+-	if (!vi)
+-		return ERR_PTR(-ENOMEM);
++		info = prev;
++		prev = prev->next;
++		info->next = curr;
++		curr = info;
+ 
+-	mutex_lock(&mapping->i_mmap_mutex);
+-	retvi = __find_next_vma_info(mapping, head, vi, offset, is_register);
++		info->mm = vma->vm_mm;
++		info->vaddr = offset_to_vaddr(vma, offset);
++	}
+ 	mutex_unlock(&mapping->i_mmap_mutex);
+ 
+-	if (!retvi)
+-		kfree(vi);
++	if (!more)
++		goto out;
++
++	prev = curr;
++	while (curr) {
++		mmput(curr->mm);
++		curr = curr->next;
++	}
+ 
+-	return retvi;
++	do {
++		info = kmalloc(sizeof(struct map_info), GFP_KERNEL);
++		if (!info) {
++			curr = ERR_PTR(-ENOMEM);
++			goto out;
++		}
++		info->next = prev;
++		prev = info;
++	} while (--more);
++
++	goto again;
++ out:
++	while (prev)
++		prev = free_map_info(prev);
++	return curr;
+ }
+ 
+ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
+ {
+-	struct list_head try_list;
+-	struct vm_area_struct *vma;
+-	struct address_space *mapping;
+-	struct vma_info *vi, *tmpvi;
+-	struct mm_struct *mm;
+-	loff_t vaddr;
+-	int ret;
++	struct map_info *info;
++	int err = 0;
+ 
+-	mapping = uprobe->inode->i_mapping;
+-	INIT_LIST_HEAD(&try_list);
++	info = build_map_info(uprobe->inode->i_mapping,
++					uprobe->offset, is_register);
++	if (IS_ERR(info))
++		return PTR_ERR(info);
+ 
+-	ret = 0;
++	while (info) {
++		struct mm_struct *mm = info->mm;
++		struct vm_area_struct *vma;
+ 
+-	for (;;) {
+-		vi = find_next_vma_info(mapping, &try_list, uprobe->offset, is_register);
+-		if (!vi)
+-			break;
++		if (err)
++			goto free;
+ 
+-		if (IS_ERR(vi)) {
+-			ret = PTR_ERR(vi);
+-			break;
+-		}
++		down_write(&mm->mmap_sem);
++		vma = find_vma(mm, info->vaddr);
++		if (!vma || !valid_vma(vma, is_register) ||
++		    vma->vm_file->f_mapping->host != uprobe->inode)
++			goto unlock;
+ 
+-		mm = vi->mm;
+-		down_read(&mm->mmap_sem);
+-		vma = find_vma(mm, (unsigned long)vi->vaddr);
+-		if (!vma || !valid_vma(vma, is_register)) {
+-			list_del(&vi->probe_list);
+-			kfree(vi);
+-			up_read(&mm->mmap_sem);
+-			mmput(mm);
+-			continue;
+-		}
+-		vaddr = vma_address(vma, uprobe->offset);
+-		if (vma->vm_file->f_mapping->host != uprobe->inode ||
+-						vaddr != vi->vaddr) {
+-			list_del(&vi->probe_list);
+-			kfree(vi);
+-			up_read(&mm->mmap_sem);
+-			mmput(mm);
+-			continue;
+-		}
++		if (vma->vm_start > info->vaddr ||
++		    vaddr_to_offset(vma, info->vaddr) != uprobe->offset)
++			goto unlock;
+ 
+ 		if (is_register)
+-			ret = install_breakpoint(uprobe, mm, vma, vi->vaddr);
++			err = install_breakpoint(uprobe, mm, vma, info->vaddr);
+ 		else
+-			remove_breakpoint(uprobe, mm, vi->vaddr);
++			remove_breakpoint(uprobe, mm, info->vaddr);
+ 
+-		up_read(&mm->mmap_sem);
++ unlock:
++		up_write(&mm->mmap_sem);
++ free:
+ 		mmput(mm);
+-		if (is_register) {
+-			if (ret && ret == -EEXIST)
+-				ret = 0;
+-			if (ret)
+-				break;
+-		}
+-	}
+-
+-	list_for_each_entry_safe(vi, tmpvi, &try_list, probe_list) {
+-		list_del(&vi->probe_list);
+-		kfree(vi);
++		info = free_map_info(info);
+ 	}
+ 
+-	return ret;
++	return err;
+ }
+ 
+ static int __uprobe_register(struct uprobe *uprobe)
+@@ -941,10 +901,12 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *
+ 	}
+ 
+ 	mutex_unlock(uprobes_hash(inode));
+-	put_uprobe(uprobe);
++	if (uprobe)
++		put_uprobe(uprobe);
+ 
+ 	return ret;
+ }
++EXPORT_SYMBOL_GPL(uprobe_register);
+ 
+ /*
+  * uprobe_unregister - unregister a already registered probe.
+@@ -976,81 +938,81 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume
+ 	if (uprobe)
+ 		put_uprobe(uprobe);
+ }
++EXPORT_SYMBOL_GPL(uprobe_unregister);
+ 
+-/*
+- * Of all the nodes that correspond to the given inode, return the node
+- * with the least offset.
+- */
+-static struct rb_node *find_least_offset_node(struct inode *inode)
++static struct rb_node *
++find_node_in_range(struct inode *inode, loff_t min, loff_t max)
+ {
+-	struct uprobe u = { .inode = inode, .offset = 0};
+ 	struct rb_node *n = uprobes_tree.rb_node;
+-	struct rb_node *close_node = NULL;
+-	struct uprobe *uprobe;
+-	int match;
+ 
+ 	while (n) {
+-		uprobe = rb_entry(n, struct uprobe, rb_node);
+-		match = match_uprobe(&u, uprobe);
+-
+-		if (uprobe->inode == inode)
+-			close_node = n;
+-
+-		if (!match)
+-			return close_node;
++		struct uprobe *u = rb_entry(n, struct uprobe, rb_node);
+ 
+-		if (match < 0)
++		if (inode < u->inode) {
+ 			n = n->rb_left;
+-		else
++		} else if (inode > u->inode) {
+ 			n = n->rb_right;
++		} else {
++			if (max < u->offset)
++				n = n->rb_left;
++			else if (min > u->offset)
++				n = n->rb_right;
++			else
++				break;
++		}
+ 	}
+ 
+-	return close_node;
++	return n;
+ }
+ 
+ /*
+- * For a given inode, build a list of probes that need to be inserted.
++ * For a given range in vma, build a list of probes that need to be inserted.
+  */
+-static void build_probe_list(struct inode *inode, struct list_head *head)
++static void build_probe_list(struct inode *inode,
++				struct vm_area_struct *vma,
++				unsigned long start, unsigned long end,
++				struct list_head *head)
+ {
+-	struct uprobe *uprobe;
+-	unsigned long flags;
+-	struct rb_node *n;
+-
+-	spin_lock_irqsave(&uprobes_treelock, flags);
+-
+-	n = find_least_offset_node(inode);
++	loff_t min, max;
++	struct rb_node *n, *t;
++	struct uprobe *u;
+ 
+-	for (; n; n = rb_next(n)) {
+-		uprobe = rb_entry(n, struct uprobe, rb_node);
+-		if (uprobe->inode != inode)
+-			break;
++	INIT_LIST_HEAD(head);
++	min = vaddr_to_offset(vma, start);
++	max = min + (end - start) - 1;
+ 
+-		list_add(&uprobe->pending_list, head);
+-		atomic_inc(&uprobe->ref);
++	spin_lock(&uprobes_treelock);
++	n = find_node_in_range(inode, min, max);
++	if (n) {
++		for (t = n; t; t = rb_prev(t)) {
++			u = rb_entry(t, struct uprobe, rb_node);
++			if (u->inode != inode || u->offset < min)
++				break;
++			list_add(&u->pending_list, head);
++			atomic_inc(&u->ref);
++		}
++		for (t = n; (t = rb_next(t)); ) {
++			u = rb_entry(t, struct uprobe, rb_node);
++			if (u->inode != inode || u->offset > max)
++				break;
++			list_add(&u->pending_list, head);
++			atomic_inc(&u->ref);
++		}
+ 	}
+-
+-	spin_unlock_irqrestore(&uprobes_treelock, flags);
++	spin_unlock(&uprobes_treelock);
+ }
+ 
+ /*
+- * Called from mmap_region.
+- * called with mm->mmap_sem acquired.
+- *
+- * Return -ve no if we fail to insert probes and we cannot
+- * bail-out.
+- * Return 0 otherwise. i.e:
++ * Called from mmap_region/vma_adjust with mm->mmap_sem acquired.
+  *
+- *	- successful insertion of probes
+- *	- (or) no possible probes to be inserted.
+- *	- (or) insertion of probes failed but we can bail-out.
++ * Currently we ignore all errors and always return 0, the callers
++ * can't handle the failure anyway.
+  */
+ int uprobe_mmap(struct vm_area_struct *vma)
+ {
+ 	struct list_head tmp_list;
+ 	struct uprobe *uprobe, *u;
+ 	struct inode *inode;
+-	int ret, count;
+ 
+ 	if (!atomic_read(&uprobe_events) || !valid_vma(vma, true))
+ 		return 0;
+@@ -1059,54 +1021,38 @@ int uprobe_mmap(struct vm_area_struct *vma)
+ 	if (!inode)
+ 		return 0;
+ 
+-	INIT_LIST_HEAD(&tmp_list);
+ 	mutex_lock(uprobes_mmap_hash(inode));
+-	build_probe_list(inode, &tmp_list);
+-
+-	ret = 0;
+-	count = 0;
++	build_probe_list(inode, vma, vma->vm_start, vma->vm_end, &tmp_list);
+ 
+ 	list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) {
+-		loff_t vaddr;
+-
+-		list_del(&uprobe->pending_list);
+-		if (!ret) {
+-			vaddr = vma_address(vma, uprobe->offset);
+-
+-			if (vaddr < vma->vm_start || vaddr >= vma->vm_end) {
+-				put_uprobe(uprobe);
+-				continue;
+-			}
+-
+-			ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr);
+-
+-			/* Ignore double add: */
+-			if (ret == -EEXIST) {
+-				ret = 0;
+-
+-				if (!is_swbp_at_addr(vma->vm_mm, vaddr))
+-					continue;
+-
+-				/*
+-				 * Unable to insert a breakpoint, but
+-				 * breakpoint lies underneath. Increment the
+-				 * probe count.
+-				 */
+-				atomic_inc(&vma->vm_mm->uprobes_state.count);
+-			}
+-
+-			if (!ret)
+-				count++;
++		if (!fatal_signal_pending(current)) {
++			unsigned long vaddr = offset_to_vaddr(vma, uprobe->offset);
++			install_breakpoint(uprobe, vma->vm_mm, vma, vaddr);
+ 		}
+ 		put_uprobe(uprobe);
+ 	}
+-
+ 	mutex_unlock(uprobes_mmap_hash(inode));
+ 
+-	if (ret)
+-		atomic_sub(count, &vma->vm_mm->uprobes_state.count);
++	return 0;
++}
+ 
+-	return ret;
++static bool
++vma_has_uprobes(struct vm_area_struct *vma, unsigned long start, unsigned long end)
++{
++	loff_t min, max;
++	struct inode *inode;
++	struct rb_node *n;
++
++	inode = vma->vm_file->f_mapping->host;
++
++	min = vaddr_to_offset(vma, start);
++	max = min + (end - start) - 1;
++
++	spin_lock(&uprobes_treelock);
++	n = find_node_in_range(inode, min, max);
++	spin_unlock(&uprobes_treelock);
++
++	return !!n;
+ }
+ 
+ /*
+@@ -1114,41 +1060,18 @@ int uprobe_mmap(struct vm_area_struct *vma)
+  */
+ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end)
+ {
+-	struct list_head tmp_list;
+-	struct uprobe *uprobe, *u;
+-	struct inode *inode;
+-
+ 	if (!atomic_read(&uprobe_events) || !valid_vma(vma, false))
+ 		return;
+ 
+-	if (!atomic_read(&vma->vm_mm->uprobes_state.count))
++	if (!atomic_read(&vma->vm_mm->mm_users)) /* called by mmput() ? */
+ 		return;
+ 
+-	inode = vma->vm_file->f_mapping->host;
+-	if (!inode)
++	if (!test_bit(MMF_HAS_UPROBES, &vma->vm_mm->flags) ||
++	     test_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags))
+ 		return;
+ 
+-	INIT_LIST_HEAD(&tmp_list);
+-	mutex_lock(uprobes_mmap_hash(inode));
+-	build_probe_list(inode, &tmp_list);
+-
+-	list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) {
+-		loff_t vaddr;
+-
+-		list_del(&uprobe->pending_list);
+-		vaddr = vma_address(vma, uprobe->offset);
+-
+-		if (vaddr >= start && vaddr < end) {
+-			/*
+-			 * An unregister could have removed the probe before
+-			 * unmap. So check before we decrement the count.
+-			 */
+-			if (is_swbp_at_addr(vma->vm_mm, vaddr) == 1)
+-				atomic_dec(&vma->vm_mm->uprobes_state.count);
+-		}
+-		put_uprobe(uprobe);
+-	}
+-	mutex_unlock(uprobes_mmap_hash(inode));
++	if (vma_has_uprobes(vma, start, end))
++		set_bit(MMF_RECALC_UPROBES, &vma->vm_mm->flags);
+ }
+ 
+ /* Slot allocation for XOL */
+@@ -1250,13 +1173,15 @@ void uprobe_clear_state(struct mm_struct *mm)
+ 	kfree(area);
+ }
+ 
+-/*
+- * uprobe_reset_state - Free the area allocated for slots.
+- */
+-void uprobe_reset_state(struct mm_struct *mm)
++void uprobe_dup_mmap(struct mm_struct *oldmm, struct mm_struct *newmm)
+ {
+-	mm->uprobes_state.xol_area = NULL;
+-	atomic_set(&mm->uprobes_state.count, 0);
++	newmm->uprobes_state.xol_area = NULL;
++
++	if (test_bit(MMF_HAS_UPROBES, &oldmm->flags)) {
++		set_bit(MMF_HAS_UPROBES, &newmm->flags);
++		/* unconditionally, dup_mmap() skips VM_DONTCOPY vmas */
++		set_bit(MMF_RECALC_UPROBES, &newmm->flags);
++	}
+ }
+ 
+ /*
+@@ -1378,9 +1303,6 @@ void uprobe_free_utask(struct task_struct *t)
+ {
+ 	struct uprobe_task *utask = t->utask;
+ 
+-	if (t->uprobe_srcu_id != -1)
+-		srcu_read_unlock_raw(&uprobes_srcu, t->uprobe_srcu_id);
+-
+ 	if (!utask)
+ 		return;
+ 
+@@ -1398,7 +1320,6 @@ void uprobe_free_utask(struct task_struct *t)
+ void uprobe_copy_process(struct task_struct *t)
+ {
+ 	t->utask = NULL;
+-	t->uprobe_srcu_id = -1;
+ }
+ 
+ /*
+@@ -1417,7 +1338,6 @@ static struct uprobe_task *add_utask(void)
+ 	if (unlikely(!utask))
+ 		return NULL;
+ 
+-	utask->active_uprobe = NULL;
+ 	current->utask = utask;
+ 	return utask;
+ }
+@@ -1479,41 +1399,93 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
+ 	return false;
+ }
+ 
++static void mmf_recalc_uprobes(struct mm_struct *mm)
++{
++	struct vm_area_struct *vma;
++
++	for (vma = mm->mmap; vma; vma = vma->vm_next) {
++		if (!valid_vma(vma, false))
++			continue;
++		/*
++		 * This is not strictly accurate, we can race with
++		 * uprobe_unregister() and see the already removed
++		 * uprobe if delete_uprobe() was not yet called.
++		 */
++		if (vma_has_uprobes(vma, vma->vm_start, vma->vm_end))
++			return;
++	}
++
++	clear_bit(MMF_HAS_UPROBES, &mm->flags);
++}
++
++static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
++{
++	struct mm_struct *mm = current->mm;
++	struct uprobe *uprobe = NULL;
++	struct vm_area_struct *vma;
++
++	down_read(&mm->mmap_sem);
++	vma = find_vma(mm, bp_vaddr);
++	if (vma && vma->vm_start <= bp_vaddr) {
++		if (valid_vma(vma, false)) {
++			struct inode *inode = vma->vm_file->f_mapping->host;
++			loff_t offset = vaddr_to_offset(vma, bp_vaddr);
++
++			uprobe = find_uprobe(inode, offset);
++		}
++
++		if (!uprobe)
++			*is_swbp = is_swbp_at_addr(mm, bp_vaddr);
++	} else {
++		*is_swbp = -EFAULT;
++	}
++
++	if (!uprobe && test_and_clear_bit(MMF_RECALC_UPROBES, &mm->flags))
++		mmf_recalc_uprobes(mm);
++	up_read(&mm->mmap_sem);
++
++	return uprobe;
++}
++
++void __weak arch_uprobe_enable_step(struct arch_uprobe *arch)
++{
++	user_enable_single_step(current);
++}
++
++void __weak arch_uprobe_disable_step(struct arch_uprobe *arch)
++{
++	user_disable_single_step(current);
++}
++
+ /*
+  * Run handler and ask thread to singlestep.
+  * Ensure all non-fatal signals cannot interrupt thread while it singlesteps.
+  */
+ static void handle_swbp(struct pt_regs *regs)
+ {
+-	struct vm_area_struct *vma;
+ 	struct uprobe_task *utask;
+ 	struct uprobe *uprobe;
+-	struct mm_struct *mm;
+ 	unsigned long bp_vaddr;
++	int uninitialized_var(is_swbp);
+ 
+-	uprobe = NULL;
+ 	bp_vaddr = uprobe_get_swbp_addr(regs);
+-	mm = current->mm;
+-	down_read(&mm->mmap_sem);
+-	vma = find_vma(mm, bp_vaddr);
+-
+-	if (vma && vma->vm_start <= bp_vaddr && valid_vma(vma, false)) {
+-		struct inode *inode;
+-		loff_t offset;
+-
+-		inode = vma->vm_file->f_mapping->host;
+-		offset = bp_vaddr - vma->vm_start;
+-		offset += (vma->vm_pgoff << PAGE_SHIFT);
+-		uprobe = find_uprobe(inode, offset);
+-	}
+-
+-	srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id);
+-	current->uprobe_srcu_id = -1;
+-	up_read(&mm->mmap_sem);
++	uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
+ 
+ 	if (!uprobe) {
+-		/* No matching uprobe; signal SIGTRAP. */
+-		send_sig(SIGTRAP, current, 0);
++		if (is_swbp > 0) {
++			/* No matching uprobe; signal SIGTRAP. */
++			send_sig(SIGTRAP, current, 0);
++		} else {
++			/*
++			 * Either we raced with uprobe_unregister() or we can't
++			 * access this memory. The latter is only possible if
++			 * another thread plays with our ->mm. In both cases
++			 * we can simply restart. If this vma was unmapped we
++			 * can pretend this insn was not executed yet and get
++			 * the (correct) SIGSEGV after restart.
++			 */
++			instruction_pointer_set(regs, bp_vaddr);
++		}
+ 		return;
+ 	}
+ 
+@@ -1531,7 +1503,7 @@ static void handle_swbp(struct pt_regs *regs)
+ 
+ 	utask->state = UTASK_SSTEP;
+ 	if (!pre_ssout(uprobe, regs, bp_vaddr)) {
+-		user_enable_single_step(current);
++		arch_uprobe_enable_step(&uprobe->arch);
+ 		return;
+ 	}
+ 
+@@ -1540,17 +1512,15 @@ cleanup_ret:
+ 		utask->active_uprobe = NULL;
+ 		utask->state = UTASK_RUNNING;
+ 	}
+-	if (uprobe) {
+-		if (!(uprobe->flags & UPROBE_SKIP_SSTEP))
++	if (!(uprobe->flags & UPROBE_SKIP_SSTEP))
+ 
+-			/*
+-			 * cannot singlestep; cannot skip instruction;
+-			 * re-execute the instruction.
+-			 */
+-			instruction_pointer_set(regs, bp_vaddr);
++		/*
++		 * cannot singlestep; cannot skip instruction;
++		 * re-execute the instruction.
++		 */
++		instruction_pointer_set(regs, bp_vaddr);
+ 
+-		put_uprobe(uprobe);
+-	}
++	put_uprobe(uprobe);
+ }
+ 
+ /*
+@@ -1569,10 +1539,10 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs)
+ 	else
+ 		WARN_ON_ONCE(1);
+ 
++	arch_uprobe_disable_step(&uprobe->arch);
+ 	put_uprobe(uprobe);
+ 	utask->active_uprobe = NULL;
+ 	utask->state = UTASK_RUNNING;
+-	user_disable_single_step(current);
+ 	xol_free_insn_slot(current);
+ 
+ 	spin_lock_irq(&current->sighand->siglock);
+@@ -1611,8 +1581,7 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs)
+ {
+ 	struct uprobe_task *utask;
+ 
+-	if (!current->mm || !atomic_read(&current->mm->uprobes_state.count))
+-		/* task is currently not uprobed */
++	if (!current->mm || !test_bit(MMF_HAS_UPROBES, &current->mm->flags))
+ 		return 0;
+ 
+ 	utask = current->utask;
+@@ -1620,7 +1589,6 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs)
+ 		utask->state = UTASK_BP_HIT;
+ 
+ 	set_thread_flag(TIF_UPROBE);
+-	current->uprobe_srcu_id = srcu_read_lock_raw(&uprobes_srcu);
+ 
+ 	return 1;
+ }
+@@ -1655,7 +1623,6 @@ static int __init init_uprobes(void)
+ 		mutex_init(&uprobes_mutex[i]);
+ 		mutex_init(&uprobes_mmap_mutex[i]);
+ 	}
+-	init_srcu_struct(&uprobes_srcu);
+ 
+ 	return register_die_notifier(&uprobe_exception_nb);
+ }
+diff --git a/kernel/fork.c b/kernel/fork.c
+index 7a1d634..5d0137c 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -355,6 +355,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
+ 
+ 	down_write(&oldmm->mmap_sem);
+ 	flush_cache_dup_mm(oldmm);
++	uprobe_dup_mmap(oldmm, mm);
+ 	/*
+ 	 * Not linked in yet - no deadlock potential:
+ 	 */
+@@ -843,8 +841,6 @@ struct mm_struct *dup_mm(struct task_struct *tsk)
+ #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ 	mm->pmd_huge_pte = NULL;
+ #endif
+-	uprobe_reset_state(mm);
+-
+ 	if (!mm_init(mm, tsk))
+ 		goto fail_nomem;
+ 
+diff --git a/kernel/ptrace.c b/kernel/ptrace.c
+index a232bb5..764fcd1 100644
+--- a/kernel/ptrace.c
++++ b/kernel/ptrace.c
+@@ -33,6 +33,12 @@ static int ptrace_trapping_sleep_fn(void *flags)
+ }
+ 
+ /*
++ * This is declared in linux/regset.h and defined in machine-dependent
++ * code.  We put the export here to ensure no machine forgets it.
++ */
++EXPORT_SYMBOL_GPL(task_user_regset_view);
++
++/*
+  * ptrace a task: make the debugger its new parent and
+  * move it to the ptrace list.
+  *
+diff --git a/mm/mmap.c b/mm/mmap.c
+index 3edfcdf..f25fd3f 100644
+--- a/mm/mmap.c
++++ b/mm/mmap.c
+@@ -2345,9 +2344,6 @@ int insert_vm_struct(struct mm_struct * mm, struct vm_area_struct * vma)
+ 	     security_vm_enough_memory_mm(mm, vma_pages(vma)))
+ 		return -ENOMEM;
+ 
+-	if (vma->vm_file && uprobe_mmap(vma))
+-		return -EINVAL;
+-
+ 	vma_link(mm, vma, prev, rb_link, rb_parent);
+ 	return 0;
+ }
+@@ -2418,9 +2414,6 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
+ 			if (new_vma->vm_file) {
+ 				get_file(new_vma->vm_file);
+ 
+-				if (uprobe_mmap(new_vma))
+-					goto out_free_mempol;
+-
+ 				if (vma->vm_flags & VM_EXECUTABLE)
+ 					added_exe_file_vma(mm);
+ 			}
+_______________________________________________
+kernel mailing list
+kernel at lists.fedoraproject.org
+https://admin.fedoraproject.org/mailman/listinfo/kernel


More information about the scm-commits mailing list