diff options
author | kib <kib@FreeBSD.org> | 2009-11-10 11:43:07 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2009-11-10 11:43:07 +0000 |
commit | 3cf53f181e7360f48fecc50a925d46029888af1d (patch) | |
tree | bba1aed931ce7ad22617119eb8a0f3b4e1652845 /sys/powerpc/aim/vm_machdep.c | |
parent | e256ac508b1a8eb7aedb8f720f3e650ecd273b53 (diff) | |
download | FreeBSD-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/powerpc/aim/vm_machdep.c')
-rw-r--r-- | sys/powerpc/aim/vm_machdep.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/sys/powerpc/aim/vm_machdep.c b/sys/powerpc/aim/vm_machdep.c index af83854..3967176 100644 --- a/sys/powerpc/aim/vm_machdep.c +++ b/sys/powerpc/aim/vm_machdep.c @@ -81,7 +81,9 @@ #include <sys/kernel.h> #include <sys/mbuf.h> #include <sys/sf_buf.h> +#include <sys/syscall.h> #include <sys/sysctl.h> +#include <sys/sysent.h> #include <sys/unistd.h> #include <machine/cpu.h> @@ -422,6 +424,59 @@ cpu_thread_swapout(struct thread *td) } void +cpu_set_syscall_retval(struct thread *td, int error) +{ + struct proc *p; + struct trapframe *tf; + int fixup; + + if (error == EJUSTRETURN) + return; + + p = td->td_proc; + tf = td->td_frame; + + if (tf->fixreg[0] == SYS___syscall) { + int code = tf->fixreg[FIRSTARG + 1]; + if (p->p_sysent->sv_mask) + code &= p->p_sysent->sv_mask; + fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek) ? + 1 : 0; + } else + fixup = 0; + + switch (error) { + case 0: + if (fixup) { + /* + * 64-bit return, 32-bit syscall. Fixup byte order + */ + tf->fixreg[FIRSTARG] = 0; + tf->fixreg[FIRSTARG + 1] = td->td_retval[0]; + } else { + tf->fixreg[FIRSTARG] = td->td_retval[0]; + tf->fixreg[FIRSTARG + 1] = td->td_retval[1]; + } + tf->cr &= ~0x10000000; /* XXX: Magic number */ + break; + case ERESTART: + /* + * Set user's pc back to redo the system call. + */ + tf->srr0 -= 4; + break; + default: + if (p->p_sysent->sv_errsize) { + error = (error < p->p_sysent->sv_errsize) ? + p->p_sysent->sv_errtbl[error] : -1; + } + tf->fixreg[FIRSTARG] = error; + tf->cr |= 0x10000000; /* XXX: Magic number */ + break; + } +} + +void cpu_set_upcall(struct thread *td, struct thread *td0) { struct pcb *pcb2; |