Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Adjust pc/npc before syscall allowing EJUSTRETURN to return



details:   https://anonhg.NetBSD.org/src/rev/f5579bbc8be3
branches:  trunk
changeset: 373921:f5579bbc8be3
user:      hannken <hannken%NetBSD.org@localhost>
date:      Mon Mar 20 11:19:29 2023 +0000

description:
Adjust pc/npc before syscall allowing EJUSTRETURN to return
to the next instruction.  Only ERESTART should return to
the same instruction.  Differences to sparc64 reduced.

Test t_ptrace_wait:syscallemu1 now passes on sparc.

Fixes PR kern/52166 "syscallemu does not work on sparc (32-bit)"

Ok: Martin Husemann

diffstat:

 sys/arch/sparc/sparc/syscall.c             |  54 +++++++++++++++++------------
 sys/arch/sparc/sparc/vm_machdep.c          |   6 +--
 tests/lib/libc/sys/t_ptrace_syscall_wait.h |   7 +---
 3 files changed, 34 insertions(+), 33 deletions(-)

diffs (159 lines):

diff -r e26d88ee9b3e -r f5579bbc8be3 sys/arch/sparc/sparc/syscall.c
--- a/sys/arch/sparc/sparc/syscall.c    Mon Mar 20 11:07:33 2023 +0000
+++ b/sys/arch/sparc/sparc/syscall.c    Mon Mar 20 11:19:29 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: syscall.c,v 1.31 2019/04/06 11:54:20 kamil Exp $ */
+/*     $NetBSD: syscall.c,v 1.32 2023/03/20 11:19:29 hannken Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -49,7 +49,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.31 2019/04/06 11:54:20 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: syscall.c,v 1.32 2023/03/20 11:19:29 hannken Exp $");
 
 #include "opt_sparc_arch.h"
 #include "opt_multiprocessor.h"
@@ -106,6 +106,17 @@
 {
        int new = *code & (SYSCALL_G7RFLAG|SYSCALL_G2RFLAG|SYSCALL_G5RFLAG);
        *code &= ~(SYSCALL_G7RFLAG|SYSCALL_G2RFLAG|SYSCALL_G5RFLAG);
+       if (new) {
+               /* jmp %g5, (or %g2 or %g7, deprecated) on success */
+               if (__predict_true((new & SYSCALL_G5RFLAG) == SYSCALL_G5RFLAG))
+                       tf->tf_pc = tf->tf_global[5];
+               else if (new & SYSCALL_G2RFLAG)
+                       tf->tf_pc = tf->tf_global[2];
+               else
+                       tf->tf_pc = tf->tf_global[7];
+       } else {
+               tf->tf_pc = tf->tf_npc;
+       }
        return new;
 }
 
@@ -207,7 +218,7 @@
        int error, new;
        union args args;
        union rval rval;
-       register_t i;
+       int opc, onpc;
        u_quad_t sticks;
 
        curcpu()->ci_data.cpu_nsyscall++;       /* XXXSMP */
@@ -221,8 +232,18 @@
 #ifdef FPU_DEBUG
        save_fpu(tf);
 #endif
+
+       /*
+        * save pc/npc in case of ERESTART
+        * adjust pc/npc to new values
+        */
+       opc = tf->tf_pc;
+       onpc = tf->tf_npc;
+
        new = handle_new(tf, &code);
 
+       tf->tf_npc = tf->tf_pc + 4;
+
        if ((error = getargs(p, tf, &code, &callp, &args)) != 0)
                goto bad;
 
@@ -236,29 +257,17 @@
                /* Note: fork() does not return here in the child */
                tf->tf_out[0] = rval.o[0];
                tf->tf_out[1] = rval.o[1];
-               if (new) {
-                       /* jmp %g5, (or %g2 or %g7, deprecated) on success */
-                       if (__predict_true((new & SYSCALL_G5RFLAG) ==
-                                       SYSCALL_G5RFLAG))
-                               i = tf->tf_global[5];
-                       else if (new & SYSCALL_G2RFLAG)
-                               i = tf->tf_global[2];
-                       else
-                               i = tf->tf_global[7];
-                       if (i & 3) {
-                               error = EINVAL;
-                               goto bad;
-                       }
-               } else {
+               if (!new) {
                        /* old system call convention: clear C on success */
                        tf->tf_psr &= ~PSR_C;   /* success */
-                       i = tf->tf_npc;
                }
-               tf->tf_pc = i;
-               tf->tf_npc = i + 4;
                break;
 
        case ERESTART:
+               tf->tf_pc = opc;
+               tf->tf_npc = onpc;
+               break;
+
        case EJUSTRETURN:
                /* nothing to do */
                break;
@@ -269,9 +278,8 @@
                        error = p->p_emul->e_errno[error];
                tf->tf_out[0] = error;
                tf->tf_psr |= PSR_C;    /* fail */
-               i = tf->tf_npc;
-               tf->tf_pc = i;
-               tf->tf_npc = i + 4;
+               tf->tf_pc = onpc;
+               tf->tf_npc = tf->tf_pc + 4;
                break;
        }
 
diff -r e26d88ee9b3e -r f5579bbc8be3 sys/arch/sparc/sparc/vm_machdep.c
--- a/sys/arch/sparc/sparc/vm_machdep.c Mon Mar 20 11:07:33 2023 +0000
+++ b/sys/arch/sparc/sparc/vm_machdep.c Mon Mar 20 11:19:29 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vm_machdep.c,v 1.107 2012/02/19 21:06:30 rmind Exp $ */
+/*     $NetBSD: vm_machdep.c,v 1.108 2023/03/20 11:19:29 hannken Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -49,7 +49,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.107 2012/02/19 21:06:30 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vm_machdep.c,v 1.108 2023/03/20 11:19:29 hannken Exp $");
 
 #include "opt_multiprocessor.h"
 
@@ -268,8 +268,6 @@
         * to user mode.
         */
        /*tf2->tf_psr &= ~PSR_C;   -* success */
-       tf2->tf_pc = tf2->tf_npc;
-       tf2->tf_npc = tf2->tf_pc + 4;
 
        /* Set return values in child mode */
        tf2->tf_out[0] = 0;
diff -r e26d88ee9b3e -r f5579bbc8be3 tests/lib/libc/sys/t_ptrace_syscall_wait.h
--- a/tests/lib/libc/sys/t_ptrace_syscall_wait.h        Mon Mar 20 11:07:33 2023 +0000
+++ b/tests/lib/libc/sys/t_ptrace_syscall_wait.h        Mon Mar 20 11:19:29 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: t_ptrace_syscall_wait.h,v 1.2 2021/10/21 17:02:37 gson Exp $   */
+/*     $NetBSD: t_ptrace_syscall_wait.h,v 1.3 2023/03/20 11:19:30 hannken Exp $        */
 
 /*-
  * Copyright (c) 2016, 2017, 2018, 2019, 2020 The NetBSD Foundation, Inc.
@@ -206,11 +206,6 @@
        int status;
 #endif
 
-#if defined(__sparc__) && !defined(__sparc64__)
-       /* syscallemu does not work on sparc (32-bit) */
-       atf_tc_expect_fail("PR kern/52166");
-#endif
-
        DPRINTF("Before forking process PID=%d\n", getpid());
        SYSCALL_REQUIRE((child = fork()) != -1);
        if (child == 0) {



Home | Main Index | Thread Index | Old Index