return -1;
 }
 
+static inline void
+syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr)
+{
+       /*
+        * Unlike syscall_get_nr(), syscall_set_nr() can be called only when
+        * the target task is stopped for tracing on entering syscall, so
+        * there is no need to have the same check syscall_get_nr() has.
+        */
+       regs->r8 = nr;
+}
+
 static inline void
 syscall_rollback(struct task_struct *task, struct pt_regs *regs)
 {
 
        regs->ARM_r0 = (long) error ? error : val;
 }
 
+static inline void syscall_set_nr(struct task_struct *task,
+                                 struct pt_regs *regs,
+                                 int nr)
+{
+       if (nr == -1) {
+               task_thread_info(task)->abi_syscall = -1;
+               /*
+                * When the syscall number is set to -1, the syscall will be
+                * skipped.  In this case the syscall return value has to be
+                * set explicitly, otherwise the first syscall argument is
+                * returned as the syscall return value.
+                */
+               syscall_set_return_value(task, regs, -ENOSYS, 0);
+               return;
+       }
+       if ((IS_ENABLED(CONFIG_AEABI) && !IS_ENABLED(CONFIG_OABI_COMPAT))) {
+               task_thread_info(task)->abi_syscall = nr;
+               return;
+       }
+       task_thread_info(task)->abi_syscall =
+               (task_thread_info(task)->abi_syscall & ~__NR_SYSCALL_MASK) |
+               (nr & __NR_SYSCALL_MASK);
+}
+
 #define SYSCALL_MAX_ARGS 7
 
 static inline void syscall_get_arguments(struct task_struct *task,
 
        regs->regs[0] = val;
 }
 
+static inline void syscall_set_nr(struct task_struct *task,
+                                 struct pt_regs *regs,
+                                 int nr)
+{
+       regs->syscallno = nr;
+       if (nr == -1) {
+               /*
+                * When the syscall number is set to -1, the syscall will be
+                * skipped.  In this case the syscall return value has to be
+                * set explicitly, otherwise the first syscall argument is
+                * returned as the syscall return value.
+                */
+               syscall_set_return_value(task, regs, -ENOSYS, 0);
+       }
+}
+
 #define SYSCALL_MAX_ARGS 6
 
 static inline void syscall_get_arguments(struct task_struct *task,
 
        return regs->r06;
 }
 
+static inline void syscall_set_nr(struct task_struct *task,
+                                 struct pt_regs *regs,
+                                 int nr)
+{
+       regs->r06 = nr;
+}
+
 static inline void syscall_get_arguments(struct task_struct *task,
                                         struct pt_regs *regs,
                                         unsigned long *args)
 
        return regs->regs[11];
 }
 
+static inline void syscall_set_nr(struct task_struct *task,
+                                 struct pt_regs *regs,
+                                 int nr)
+{
+       regs->regs[11] = nr;
+}
+
 static inline void syscall_rollback(struct task_struct *task,
                                    struct pt_regs *regs)
 {
 
        return regs->orig_d0;
 }
 
+static inline void syscall_set_nr(struct task_struct *task,
+                                 struct pt_regs *regs,
+                                 int nr)
+{
+       regs->orig_d0 = nr;
+}
+
 static inline void syscall_rollback(struct task_struct *task,
                                    struct pt_regs *regs)
 {
 
        return regs->r12;
 }
 
+static inline void syscall_set_nr(struct task_struct *task,
+                                 struct pt_regs *regs,
+                                 int nr)
+{
+       regs->r12 = nr;
+}
+
 static inline void syscall_rollback(struct task_struct *task,
                                    struct pt_regs *regs)
 {
 
        return task_thread_info(task)->syscall;
 }
 
+static inline void syscall_set_nr(struct task_struct *task,
+                                 struct pt_regs *regs,
+                                 int nr)
+{
+       /*
+        * New syscall number has to be assigned to regs[2] because
+        * it is loaded from there unconditionally after return from
+        * syscall_trace_enter() invocation.
+        *
+        * Consequently, if the syscall was indirect and nr != __NR_syscall,
+        * then after this assignment the syscall will cease to be indirect.
+        */
+       task_thread_info(task)->syscall = regs->regs[2] = nr;
+}
+
 static inline void mips_syscall_update_nr(struct task_struct *task,
                                          struct pt_regs *regs)
 {
 
        return regs->r2;
 }
 
+static inline void syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr)
+{
+       regs->r2 = nr;
+}
+
 static inline void syscall_rollback(struct task_struct *task,
                                struct pt_regs *regs)
 {
 
        return regs->orig_gpr11;
 }
 
+static inline void
+syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr)
+{
+       regs->orig_gpr11 = nr;
+}
+
 static inline void
 syscall_rollback(struct task_struct *task, struct pt_regs *regs)
 {
 
        return regs->gr[20];
 }
 
