summaryrefslogtreecommitdiffstats
path: root/sys/arm
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-11-10 11:43:07 +0000
committerkib <kib@FreeBSD.org>2009-11-10 11:43:07 +0000
commit3cf53f181e7360f48fecc50a925d46029888af1d (patch)
treebba1aed931ce7ad22617119eb8a0f3b4e1652845 /sys/arm
parente256ac508b1a8eb7aedb8f720f3e650ecd273b53 (diff)
downloadFreeBSD-src-3cf53f181e7360f48fecc50a925d46029888af1d.zip
FreeBSD-src-3cf53f181e7360f48fecc50a925d46029888af1d.tar.gz
Extract the code that records syscall results in the frame into MD
function cpu_set_syscall_retval(). Suggested by: marcel Reviewed by: marcel, davidxu PowerPC, ARM, ia64 changes: marcel Sparc64 tested and reviewed by: marius, also sunv reviewed MIPS tested by: gonzo MFC after: 1 month
Diffstat (limited to 'sys/arm')
-rw-r--r--sys/arm/arm/trap.c37
-rw-r--r--sys/arm/arm/vm_machdep.c53
2 files changed, 54 insertions, 36 deletions
diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c
index e6150c0..348ec5a 100644
--- a/sys/arm/arm/trap.c
+++ b/sys/arm/arm/trap.c
@@ -932,43 +932,8 @@ syscall(struct thread *td, trapframe_t *frame, u_int32_t insn)
KASSERT(td->td_ar == NULL,
("returning from syscall with td_ar set!"));
}
- switch (error) {
- case 0:
-#ifdef __ARMEB__
- if ((insn & 0x000fffff) == SYS___syscall &&
- code != SYS_freebsd6_lseek && code != SYS_lseek) {
- /*
- * 64-bit return, 32-bit syscall. Fixup byte order
- */
- frame->tf_r0 = 0;
- frame->tf_r1 = td->td_retval[0];
- } else {
- frame->tf_r0 = td->td_retval[0];
- frame->tf_r1 = td->td_retval[1];
- }
-#else
- frame->tf_r0 = td->td_retval[0];
- frame->tf_r1 = td->td_retval[1];
-#endif
-
- frame->tf_spsr &= ~PSR_C_bit; /* carry bit */
- break;
-
- case ERESTART:
- /*
- * Reconstruct the pc to point at the swi.
- */
- frame->tf_pc -= INSN_SIZE;
- break;
- case EJUSTRETURN:
- /* nothing to do */
- break;
- default:
bad:
- frame->tf_r0 = error;
- frame->tf_spsr |= PSR_C_bit; /* carry bit */
- break;
- }
+ cpu_set_syscall_retval(td, error);
WITNESS_WARN(WARN_PANIC, NULL, "System call %s returning",
(code >= 0 && code < SYS_MAXSYSCALL) ? syscallnames[code] : "???");
diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c
index 6bd5799..95b9ca8 100644
--- a/sys/arm/arm/vm_machdep.c
+++ b/sys/arm/arm/vm_machdep.c
@@ -51,6 +51,8 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/socketvar.h>
#include <sys/sf_buf.h>
+#include <sys/syscall.h>
+#include <sys/sysent.h>
#include <sys/unistd.h>
#include <machine/cpu.h>
#include <machine/pcb.h>
@@ -261,6 +263,57 @@ done:
#endif
}
+void
+cpu_set_syscall_retval(struct thread *td, int error)
+{
+ trapframe_t *frame;
+ int fixup;
+#ifdef __ARMEB__
+ uint32_t insn;
+#endif
+
+ frame = td->td_frame;
+ fixup = 0;
+
+#ifdef __ARMEB__
+ insn = *(u_int32_t *)(frame->tf_pc - INSN_SIZE);
+ if ((insn & 0x000fffff) == SYS___syscall) {
+ register_t *ap = &frame->tf_r0;
+ register_t code = ap[_QUAD_LOWWORD];
+ if (td->td_proc->p_sysent->sv_mask)
+ code &= td->td_proc->p_sysent->sv_mask;
+ fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek)
+ ? 1 : 0;
+ }
+#endif
+
+ switch (error) {
+ case 0:
+ if (fixup) {
+ frame->tf_r0 = 0;
+ frame->tf_r1 = td->td_retval[0];
+ } else {
+ frame->tf_r0 = td->td_retval[0];
+ frame->tf_r1 = td->td_retval[1];
+ }
+ frame->tf_spsr &= ~PSR_C_bit; /* carry bit */
+ break;
+ case ERESTART:
+ /*
+ * Reconstruct the pc to point at the swi.
+ */
+ frame->tf_pc -= INSN_SIZE;
+ break;
+ case EJUSTRETURN:
+ /* nothing to do */
+ break;
+ default:
+ frame->tf_r0 = error;
+ frame->tf_spsr |= PSR_C_bit; /* carry bit */
+ break;
+ }
+}
+
/*
* Initialize machine state (pcb and trap frame) for a new thread about to
* upcall. Put enough state in the new thread's PCB to get it to go back
OpenPOWER on IntegriCloud