diff -Nur linux-4.1.26.orig/arch/alpha/mm/fault.c linux-4.1.26/arch/alpha/mm/fault.c --- linux-4.1.26.orig/arch/alpha/mm/fault.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/alpha/mm/fault.c 2016-06-19 15:30:54.915151887 +0200 @@ -23,8 +23,7 @@ #include #include #include - -#include +#include extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *); @@ -107,7 +106,7 @@ /* If we're in an interrupt context, or have no user context, we must not take the fault. */ - if (!mm || in_atomic()) + if (!mm || faulthandler_disabled()) goto no_context; #ifdef CONFIG_ALPHA_LARGE_VMALLOC diff -Nur linux-4.1.26.orig/arch/arc/include/asm/futex.h linux-4.1.26/arch/arc/include/asm/futex.h --- linux-4.1.26.orig/arch/arc/include/asm/futex.h 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arc/include/asm/futex.h 2016-06-19 15:30:54.915151887 +0200 @@ -53,7 +53,7 @@ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - pagefault_disable(); /* implies preempt_disable() */ + pagefault_disable(); switch (op) { case FUTEX_OP_SET: @@ -75,7 +75,7 @@ ret = -ENOSYS; } - pagefault_enable(); /* subsumes preempt_enable() */ + pagefault_enable(); if (!ret) { switch (cmp) { @@ -104,7 +104,7 @@ return ret; } -/* Compare-xchg with preemption disabled. +/* Compare-xchg with pagefaults disabled. * Notes: * -Best-Effort: Exchg happens only if compare succeeds. * If compare fails, returns; leaving retry/looping to upper layers @@ -121,7 +121,7 @@ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) return -EFAULT; - pagefault_disable(); /* implies preempt_disable() */ + pagefault_disable(); /* TBD : can use llock/scond */ __asm__ __volatile__( @@ -142,7 +142,7 @@ : "r"(oldval), "r"(newval), "r"(uaddr), "ir"(-EFAULT) : "cc", "memory"); - pagefault_enable(); /* subsumes preempt_enable() */ + pagefault_enable(); *uval = val; return val; diff -Nur linux-4.1.26.orig/arch/arc/mm/fault.c linux-4.1.26/arch/arc/mm/fault.c --- linux-4.1.26.orig/arch/arc/mm/fault.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arc/mm/fault.c 2016-06-19 15:30:54.915151887 +0200 @@ -86,7 +86,7 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_atomic() || !mm) + if (faulthandler_disabled() || !mm) goto no_context; if (user_mode(regs)) diff -Nur linux-4.1.26.orig/arch/arm/include/asm/cmpxchg.h linux-4.1.26/arch/arm/include/asm/cmpxchg.h --- linux-4.1.26.orig/arch/arm/include/asm/cmpxchg.h 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/include/asm/cmpxchg.h 2016-06-19 15:30:54.919152041 +0200 @@ -129,6 +129,8 @@ #else /* min ARCH >= ARMv6 */ +#define __HAVE_ARCH_CMPXCHG 1 + extern void __bad_cmpxchg(volatile void *ptr, int size); /* diff -Nur linux-4.1.26.orig/arch/arm/include/asm/futex.h linux-4.1.26/arch/arm/include/asm/futex.h --- linux-4.1.26.orig/arch/arm/include/asm/futex.h 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/include/asm/futex.h 2016-06-19 15:30:54.919152041 +0200 @@ -93,6 +93,7 @@ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) return -EFAULT; + preempt_disable(); __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" "1: " TUSER(ldr) " %1, [%4]\n" " teq %1, %2\n" @@ -104,6 +105,8 @@ : "cc", "memory"); *uval = val; + preempt_enable(); + return ret; } @@ -124,7 +127,10 @@ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) return -EFAULT; - pagefault_disable(); /* implies preempt_disable() */ +#ifndef CONFIG_SMP + preempt_disable(); +#endif + pagefault_disable(); switch (op) { case FUTEX_OP_SET: @@ -146,7 +152,10 @@ ret = -ENOSYS; } - pagefault_enable(); /* subsumes preempt_enable() */ + pagefault_enable(); +#ifndef CONFIG_SMP + preempt_enable(); +#endif if (!ret) { switch (cmp) { diff -Nur linux-4.1.26.orig/arch/arm/include/asm/switch_to.h linux-4.1.26/arch/arm/include/asm/switch_to.h --- linux-4.1.26.orig/arch/arm/include/asm/switch_to.h 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/include/asm/switch_to.h 2016-06-19 15:30:54.919152041 +0200 @@ -3,6 +3,13 @@ #include +#if defined CONFIG_PREEMPT_RT_FULL && defined CONFIG_HIGHMEM +void switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p); +#else +static inline void +switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p) { } +#endif + /* * For v7 SMP cores running a preemptible kernel we may be pre-empted * during a TLB maintenance operation, so execute an inner-shareable dsb @@ -22,6 +29,7 @@ #define switch_to(prev,next,last) \ do { \ + switch_kmaps(prev, next); \ last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \ } while (0) diff -Nur linux-4.1.26.orig/arch/arm/include/asm/thread_info.h linux-4.1.26/arch/arm/include/asm/thread_info.h --- linux-4.1.26.orig/arch/arm/include/asm/thread_info.h 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/include/asm/thread_info.h 2016-06-19 15:30:54.919152041 +0200 @@ -50,6 +50,7 @@ struct thread_info { unsigned long flags; /* low level flags */ int preempt_count; /* 0 => preemptable, <0 => bug */ + int preempt_lazy_count; /* 0 => preemptable, <0 => bug */ mm_segment_t addr_limit; /* address limit */ struct task_struct *task; /* main task structure */ __u32 cpu; /* cpu */ @@ -147,6 +148,7 @@ #define TIF_SIGPENDING 0 #define TIF_NEED_RESCHED 1 #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ +#define TIF_NEED_RESCHED_LAZY 3 #define TIF_UPROBE 7 #define TIF_SYSCALL_TRACE 8 #define TIF_SYSCALL_AUDIT 9 @@ -160,6 +162,7 @@ #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) +#define _TIF_NEED_RESCHED_LAZY (1 << TIF_NEED_RESCHED_LAZY) #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-4.1.26.orig/arch/arm/Kconfig linux-4.1.26/arch/arm/Kconfig --- linux-4.1.26.orig/arch/arm/Kconfig 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/Kconfig 2016-06-19 15:30:54.919152041 +0200 @@ -31,7 +31,7 @@ select HARDIRQS_SW_RESEND select HAVE_ARCH_AUDITSYSCALL if (AEABI && !OABI_COMPAT) select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6 - select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL + select HAVE_ARCH_JUMP_LABEL if (!XIP_KERNEL && !PREEMPT_RT_BASE) select HAVE_ARCH_KGDB select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT) select HAVE_ARCH_TRACEHOOK @@ -66,6 +66,7 @@ select HAVE_PERF_EVENTS select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP + select HAVE_PREEMPT_LAZY select HAVE_RCU_TABLE_FREE if (SMP && ARM_LPAE) select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_SYSCALL_TRACEPOINTS diff -Nur linux-4.1.26.orig/arch/arm/kernel/asm-offsets.c linux-4.1.26/arch/arm/kernel/asm-offsets.c --- linux-4.1.26.orig/arch/arm/kernel/asm-offsets.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/kernel/asm-offsets.c 2016-06-19 15:30:54.919152041 +0200 @@ -65,6 +65,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_CPU, offsetof(struct thread_info, cpu)); diff -Nur linux-4.1.26.orig/arch/arm/kernel/entry-armv.S linux-4.1.26/arch/arm/kernel/entry-armv.S --- linux-4.1.26.orig/arch/arm/kernel/entry-armv.S 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/kernel/entry-armv.S 2016-06-19 15:30:54.919152041 +0200 @@ -208,11 +208,18 @@ #ifdef CONFIG_PREEMPT get_thread_info tsk ldr r8, [tsk, #TI_PREEMPT] @ get preempt count - ldr r0, [tsk, #TI_FLAGS] @ get flags teq r8, #0 @ if preempt count != 0 + bne 1f @ return from exeption + ldr r0, [tsk, #TI_FLAGS] @ get flags + tst r0, #_TIF_NEED_RESCHED @ if NEED_RESCHED is set + blne svc_preempt @ preempt! + + ldr r8, [tsk, #TI_PREEMPT_LAZY] @ get preempt lazy count + teq r8, #0 @ if preempt lazy count != 0 movne r0, #0 @ force flags to 0 - tst r0, #_TIF_NEED_RESCHED + tst r0, #_TIF_NEED_RESCHED_LAZY blne svc_preempt +1: #endif svc_exit r5, irq = 1 @ return from exception @@ -227,6 +234,8 @@ 1: bl preempt_schedule_irq @ irq en/disable is done inside ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS tst r0, #_TIF_NEED_RESCHED + bne 1b + tst r0, #_TIF_NEED_RESCHED_LAZY reteq r8 @ go again b 1b #endif diff -Nur linux-4.1.26.orig/arch/arm/kernel/process.c linux-4.1.26/arch/arm/kernel/process.c --- linux-4.1.26.orig/arch/arm/kernel/process.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/kernel/process.c 2016-06-19 15:30:54.919152041 +0200 @@ -290,6 +290,30 @@ } #ifdef CONFIG_MMU +/* + * CONFIG_SPLIT_PTLOCK_CPUS results in a page->ptl lock. If the lock is not + * initialized by pgtable_page_ctor() then a coredump of the vector page will + * fail. + */ +static int __init vectors_user_mapping_init_page(void) +{ + struct page *page; + unsigned long addr = 0xffff0000; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + + pgd = pgd_offset_k(addr); + pud = pud_offset(pgd, addr); + pmd = pmd_offset(pud, addr); + page = pmd_page(*(pmd)); + + pgtable_page_ctor(page); + + return 0; +} +late_initcall(vectors_user_mapping_init_page); + #ifdef CONFIG_KUSER_HELPERS /* * The vectors page is always readable from user space for the diff -Nur linux-4.1.26.orig/arch/arm/kernel/signal.c linux-4.1.26/arch/arm/kernel/signal.c --- linux-4.1.26.orig/arch/arm/kernel/signal.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/kernel/signal.c 2016-06-19 15:30:54.919152041 +0200 @@ -568,7 +568,8 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) { do { - if (likely(thread_flags & _TIF_NEED_RESCHED)) { + if (likely(thread_flags & (_TIF_NEED_RESCHED | + _TIF_NEED_RESCHED_LAZY))) { schedule(); } else { if (unlikely(!user_mode(regs))) diff -Nur linux-4.1.26.orig/arch/arm/kernel/smp.c linux-4.1.26/arch/arm/kernel/smp.c --- linux-4.1.26.orig/arch/arm/kernel/smp.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/kernel/smp.c 2016-06-19 15:30:54.919152041 +0200 @@ -213,8 +213,6 @@ flush_cache_louis(); local_flush_tlb_all(); - clear_tasks_mm_cpumask(cpu); - return 0; } @@ -230,6 +228,9 @@ pr_err("CPU%u: cpu didn't die\n", cpu); return; } + + clear_tasks_mm_cpumask(cpu); + pr_notice("CPU%u: shutdown\n", cpu); /* diff -Nur linux-4.1.26.orig/arch/arm/kernel/unwind.c linux-4.1.26/arch/arm/kernel/unwind.c --- linux-4.1.26.orig/arch/arm/kernel/unwind.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/kernel/unwind.c 2016-06-19 15:30:54.919152041 +0200 @@ -93,7 +93,7 @@ static const struct unwind_idx *__origin_unwind_idx; extern const struct unwind_idx __stop_unwind_idx[]; -static DEFINE_SPINLOCK(unwind_lock); +static DEFINE_RAW_SPINLOCK(unwind_lock); static LIST_HEAD(unwind_tables); /* Convert a prel31 symbol to an absolute address */ @@ -201,7 +201,7 @@ /* module unwind tables */ struct unwind_table *table; - spin_lock_irqsave(&unwind_lock, flags); + raw_spin_lock_irqsave(&unwind_lock, flags); list_for_each_entry(table, &unwind_tables, list) { if (addr >= table->begin_addr && addr < table->end_addr) { @@ -213,7 +213,7 @@ break; } } - spin_unlock_irqrestore(&unwind_lock, flags); + raw_spin_unlock_irqrestore(&unwind_lock, flags); } pr_debug("%s: idx = %p\n", __func__, idx); @@ -529,9 +529,9 @@ tab->begin_addr = text_addr; tab->end_addr = text_addr + text_size; - spin_lock_irqsave(&unwind_lock, flags); + raw_spin_lock_irqsave(&unwind_lock, flags); list_add_tail(&tab->list, &unwind_tables); - spin_unlock_irqrestore(&unwind_lock, flags); + raw_spin_unlock_irqrestore(&unwind_lock, flags); return tab; } @@ -543,9 +543,9 @@ if (!tab) return; - spin_lock_irqsave(&unwind_lock, flags); + raw_spin_lock_irqsave(&unwind_lock, flags); list_del(&tab->list); - spin_unlock_irqrestore(&unwind_lock, flags); + raw_spin_unlock_irqrestore(&unwind_lock, flags); kfree(tab); } diff -Nur linux-4.1.26.orig/arch/arm/kvm/arm.c linux-4.1.26/arch/arm/kvm/arm.c --- linux-4.1.26.orig/arch/arm/kvm/arm.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/kvm/arm.c 2016-06-19 15:30:54.919152041 +0200 @@ -474,9 +474,9 @@ static void vcpu_pause(struct kvm_vcpu *vcpu) { - wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu); + struct swait_head *wq = kvm_arch_vcpu_wq(vcpu); - wait_event_interruptible(*wq, !vcpu->arch.pause); + swait_event_interruptible(*wq, !vcpu->arch.pause); } static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu) diff -Nur linux-4.1.26.orig/arch/arm/kvm/psci.c linux-4.1.26/arch/arm/kvm/psci.c --- linux-4.1.26.orig/arch/arm/kvm/psci.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/kvm/psci.c 2016-06-19 15:30:54.919152041 +0200 @@ -68,7 +68,7 @@ { struct kvm *kvm = source_vcpu->kvm; struct kvm_vcpu *vcpu = NULL; - wait_queue_head_t *wq; + struct swait_head *wq; unsigned long cpu_id; unsigned long context_id; phys_addr_t target_pc; @@ -117,7 +117,7 @@ smp_mb(); /* Make sure the above is visible */ wq = kvm_arch_vcpu_wq(vcpu); - wake_up_interruptible(wq); + swait_wake_interruptible(wq); return PSCI_RET_SUCCESS; } diff -Nur linux-4.1.26.orig/arch/arm/mach-exynos/platsmp.c linux-4.1.26/arch/arm/mach-exynos/platsmp.c --- linux-4.1.26.orig/arch/arm/mach-exynos/platsmp.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/mach-exynos/platsmp.c 2016-06-19 15:30:54.919152041 +0200 @@ -231,7 +231,7 @@ return (void __iomem *)(S5P_VA_SCU); } -static DEFINE_SPINLOCK(boot_lock); +static DEFINE_RAW_SPINLOCK(boot_lock); static void exynos_secondary_init(unsigned int cpu) { @@ -244,8 +244,8 @@ /* * Synchronise with the boot thread. */ - spin_lock(&boot_lock); - spin_unlock(&boot_lock); + raw_spin_lock(&boot_lock); + raw_spin_unlock(&boot_lock); } static int exynos_boot_secondary(unsigned int cpu, struct task_struct *idle) @@ -259,7 +259,7 @@ * Set synchronisation state between this boot processor * and the secondary one */ - spin_lock(&boot_lock); + raw_spin_lock(&boot_lock); /* * The secondary processor is waiting to be released from @@ -286,7 +286,7 @@ if (timeout == 0) { printk(KERN_ERR "cpu1 power enable failed"); - spin_unlock(&boot_lock); + raw_spin_unlock(&boot_lock); return -ETIMEDOUT; } } @@ -342,7 +342,7 @@ * calibrations, then wait for it to finish */ fail: - spin_unlock(&boot_lock); + raw_spin_unlock(&boot_lock); return pen_release != -1 ? ret : 0; } diff -Nur linux-4.1.26.orig/arch/arm/mach-hisi/platmcpm.c linux-4.1.26/arch/arm/mach-hisi/platmcpm.c --- linux-4.1.26.orig/arch/arm/mach-hisi/platmcpm.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/mach-hisi/platmcpm.c 2016-06-19 15:30:54.923152195 +0200 @@ -57,7 +57,7 @@ static void __iomem *sysctrl, *fabric; static int hip04_cpu_table[HIP04_MAX_CLUSTERS][HIP04_MAX_CPUS_PER_CLUSTER]; -static DEFINE_SPINLOCK(boot_lock); +static DEFINE_RAW_SPINLOCK(boot_lock); static u32 fabric_phys_addr; /* * [0]: bootwrapper physical address @@ -104,7 +104,7 @@ if (cluster >= HIP04_MAX_CLUSTERS || cpu >= HIP04_MAX_CPUS_PER_CLUSTER) return -EINVAL; - spin_lock_irq(&boot_lock); + raw_spin_lock_irq(&boot_lock); if (hip04_cpu_table[cluster][cpu]) goto out; @@ -133,7 +133,7 @@ udelay(20); out: hip04_cpu_table[cluster][cpu]++; - spin_unlock_irq(&boot_lock); + raw_spin_unlock_irq(&boot_lock); return 0; } @@ -149,7 +149,7 @@ __mcpm_cpu_going_down(cpu, cluster); - spin_lock(&boot_lock); + raw_spin_lock(&boot_lock); BUG_ON(__mcpm_cluster_state(cluster) != CLUSTER_UP); hip04_cpu_table[cluster][cpu]--; if (hip04_cpu_table[cluster][cpu] == 1) { @@ -162,7 +162,7 @@ last_man = hip04_cluster_is_down(cluster); if (last_man && __mcpm_outbound_enter_critical(cpu, cluster)) { - spin_unlock(&boot_lock); + raw_spin_unlock(&boot_lock); /* Since it's Cortex A15, disable L2 prefetching. */ asm volatile( "mcr p15, 1, %0, c15, c0, 3 \n\t" @@ -173,7 +173,7 @@ hip04_set_snoop_filter(cluster, 0); __mcpm_outbound_leave_critical(cluster, CLUSTER_DOWN); } else { - spin_unlock(&boot_lock); + raw_spin_unlock(&boot_lock); v7_exit_coherency_flush(louis); } @@ -192,7 +192,7 @@ cpu >= HIP04_MAX_CPUS_PER_CLUSTER); count = TIMEOUT_MSEC / POLL_MSEC; - spin_lock_irq(&boot_lock); + raw_spin_lock_irq(&boot_lock); for (tries = 0; tries < count; tries++) { if (hip04_cpu_table[cluster][cpu]) { ret = -EBUSY; @@ -202,10 +202,10 @@ data = readl_relaxed(sysctrl + SC_CPU_RESET_STATUS(cluster)); if (data & CORE_WFI_STATUS(cpu)) break; - spin_unlock_irq(&boot_lock); + raw_spin_unlock_irq(&boot_lock); /* Wait for clean L2 when the whole cluster is down. */ msleep(POLL_MSEC); - spin_lock_irq(&boot_lock); + raw_spin_lock_irq(&boot_lock); } if (tries >= count) goto err; @@ -220,10 +220,10 @@ } if (tries >= count) goto err; - spin_unlock_irq(&boot_lock); + raw_spin_unlock_irq(&boot_lock); return 0; err: - spin_unlock_irq(&boot_lock); + raw_spin_unlock_irq(&boot_lock); return ret; } @@ -235,10 +235,10 @@ cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0); cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); - spin_lock(&boot_lock); + raw_spin_lock(&boot_lock); if (!hip04_cpu_table[cluster][cpu]) hip04_cpu_table[cluster][cpu] = 1; - spin_unlock(&boot_lock); + raw_spin_unlock(&boot_lock); } static void __naked hip04_mcpm_power_up_setup(unsigned int affinity_level) diff -Nur linux-4.1.26.orig/arch/arm/mach-omap2/gpio.c linux-4.1.26/arch/arm/mach-omap2/gpio.c --- linux-4.1.26.orig/arch/arm/mach-omap2/gpio.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/mach-omap2/gpio.c 2016-06-19 15:30:54.923152195 +0200 @@ -130,7 +130,6 @@ } pwrdm = omap_hwmod_get_pwrdm(oh); - pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm); pdev = omap_device_build(name, id - 1, oh, pdata, sizeof(*pdata)); kfree(pdata); diff -Nur linux-4.1.26.orig/arch/arm/mach-omap2/omap-smp.c linux-4.1.26/arch/arm/mach-omap2/omap-smp.c --- linux-4.1.26.orig/arch/arm/mach-omap2/omap-smp.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/mach-omap2/omap-smp.c 2016-06-19 15:30:54.923152195 +0200 @@ -43,7 +43,7 @@ /* SCU base address */ static void __iomem *scu_base; -static DEFINE_SPINLOCK(boot_lock); +static DEFINE_RAW_SPINLOCK(boot_lock); void __iomem *omap4_get_scu_base(void) { @@ -74,8 +74,8 @@ /* * Synchronise with the boot thread. */ - spin_lock(&boot_lock); - spin_unlock(&boot_lock); + raw_spin_lock(&boot_lock); + raw_spin_unlock(&boot_lock); } static int omap4_boot_secondary(unsigned int cpu, struct task_struct *idle) @@ -89,7 +89,7 @@ * Set synchronisation state between this boot processor * and the secondary one */ - spin_lock(&boot_lock); + raw_spin_lock(&boot_lock); /* * Update the AuxCoreBoot0 with boot state for secondary core. @@ -166,7 +166,7 @@ * Now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ - spin_unlock(&boot_lock); + raw_spin_unlock(&boot_lock); return 0; } diff -Nur linux-4.1.26.orig/arch/arm/mach-omap2/powerdomain.c linux-4.1.26/arch/arm/mach-omap2/powerdomain.c --- linux-4.1.26.orig/arch/arm/mach-omap2/powerdomain.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/mach-omap2/powerdomain.c 2016-06-19 15:30:54.923152195 +0200 @@ -1166,43 +1166,3 @@ return count; } -/** - * pwrdm_can_ever_lose_context - can this powerdomain ever lose context? - * @pwrdm: struct powerdomain * - * - * Given a struct powerdomain * @pwrdm, returns 1 if the powerdomain - * can lose either memory or logic context or if @pwrdm is invalid, or - * returns 0 otherwise. This function is not concerned with how the - * powerdomain registers are programmed (i.e., to go off or not); it's - * concerned with whether it's ever possible for this powerdomain to - * go off while some other part of the chip is active. This function - * assumes that every powerdomain can go to either ON or INACTIVE. - */ -bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm) -{ - int i; - - if (!pwrdm) { - pr_debug("powerdomain: %s: invalid powerdomain pointer\n", - __func__); - return 1; - } - - if (pwrdm->pwrsts & PWRSTS_OFF) - return 1; - - if (pwrdm->pwrsts & PWRSTS_RET) { - if (pwrdm->pwrsts_logic_ret & PWRSTS_OFF) - return 1; - - for (i = 0; i < pwrdm->banks; i++) - if (pwrdm->pwrsts_mem_ret[i] & PWRSTS_OFF) - return 1; - } - - for (i = 0; i < pwrdm->banks; i++) - if (pwrdm->pwrsts_mem_on[i] & PWRSTS_OFF) - return 1; - - return 0; -} diff -Nur linux-4.1.26.orig/arch/arm/mach-omap2/powerdomain.h linux-4.1.26/arch/arm/mach-omap2/powerdomain.h --- linux-4.1.26.orig/arch/arm/mach-omap2/powerdomain.h 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/mach-omap2/powerdomain.h 2016-06-19 15:30:54.923152195 +0200 @@ -244,7 +244,6 @@ int pwrdm_pre_transition(struct powerdomain *pwrdm); int pwrdm_post_transition(struct powerdomain *pwrdm); int pwrdm_get_context_loss_count(struct powerdomain *pwrdm); -bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 state); diff -Nur linux-4.1.26.orig/arch/arm/mach-prima2/platsmp.c linux-4.1.26/arch/arm/mach-prima2/platsmp.c --- linux-4.1.26.orig/arch/arm/mach-prima2/platsmp.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/mach-prima2/platsmp.c 2016-06-19 15:30:54.923152195 +0200 @@ -22,7 +22,7 @@ static void __iomem *clk_base; -static DEFINE_SPINLOCK(boot_lock); +static DEFINE_RAW_SPINLOCK(boot_lock); static void sirfsoc_secondary_init(unsigned int cpu) { @@ -36,8 +36,8 @@ /* * Synchronise with the boot thread. */ - spin_lock(&boot_lock); - spin_unlock(&boot_lock); + raw_spin_lock(&boot_lock); + raw_spin_unlock(&boot_lock); } static const struct of_device_id clk_ids[] = { @@ -75,7 +75,7 @@ /* make sure write buffer is drained */ mb(); - spin_lock(&boot_lock); + raw_spin_lock(&boot_lock); /* * The secondary processor is waiting to be released from @@ -107,7 +107,7 @@ * now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ - spin_unlock(&boot_lock); + raw_spin_unlock(&boot_lock); return pen_release != -1 ? -ENOSYS : 0; } diff -Nur linux-4.1.26.orig/arch/arm/mach-qcom/platsmp.c linux-4.1.26/arch/arm/mach-qcom/platsmp.c --- linux-4.1.26.orig/arch/arm/mach-qcom/platsmp.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/mach-qcom/platsmp.c 2016-06-19 15:30:54.923152195 +0200 @@ -46,7 +46,7 @@ extern void secondary_startup_arm(void); -static DEFINE_SPINLOCK(boot_lock); +static DEFINE_RAW_SPINLOCK(boot_lock); #ifdef CONFIG_HOTPLUG_CPU static void __ref qcom_cpu_die(unsigned int cpu) @@ -60,8 +60,8 @@ /* * Synchronise with the boot thread. */ - spin_lock(&boot_lock); - spin_unlock(&boot_lock); + raw_spin_lock(&boot_lock); + raw_spin_unlock(&boot_lock); } static int scss_release_secondary(unsigned int cpu) @@ -284,7 +284,7 @@ * set synchronisation state between this boot processor * and the secondary one */ - spin_lock(&boot_lock); + raw_spin_lock(&boot_lock); /* * Send the secondary CPU a soft interrupt, thereby causing @@ -297,7 +297,7 @@ * now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ - spin_unlock(&boot_lock); + raw_spin_unlock(&boot_lock); return ret; } diff -Nur linux-4.1.26.orig/arch/arm/mach-spear/platsmp.c linux-4.1.26/arch/arm/mach-spear/platsmp.c --- linux-4.1.26.orig/arch/arm/mach-spear/platsmp.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/mach-spear/platsmp.c 2016-06-19 15:30:54.923152195 +0200 @@ -32,7 +32,7 @@ sync_cache_w(&pen_release); } -static DEFINE_SPINLOCK(boot_lock); +static DEFINE_RAW_SPINLOCK(boot_lock); static void __iomem *scu_base = IOMEM(VA_SCU_BASE); @@ -47,8 +47,8 @@ /* * Synchronise with the boot thread. */ - spin_lock(&boot_lock); - spin_unlock(&boot_lock); + raw_spin_lock(&boot_lock); + raw_spin_unlock(&boot_lock); } static int spear13xx_boot_secondary(unsigned int cpu, struct task_struct *idle) @@ -59,7 +59,7 @@ * set synchronisation state between this boot processor * and the secondary one */ - spin_lock(&boot_lock); + raw_spin_lock(&boot_lock); /* * The secondary processor is waiting to be released from @@ -84,7 +84,7 @@ * now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ - spin_unlock(&boot_lock); + raw_spin_unlock(&boot_lock); return pen_release != -1 ? -ENOSYS : 0; } diff -Nur linux-4.1.26.orig/arch/arm/mach-sti/platsmp.c linux-4.1.26/arch/arm/mach-sti/platsmp.c --- linux-4.1.26.orig/arch/arm/mach-sti/platsmp.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/mach-sti/platsmp.c 2016-06-19 15:30:54.923152195 +0200 @@ -34,7 +34,7 @@ sync_cache_w(&pen_release); } -static DEFINE_SPINLOCK(boot_lock); +static DEFINE_RAW_SPINLOCK(boot_lock); static void sti_secondary_init(unsigned int cpu) { @@ -49,8 +49,8 @@ /* * Synchronise with the boot thread. */ - spin_lock(&boot_lock); - spin_unlock(&boot_lock); + raw_spin_lock(&boot_lock); + raw_spin_unlock(&boot_lock); } static int sti_boot_secondary(unsigned int cpu, struct task_struct *idle) @@ -61,7 +61,7 @@ * set synchronisation state between this boot processor * and the secondary one */ - spin_lock(&boot_lock); + raw_spin_lock(&boot_lock); /* * The secondary processor is waiting to be released from @@ -92,7 +92,7 @@ * now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ - spin_unlock(&boot_lock); + raw_spin_unlock(&boot_lock); return pen_release != -1 ? -ENOSYS : 0; } diff -Nur linux-4.1.26.orig/arch/arm/mach-ux500/platsmp.c linux-4.1.26/arch/arm/mach-ux500/platsmp.c --- linux-4.1.26.orig/arch/arm/mach-ux500/platsmp.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/mach-ux500/platsmp.c 2016-06-19 15:30:54.923152195 +0200 @@ -51,7 +51,7 @@ return NULL; } -static DEFINE_SPINLOCK(boot_lock); +static DEFINE_RAW_SPINLOCK(boot_lock); static void ux500_secondary_init(unsigned int cpu) { @@ -64,8 +64,8 @@ /* * Synchronise with the boot thread. */ - spin_lock(&boot_lock); - spin_unlock(&boot_lock); + raw_spin_lock(&boot_lock); + raw_spin_unlock(&boot_lock); } static int ux500_boot_secondary(unsigned int cpu, struct task_struct *idle) @@ -76,7 +76,7 @@ * set synchronisation state between this boot processor * and the secondary one */ - spin_lock(&boot_lock); + raw_spin_lock(&boot_lock); /* * The secondary processor is waiting to be released from @@ -97,7 +97,7 @@ * now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ - spin_unlock(&boot_lock); + raw_spin_unlock(&boot_lock); return pen_release != -1 ? -ENOSYS : 0; } diff -Nur linux-4.1.26.orig/arch/arm/mm/fault.c linux-4.1.26/arch/arm/mm/fault.c --- linux-4.1.26.orig/arch/arm/mm/fault.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/mm/fault.c 2016-06-19 15:30:54.923152195 +0200 @@ -276,7 +276,7 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_atomic() || !mm) + if (faulthandler_disabled() || !mm) goto no_context; if (user_mode(regs)) @@ -430,6 +430,9 @@ if (addr < TASK_SIZE) return do_page_fault(addr, fsr, regs); + if (interrupts_enabled(regs)) + local_irq_enable(); + if (user_mode(regs)) goto bad_area; @@ -497,6 +500,9 @@ static int do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { + if (interrupts_enabled(regs)) + local_irq_enable(); + do_bad_area(addr, fsr, regs); return 0; } diff -Nur linux-4.1.26.orig/arch/arm/mm/highmem.c linux-4.1.26/arch/arm/mm/highmem.c --- linux-4.1.26.orig/arch/arm/mm/highmem.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/mm/highmem.c 2016-06-19 15:30:54.923152195 +0200 @@ -54,11 +54,13 @@ void *kmap_atomic(struct page *page) { + pte_t pte = mk_pte(page, kmap_prot); unsigned int idx; unsigned long vaddr; void *kmap; int type; + preempt_disable_nort(); pagefault_disable(); if (!PageHighMem(page)) return page_address(page); @@ -92,7 +94,10 @@ * in place, so the contained TLB flush ensures the TLB is updated * with the new mapping. */ - set_fixmap_pte(idx, mk_pte(page, kmap_prot)); +#ifdef CONFIG_PREEMPT_RT_FULL + current->kmap_pte[type] = pte; +#endif + set_fixmap_pte(idx, pte); return (void *)vaddr; } @@ -109,27 +114,33 @@ if (cache_is_vivt()) __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE); +#ifdef CONFIG_PREEMPT_RT_FULL + current->kmap_pte[type] = __pte(0); +#endif #ifdef CONFIG_DEBUG_HIGHMEM BUG_ON(vaddr != __fix_to_virt(idx)); - set_fixmap_pte(idx, __pte(0)); #else (void) idx; /* to kill a warning */ #endif + set_fixmap_pte(idx, __pte(0)); kmap_atomic_idx_pop(); } else if (vaddr >= PKMAP_ADDR(0) && vaddr < PKMAP_ADDR(LAST_PKMAP)) { /* this address was obtained through kmap_high_get() */ kunmap_high(pte_page(pkmap_page_table[PKMAP_NR(vaddr)])); } pagefault_enable(); + preempt_enable_nort(); } EXPORT_SYMBOL(__kunmap_atomic); void *kmap_atomic_pfn(unsigned long pfn) { + pte_t pte = pfn_pte(pfn, kmap_prot); unsigned long vaddr; int idx, type; struct page *page = pfn_to_page(pfn); + preempt_disable_nort(); pagefault_disable(); if (!PageHighMem(page)) return page_address(page); @@ -140,7 +151,10 @@ #ifdef CONFIG_DEBUG_HIGHMEM BUG_ON(!pte_none(get_fixmap_pte(vaddr))); #endif - set_fixmap_pte(idx, pfn_pte(pfn, kmap_prot)); +#ifdef CONFIG_PREEMPT_RT_FULL + current->kmap_pte[type] = pte; +#endif + set_fixmap_pte(idx, pte); return (void *)vaddr; } @@ -154,3 +168,28 @@ return pte_page(get_fixmap_pte(vaddr)); } + +#if defined CONFIG_PREEMPT_RT_FULL +void switch_kmaps(struct task_struct *prev_p, struct task_struct *next_p) +{ + int i; + + /* + * Clear @prev's kmap_atomic mappings + */ + for (i = 0; i < prev_p->kmap_idx; i++) { + int idx = i + KM_TYPE_NR * smp_processor_id(); + + set_fixmap_pte(idx, __pte(0)); + } + /* + * Restore @next_p's kmap_atomic mappings + */ + for (i = 0; i < next_p->kmap_idx; i++) { + int idx = i + KM_TYPE_NR * smp_processor_id(); + + if (!pte_none(next_p->kmap_pte[i])) + set_fixmap_pte(idx, next_p->kmap_pte[i]); + } +} +#endif diff -Nur linux-4.1.26.orig/arch/arm/plat-versatile/platsmp.c linux-4.1.26/arch/arm/plat-versatile/platsmp.c --- linux-4.1.26.orig/arch/arm/plat-versatile/platsmp.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm/plat-versatile/platsmp.c 2016-06-19 15:30:54.923152195 +0200 @@ -30,7 +30,7 @@ sync_cache_w(&pen_release); } -static DEFINE_SPINLOCK(boot_lock); +static DEFINE_RAW_SPINLOCK(boot_lock); void versatile_secondary_init(unsigned int cpu) { @@ -43,8 +43,8 @@ /* * Synchronise with the boot thread. */ - spin_lock(&boot_lock); - spin_unlock(&boot_lock); + raw_spin_lock(&boot_lock); + raw_spin_unlock(&boot_lock); } int versatile_boot_secondary(unsigned int cpu, struct task_struct *idle) @@ -55,7 +55,7 @@ * Set synchronisation state between this boot processor * and the secondary one */ - spin_lock(&boot_lock); + raw_spin_lock(&boot_lock); /* * This is really belt and braces; we hold unintended secondary @@ -85,7 +85,7 @@ * now the secondary core is starting up let it run its * calibrations, then wait for it to finish */ - spin_unlock(&boot_lock); + raw_spin_unlock(&boot_lock); return pen_release != -1 ? -ENOSYS : 0; } diff -Nur linux-4.1.26.orig/arch/arm64/include/asm/futex.h linux-4.1.26/arch/arm64/include/asm/futex.h --- linux-4.1.26.orig/arch/arm64/include/asm/futex.h 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm64/include/asm/futex.h 2016-06-19 15:30:54.923152195 +0200 @@ -58,7 +58,7 @@ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) return -EFAULT; - pagefault_disable(); /* implies preempt_disable() */ + pagefault_disable(); switch (op) { case FUTEX_OP_SET: @@ -85,7 +85,7 @@ ret = -ENOSYS; } - pagefault_enable(); /* subsumes preempt_enable() */ + pagefault_enable(); if (!ret) { switch (cmp) { diff -Nur linux-4.1.26.orig/arch/arm64/include/asm/thread_info.h linux-4.1.26/arch/arm64/include/asm/thread_info.h --- linux-4.1.26.orig/arch/arm64/include/asm/thread_info.h 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm64/include/asm/thread_info.h 2016-06-19 15:30:54.923152195 +0200 @@ -47,6 +47,7 @@ mm_segment_t addr_limit; /* address limit */ struct task_struct *task; /* main task structure */ int preempt_count; /* 0 => preemptable, <0 => bug */ + int preempt_lazy_count; /* 0 => preemptable, <0 => bug */ int cpu; /* cpu */ }; @@ -101,6 +102,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 @@ -117,6 +119,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-4.1.26.orig/arch/arm64/Kconfig linux-4.1.26/arch/arm64/Kconfig --- linux-4.1.26.orig/arch/arm64/Kconfig 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm64/Kconfig 2016-06-19 15:30:54.923152195 +0200 @@ -69,8 +69,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 @@ -599,7 +601,7 @@ config XEN bool "Xen guest support on ARM64" - depends on ARM64 && OF + depends on ARM64 && OF && !PREEMPT_RT_FULL select SWIOTLB_XEN help Say Y if you want to run Linux in a Virtual Machine on Xen on ARM64. diff -Nur linux-4.1.26.orig/arch/arm64/kernel/asm-offsets.c linux-4.1.26/arch/arm64/kernel/asm-offsets.c --- linux-4.1.26.orig/arch/arm64/kernel/asm-offsets.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm64/kernel/asm-offsets.c 2016-06-19 15:30:54.923152195 +0200 @@ -35,6 +35,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_CPU, offsetof(struct thread_info, cpu)); diff -Nur linux-4.1.26.orig/arch/arm64/kernel/entry.S linux-4.1.26/arch/arm64/kernel/entry.S --- linux-4.1.26.orig/arch/arm64/kernel/entry.S 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm64/kernel/entry.S 2016-06-19 15:30:58.591293647 +0200 @@ -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 @@ -622,6 +628,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-4.1.26.orig/arch/arm64/kernel/insn.c linux-4.1.26/arch/arm64/kernel/insn.c --- linux-4.1.26.orig/arch/arm64/kernel/insn.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm64/kernel/insn.c 2016-06-19 15:30:58.595293802 +0200 @@ -77,7 +77,7 @@ } } -static DEFINE_SPINLOCK(patch_lock); +static DEFINE_RAW_SPINLOCK(patch_lock); static void __kprobes *patch_map(void *addr, int fixmap) { @@ -124,13 +124,13 @@ unsigned long flags = 0; int ret; - spin_lock_irqsave(&patch_lock, flags); + raw_spin_lock_irqsave(&patch_lock, flags); waddr = patch_map(addr, FIX_TEXT_POKE0); ret = probe_kernel_write(waddr, &insn, AARCH64_INSN_SIZE); patch_unmap(FIX_TEXT_POKE0); - spin_unlock_irqrestore(&patch_lock, flags); + raw_spin_unlock_irqrestore(&patch_lock, flags); return ret; } diff -Nur linux-4.1.26.orig/arch/arm64/kernel/perf_event.c linux-4.1.26/arch/arm64/kernel/perf_event.c --- linux-4.1.26.orig/arch/arm64/kernel/perf_event.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm64/kernel/perf_event.c 2016-06-19 15:30:58.595293802 +0200 @@ -488,7 +488,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-4.1.26.orig/arch/arm64/mm/fault.c linux-4.1.26/arch/arm64/mm/fault.c --- linux-4.1.26.orig/arch/arm64/mm/fault.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/arm64/mm/fault.c 2016-06-19 15:30:58.595293802 +0200 @@ -211,7 +211,7 @@ * If we're in an interrupt or have no user context, we must not take * the fault. */ - if (in_atomic() || !mm) + if (faulthandler_disabled() || !mm) goto no_context; if (user_mode(regs)) diff -Nur linux-4.1.26.orig/arch/avr32/include/asm/uaccess.h linux-4.1.26/arch/avr32/include/asm/uaccess.h --- linux-4.1.26.orig/arch/avr32/include/asm/uaccess.h 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/avr32/include/asm/uaccess.h 2016-06-19 15:30:58.595293802 +0200 @@ -97,7 +97,8 @@ * @x: Value to copy to user space. * @ptr: Destination address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple value from kernel space to user * space. It supports simple types like char and int, but not larger @@ -116,7 +117,8 @@ * @x: Variable to store result. * @ptr: Source address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple variable from user space to kernel * space. It supports simple types like char and int, but not larger @@ -136,7 +138,8 @@ * @x: Value to copy to user space. * @ptr: Destination address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple value from kernel space to user * space. It supports simple types like char and int, but not larger @@ -158,7 +161,8 @@ * @x: Variable to store result. * @ptr: Source address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple variable from user space to kernel * space. It supports simple types like char and int, but not larger diff -Nur linux-4.1.26.orig/arch/avr32/mm/fault.c linux-4.1.26/arch/avr32/mm/fault.c --- linux-4.1.26.orig/arch/avr32/mm/fault.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/avr32/mm/fault.c 2016-06-19 15:30:58.595293802 +0200 @@ -14,11 +14,11 @@ #include #include #include +#include #include #include #include -#include #ifdef CONFIG_KPROBES static inline int notify_page_fault(struct pt_regs *regs, int trap) @@ -81,7 +81,7 @@ * If we're in an interrupt or have no user context, we must * not take the fault... */ - if (in_atomic() || !mm || regs->sr & SYSREG_BIT(GM)) + if (faulthandler_disabled() || !mm || regs->sr & SYSREG_BIT(GM)) goto no_context; local_irq_enable(); diff -Nur linux-4.1.26.orig/arch/cris/mm/fault.c linux-4.1.26/arch/cris/mm/fault.c --- linux-4.1.26.orig/arch/cris/mm/fault.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/cris/mm/fault.c 2016-06-19 15:30:58.595293802 +0200 @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include extern int find_fixup_code(struct pt_regs *); @@ -109,11 +109,11 @@ info.si_code = SEGV_MAPERR; /* - * If we're in an interrupt or "atomic" operation or have no + * If we're in an interrupt, have pagefaults disabled or have no * user context, we must not take the fault. */ - if (in_atomic() || !mm) + if (faulthandler_disabled() || !mm) goto no_context; if (user_mode(regs)) diff -Nur linux-4.1.26.orig/arch/frv/mm/fault.c linux-4.1.26/arch/frv/mm/fault.c --- linux-4.1.26.orig/arch/frv/mm/fault.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/frv/mm/fault.c 2016-06-19 15:30:58.595293802 +0200 @@ -19,9 +19,9 @@ #include #include #include +#include #include -#include #include /*****************************************************************************/ @@ -78,7 +78,7 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_atomic() || !mm) + if (faulthandler_disabled() || !mm) goto no_context; if (user_mode(__frame)) diff -Nur linux-4.1.26.orig/arch/frv/mm/highmem.c linux-4.1.26/arch/frv/mm/highmem.c --- linux-4.1.26.orig/arch/frv/mm/highmem.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/frv/mm/highmem.c 2016-06-19 15:30:58.595293802 +0200 @@ -42,6 +42,7 @@ unsigned long paddr; int type; + preempt_disable(); pagefault_disable(); type = kmap_atomic_idx_push(); paddr = page_to_phys(page); @@ -85,5 +86,6 @@ } kmap_atomic_idx_pop(); pagefault_enable(); + preempt_enable(); } EXPORT_SYMBOL(__kunmap_atomic); diff -Nur linux-4.1.26.orig/arch/hexagon/include/asm/uaccess.h linux-4.1.26/arch/hexagon/include/asm/uaccess.h --- linux-4.1.26.orig/arch/hexagon/include/asm/uaccess.h 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/hexagon/include/asm/uaccess.h 2016-06-19 15:30:58.595293802 +0200 @@ -36,7 +36,8 @@ * @addr: User space pointer to start of block to check * @size: Size of block to check * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * Checks if a pointer to a block of memory in user space is valid. * diff -Nur linux-4.1.26.orig/arch/ia64/mm/fault.c linux-4.1.26/arch/ia64/mm/fault.c --- linux-4.1.26.orig/arch/ia64/mm/fault.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/ia64/mm/fault.c 2016-06-19 15:30:58.595293802 +0200 @@ -11,10 +11,10 @@ #include #include #include +#include #include #include -#include extern int die(char *, struct pt_regs *, long); @@ -96,7 +96,7 @@ /* * If we're in an interrupt or have no user context, we must not take the fault.. */ - if (in_atomic() || !mm) + if (faulthandler_disabled() || !mm) goto no_context; #ifdef CONFIG_VIRTUAL_MEM_MAP diff -Nur linux-4.1.26.orig/arch/Kconfig linux-4.1.26/arch/Kconfig --- linux-4.1.26.orig/arch/Kconfig 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/Kconfig 2016-06-19 15:30:54.915151887 +0200 @@ -6,6 +6,7 @@ tristate "OProfile system profiling" depends on PROFILING depends on HAVE_OPROFILE + depends on !PREEMPT_RT_FULL select RING_BUFFER select RING_BUFFER_ALLOW_SWAP help @@ -49,6 +50,7 @@ config JUMP_LABEL bool "Optimize very unlikely/likely branches" depends on HAVE_ARCH_JUMP_LABEL + depends on (!INTERRUPT_OFF_HIST && !PREEMPT_OFF_HIST && !WAKEUP_LATENCY_HIST && !MISSED_TIMER_OFFSETS_HIST) help This option enables a transparent branch optimization that makes certain almost-always-true or almost-always-false branch diff -Nur linux-4.1.26.orig/arch/m32r/include/asm/uaccess.h linux-4.1.26/arch/m32r/include/asm/uaccess.h --- linux-4.1.26.orig/arch/m32r/include/asm/uaccess.h 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/m32r/include/asm/uaccess.h 2016-06-19 15:30:58.595293802 +0200 @@ -91,7 +91,8 @@ * @addr: User space pointer to start of block to check * @size: Size of block to check * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * Checks if a pointer to a block of memory in user space is valid. * @@ -155,7 +156,8 @@ * @x: Variable to store result. * @ptr: Source address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple variable from user space to kernel * space. It supports simple types like char and int, but not larger @@ -175,7 +177,8 @@ * @x: Value to copy to user space. * @ptr: Destination address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple value from kernel space to user * space. It supports simple types like char and int, but not larger @@ -194,7 +197,8 @@ * @x: Variable to store result. * @ptr: Source address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple variable from user space to kernel * space. It supports simple types like char and int, but not larger @@ -274,7 +278,8 @@ * @x: Value to copy to user space. * @ptr: Destination address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple value from kernel space to user * space. It supports simple types like char and int, but not larger @@ -568,7 +573,8 @@ * @from: Source address, in kernel space. * @n: Number of bytes to copy. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * Copy data from kernel space to user space. Caller must check * the specified block with access_ok() before calling this function. @@ -588,7 +594,8 @@ * @from: Source address, in kernel space. * @n: Number of bytes to copy. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * Copy data from kernel space to user space. * @@ -606,7 +613,8 @@ * @from: Source address, in user space. * @n: Number of bytes to copy. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * Copy data from user space to kernel space. Caller must check * the specified block with access_ok() before calling this function. @@ -626,7 +634,8 @@ * @from: Source address, in user space. * @n: Number of bytes to copy. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * Copy data from user space to kernel space. * @@ -677,7 +686,8 @@ * strlen_user: - Get the size of a string in user space. * @str: The string to measure. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * Get the size of a NUL-terminated string in user space. * diff -Nur linux-4.1.26.orig/arch/m32r/mm/fault.c linux-4.1.26/arch/m32r/mm/fault.c --- linux-4.1.26.orig/arch/m32r/mm/fault.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/m32r/mm/fault.c 2016-06-19 15:30:58.595293802 +0200 @@ -24,9 +24,9 @@ #include /* For unblank_screen() */ #include #include +#include #include -#include #include #include #include @@ -111,10 +111,10 @@ mm = tsk->mm; /* - * 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.. + * If we're in an interrupt or have no user context or have pagefaults + * disabled then we must not take the fault. */ - if (in_atomic() || !mm) + if (faulthandler_disabled() || !mm) goto bad_area_nosemaphore; if (error_code & ACE_USERMODE) diff -Nur linux-4.1.26.orig/arch/m68k/mm/fault.c linux-4.1.26/arch/m68k/mm/fault.c --- linux-4.1.26.orig/arch/m68k/mm/fault.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/m68k/mm/fault.c 2016-06-19 15:30:58.595293802 +0200 @@ -10,10 +10,10 @@ #include #include #include +#include #include #include -#include #include extern void die_if_kernel(char *, struct pt_regs *, long); @@ -81,7 +81,7 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_atomic() || !mm) + if (faulthandler_disabled() || !mm) goto no_context; if (user_mode(regs)) diff -Nur linux-4.1.26.orig/arch/metag/mm/fault.c linux-4.1.26/arch/metag/mm/fault.c --- linux-4.1.26.orig/arch/metag/mm/fault.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/metag/mm/fault.c 2016-06-19 15:30:58.595293802 +0200 @@ -105,7 +105,7 @@ mm = tsk->mm; - if (in_atomic() || !mm) + if (faulthandler_disabled() || !mm) goto no_context; if (user_mode(regs)) diff -Nur linux-4.1.26.orig/arch/metag/mm/highmem.c linux-4.1.26/arch/metag/mm/highmem.c --- linux-4.1.26.orig/arch/metag/mm/highmem.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/metag/mm/highmem.c 2016-06-19 15:30:58.595293802 +0200 @@ -43,7 +43,7 @@ unsigned long vaddr; int type; - /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ + preempt_disable(); pagefault_disable(); if (!PageHighMem(page)) return page_address(page); @@ -82,6 +82,7 @@ } pagefault_enable(); + preempt_enable(); } EXPORT_SYMBOL(__kunmap_atomic); @@ -95,6 +96,7 @@ unsigned long vaddr; int type; + preempt_disable(); pagefault_disable(); type = kmap_atomic_idx_push(); diff -Nur linux-4.1.26.orig/arch/microblaze/include/asm/uaccess.h linux-4.1.26/arch/microblaze/include/asm/uaccess.h --- linux-4.1.26.orig/arch/microblaze/include/asm/uaccess.h 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/microblaze/include/asm/uaccess.h 2016-06-19 15:30:58.595293802 +0200 @@ -178,7 +178,8 @@ * @x: Variable to store result. * @ptr: Source address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple variable from user space to kernel * space. It supports simple types like char and int, but not larger @@ -290,7 +291,8 @@ * @x: Value to copy to user space. * @ptr: Destination address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple value from kernel space to user * space. It supports simple types like char and int, but not larger diff -Nur linux-4.1.26.orig/arch/microblaze/mm/fault.c linux-4.1.26/arch/microblaze/mm/fault.c --- linux-4.1.26.orig/arch/microblaze/mm/fault.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/microblaze/mm/fault.c 2016-06-19 15:30:58.595293802 +0200 @@ -107,14 +107,14 @@ if ((error_code & 0x13) == 0x13 || (error_code & 0x11) == 0x11) is_write = 0; - if (unlikely(in_atomic() || !mm)) { + if (unlikely(faulthandler_disabled() || !mm)) { if (kernel_mode(regs)) goto bad_area_nosemaphore; - /* in_atomic() in user mode is really bad, + /* faulthandler_disabled() in user mode is really bad, as is current->mm == NULL. */ - pr_emerg("Page fault in user mode with in_atomic(), mm = %p\n", - mm); + pr_emerg("Page fault in user mode with faulthandler_disabled(), mm = %p\n", + mm); pr_emerg("r15 = %lx MSR = %lx\n", regs->r15, regs->msr); die("Weird page fault", regs, SIGSEGV); diff -Nur linux-4.1.26.orig/arch/microblaze/mm/highmem.c linux-4.1.26/arch/microblaze/mm/highmem.c --- linux-4.1.26.orig/arch/microblaze/mm/highmem.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/microblaze/mm/highmem.c 2016-06-19 15:30:58.599293956 +0200 @@ -37,7 +37,7 @@ unsigned long vaddr; int idx, type; - /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ + preempt_disable(); pagefault_disable(); if (!PageHighMem(page)) return page_address(page); @@ -63,6 +63,7 @@ if (vaddr < __fix_to_virt(FIX_KMAP_END)) { pagefault_enable(); + preempt_enable(); return; } @@ -84,5 +85,6 @@ #endif kmap_atomic_idx_pop(); pagefault_enable(); + preempt_enable(); } EXPORT_SYMBOL(__kunmap_atomic); diff -Nur linux-4.1.26.orig/arch/mips/include/asm/uaccess.h linux-4.1.26/arch/mips/include/asm/uaccess.h --- linux-4.1.26.orig/arch/mips/include/asm/uaccess.h 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/mips/include/asm/uaccess.h 2016-06-19 15:30:58.599293956 +0200 @@ -103,7 +103,8 @@ * @addr: User space pointer to start of block to check * @size: Size of block to check * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * Checks if a pointer to a block of memory in user space is valid. * @@ -138,7 +139,8 @@ * @x: Value to copy to user space. * @ptr: Destination address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple value from kernel space to user * space. It supports simple types like char and int, but not larger @@ -157,7 +159,8 @@ * @x: Variable to store result. * @ptr: Source address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple variable from user space to kernel * space. It supports simple types like char and int, but not larger @@ -177,7 +180,8 @@ * @x: Value to copy to user space. * @ptr: Destination address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple value from kernel space to user * space. It supports simple types like char and int, but not larger @@ -199,7 +203,8 @@ * @x: Variable to store result. * @ptr: Source address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple variable from user space to kernel * space. It supports simple types like char and int, but not larger @@ -498,7 +503,8 @@ * @x: Value to copy to user space. * @ptr: Destination address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple value from kernel space to user * space. It supports simple types like char and int, but not larger @@ -517,7 +523,8 @@ * @x: Variable to store result. * @ptr: Source address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple variable from user space to kernel * space. It supports simple types like char and int, but not larger @@ -537,7 +544,8 @@ * @x: Value to copy to user space. * @ptr: Destination address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple value from kernel space to user * space. It supports simple types like char and int, but not larger @@ -559,7 +567,8 @@ * @x: Variable to store result. * @ptr: Source address, in user space. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * This macro copies a single simple variable from user space to kernel * space. It supports simple types like char and int, but not larger @@ -815,7 +824,8 @@ * @from: Source address, in kernel space. * @n: Number of bytes to copy. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * Copy data from kernel space to user space. Caller must check * the specified block with access_ok() before calling this function. @@ -888,7 +898,8 @@ * @from: Source address, in kernel space. * @n: Number of bytes to copy. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * Copy data from kernel space to user space. * @@ -1075,7 +1086,8 @@ * @from: Source address, in user space. * @n: Number of bytes to copy. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * Copy data from user space to kernel space. Caller must check * the specified block with access_ok() before calling this function. @@ -1107,7 +1119,8 @@ * @from: Source address, in user space. * @n: Number of bytes to copy. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * Copy data from user space to kernel space. * @@ -1329,7 +1342,8 @@ * strlen_user: - Get the size of a string in user space. * @str: The string to measure. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * Get the size of a NUL-terminated string in user space. * @@ -1398,7 +1412,8 @@ * strnlen_user: - Get the size of a string in user space. * @str: The string to measure. * - * Context: User context only. This function may sleep. + * Context: User context only. This function may sleep if pagefaults are + * enabled. * * Get the size of a NUL-terminated string in user space. * diff -Nur linux-4.1.26.orig/arch/mips/Kconfig linux-4.1.26/arch/mips/Kconfig --- linux-4.1.26.orig/arch/mips/Kconfig 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/mips/Kconfig 2016-06-19 15:30:58.599293956 +0200 @@ -2367,7 +2367,7 @@ # config HIGHMEM bool "High Memory Support" - depends on 32BIT && CPU_SUPPORTS_HIGHMEM && SYS_SUPPORTS_HIGHMEM && !CPU_MIPS32_3_5_EVA + depends on 32BIT && CPU_SUPPORTS_HIGHMEM && SYS_SUPPORTS_HIGHMEM && !CPU_MIPS32_3_5_EVA && !PREEMPT_RT_FULL config CPU_SUPPORTS_HIGHMEM bool diff -Nur linux-4.1.26.orig/arch/mips/kernel/signal-common.h linux-4.1.26/arch/mips/kernel/signal-common.h --- linux-4.1.26.orig/arch/mips/kernel/signal-common.h 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/mips/kernel/signal-common.h 2016-06-19 15:30:58.599293956 +0200 @@ -28,12 +28,7 @@ extern int fpcsr_pending(unsigned int __user *fpcsr); /* Make sure we will not lose FPU ownership */ -#ifdef CONFIG_PREEMPT -#define lock_fpu_owner() preempt_disable() -#define unlock_fpu_owner() preempt_enable() -#else -#define lock_fpu_owner() pagefault_disable() -#define unlock_fpu_owner() pagefault_enable() -#endif +#define lock_fpu_owner() ({ preempt_disable(); pagefault_disable(); }) +#define unlock_fpu_owner() ({ pagefault_enable(); preempt_enable(); }) #endif /* __SIGNAL_COMMON_H */ diff -Nur linux-4.1.26.orig/arch/mips/mm/fault.c linux-4.1.26/arch/mips/mm/fault.c --- linux-4.1.26.orig/arch/mips/mm/fault.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/mips/mm/fault.c 2016-06-19 15:30:58.599293956 +0200 @@ -21,10 +21,10 @@ #include #include #include +#include #include #include -#include #include #include /* For VMALLOC_END */ #include @@ -94,7 +94,7 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_atomic() || !mm) + if (faulthandler_disabled() || !mm) goto bad_area_nosemaphore; if (user_mode(regs)) diff -Nur linux-4.1.26.orig/arch/mips/mm/highmem.c linux-4.1.26/arch/mips/mm/highmem.c --- linux-4.1.26.orig/arch/mips/mm/highmem.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/mips/mm/highmem.c 2016-06-19 15:30:58.599293956 +0200 @@ -47,7 +47,7 @@ unsigned long vaddr; int idx, type; - /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ + preempt_disable(); pagefault_disable(); if (!PageHighMem(page)) return page_address(page); @@ -72,6 +72,7 @@ if (vaddr < FIXADDR_START) { // FIXME pagefault_enable(); + preempt_enable(); return; } @@ -92,6 +93,7 @@ #endif kmap_atomic_idx_pop(); pagefault_enable(); + preempt_enable(); } EXPORT_SYMBOL(__kunmap_atomic); @@ -104,6 +106,7 @@ unsigned long vaddr; int idx, type; + preempt_disable(); pagefault_disable(); type = kmap_atomic_idx_push(); diff -Nur linux-4.1.26.orig/arch/mips/mm/init.c linux-4.1.26/arch/mips/mm/init.c --- linux-4.1.26.orig/arch/mips/mm/init.c 2016-06-07 01:13:11.000000000 +0200 +++ linux-4.1.26/arch/mips/mm/init.c 2016-06-19 15:30:58.599293956 +0200 @@ -90,6 +90,7 @@ BUG_ON(Page_dcache_dirty(page)); + preempt_disable(); pagefault_disable(); idx = (addr >> PAGE_SHIFT) & (FIX_N_COLOURS - 1); idx += in_interrupt() ? FIX_N_COLOURS : 0; @@ -152,6 +153,7 @@ write_c0_entryhi(old_ctx); local_irq