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>
static unsigned long resume_userspace_addr;
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;
static void __used __up_handler(void)
{
struct pt_regs *regs = current_ctx()->ptr_regs;
regs->gs = 0;
regs->flags = X86_EFLAGS_IF | X86_EFLAGS_FIXED;
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();
+
if (kp_do_exit.addr == 0)
goto not_found;
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;
ret = swap_td_raw_reg(&td_raw, sizeof(struct uprobe_ctlblk));
if (ret)
return ret;