#define instruction_pointer(regs) ((regs)->cp0_epc)
 #define profile_pc(regs) instruction_pointer(regs)
 
-extern asmlinkage long syscall_trace_enter(struct pt_regs *regs);
+extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall);
 extern asmlinkage void syscall_trace_leave(struct pt_regs *regs);
 
 extern void die(const char *, struct pt_regs *) __noreturn;
 
 #include <linux/sched.h>
 #include <linux/uaccess.h>
 #include <asm/ptrace.h>
+#include <asm/unistd.h>
+
+#ifndef __NR_syscall /* Only defined if _MIPS_SIM == _MIPS_SIM_ABI32 */
+#define __NR_syscall 4000
+#endif
 
 static inline long syscall_get_nr(struct task_struct *task,
                                  struct pt_regs *regs)
 {
-       return regs->regs[2];
+       /* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */
+       if ((config_enabled(CONFIG_32BIT) ||
+           test_tsk_thread_flag(task, TIF_32BIT_REGS)) &&
+           (regs->regs[2] == __NR_syscall))
+               return regs->regs[4];
+       else
+               return regs->regs[2];
 }
 
 static inline unsigned long mips_get_syscall_arg(unsigned long *arg,
 {
        unsigned long arg;
        int ret;
+       /* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */
+       if ((config_enabled(CONFIG_32BIT) ||
+           test_tsk_thread_flag(task, TIF_32BIT_REGS)) &&
+           (regs->regs[2] == __NR_syscall)) {
+               i++;
+               n++;
+       }
 
        while (n--)
                ret |= mips_get_syscall_arg(&arg, task, regs, i++);
 
  * Notification of system call entry/exit
  * - triggered by current->work.syscall_trace
  */
-asmlinkage long syscall_trace_enter(struct pt_regs *regs)
+asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall)
 {
-       long syscall = regs->regs[2];
        long ret = 0;
        user_exit();
 
 
        SAVE_STATIC
        move    s0, t2
        move    a0, sp
-       jal     syscall_trace_enter
+
+       /*
+        * syscall number is in v0 unless we called syscall(__NR_###)
+        * where the real syscall number is in a0
+        */
+       addiu   a1, v0,  __NR_O32_Linux
+       bnez    v0, 1f /* __NR_syscall at offset 0 */
+       lw      a1, PT_R4(sp)
+
+1:     jal     syscall_trace_enter
 
        bltz    v0, 2f                  # seccomp failed? Skip syscall
 
 
        SAVE_STATIC
        move    s0, t2
        move    a0, sp
+       daddiu  a1, v0, __NR_64_Linux
        jal     syscall_trace_enter
 
        bltz    v0, 2f                  # seccomp failed? Skip syscall
 
        SAVE_STATIC
        move    s0, t2
        move    a0, sp
+       daddiu  a1, v0, __NR_N32_Linux
        jal     syscall_trace_enter
 
        bltz    v0, 2f                  # seccomp failed? Skip syscall
 
 
        move    s0, t2                  # Save syscall pointer
        move    a0, sp
-       jal     syscall_trace_enter
+       /*
+        * syscall number is in v0 unless we called syscall(__NR_###)
+        * where the real syscall number is in a0
+        * note: NR_syscall is the first O32 syscall but the macro is
+        * only defined when compiling with -mabi=32 (CONFIG_32BIT)
+        * therefore __NR_O32_Linux is used (4000)
+        */
+       addiu   a1, v0,  __NR_O32_Linux
+       bnez    v0, 1f /* __NR_syscall at offset 0 */
+       lw      a1, PT_R4(sp)
+
+1:     jal     syscall_trace_enter
 
        bltz    v0, 2f                  # seccomp failed? Skip syscall