From 4ca0a2ecda8f72cf4e44b0c5169eb61999220f7a Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Tue, 27 Oct 2015 21:55:12 +0100 Subject: drop rt support for 3.14.x/3.18.x kernels --- target/linux/config/Config.in.kernel | 7 +- target/linux/patches/3.18.22/realtime.patch | 36846 -------------------------- 2 files changed, 2 insertions(+), 36851 deletions(-) delete mode 100644 target/linux/patches/3.18.22/realtime.patch diff --git a/target/linux/config/Config.in.kernel b/target/linux/config/Config.in.kernel index 6516c133c..b53df07bf 100644 --- a/target/linux/config/Config.in.kernel +++ b/target/linux/config/Config.in.kernel @@ -294,13 +294,10 @@ endchoice config ADK_KERNEL_HIGH_RES_TIMERS bool "Enable high resolution timers" - help config ADK_KERNEL_PREEMPT_RT_FULL - bool "Enable Realtime support (external kernel patch)" - depends on ADK_TARGET_KERNEL_VERSION_3_18 \ - || ADK_TARGET_KERNEL_VERSION_3_14 \ - || ADK_TARGET_KERNEL_VERSION_4_1 + bool "Enable Full Realtime support (external kernel patch)" + depends on ADK_TARGET_KERNEL_VERSION_4_1 help https://www.kernel.org/pub/linux/kernel/projects/rt/ diff --git a/target/linux/patches/3.18.22/realtime.patch b/target/linux/patches/3.18.22/realtime.patch deleted file mode 100644 index 28b9b271c..000000000 --- a/target/linux/patches/3.18.22/realtime.patch +++ /dev/null @@ -1,36846 +0,0 @@ -diff -Nur linux-3.18.14.orig/arch/alpha/mm/fault.c linux-3.18.14-rt/arch/alpha/mm/fault.c ---- linux-3.18.14.orig/arch/alpha/mm/fault.c 2015-05-20 10:04:50.000000000 -0500 -+++ linux-3.18.14-rt/arch/alpha/mm/fault.c 2015-05-31 15:32:45.517635394 -0500 -@@ -107,7 +107,7 @@ - - /* If we're in an interrupt context, or have no user context, - we must not take the fault. */ -- if (!mm || in_atomic()) -+ if (!mm || pagefault_disabled()) - goto no_context; - - #ifdef CONFIG_ALPHA_LARGE_VMALLOC -diff -Nur linux-3.18.14.orig/arch/arm/include/asm/cmpxchg.h linux-3.18.14-rt/arch/arm/include/asm/cmpxchg.h ---- linux-3.18.14.orig/arch/arm/include/asm/cmpxchg.h 2015-05-20 10:04:50.000000000 -0500 -+++ linux-3.18.14-rt/arch/arm/include/asm/cmpxchg.h 2015-05-31 15:32:45.557635393 -0500 -@@ -129,6 +129,8 @@ - - #else /* min ARCH >= ARMv6 */ - -+#define __HAVE_ARCH_CMPXCHG 1 -+ - extern void __bad_cmpxchg(volatile void *ptr, int size); - - /* -diff -Nur linux-3.18.14.orig/arch/arm/include/asm/futex.h linux-3.18.14-rt/arch/arm/include/asm/futex.h ---- linux-3.18.14.orig/arch/arm/include/asm/futex.h 2015-05-20 10:04:50.000000000 -0500 -+++ linux-3.18.14-rt/arch/arm/include/asm/futex.h 2015-05-31 15:32:45.561635393 -0500 -@@ -93,6 +93,8 @@ - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) - return -EFAULT; - -+ preempt_disable_rt(); -+ - __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n" - "1: " TUSER(ldr) " %1, [%4]\n" - " teq %1, %2\n" -@@ -104,6 +106,8 @@ - : "cc", "memory"); - - *uval = val; -+ -+ preempt_enable_rt(); - return ret; - } - -diff -Nur linux-3.18.14.orig/arch/arm/include/asm/switch_to.h linux-3.18.14-rt/arch/arm/include/asm/switch_to.h ---- linux-3.18.14.orig/arch/arm/include/asm/switch_to.h 2015-05-20 10:04:50.000000000 -0500 -+++ linux-3.18.14-rt/arch/arm/include/asm/switch_to.h 2015-05-31 15:32:45.565635393 -0500 -@@ -3,6 +3,13 @@ - - #include - -+#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-3.18.14.orig/arch/arm/include/asm/thread_info.h linux-3.18.14-rt/arch/arm/include/asm/thread_info.h ---- linux-3.18.14.orig/arch/arm/include/asm/thread_info.h 2015-05-20 10:04:50.000000000 -0500 -+++ linux-3.18.14-rt/arch/arm/include/asm/thread_info.h 2015-05-31 15:32:45.585635393 -0500 -@@ -51,6 +51,7 @@ - struct thread_info { - unsigned long flags; /* low level flags */ - 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 */ - struct exec_domain *exec_domain; /* execution domain */ -@@ -149,6 +150,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 -@@ -162,6 +164,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-3.18.14.orig/arch/arm/Kconfig linux-3.18.14-rt/arch/arm/Kconfig ---- linux-3.18.14.orig/arch/arm/Kconfig 2015-05-20 10:04:50.000000000 -0500 -+++ linux-3.18.14-rt/arch/arm/Kconfig 2015-05-31 15:32:45.529635394 -0500 -@@ -62,6 +62,7 @@ - select HAVE_PERF_EVENTS - select HAVE_PERF_REGS - 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-3.18.14.orig/arch/arm/kernel/asm-offsets.c linux-3.18.14-rt/arch/arm/kernel/asm-offsets.c ---- linux-3.18.14.orig/arch/arm/kernel/asm-offsets.c 2015-05-20 10:04:50.000000000 -0500 -+++ linux-3.18.14-rt/arch/arm/kernel/asm-offsets.c 2015-05-31 15:32:45.605635393 -0500 -@@ -64,6 +64,7 @@ - BLANK(); - DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); - DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); -+ DEFINE(TI_PREEMPT_LAZY, offsetof(struct thread_info, preempt_lazy_count)); - DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); - DEFINE(TI_TASK, offsetof(struct thread_info, task)); - DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain)); -diff -Nur linux-3.18.14.orig/arch/arm/kernel/entry-armv.S linux-3.18.14-rt/arch/arm/kernel/entry-armv.S ---- linux-3.18.14.orig/arch/arm/kernel/entry-armv.S 2015-05-20 10:04:50.000000000 -0500 -+++ linux-3.18.14-rt/arch/arm/kernel/entry-armv.S 2015-05-31 15:32:45.613635393 -0500 -@@ -207,11 +207,18 @@ - #ifdef CONFIG_PREEMPT - get_thread_info tsk - 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 -@@ -226,6 +233,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-3.18.14.orig/arch/arm/kernel/process.c linux-3.18.14-rt/arch/arm/kernel/process.c ---- linux-3.18.14.orig/arch/arm/kernel/process.c 2015-05-20 10:04:50.000000000 -0500 -+++ linux-3.18.14-rt/arch/arm/kernel/process.c 2015-05-31 15:32:45.617635393 -0500 -@@ -437,6 +437,30 @@ - } - - #ifdef CONFIG_MMU -+/* -+ * 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-3.18.14.orig/arch/arm/kernel/process.c.orig linux-3.18.14-rt/arch/arm/kernel/process.c.orig ---- linux-3.18.14.orig/arch/arm/kernel/process.c.orig 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.14-rt/arch/arm/kernel/process.c.orig 2015-05-20 10:04:50.000000000 -0500 -@@ -0,0 +1,560 @@ -+/* -+ * linux/arch/arm/kernel/process.c -+ * -+ * Copyright (C) 1996-2000 Russell King - Converted to ARM. -+ * Original Copyright (C) 1995 Linus Torvalds -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "reboot.h" -+ -+#ifdef CONFIG_CC_STACKPROTECTOR -+#include -+unsigned long __stack_chk_guard __read_mostly; -+EXPORT_SYMBOL(__stack_chk_guard); -+#endif -+ -+static const char *processor_modes[] __maybe_unused = { -+ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , -+ "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", -+ "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" , -+ "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" -+}; -+ -+static const char *isa_modes[] __maybe_unused = { -+ "ARM" , "Thumb" , "Jazelle", "ThumbEE" -+}; -+ -+extern void call_with_stack(void (*fn)(void *), void *arg, void *sp); -+typedef void (*phys_reset_t)(unsigned long); -+ -+/* -+ * A temporary stack to use for CPU reset. This is static so that we -+ * don't clobber it with the identity mapping. When running with this -+ * stack, any references to the current task *will not work* so you -+ * should really do as little as possible before jumping to your reset -+ * code. -+ */ -+static u64 soft_restart_stack[16]; -+ -+static void __soft_restart(void *addr) -+{ -+ phys_reset_t phys_reset; -+ -+ /* Take out a flat memory mapping. */ -+ setup_mm_for_reboot(); -+ -+ /* Clean and invalidate caches */ -+ flush_cache_all(); -+ -+ /* Turn off caching */ -+ cpu_proc_fin(); -+ -+ /* Push out any further dirty data, and ensure cache is empty */ -+ flush_cache_all(); -+ -+ /* Switch to the identity mapping. */ -+ phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset); -+ phys_reset((unsigned long)addr); -+ -+ /* Should never get here. */ -+ BUG(); -+} -+ -+void _soft_restart(unsigned long addr, bool disable_l2) -+{ -+ u64 *stack = soft_restart_stack + ARRAY_SIZE(soft_restart_stack); -+ -+ /* Disable interrupts first */ -+ raw_local_irq_disable(); -+ local_fiq_disable(); -+ -+ /* Disable the L2 if we're the last man standing. */ -+ if (disable_l2) -+ outer_disable(); -+ -+ /* Change to the new stack and continue with the reset. */ -+ call_with_stack(__soft_restart, (void *)addr, (void *)stack); -+ -+ /* Should never get here. */ -+ BUG(); -+} -+ -+void soft_restart(unsigned long addr) -+{ -+ _soft_restart(addr, num_online_cpus() == 1); -+} -+ -+/* -+ * Function pointers to optional machine specific functions -+ */ -+void (*pm_power_off)(void); -+EXPORT_SYMBOL(pm_power_off); -+ -+void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd); -+ -+/* -+ * This is our default idle handler. -+ */ -+ -+void (*arm_pm_idle)(void); -+ -+/* -+ * Called from the core idle loop. -+ */ -+ -+void arch_cpu_idle(void) -+{ -+ if (arm_pm_idle) -+ arm_pm_idle(); -+ else -+ cpu_do_idle(); -+ local_irq_enable(); -+} -+ -+void arch_cpu_idle_prepare(void) -+{ -+ local_fiq_enable(); -+} -+ -+void arch_cpu_idle_enter(void) -+{ -+ ledtrig_cpu(CPU_LED_IDLE_START); -+#ifdef CONFIG_PL310_ERRATA_769419 -+ wmb(); -+#endif -+} -+ -+void arch_cpu_idle_exit(void) -+{ -+ ledtrig_cpu(CPU_LED_IDLE_END); -+} -+ -+#ifdef CONFIG_HOTPLUG_CPU -+void arch_cpu_idle_dead(void) -+{ -+ cpu_die(); -+} -+#endif -+ -+/* -+ * Called by kexec, immediately prior to machine_kexec(). -+ * -+ * This must completely disable all secondary CPUs; simply causing those CPUs -+ * to execute e.g. a RAM-based pin loop is not sufficient. This allows the -+ * kexec'd kernel to use any and all RAM as it sees fit, without having to -+ * avoid any code or data used by any SW CPU pin loop. The CPU hotplug -+ * functionality embodied in disable_nonboot_cpus() to achieve this. -+ */ -+void machine_shutdown(void) -+{ -+ disable_nonboot_cpus(); -+} -+ -+/* -+ * Halting simply requires that the secondary CPUs stop performing any -+ * activity (executing tasks, handling interrupts). smp_send_stop() -+ * achieves this. -+ */ -+void machine_halt(void) -+{ -+ local_irq_disable(); -+ smp_send_stop(); -+ -+ local_irq_disable(); -+ while (1); -+} -+ -+/* -+ * Power-off simply requires that the secondary CPUs stop performing any -+ * activity (executing tasks, handling interrupts). smp_send_stop() -+ * achieves this. When the system power is turned off, it will take all CPUs -+ * with it. -+ */ -+void machine_power_off(void) -+{ -+ local_irq_disable(); -+ smp_send_stop(); -+ -+ if (pm_power_off) -+ pm_power_off(); -+} -+ -+/* -+ * Restart requires that the secondary CPUs stop performing any activity -+ * while the primary CPU resets the system. Systems with a single CPU can -+ * use soft_restart() as their machine descriptor's .restart hook, since that -+ * will cause the only available CPU to reset. Systems with multiple CPUs must -+ * provide a HW restart implementation, to ensure that all CPUs reset at once. -+ * This is required so that any code running after reset on the primary CPU -+ * doesn't have to co-ordinate with other CPUs to ensure they aren't still -+ * executing pre-reset code, and using RAM that the primary CPU's code wishes -+ * to use. Implementing such co-ordination would be essentially impossible. -+ */ -+void machine_restart(char *cmd) -+{ -+ local_irq_disable(); -+ smp_send_stop(); -+ -+ if (arm_pm_restart) -+ arm_pm_restart(reboot_mode, cmd); -+ else -+ do_kernel_restart(cmd); -+ -+ /* Give a grace period for failure to restart of 1s */ -+ mdelay(1000); -+ -+ /* Whoops - the platform was unable to reboot. Tell the user! */ -+ printk("Reboot failed -- System halted\n"); -+ local_irq_disable(); -+ while (1); -+} -+ -+void __show_regs(struct pt_regs *regs) -+{ -+ unsigned long flags; -+ char buf[64]; -+ -+ show_regs_print_info(KERN_DEFAULT); -+ -+ print_symbol("PC is at %s\n", instruction_pointer(regs)); -+ print_symbol("LR is at %s\n", regs->ARM_lr); -+ printk("pc : [<%08lx>] lr : [<%08lx>] psr: %08lx\n" -+ "sp : %08lx ip : %08lx fp : %08lx\n", -+ regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr, -+ regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); -+ printk("r10: %08lx r9 : %08lx r8 : %08lx\n", -+ regs->ARM_r10, regs->ARM_r9, -+ regs->ARM_r8); -+ printk("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", -+ regs->ARM_r7, regs->ARM_r6, -+ regs->ARM_r5, regs->ARM_r4); -+ printk("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", -+ regs->ARM_r3, regs->ARM_r2, -+ regs->ARM_r1, regs->ARM_r0); -+ -+ flags = regs->ARM_cpsr; -+ buf[0] = flags & PSR_N_BIT ? 'N' : 'n'; -+ buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z'; -+ buf[2] = flags & PSR_C_BIT ? 'C' : 'c'; -+ buf[3] = flags & PSR_V_BIT ? 'V' : 'v'; -+ buf[4] = '\0'; -+ -+#ifndef CONFIG_CPU_V7M -+ printk("Flags: %s IRQs o%s FIQs o%s Mode %s ISA %s Segment %s\n", -+ buf, interrupts_enabled(regs) ? "n" : "ff", -+ fast_interrupts_enabled(regs) ? "n" : "ff", -+ processor_modes[processor_mode(regs)], -+ isa_modes[isa_mode(regs)], -+ get_fs() == get_ds() ? "kernel" : "user"); -+#else -+ printk("xPSR: %08lx\n", regs->ARM_cpsr); -+#endif -+ -+#ifdef CONFIG_CPU_CP15 -+ { -+ unsigned int ctrl; -+ -+ buf[0] = '\0'; -+#ifdef CONFIG_CPU_CP15_MMU -+ { -+ unsigned int transbase, dac; -+ asm("mrc p15, 0, %0, c2, c0\n\t" -+ "mrc p15, 0, %1, c3, c0\n" -+ : "=r" (transbase), "=r" (dac)); -+ snprintf(buf, sizeof(buf), " Table: %08x DAC: %08x", -+ transbase, dac); -+ } -+#endif -+ asm("mrc p15, 0, %0, c1, c0\n" : "=r" (ctrl)); -+ -+ printk("Control: %08x%s\n", ctrl, buf); -+ } -+#endif -+} -+ -+void show_regs(struct pt_regs * regs) -+{ -+ __show_regs(regs); -+ dump_stack(); -+} -+ -+ATOMIC_NOTIFIER_HEAD(thread_notify_head); -+ -+EXPORT_SYMBOL_GPL(thread_notify_head); -+ -+/* -+ * Free current thread data structures etc.. -+ */ -+void exit_thread(void) -+{ -+ thread_notify(THREAD_NOTIFY_EXIT, current_thread_info()); -+} -+ -+void flush_thread(void) -+{ -+ struct thread_info *thread = current_thread_info(); -+ struct task_struct *tsk = current; -+ -+ flush_ptrace_hw_breakpoint(tsk); -+ -+ memset(thread->used_cp, 0, sizeof(thread->used_cp)); -+ memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); -+ memset(&thread->fpstate, 0, sizeof(union fp_state)); -+ -+ flush_tls(); -+ -+ thread_notify(THREAD_NOTIFY_FLUSH, thread); -+} -+ -+void release_thread(struct task_struct *dead_task) -+{ -+} -+ -+asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); -+ -+int -+copy_thread(unsigned long clone_flags, unsigned long stack_start, -+ unsigned long stk_sz, struct task_struct *p) -+{ -+ struct thread_info *thread = task_thread_info(p); -+ struct pt_regs *childregs = task_pt_regs(p); -+ -+ memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); -+ -+ if (likely(!(p->flags & PF_KTHREAD))) { -+ *childregs = *current_pt_regs(); -+ childregs->ARM_r0 = 0; -+ if (stack_start) -+ childregs->ARM_sp = stack_start; -+ } else { -+ memset(childregs, 0, sizeof(struct pt_regs)); -+ thread->cpu_context.r4 = stk_sz; -+ thread->cpu_context.r5 = stack_start; -+ childregs->ARM_cpsr = SVC_MODE; -+ } -+ thread->cpu_context.pc = (unsigned long)ret_from_fork; -+ thread->cpu_context.sp = (unsigned long)childregs; -+ -+ clear_ptrace_hw_breakpoint(p); -+ -+ if (clone_flags & CLONE_SETTLS) -+ thread->tp_value[0] = childregs->ARM_r3; -+ thread->tp_value[1] = get_tpuser(); -+ -+ thread_notify(THREAD_NOTIFY_COPY, thread); -+ -+ return 0; -+} -+ -+/* -+ * Fill in the task's elfregs structure for a core dump. -+ */ -+int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs) -+{ -+ elf_core_copy_regs(elfregs, task_pt_regs(t)); -+ return 1; -+} -+ -+/* -+ * fill in the fpe structure for a core dump... -+ */ -+int dump_fpu (struct pt_regs *regs, struct user_fp *fp) -+{ -+ struct thread_info *thread = current_thread_info(); -+ int used_math = thread->used_cp[1] | thread->used_cp[2]; -+ -+ if (used_math) -+ memcpy(fp, &thread->fpstate.soft, sizeof (*fp)); -+ -+ return used_math != 0; -+} -+EXPORT_SYMBOL(dump_fpu); -+ -+unsigned long get_wchan(struct task_struct *p) -+{ -+ struct stackframe frame; -+ unsigned long stack_page; -+ int count = 0; -+ if (!p || p == current || p->state == TASK_RUNNING) -+ return 0; -+ -+ frame.fp = thread_saved_fp(p); -+ frame.sp = thread_saved_sp(p); -+ frame.lr = 0; /* recovered from the stack */ -+ frame.pc = thread_saved_pc(p); -+ stack_page = (unsigned long)task_stack_page(p); -+ do { -+ if (frame.sp < stack_page || -+ frame.sp >= stack_page + THREAD_SIZE || -+ unwind_frame(&frame) < 0) -+ return 0; -+ if (!in_sched_functions(frame.pc)) -+ return frame.pc; -+ } while (count ++ < 16); -+ return 0; -+} -+ -+unsigned long arch_randomize_brk(struct mm_struct *mm) -+{ -+ unsigned long range_end = mm->brk + 0x02000000; -+ return randomize_range(mm->brk, range_end, 0) ? : mm->brk; -+} -+ -+#ifdef CONFIG_MMU -+#ifdef CONFIG_KUSER_HELPERS -+/* -+ * The vectors page is always readable from user space for the -+ * atomic helpers. Insert it into the gate_vma so that it is visible -+ * through ptrace and /proc//mem. -+ */ -+static struct vm_area_struct gate_vma = { -+ .vm_start = 0xffff0000, -+ .vm_end = 0xffff0000 + PAGE_SIZE, -+ .vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC, -+}; -+ -+static int __init gate_vma_init(void) -+{ -+ gate_vma.vm_page_prot = PAGE_READONLY_EXEC; -+ return 0; -+} -+arch_initcall(gate_vma_init); -+ -+struct vm_area_struct *get_gate_vma(struct mm_struct *mm) -+{ -+ return &gate_vma; -+} -+ -+int in_gate_area(struct mm_struct *mm, unsigned long addr) -+{ -+ return (addr >= gate_vma.vm_start) && (addr < gate_vma.vm_end); -+} -+ -+int in_gate_area_no_mm(unsigned long addr) -+{ -+ return in_gate_area(NULL, addr); -+} -+#define is_gate_vma(vma) ((vma) == &gate_vma) -+#else -+#define is_gate_vma(vma) 0 -+#endif -+ -+const char *arch_vma_name(struct vm_area_struct *vma) -+{ -+ return is_gate_vma(vma) ? "[vectors]" : NULL; -+} -+ -+/* If possible, provide a placement hint at a random offset from the -+ * stack for the signal page. -+ */ -+static unsigned long sigpage_addr(const struct mm_struct *mm, -+ unsigned int npages) -+{ -+ unsigned long offset; -+ unsigned long first; -+ unsigned long last; -+ unsigned long addr; -+ unsigned int slots; -+ -+ first = PAGE_ALIGN(mm->start_stack); -+ -+ last = TASK_SIZE - (npages << PAGE_SHIFT); -+ -+ /* No room after stack? */ -+ if (first > last) -+ return 0; -+ -+ /* Just enough room? */ -+ if (first == last) -+ return first; -+ -+ slots = ((last - first) >> PAGE_SHIFT) + 1; -+ -+ offset = get_random_int() % slots; -+ -+ addr = first + (offset << PAGE_SHIFT); -+ -+ return addr; -+} -+ -+static struct page *signal_page; -+extern struct page *get_signal_page(void); -+ -+static const struct vm_special_mapping sigpage_mapping = { -+ .name = "[sigpage]", -+ .pages = &signal_page, -+}; -+ -+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) -+{ -+ struct mm_struct *mm = current->mm; -+ struct vm_area_struct *vma; -+ unsigned long addr; -+ unsigned long hint; -+ int ret = 0; -+ -+ if (!signal_page) -+ signal_page = get_signal_page(); -+ if (!signal_page) -+ return -ENOMEM; -+ -+ down_write(&mm->mmap_sem); -+ hint = sigpage_addr(mm, 1); -+ addr = get_unmapped_area(NULL, hint, PAGE_SIZE, 0, 0); -+ if (IS_ERR_VALUE(addr)) { -+ ret = addr; -+ goto up_fail; -+ } -+ -+ vma = _install_special_mapping(mm, addr, PAGE_SIZE, -+ VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, -+ &sigpage_mapping); -+ -+ if (IS_ERR(vma)) { -+ ret = PTR_ERR(vma); -+ goto up_fail; -+ } -+ -+ mm->context.sigpage = addr; -+ -+ up_fail: -+ up_write(&mm->mmap_sem); -+ return ret; -+} -+#endif -diff -Nur linux-3.18.14.orig/arch/arm/kernel/signal.c linux-3.18.14-rt/arch/arm/kernel/signal.c ---- linux-3.18.14.orig/arch/arm/kernel/signal.c 2015-05-20 10:04:50.000000000 -0500 -+++ linux-3.18.14-rt/arch/arm/kernel/signal.c 2015-05-31 15:32:45.617635393 -0500 -@@ -574,7 +574,8 @@ - do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall) - { - 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-3.18.14.orig/arch/arm/kernel/unwind.c linux-3.18.14-rt/arch/arm/kernel/unwind.c ---- linux-3.18.14.orig/arch/arm/kernel/unwind.c 2015-05-20 10:04:50.000000000 -0500 -+++ linux-3.18.14-rt/arch/arm/kernel/unwind.c 2015-05-31 15:32:45.653635392 -0500 -@@ -93,7 +93,7 @@ - static const struct unwind_idx *__origin_unwind_idx; - extern const struct unwind_idx __stop_unwind_idx[]; - --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); -@@ -530,9 +530,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; - } -@@ -544,9 +544,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-3.18.14.orig/arch/arm/kvm/arm.c linux-3.18.14-rt/arch/arm/kvm/arm.c ---- linux-3.18.14.orig/arch/arm/kvm/arm.c 2015-05-20 10:04:50.000000000 -0500 -+++ linux-3.18.14-rt/arch/arm/kvm/arm.c 2015-05-31 15:32:45.669635392 -0500 -@@ -455,9 +455,9 @@ - - static void vcpu_pause(struct kvm_vcpu *vcpu) - { -- 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-3.18.14.orig/arch/arm/kvm/arm.c.orig linux-3.18.14-rt/arch/arm/kvm/arm.c.orig ---- linux-3.18.14.orig/arch/arm/kvm/arm.c.orig 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.14-rt/arch/arm/kvm/arm.c.orig 2015-05-20 10:04:50.000000000 -0500 -@@ -0,0 +1,1060 @@ -+/* -+ * Copyright (C) 2012 - Virtual Open Systems and Columbia University -+ * Author: Christoffer Dall -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define CREATE_TRACE_POINTS -+#include "trace.h" -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef REQUIRES_VIRT -+__asm__(".arch_extension virt"); -+#endif -+ -+static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page); -+static kvm_cpu_context_t __percpu *kvm_host_cpu_state; -+static unsigned long hyp_default_vectors; -+ -+/* Per-CPU variable containing the currently running vcpu. */ -+static DEFINE_PER_CPU(struct kvm_vcpu *, kvm_arm_running_vcpu); -+ -+/* The VMID used in the VTTBR */ -+static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1); -+static u8 kvm_next_vmid; -+static DEFINE_SPINLOCK(kvm_vmid_lock); -+ -+static bool vgic_present; -+ -+static void kvm_arm_set_running_vcpu(struct kvm_vcpu *vcpu) -+{ -+ BUG_ON(preemptible()); -+ __this_cpu_write(kvm_arm_running_vcpu, vcpu); -+} -+ -+/** -+ * kvm_arm_get_running_vcpu - get the vcpu running on the current CPU. -+ * Must be called from non-preemptible context -+ */ -+struct kvm_vcpu *kvm_arm_get_running_vcpu(void) -+{ -+ BUG_ON(preemptible()); -+ return __this_cpu_read(kvm_arm_running_vcpu); -+} -+ -+/** -+ * kvm_arm_get_running_vcpus - get the per-CPU array of currently running vcpus. -+ */ -+struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void) -+{ -+ return &kvm_arm_running_vcpu; -+} -+ -+int kvm_arch_hardware_enable(void) -+{ -+ return 0; -+} -+ -+int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) -+{ -+ return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE; -+} -+ -+int kvm_arch_hardware_setup(void) -+{ -+ return 0; -+} -+ -+void kvm_arch_check_processor_compat(void *rtn) -+{ -+ *(int *)rtn = 0; -+} -+ -+ -+/** -+ * kvm_arch_init_vm - initializes a VM data structure -+ * @kvm: pointer to the KVM struct -+ */ -+int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) -+{ -+ int ret = 0; -+ -+ if (type) -+ return -EINVAL; -+ -+ ret = kvm_alloc_stage2_pgd(kvm); -+ if (ret) -+ goto out_fail_alloc; -+ -+ ret = create_hyp_mappings(kvm, kvm + 1); -+ if (ret) -+ goto out_free_stage2_pgd; -+ -+ kvm_timer_init(kvm); -+ -+ /* Mark the initial VMID generation invalid */ -+ kvm->arch.vmid_gen = 0; -+ -+ return ret; -+out_free_stage2_pgd: -+ kvm_free_stage2_pgd(kvm); -+out_fail_alloc: -+ return ret; -+} -+ -+int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf) -+{ -+ return VM_FAULT_SIGBUS; -+} -+ -+ -+/** -+ * kvm_arch_destroy_vm - destroy the VM data structure -+ * @kvm: pointer to the KVM struct -+ */ -+void kvm_arch_destroy_vm(struct kvm *kvm) -+{ -+ int i; -+ -+ kvm_free_stage2_pgd(kvm); -+ -+ for (i = 0; i < KVM_MAX_VCPUS; ++i) { -+ if (kvm->vcpus[i]) { -+ kvm_arch_vcpu_free(kvm->vcpus[i]); -+ kvm->vcpus[i] = NULL; -+ } -+ } -+ -+ kvm_vgic_destroy(kvm); -+} -+ -+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) -+{ -+ int r; -+ switch (ext) { -+ case KVM_CAP_IRQCHIP: -+ r = vgic_present; -+ break; -+ case KVM_CAP_DEVICE_CTRL: -+ case KVM_CAP_USER_MEMORY: -+ case KVM_CAP_SYNC_MMU: -+ case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: -+ case KVM_CAP_ONE_REG: -+ case KVM_CAP_ARM_PSCI: -+ case KVM_CAP_ARM_PSCI_0_2: -+ case KVM_CAP_READONLY_MEM: -+ r = 1; -+ break; -+ case KVM_CAP_COALESCED_MMIO: -+ r = KVM_COALESCED_MMIO_PAGE_OFFSET; -+ break; -+ case KVM_CAP_ARM_SET_DEVICE_ADDR: -+ r = 1; -+ break; -+ case KVM_CAP_NR_VCPUS: -+ r = num_online_cpus(); -+ break; -+ case KVM_CAP_MAX_VCPUS: -+ r = KVM_MAX_VCPUS; -+ break; -+ default: -+ r = kvm_arch_dev_ioctl_check_extension(ext); -+ break; -+ } -+ return r; -+} -+ -+long kvm_arch_dev_ioctl(struct file *filp, -+ unsigned int ioctl, unsigned long arg) -+{ -+ return -EINVAL; -+} -+ -+ -+struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) -+{ -+ int err; -+ struct kvm_vcpu *vcpu; -+ -+ if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) { -+ err = -EBUSY; -+ goto out; -+ } -+ -+ vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); -+ if (!vcpu) { -+ err = -ENOMEM; -+ goto out; -+ } -+ -+ err = kvm_vcpu_init(vcpu, kvm, id); -+ if (err) -+ goto free_vcpu; -+ -+ err = create_hyp_mappings(vcpu, vcpu + 1); -+ if (err) -+ goto vcpu_uninit; -+ -+ return vcpu; -+vcpu_uninit: -+ kvm_vcpu_uninit(vcpu); -+free_vcpu: -+ kmem_cache_free(kvm_vcpu_cache, vcpu); -+out: -+ return ERR_PTR(err); -+} -+ -+int kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) -+{ -+ return 0; -+} -+ -+void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) -+{ -+ kvm_mmu_free_memory_caches(vcpu); -+ kvm_timer_vcpu_terminate(vcpu); -+ kvm_vgic_vcpu_destroy(vcpu); -+ kmem_cache_free(kvm_vcpu_cache, vcpu); -+} -+ -+void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) -+{ -+ kvm_arch_vcpu_free(vcpu); -+} -+ -+int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) -+{ -+ return 0; -+} -+ -+int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) -+{ -+ /* Force users to call KVM_ARM_VCPU_INIT */ -+ vcpu->arch.target = -1; -+ -+ /* Set up the timer */ -+ kvm_timer_vcpu_init(vcpu); -+ -+ return 0; -+} -+ -+void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) -+{ -+ vcpu->cpu = cpu; -+ vcpu->arch.host_cpu_context = this_cpu_ptr(kvm_host_cpu_state); -+ -+ /* -+ * Check whether this vcpu requires the cache to be flushed on -+ * this physical CPU. This is a consequence of doing dcache -+ * operations by set/way on this vcpu. We do it here to be in -+ * a non-preemptible section. -+ */ -+ if (cpumask_test_and_clear_cpu(cpu, &vcpu->arch.require_dcache_flush)) -+ flush_cache_all(); /* We'd really want v7_flush_dcache_all() */ -+ -+ kvm_arm_set_running_vcpu(vcpu); -+} -+ -+void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) -+{ -+ /* -+ * The arch-generic KVM code expects the cpu field of a vcpu to be -1 -+ * if the vcpu is no longer assigned to a cpu. This is used for the -+ * optimized make_all_cpus_request path. -+ */ -+ vcpu->cpu = -1; -+ -+ kvm_arm_set_running_vcpu(NULL); -+} -+ -+int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, -+ struct kvm_guest_debug *dbg) -+{ -+ return -EINVAL; -+} -+ -+ -+int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, -+ struct kvm_mp_state *mp_state) -+{ -+ return -EINVAL; -+} -+ -+int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, -+ struct kvm_mp_state *mp_state) -+{ -+ return -EINVAL; -+} -+ -+/** -+ * kvm_arch_vcpu_runnable - determine if the vcpu can be scheduled -+ * @v: The VCPU pointer -+ * -+ * If the guest CPU is not waiting for interrupts or an interrupt line is -+ * asserted, the CPU is by definition runnable. -+ */ -+int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) -+{ -+ return !!v->arch.irq_lines || kvm_vgic_vcpu_pending_irq(v); -+} -+ -+/* Just ensure a guest exit from a particular CPU */ -+static void exit_vm_noop(void *info) -+{ -+} -+ -+void force_vm_exit(const cpumask_t *mask) -+{ -+ smp_call_function_many(mask, exit_vm_noop, NULL, true); -+} -+ -+/** -+ * need_new_vmid_gen - check that the VMID is still valid -+ * @kvm: The VM's VMID to checkt -+ * -+ * return true if there is a new generation of VMIDs being used -+ * -+ * The hardware supports only 256 values with the value zero reserved for the -+ * host, so we check if an assigned value belongs to a previous generation, -+ * which which requires us to assign a new value. If we're the first to use a -+ * VMID for the new generation, we must flush necessary caches and TLBs on all -+ * CPUs. -+ */ -+static bool need_new_vmid_gen(struct kvm *kvm) -+{ -+ return unlikely(kvm->arch.vmid_gen != atomic64_read(&kvm_vmid_gen)); -+} -+ -+/** -+ * update_vttbr - Update the VTTBR with a valid VMID before the guest runs -+ * @kvm The guest that we are about to run -+ * -+ * Called from kvm_arch_vcpu_ioctl_run before entering the guest to ensure the -+ * VM has a valid VMID, otherwise assigns a new one and flushes corresponding -+ * caches and TLBs. -+ */ -+static void update_vttbr(struct kvm *kvm) -+{ -+ phys_addr_t pgd_phys; -+ u64 vmid; -+ -+ if (!need_new_vmid_gen(kvm)) -+ return; -+ -+ spin_lock(&kvm_vmid_lock); -+ -+ /* -+ * We need to re-check the vmid_gen here to ensure that if another vcpu -+ * already allocated a valid vmid for this vm, then this vcpu should -+ * use the same vmid. -+ */ -+ if (!need_new_vmid_gen(kvm)) { -+ spin_unlock(&kvm_vmid_lock); -+ return; -+ } -+ -+ /* First user of a new VMID generation? */ -+ if (unlikely(kvm_next_vmid == 0)) { -+ atomic64_inc(&kvm_vmid_gen); -+ kvm_next_vmid = 1; -+ -+ /* -+ * On SMP we know no other CPUs can use this CPU's or each -+ * other's VMID after force_vm_exit returns since the -+ * kvm_vmid_lock blocks them from reentry to the guest. -+ */ -+ force_vm_exit(cpu_all_mask); -+ /* -+ * Now broadcast TLB + ICACHE invalidation over the inner -+ * shareable domain to make sure all data structures are -+ * clean. -+ */ -+ kvm_call_hyp(__kvm_flush_vm_context); -+ } -+ -+ kvm->arch.vmid_gen = atomic64_read(&kvm_vmid_gen); -+ kvm->arch.vmid = kvm_next_vmid; -+ kvm_next_vmid++; -+ -+ /* update vttbr to be used with the new vmid */ -+ pgd_phys = virt_to_phys(kvm_get_hwpgd(kvm)); -+ BUG_ON(pgd_phys & ~VTTBR_BADDR_MASK); -+ vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK; -+ kvm->arch.vttbr = pgd_phys | vmid; -+ -+ spin_unlock(&kvm_vmid_lock); -+} -+ -+static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) -+{ -+ struct kvm *kvm = vcpu->kvm; -+ int ret; -+ -+ if (likely(vcpu->arch.has_run_once)) -+ return 0; -+ -+ vcpu->arch.has_run_once = true; -+ -+ /* -+ * Map the VGIC hardware resources before running a vcpu the first -+ * time on this VM. -+ */ -+ if (unlikely(!vgic_initialized(kvm))) { -+ ret = kvm_vgic_map_resources(kvm); -+ if (ret) -+ return ret; -+ } -+ -+ /* -+ * Enable the arch timers only if we have an in-kernel VGIC -+ * and it has been properly initialized, since we cannot handle -+ * interrupts from the virtual timer with a userspace gic. -+ */ -+ if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) -+ kvm_timer_enable(kvm); -+ -+ return 0; -+} -+ -+static void vcpu_pause(struct kvm_vcpu *vcpu) -+{ -+ wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu); -+ -+ wait_event_interruptible(*wq, !vcpu->arch.pause); -+} -+ -+static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu) -+{ -+ return vcpu->arch.target >= 0; -+} -+ -+/** -+ * kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code -+ * @vcpu: The VCPU pointer -+ * @run: The kvm_run structure pointer used for userspace state exchange -+ * -+ * This function is called through the VCPU_RUN ioctl called from user space. It -+ * will execute VM code in a loop until the time slice for the process is used -+ * or some emulation is needed from user space in which case the function will -+ * return with return value 0 and with the kvm_run structure filled in with the -+ * required data for the requested emulation. -+ */ -+int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) -+{ -+ int ret; -+ sigset_t sigsaved; -+ -+ if (unlikely(!kvm_vcpu_initialized(vcpu))) -+ return -ENOEXEC; -+ -+ ret = kvm_vcpu_first_run_init(vcpu); -+ if (ret) -+ return ret; -+ -+ if (run->exit_reason == KVM_EXIT_MMIO) { -+ ret = kvm_handle_mmio_return(vcpu, vcpu->run); -+ if (ret) -+ return ret; -+ } -+ -+ if (vcpu->sigset_active) -+ sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); -+ -+ ret = 1; -+ run->exit_reason = KVM_EXIT_UNKNOWN; -+ while (ret > 0) { -+ /* -+ * Check conditions before entering the guest -+ */ -+ cond_resched(); -+ -+ update_vttbr(vcpu->kvm); -+ -+ if (vcpu->arch.pause) -+ vcpu_pause(vcpu); -+ -+ kvm_vgic_flush_hwstate(vcpu); -+ kvm_timer_flush_hwstate(vcpu); -+ -+ local_irq_disable(); -+ -+ /* -+ * Re-check atomic conditions -+ */ -+ if (signal_pending(current)) { -+ ret = -EINTR; -+ run->exit_reason = KVM_EXIT_INTR; -+ } -+ -+ if (ret <= 0 || need_new_vmid_gen(vcpu->kvm)) { -+ local_irq_enable(); -+ kvm_timer_sync_hwstate(vcpu); -+ kvm_vgic_sync_hwstate(vcpu); -+ continue; -+ } -+ -+ /************************************************************** -+ * Enter the guest -+ */ -+ trace_kvm_entry(*vcpu_pc(vcpu)); -+ kvm_guest_enter(); -+ vcpu->mode = IN_GUEST_MODE; -+ -+ ret = kvm_call_hyp(__kvm_vcpu_run, vcpu); -+ -+ vcpu->mode = OUTSIDE_GUEST_MODE; -+ vcpu->arch.last_pcpu = smp_processor_id(); -+ kvm_guest_exit(); -+ trace_kvm_exit(*vcpu_pc(vcpu)); -+ /* -+ * We may have taken a host interrupt in HYP mode (ie -+ * while executing the guest). This interrupt is still -+ * pending, as we haven't serviced it yet! -+ * -+ * We're now back in SVC mode, with interrupts -+ * disabled. Enabling the interrupts now will have -+ * the effect of taking the interrupt again, in SVC -+ * mode this time. -+ */ -+ local_irq_enable(); -+ -+ /* -+ * Back from guest -+ *************************************************************/ -+ -+ kvm_timer_sync_hwstate(vcpu); -+ kvm_vgic_sync_hwstate(vcpu); -+ -+ ret = handle_exit(vcpu, run, ret); -+ } -+ -+ if (vcpu->sigset_active) -+ sigprocmask(SIG_SETMASK, &sigsaved, NULL); -+ return ret; -+} -+ -+static int vcpu_interrupt_line(struct kvm_vcpu *vcpu, int number, bool level) -+{ -+ int bit_index; -+ bool set; -+ unsigned long *ptr; -+ -+ if (number == KVM_ARM_IRQ_CPU_IRQ) -+ bit_index = __ffs(HCR_VI); -+ else /* KVM_ARM_IRQ_CPU_FIQ */ -+ bit_index = __ffs(HCR_VF); -+ -+ ptr = (unsigned long *)&vcpu->arch.irq_lines; -+ if (level) -+ set = test_and_set_bit(bit_index, ptr); -+ else -+ set = test_and_clear_bit(bit_index, ptr); -+ -+ /* -+ * If we didn't change anything, no need to wake up or kick other CPUs -+ */ -+ if (set == level) -+ return 0; -+ -+ /* -+ * The vcpu irq_lines field was updated, wake up sleeping VCPUs and -+ * trigger a world-switch round on the running physical CPU to set the -+ * virtual IRQ/FIQ fields in the HCR appropriately. -+ */ -+ kvm_vcpu_kick(vcpu); -+ -+ return 0; -+} -+ -+int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_level, -+ bool line_status) -+{ -+ u32 irq = irq_level->irq; -+ unsigned int irq_type, vcpu_idx, irq_num; -+ int nrcpus = atomic_read(&kvm->online_vcpus); -+ struct kvm_vcpu *vcpu = NULL; -+ bool level = irq_level->level; -+ -+ irq_type = (irq >> KVM_ARM_IRQ_TYPE_SHIFT) & KVM_ARM_IRQ_TYPE_MASK; -+ vcpu_idx = (irq >> KVM_ARM_IRQ_VCPU_SHIFT) & KVM_ARM_IRQ_VCPU_MASK; -+ irq_num = (irq >> KVM_ARM_IRQ_NUM_SHIFT) & KVM_ARM_IRQ_NUM_MASK; -+ -+ trace_kvm_irq_line(irq_type, vcpu_idx, irq_num, irq_level->level); -+ -+ switch (irq_type) { -+ case KVM_ARM_IRQ_TYPE_CPU: -+ if (irqchip_in_kernel(kvm)) -+ return -ENXIO; -+ -+ if (vcpu_idx >= nrcpus) -+ return -EINVAL; -+ -+ vcpu = kvm_get_vcpu(kvm, vcpu_idx); -+ if (!vcpu) -+ return -EINVAL; -+ -+ if (irq_num > KVM_ARM_IRQ_CPU_FIQ) -+ return -EINVAL; -+ -+ return vcpu_interrupt_line(vcpu, irq_num, level); -+ case KVM_ARM_IRQ_TYPE_PPI: -+ if (!irqchip_in_kernel(kvm)) -+ return -ENXIO; -+ -+ if (vcpu_idx >= nrcpus) -+ return -EINVAL; -+ -+ vcpu = kvm_get_vcpu(kvm, vcpu_idx); -+ if (!vcpu) -+ return -EINVAL; -+ -+ if (irq_num < VGIC_NR_SGIS || irq_num >= VGIC_NR_PRIVATE_IRQS) -+ return -EINVAL; -+ -+ return kvm_vgic_inject_irq(kvm, vcpu->vcpu_id, irq_num, level); -+ case KVM_ARM_IRQ_TYPE_SPI: -+ if (!irqchip_in_kernel(kvm)) -+ return -ENXIO; -+ -+ if (irq_num < VGIC_NR_PRIVATE_IRQS) -+ return -EINVAL; -+ -+ return kvm_vgic_inject_irq(kvm, 0, irq_num, level); -+ } -+ -+ return -EINVAL; -+} -+ -+static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu, -+ struct kvm_vcpu_init *init) -+{ -+ int ret; -+ -+ ret = kvm_vcpu_set_target(vcpu, init); -+ if (ret) -+ return ret; -+ -+ /* -+ * Ensure a rebooted VM will fault in RAM pages and detect if the -+ * guest MMU is turned off and flush the caches as needed. -+ */ -+ if (vcpu->arch.has_run_once) -+ stage2_unmap_vm(vcpu->kvm); -+ -+ vcpu_reset_hcr(vcpu); -+ -+ /* -+ * Handle the "start in power-off" case by marking the VCPU as paused. -+ */ -+ if (test_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features)) -+ vcpu->arch.pause = true; -+ else -+ vcpu->arch.pause = false; -+ -+ return 0; -+} -+ -+long kvm_arch_vcpu_ioctl(struct file *filp, -+ unsigned int ioctl, unsigned long arg) -+{ -+ struct kvm_vcpu *vcpu = filp->private_data; -+ void __user *argp = (void __user *)arg; -+ -+ switch (ioctl) { -+ case KVM_ARM_VCPU_INIT: { -+ struct kvm_vcpu_init init; -+ -+ if (copy_from_user(&init, argp, sizeof(init))) -+ return -EFAULT; -+ -+ return kvm_arch_vcpu_ioctl_vcpu_init(vcpu, &init); -+ } -+ case KVM_SET_ONE_REG: -+ case KVM_GET_ONE_REG: { -+ struct kvm_one_reg reg; -+ -+ if (unlikely(!kvm_vcpu_initialized(vcpu))) -+ return -ENOEXEC; -+ -+ if (copy_from_user(®, argp, sizeof(reg))) -+ return -EFAULT; -+ if (ioctl == KVM_SET_ONE_REG) -+ return kvm_arm_set_reg(vcpu, ®); -+ else -+ return kvm_arm_get_reg(vcpu, ®); -+ } -+ case KVM_GET_REG_LIST: { -+ struct kvm_reg_list __user *user_list = argp; -+ struct kvm_reg_list reg_list; -+ unsigned n; -+ -+ if (unlikely(!kvm_vcpu_initialized(vcpu))) -+ return -ENOEXEC; -+ -+ if (copy_from_user(®_list, user_list, sizeof(reg_list))) -+ return -EFAULT; -+ n = reg_list.n; -+ reg_list.n = kvm_arm_num_regs(vcpu); -+ if (copy_to_user(user_list, ®_list, sizeof(reg_list))) -+ return -EFAULT; -+ if (n < reg_list.n) -+ return -E2BIG; -+ return kvm_arm_copy_reg_indices(vcpu, user_list->reg); -+ } -+ default: -+ return -EINVAL; -+ } -+} -+ -+int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) -+{ -+ return -EINVAL; -+} -+ -+static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm, -+ struct kvm_arm_device_addr *dev_addr) -+{ -+ unsigned long dev_id, type; -+ -+ dev_id = (dev_addr->id & KVM_ARM_DEVICE_ID_MASK) >> -+ KVM_ARM_DEVICE_ID_SHIFT; -+ type = (dev_addr->id & KVM_ARM_DEVICE_TYPE_MASK) >> -+ KVM_ARM_DEVICE_TYPE_SHIFT; -+ -+ switch (dev_id) { -+ case KVM_ARM_DEVICE_VGIC_V2: -+ if (!vgic_present) -+ return -ENXIO; -+ return kvm_vgic_addr(kvm, type, &dev_addr->addr, true); -+ default: -+ return -ENODEV; -+ } -+} -+ -+long kvm_arch_vm_ioctl(struct file *filp, -+ unsigned int ioctl, unsigned long arg) -+{ -+ struct kvm *kvm = filp->private_data; -+ void __user *argp = (void __user *)arg; -+ -+ switch (ioctl) { -+ case KVM_CREATE_IRQCHIP: { -+ if (vgic_present) -+ return kvm_vgic_create(kvm); -+ else -+ return -ENXIO; -+ } -+ case KVM_ARM_SET_DEVICE_ADDR: { -+ struct kvm_arm_device_addr dev_addr; -+ -+ if (copy_from_user(&dev_addr, argp, sizeof(dev_addr))) -+ return -EFAULT; -+ return kvm_vm_ioctl_set_device_addr(kvm, &dev_addr); -+ } -+ case KVM_ARM_PREFERRED_TARGET: { -+ int err; -+ struct kvm_vcpu_init init; -+ -+ err = kvm_vcpu_preferred_target(&init); -+ if (err) -+ return err; -+ -+ if (copy_to_user(argp, &init, sizeof(init))) -+ return -EFAULT; -+ -+ return 0; -+ } -+ default: -+ return -EINVAL; -+ } -+} -+ -+static void cpu_init_hyp_mode(void *dummy) -+{ -+ phys_addr_t boot_pgd_ptr; -+ phys_addr_t pgd_ptr; -+ unsigned long hyp_stack_ptr; -+ unsigned long stack_page; -+ unsigned long vector_ptr; -+ -+ /* Switch from the HYP stub to our own HYP init vector */ -+ __hyp_set_vectors(kvm_get_idmap_vector()); -+ -+ boot_pgd_ptr = kvm_mmu_get_boot_httbr(); -+ pgd_ptr = kvm_mmu_get_httbr(); -+ stack_page = __this_cpu_read(kvm_arm_hyp_stack_page); -+ hyp_stack_ptr = stack_page + PAGE_SIZE; -+ vector_ptr = (unsigned long)__kvm_hyp_vector; -+ -+ __cpu_init_hyp_mode(boot_pgd_ptr, pgd_ptr, hyp_stack_ptr, vector_ptr); -+} -+ -+static int hyp_init_cpu_notify(struct notifier_block *self, -+ unsigned long action, void *cpu) -+{ -+ switch (action) { -+ case CPU_STARTING: -+ case CPU_STARTING_FROZEN: -+ if (__hyp_get_vectors() == hyp_default_vectors) -+ cpu_init_hyp_mode(NULL); -+ break; -+ } -+ -+ return NOTIFY_OK; -+} -+ -+static struct notifier_block hyp_init_cpu_nb = { -+ .notifier_call = hyp_init_cpu_notify, -+}; -+ -+#ifdef CONFIG_CPU_PM -+static int hyp_init_cpu_pm_notifier(struct notifier_block *self, -+ unsigned long cmd, -+ void *v) -+{ -+ if (cmd == CPU_PM_EXIT && -+ __hyp_get_vectors() == hyp_default_vectors) { -+ cpu_init_hyp_mode(NULL); -+ return NOTIFY_OK; -+ } -+ -+ return NOTIFY_DONE; -+} -+ -+static struct notifier_block hyp_init_cpu_pm_nb = { -+ .notifier_call = hyp_init_cpu_pm_notifier, -+}; -+ -+static void __init hyp_cpu_pm_init(void) -+{ -+ cpu_pm_register_notifier(&hyp_init_cpu_pm_nb); -+} -+#else -+static inline void hyp_cpu_pm_init(void) -+{ -+} -+#endif -+ -+/** -+ * Inits Hyp-mode on all online CPUs -+ */ -+static int init_hyp_mode(void) -+{ -+ int cpu; -+ int err = 0; -+ -+ /* -+ * Allocate Hyp PGD and setup Hyp identity mapping -+ */ -+ err = kvm_mmu_init(); -+ if (err) -+ goto out_err; -+ -+ /* -+ * It is probably enough to obtain the default on one -+ * CPU. It's unlikely to be different on the others. -+ */ -+ hyp_default_vectors = __hyp_get_vectors(); -+ -+ /* -+ * Allocate stack pages for Hypervisor-mode -+ */ -+ for_each_possible_cpu(cpu) { -+ unsigned long stack_page; -+ -+ stack_page = __get_free_page(GFP_KERNEL); -+ if (!stack_page) { -+ err = -ENOMEM; -+ goto out_free_stack_pages; -+ } -+ -+ per_cpu(kvm_arm_hyp_stack_page, cpu) = stack_page; -+ } -+ -+ /* -+ * Map the Hyp-code called directly from the host -+ */ -+ err = create_hyp_mappings(__kvm_hyp_code_start, __kvm_hyp_code_end); -+ if (err) { -+ kvm_err("Cannot map world-switch code\n"); -+ goto out_free_mappings; -+ } -+ -+ /* -+ * Map the Hyp stack pages -+ */ -+ for_each_possible_cpu(cpu) { -+ char *stack_page = (char *)per_cpu(kvm_arm_hyp_stack_page, cpu); -+ err = create_hyp_mappings(stack_page, stack_page + PAGE_SIZE); -+ -+ if (err) { -+ kvm_err("Cannot map hyp stack\n"); -+ goto out_free_mappings; -+ } -+ } -+ -+ /* -+ * Map the host CPU structures -+ */ -+ kvm_host_cpu_state = alloc_percpu(kvm_cpu_context_t); -+ if (!kvm_host_cpu_state) { -+ err = -ENOMEM; -+ kvm_err("Cannot allocate host CPU state\n"); -+ goto out_free_mappings; -+ } -+ -+ for_each_possible_cpu(cpu) { -+ kvm_cpu_context_t *cpu_ctxt; -+ -+ cpu_ctxt = per_cpu_ptr(kvm_host_cpu_state, cpu); -+ err = create_hyp_mappings(cpu_ctxt, cpu_ctxt + 1); -+ -+ if (err) { -+ kvm_err("Cannot map host CPU state: %d\n", err); -+ goto out_free_context; -+ } -+ } -+ -+ /* -+ * Execute the init code on each CPU. -+ */ -+ on_each_cpu(cpu_init_hyp_mode, NULL, 1); -+ -+ /* -+ * Init HYP view of VGIC -+ */ -+ err = kvm_vgic_hyp_init(); -+ if (err) -+ goto out_free_context; -+ -+#ifdef CONFIG_KVM_ARM_VGIC -+ vgic_present = true; -+#endif -+ -+ /* -+ * Init HYP architected timer support -+ */ -+ err = kvm_timer_hyp_init(); -+ if (err) -+ goto out_free_mappings; -+ -+#ifndef CONFIG_HOTPLUG_CPU -+ free_boot_hyp_pgd(); -+#endif -+ -+ kvm_perf_init(); -+ -+ kvm_info("Hyp mode initialized successfully\n"); -+ -+ return 0; -+out_free_context: -+ free_percpu(kvm_host_cpu_state); -+out_free_mappings: -+ free_hyp_pgds(); -+out_free_stack_pages: -+ for_each_possible_cpu(cpu) -+ free_page(per_cpu(kvm_arm_hyp_stack_page, cpu)); -+out_err: -+ kvm_err("error initializing Hyp mode: %d\n", err); -+ return err; -+} -+ -+static void check_kvm_target_cpu(void *ret) -+{ -+ *(int *)ret = kvm_target_cpu(); -+} -+ -+/** -+ * Initialize Hyp-mode and memory mappings on all CPUs. -+ */ -+int kvm_arch_init(void *opaque) -+{ -+ int err; -+ int ret, cpu; -+ -+ if (!is_hyp_mode_available()) { -+ kvm_err("HYP mode not available\n"); -+ return -ENODEV; -+ } -+ -+ for_each_online_cpu(cpu) { -+ smp_call_function_single(cpu, check_kvm_target_cpu, &ret, 1); -+ if (ret < 0) { -+ kvm_err("Error, CPU %d not supported!\n", cpu); -+ return -ENODEV; -+ } -+ } -+ -+ cpu_notifier_register_begin(); -+ -+ err = init_hyp_mode(); -+ if (err) -+ goto out_err; -+ -+ err = __register_cpu_notifier(&hyp_init_cpu_nb); -+ if (err) { -+ kvm_err("Cannot register HYP init CPU notifier (%d)\n", err); -+ goto out_err; -+ } -+ -+ cpu_notifier_register_done(); -+ -+ hyp_cpu_pm_init(); -+ -+ kvm_coproc_table_init(); -+ return 0; -+out_err: -+ cpu_notifier_register_done(); -+ return err; -+} -+ -+/* NOP: Compiling as a module not supported */ -+void kvm_arch_exit(void) -+{ -+ kvm_perf_teardown(); -+} -+ -+static int arm_init(void) -+{ -+ int rc = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE); -+ return rc; -+} -+ -+module_init(arm_init); -diff -Nur linux-3.18.14.orig/arch/arm/kvm/psci.c linux-3.18.14-rt/arch/arm/kvm/psci.c ---- linux-3.18.14.orig/arch/arm/kvm/psci.c 2015-05-20 10:04:50.000000000 -0500 -+++ linux-3.18.14-rt/arch/arm/kvm/psci.c 2015-05-31 15:32:45.673635392 -0500 -@@ -67,7 +67,7 @@ - { - struct kvm *kvm = source_vcpu->kvm; - struct kvm_vcpu *vcpu = NULL, *tmp; -- wait_queue_head_t *wq; -+ struct swait_head *wq; - unsigned long cpu_id; - unsigned long context_id; - unsigned long mpidr; -@@ -124,7 +124,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-3.18.14.orig/arch/arm/kvm/psci.c.orig linux-3.18.14-rt/arch/arm/kvm/psci.c.orig ---- linux-3.18.14.orig/arch/arm/kvm/psci.c.orig 1969-12-31 18:00:00.000000000 -0600 -+++ linux-3.18.14-rt/arch/arm/kvm/psci.c.orig 2015-05-20 10:04:50.000000000 -0500 -@@ -0,0 +1,337 @@ -+/* -+ * Copyright (C) 2012 - ARM Ltd -+ * Author: Marc Zyngier -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program. If not, see . -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+/* -+ * This is an implementation of the Power State Coordination Interface -+ * as described in ARM document number ARM DEN 0022A. -+ */ -+ -+#define AFFINITY_MASK(level) ~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1) -+ -+static unsigned long psci_affinity_mask(unsigned long affinity_level) -+{ -+ if (affinity_level <= 3) -+ return MPIDR_HWID_BITMASK & AFFINITY_MASK(affinity_level); -+ -+ return 0; -+} -+ -+static unsigned long kvm_psci_vcpu_suspend(struct kvm_vcpu *vcpu) -+{ -+ /* -+ * NOTE: For simplicity, we make VCPU suspend emulation to be -+ * same-as WFI (Wait-for-interrupt) emulation. -+ * -+ * This means for KVM the wakeup events are interrupts and -+ * this is consistent with intended use of StateID as described -+ * in section 5.4.1 of PSCI v0.2 specification (ARM DEN 0022A). -+ * -+ * Further, we also treat power-down request to be same as -+ * stand-by request as-per section 5.4.2 clause 3 of PSCI v0.2 -+ * specification (ARM DEN 0022A). This means all suspend states -+ * for KVM will preserve the register state. -+ */ -+ kvm_vcpu_block(vcpu); -+ -+ return PSCI_RET_SUCCESS; -+} -+ -+static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu) -+{ -+ vcpu->arch.pause = true; -+} -+ -+static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) -+{ -+ struct kvm *kvm = source_vcpu->kvm; -+ struct kvm_vcpu *vcpu = NULL, *tmp; -+ wait_queue_head_t *wq; -+ unsigned long cpu_id; -+ unsigned long context_id; -+ unsigned long mpidr; -+ phys_addr_t target_pc; -+ int i; -+ -+ cpu_id = *vcpu_reg(source_vcpu, 1); -+ if (vcpu_mode_is_32bit(source_vcpu)) -+ cpu_id &= ~((u32) 0); -+ -+ kvm_for_each_vcpu(i, tmp, kvm) { -+ mpidr = kvm_vcpu_get_mpidr(tmp); -+ if ((mpidr & MPIDR_HWID_BITMASK) == (cpu_id & MPIDR_HWID_BITMASK)) { -+ vcpu = tmp; -+ break; -+ } -+ } -+ -+ /* -+ * Make sure the caller requested a valid CPU and that the CPU is -+ * turned off. -+ */ -+ if (!vcpu) -+ return PSCI_RET_INVALID_PARAMS; -+ if (!vcpu->arch.pause) { -+ if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1) -+ return PSCI_RET_ALREADY_ON; -+ else -+ return PSCI_RET_INVALID_PARAMS; -+ } -+ -+ target_pc = *vcpu_reg(source_vcpu, 2); -+ context_id = *vcpu_reg(source_vcpu, 3); -+ -+ kvm_reset_vcpu(vcpu); -+ -+ /* Gracefully handle Thumb2 entry point */ -+ if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) { -+ target_pc &= ~((phys_addr_t) 1); -+ vcpu_set_thumb(vcpu); -+ } -+ -+ /* Propagate caller endianness */ -+ if (kvm_vcpu_is_be(source_vcpu)) -+ kvm_vcpu_set_be(vcpu); -+ -+ *vcpu_pc(vcpu) = target_pc; -+ /* -+ * NOTE: We always update r0 (or x0) because for PSCI v0.1 -+ * the general puspose registers are undefined upon CPU_ON. -+ */ -+ *vcpu_reg(vcpu, 0) = context_id; -+ vcpu->arch.pause = false; -+ smp_mb(); /* Make sure the above is visible */ -+ -+ wq = kvm_arch_vcpu_wq(vcpu); -+ wake_up_interruptible(wq); -+ -+ return PSCI_RET_SUCCESS; -+} -+ -+static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu) -+{ -+ int i; -+ unsigned long mpidr; -+ unsigned long target_affinity; -+ unsigned long target_affinity_mask; -+ unsigned long lowest_affinity_level; -+ struct kvm *kvm = vcpu->kvm; -+ struct kvm_vcpu *tmp; -+ -+ target_affinity = *vcpu_reg(vcpu, 1); -+ lowest_affinity_level = *vcpu_reg(vcpu, 2); -+ -+ /* Determine target affinity mask */ -+ target_affinity_mask = psci_affinity_mask(lowest_affinity_level); -+ if (!target_affinity_mask) -+ return PSCI_RET_INVALID_PARAMS; -+ -+ /* Ignore other bits of target affinity */ -+ target_affinity &= target_affinity_mask; -+ -+ /* -+ * If one or more VCPU matching target affinity are running -+ * then ON else OFF -+ */ -+ kvm_for_each_vcpu(i, tmp, kvm) { -+ mpidr = kvm_vcpu_get_mpidr(tmp); -+ if (((mpidr & target_affinity_mask) == target_affinity) && -+ !tmp->arch.pause) { -+ return PSCI_0_2_AFFINITY_LEVEL_ON; -+ } -+ } -+ -+ return PSCI_0_2_AFFINITY_LEVEL_OFF; -+} -+ -+static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type) -+{ -+ int i; -+ struct kvm_vcpu *tmp; -+ -+ /* -+ * The KVM ABI specifies that a system event exit may call KVM_RUN -+ * again and may perform shutdown/reboot at a later time that when the -+ * actual request is made. Since we are implementing PSCI and a -+ * caller of PSCI reboot and shutdown expects that the system shuts -+ * down or reboots immediately, let's make sure that VCPUs are not run -+ * after this call is handled and before the VCPUs have been -+ * re-initialized. -+ */ -+ kvm_for_each_vcpu(i, tmp, vcpu->kvm) { -+ tmp->arch.pause = true; -+ kvm_vcpu_kick(tmp); -+ } -+ -+ memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event)); -+ vcpu->run->system_event.type = type; -+ vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT; -+} -+ -+static void kvm_psci_system_off(struct kvm_vcpu *vcpu) -+{ -+ kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_SHUTDOWN); -+} -+ -+static void kvm_psci_system_reset(struct kvm_vcpu *vcpu) -+{ -+ kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET); -+} -+ -+int kvm_psci_version(struct kvm_vcpu *vcpu) -+{ -+ if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) -+ return KVM_ARM_PSCI_0_2; -+ -+ return KVM_ARM_PSCI_0_1; -+} -+ -+static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) -+{ -+ int ret = 1; -+ unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); -+ unsigned long val; -+ -+ switch (psci_fn) { -+ case PSCI_0_2_FN_PSCI_VERSION: -+ /* -+ * Bits[31:16] = Major Version = 0 -+ * Bits[15:0] = Minor Version = 2 -+ */ -+ val = 2; -+ break; -+ case PSCI_0_2_FN_CPU_SUSPEND: -+ case PSCI_0_2_FN64_CPU_SUSPEND: -+ val = kvm_psci_vcpu_suspend(vcpu); -+ break; -+ case PSCI_0_2_FN_CPU_OFF: -+ kvm_psci_vcpu_off(vcpu); -+ val = PSCI_RET_SUCCESS; -+ break; -+ case PSCI_0_2_FN_CPU_ON: -+ case PSCI_0_2_FN64_CPU_ON: -+ val = kvm_psci_vcpu_on(vcpu); -+ break; -+ case PSCI_0_2_FN_AFFINITY_INFO: -+ case PSCI_0_2_FN64_AFFINITY_INFO: -+ val = kvm_psci_vcpu_affinity_info(vcpu); -+ break; -+ case PSCI_0_2_FN_MIGRATE: -+ case PSCI_0_2_FN64_MIGRATE: -+ val = PSCI_RET_NOT_SUPPORTED; -+ break; -+ case PSCI_0_2_FN_MIGRATE_INFO_TYPE: -+ /* -+ * Trusted OS is MP hence does not require migration -+ * or -+ * Trusted OS is not present -+ */ -+ val = PSCI_0_2_TOS_MP; -+ break; -+ case PSCI_0_2_FN_MIGRATE_INFO_UP_CPU: -+ case PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU: -+ val = PSCI_RET_NOT_SUPPORTED; -+ break; -+ case PSCI_0_2_FN_SYSTEM_OFF: -+ kvm_psci_system_off(vcpu); -+ /* -+ * We should'nt be going back to guest VCPU after -+ * receiving SYSTEM_OFF request. -+ * -+ * If user space accidently/deliberately resumes -+ * guest VCPU after SYSTEM_OFF request then guest -+ * VCPU should see internal failure from PSCI return -+ * value. To achieve this, we preload r0 (or x0) with -+ * PSCI return value INTERNAL_FAILURE. -+ */ -+ val = PSCI_RET_INTERNAL_FAILURE; -+ ret = 0; -+ break; -+ case PSCI_0_2_FN_SYSTEM_RESET: -+ kvm_psci_system_reset(vcpu); -+ /* -+ * Same reason as SYSTEM_OFF for preloading r0 (or x0) -+ * with PSCI return value INTERNAL_FAILURE. -+ */ -+ val = PSCI_RET_INTERNAL_FAILURE; -+ ret = 0; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ *vcpu_reg(vcpu, 0) = val; -+ return ret; -+} -+ -+static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) -+{ -+ unsigned long psci_fn = *vcpu_reg(vcpu, 0) & ~((u32) 0); -+ unsigned long val; -+ -+ switch (psci_fn) { -+ case KVM_PSCI_FN_CPU_OFF: -+ kvm_psci_vcpu_off(vcpu); -+ val = PSCI_RET_SUCCESS; -+ break; -+ case KVM_PSCI_FN_CPU_ON: -+ val = kvm_psci_vcpu_on(vcpu); -+ break; -+ case KVM_PSCI_FN_CPU_SUSPEND: -+ case KVM_PSCI_FN_MIGRATE: -+ val = PSCI_RET_NOT_SUPPORTED; -+ break; -+ default: -+ return -EINVAL; -+ } -+ -+ *vcpu_reg(vcpu, 0) = val; -+ return 1; -+} -+ -+/** -+ * kvm_psci_call - handle PSCI call if r0 value is in range -+ * @vcpu: Pointer to the VCPU struct -+ * -+ * Handle PSCI calls from guests through traps from HVC instructions. -+ * The calling convention is similar to SMC calls to the secure world -+ * where the function number is placed in r0. -+ * -+ * This function returns: > 0 (success), 0 (success but exit to user -+ * space), and < 0 (errors) -+ * -+ * Errors: -+ * -EINVAL: Unrecognized PSCI function -+ */ -+int kvm_psci_call(struct kvm_vcpu *vcpu) -+{ -+ switch (kvm_psci_version(vcpu)) { -+ case KVM_ARM_PSCI_0_2: -+ return kvm_psci_0_2_call(vcpu); -+ case KVM_ARM_PSCI_0_1: -+ return kvm_psci_0_1_call(vcpu); -+ default: -+ return -EINVAL; -+ }; -+} -diff -Nur linux-3.18.14.orig/arch/arm/mach-at91/at91rm9200_time.c linux-3.18.14-rt/arch/arm/mach-at91/at91rm9200_time.c ---- linux-3.18.14.orig/arch/arm/mach-at91/at91rm9200_time.c 2015-05-20 10:04:50.000000000 -0500 -+++ linux-3.18.14-rt/arch/arm/mach-at91/at91rm9200_time.c 2015-05-31 15:32:45.673635392 -0500 -@@ -135,6 +135,7 @@ - break; - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_UNUSED: -+ remove_irq(NR_IRQS_LEGACY + AT91_ID_SYS, &at91rm9200_timer_irq); - case CLOCK_EVT_MODE_RESUME: - irqmask = 0; - break; -diff -Nur linux-3.18.14.orig/arch/arm/mach-exynos/platsmp.c linux-3.18.14-rt/arch/arm/mach-exynos/platsmp.c ---- linux-3.18.14.orig/arch/arm/mach-exynos/platsmp.c 2015-05-20 10:04:50.000000000 -0500 -+++ linux-3.18.14-rt/arch/arm/mach-exynos/platsmp.c 2015-05-31 15:32:45.673635392 -0500 -@@ -137,7 +137,7 @@ - return (void __iomem *)(S5P_VA_SCU); - } - --static DEFINE_SPINLOCK(boot_lock); -+static DEFINE_RAW_SPINLOCK(boot_lock); - - static void exynos_secondary_init(unsigned int cpu) - { -@@ -150,8 +150,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) -@@ -165,7 +165,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 -@@ -192,7 +192,7 @@ - - if (timeout == 0) { - printk(KERN_ERR "cpu1 power enable failed"); -- spin_unlock(&boot_lock); -+ raw_spin_unlock(&boot_lock); - return -ETIMEDOUT; - } - } -@@ -242,7 +242,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-3.18.14.orig/arch/arm/mach-hisi/platmcpm.c linux-3.18.14-rt/arch/arm/mach-hisi/platmcpm.c ---- l