[FIX] rcu_nmi_enter/exit() inconsistentence (for x86) 24/75624/3
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Mon, 20 Jun 2016 18:11:01 +0000 (21:11 +0300)
committerDmitry Kovalenko <d.kovalenko@samsung.com>
Thu, 23 Jun 2016 15:01:40 +0000 (08:01 -0700)
Add rcu_nmi_enter() call to exceptions_handler(), because we change
US context to KS context as a result rcu_nmi_exit() will  be called
on exiting exception and rcu_nmi_enter() and  rcu_nmi_exit() calls
must be consistent.

Change-Id: Idbf5a7d6be1284ba841c4b43b565aaf18197ab28
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
uprobe/arch/x86/swap-asm/swap_uprobes.c

index 97daf85..99308bc 100644 (file)
@@ -468,6 +468,14 @@ static void prepare_ss(struct pt_regs *regs)
 
 static unsigned long resume_userspace_addr;
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
+static void __rcu_nmi_enter(void) {}
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)
+#error "This kernel is not support"
+#else /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) */
+static void (*__rcu_nmi_enter)(void);
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0) */
+
 static void __used __up_handler(void)
 {
        struct pt_regs *regs = current_ctx()->ptr_regs;
@@ -517,6 +525,14 @@ static int exceptions_handler(struct pt_regs *regs,
        regs->gs = 0;
        regs->flags = X86_EFLAGS_IF | X86_EFLAGS_FIXED;
 
+       /*
+        * Here rcu_nmi_enter() call is needed, because we change
+        * US context to KS context as a result rcu_nmi_exit() will
+        * be called on exiting exception and rcu_nmi_enter() and
+        * rcu_nmi_exit() calls must be consistent
+        */
+       __rcu_nmi_enter();
+
        return 1;
 }
 
@@ -711,6 +727,13 @@ int swap_arch_init_uprobes(void)
        if (kp_do_exit.addr == 0)
                goto not_found;
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0)
+       sym = "rcu_nmi_enter";
+       __rcu_nmi_enter = (void *)swap_ksyms(sym);
+       if (__rcu_nmi_enter == NULL)
+               goto not_found;
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) */
+
        ret = swap_td_raw_reg(&td_raw, sizeof(struct uprobe_ctlblk));
        if (ret)
                return ret;