+static inline void syscall_set_nr(struct task_struct *tsk,
+                                 struct pt_regs *regs,
+                                 int nr)
+{
+       regs->gr[20] = nr;
+}
+
 static inline void syscall_get_arguments(struct task_struct *tsk,
                                         struct pt_regs *regs,
                                         unsigned long *args)
 
                return -1;
 }
 
+static inline void syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr)
+{
+       /*
+        * Unlike syscall_get_nr(), syscall_set_nr() can be called only when
+        * the target task is stopped for tracing on entering syscall, so
+        * there is no need to have the same check syscall_get_nr() has.
+        */
+       regs->gpr[0] = nr;
+}
+
 static inline void syscall_rollback(struct task_struct *task,
                                    struct pt_regs *regs)
 {
 
        return regs->a7;
 }
 
+static inline void syscall_set_nr(struct task_struct *task,
+                                 struct pt_regs *regs,
+                                 int nr)
+{
+       regs->a7 = nr;
+}
+
 static inline void syscall_rollback(struct task_struct *task,
                                    struct pt_regs *regs)
 {
 
                (regs->int_code & 0xffff) : -1;
 }
 
+static inline void syscall_set_nr(struct task_struct *task,
+                                 struct pt_regs *regs,
+                                 int nr)
+{
+       /*
+        * Unlike syscall_get_nr(), syscall_set_nr() can be called only when
+        * the target task is stopped for tracing on entering syscall, so
+        * there is no need to have the same check syscall_get_nr() has.
+        */
+       regs->int_code = (regs->int_code & ~0xffff) | (nr & 0xffff);
+}
+
 static inline void syscall_rollback(struct task_struct *task,
                                    struct pt_regs *regs)
 {
 
        return (regs->tra >= 0) ? regs->regs[3] : -1L;
 }
 
+static inline void syscall_set_nr(struct task_struct *task,
+                                 struct pt_regs *regs,
+                                 int nr)
+{
+       /*
+        * Unlike syscall_get_nr(), syscall_set_nr() can be called only when
+        * the target task is stopped for tracing on entering syscall, so
+        * there is no need to have the same check syscall_get_nr() has.
+        */
+       regs->regs[3] = nr;
+}
+
 static inline void syscall_rollback(struct task_struct *task,
                                    struct pt_regs *regs)
 {
 
        return (syscall_p ? regs->u_regs[UREG_G1] : -1L);
 }
 
+static inline void syscall_set_nr(struct task_struct *task,
+                                 struct pt_regs *regs,
+                                 int nr)
+{
+       /*
+        * Unlike syscall_get_nr(), syscall_set_nr() can be called only when
+        * the target task is stopped for tracing on entering syscall, so
+        * there is no need to have the same check syscall_get_nr() has.
+        */
+       regs->u_regs[UREG_G1] = nr;
+}
+
 static inline void syscall_rollback(struct task_struct *task,
                                    struct pt_regs *regs)
 {
 
        return PT_REGS_SYSCALL_NR(regs);
 }
 
+static inline void syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr)
+{
+       PT_REGS_SYSCALL_NR(regs) = nr;
+}
+
 static inline void syscall_rollback(struct task_struct *task,
                                    struct pt_regs *regs)
 {
 
        return regs->orig_ax;
 }
 
+static inline void syscall_set_nr(struct task_struct *task,
+                                 struct pt_regs *regs,
+                                 int nr)
+{
+       regs->orig_ax = nr;
+}
+
 static inline void syscall_rollback(struct task_struct *task,
                                    struct pt_regs *regs)
 {
 
        return regs->syscall;
 }
 
+static inline void syscall_set_nr(struct task_struct *task,
+                                 struct pt_regs *regs,
+                                 int nr)
+{
+       regs->syscall = nr;
+}
+
 static inline void syscall_rollback(struct task_struct *task,
                                    struct pt_regs *regs)
 {
 
  */
 int syscall_get_nr(struct task_struct *task, struct pt_regs *regs);
 
+/**
+ * syscall_set_nr - change the system call a task is executing
+ * @task:      task of interest, must be blocked
+ * @regs:      task_pt_regs() of @task
+ * @nr:                system call number
+ *
+ * Changes the system call number @task is about to execute.
+ *
+ * It's only valid to call this when @task is stopped for tracing on
+ * entry to a system call, due to %SYSCALL_WORK_SYSCALL_TRACE or
+ * %SYSCALL_WORK_SYSCALL_AUDIT.
+ */
+void syscall_set_nr(struct task_struct *task, struct pt_regs *regs, int nr);
+
 /**
  * syscall_rollback - roll back registers after an aborted system call
  * @task:      task of interest, must be in system call exit tracing