summaryrefslogtreecommitdiff
path: root/coregrind/m_syswrap/syswrap-main.c
diff options
context:
space:
mode:
Diffstat (limited to 'coregrind/m_syswrap/syswrap-main.c')
-rw-r--r--coregrind/m_syswrap/syswrap-main.c85
1 files changed, 78 insertions, 7 deletions
diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c
index 21f0f88d..4d33eb8d 100644
--- a/coregrind/m_syswrap/syswrap-main.c
+++ b/coregrind/m_syswrap/syswrap-main.c
@@ -60,14 +60,20 @@
/* Useful info which needs to be recorded somewhere:
Use of registers in syscalls is:
- NUM ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8 RESULT
+ NUM ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8 RESULT
LINUX:
- x86 eax ebx ecx edx esi edi ebp n/a n/a eax (== NUM)
- amd64 rax rdi rsi rdx r10 r8 r9 n/a n/a rax (== NUM)
- ppc32 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
- ppc64 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
- arm r7 r0 r1 r2 r3 r4 r5 n/a n/a r0 (== ARG1)
-
+ x86 eax ebx ecx edx esi edi ebp n/a n/a eax (== NUM)
+ amd64 rax rdi rsi rdx r10 r8 r9 n/a n/a rax (== NUM)
+ ppc32 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
+ ppc64 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
+ arm r7 r0 r1 r2 r3 r4 r5 n/a n/a r0 (== ARG1)
+ On s390x the svc instruction is used for system calls. The system call
+ number is encoded in the instruction (8 bit immediate field). Since Linux
+ 2.6 it is also allowed to use svc 0 with the system call number in r1.
+ This was introduced for system calls >255, but works for all. It is
+ also possible to see the svc 0 together with an EXecute instruction, that
+ fills in the immediate field.
+ s390x r1/SVC r2 r3 r4 r5 r6 r7 n/a n/a r2 (== ARG1)
AIX:
ppc32 r2 r3 r4 r5 r6 r7 r8 r9 r10 r3(res),r4(err)
ppc64 r2 r3 r4 r5 r6 r7 r8 r9 r10 r3(res),r4(err)
@@ -160,6 +166,9 @@
x86: Success(N) ==> edx:eax = N, cc = 0
Fail(N) ==> edx:eax = N, cc = 1
+ s390x: Success(N) ==> r2 = N
+ Fail(N) ==> r2 = -N
+
* The post wrapper is called if:
- it exists, and
@@ -611,6 +620,17 @@ void getSyscallArgsFromGuestState ( /*OUT*/SyscallArgs* canonical,
// no canonical->sysno adjustment needed
+#elif defined(VGP_s390x_linux)
+ VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
+ canonical->sysno = gst->guest_SYSNO;
+ canonical->arg1 = gst->guest_r2;
+ canonical->arg2 = gst->guest_r3;
+ canonical->arg3 = gst->guest_r4;
+ canonical->arg4 = gst->guest_r5;
+ canonical->arg5 = gst->guest_r6;
+ canonical->arg6 = gst->guest_r7;
+ canonical->arg7 = 0;
+ canonical->arg8 = 0;
#else
# error "getSyscallArgsFromGuestState: unknown arch"
#endif
@@ -728,6 +748,16 @@ void putSyscallArgsIntoGuestState ( /*IN*/ SyscallArgs* canonical,
stack[1] = canonical->arg7;
stack[2] = canonical->arg8;
+#elif defined(VGP_s390x_linux)
+ VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
+ gst->guest_SYSNO = canonical->sysno;
+ gst->guest_r2 = canonical->arg1;
+ gst->guest_r3 = canonical->arg2;
+ gst->guest_r4 = canonical->arg3;
+ gst->guest_r5 = canonical->arg4;
+ gst->guest_r6 = canonical->arg5;
+ gst->guest_r7 = canonical->arg6;
+
#else
# error "putSyscallArgsIntoGuestState: unknown arch"
#endif
@@ -842,6 +872,11 @@ void getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus* canonical,
);
canonical->what = SsComplete;
+# elif defined(VGP_s390x_linux)
+ VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
+ canonical->sres = VG_(mk_SysRes_s390x_linux)( gst->guest_r2 );
+ canonical->what = SsComplete;
+
# else
# error "getSyscallStatusFromGuestState: unknown arch"
# endif
@@ -1016,6 +1051,15 @@ void putSyscallStatusIntoGuestState ( /*IN*/ ThreadId tid,
break;
}
+# elif defined(VGP_s390x_linux)
+ VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
+ vg_assert(canonical->what == SsComplete);
+ if (sr_isError(canonical->sres)) {
+ gst->guest_r2 = - (Long)sr_Err(canonical->sres);
+ } else {
+ gst->guest_r2 = sr_Res(canonical->sres);
+ }
+
# else
# error "putSyscallStatusIntoGuestState: unknown arch"
# endif
@@ -1129,6 +1173,16 @@ void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout )
layout->s_arg7 = sizeof(UWord) * 1;
layout->s_arg8 = sizeof(UWord) * 2;
+#elif defined(VGP_s390x_linux)
+ layout->o_sysno = OFFSET_s390x_SYSNO;
+ layout->o_arg1 = OFFSET_s390x_r2;
+ layout->o_arg2 = OFFSET_s390x_r3;
+ layout->o_arg3 = OFFSET_s390x_r4;
+ layout->o_arg4 = OFFSET_s390x_r5;
+ layout->o_arg5 = OFFSET_s390x_r6;
+ layout->o_arg6 = OFFSET_s390x_r7;
+ layout->uu_arg7 = -1; /* impossible value */
+ layout->uu_arg8 = -1; /* impossible value */
#else
# error "getSyscallLayout: unknown arch"
#endif
@@ -1957,6 +2011,23 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch )
// DDD: #warning GrP fixme amd64 restart unimplemented
vg_assert(0);
+#elif defined(VGP_s390x_linux)
+ arch->vex.guest_IA -= 2; // sizeof(syscall)
+
+ /* Make sure our caller is actually sane, and we're really backing
+ back over a syscall.
+
+ syscall == 0A <num>
+ */
+ {
+ UChar *p = (UChar *)arch->vex.guest_IA;
+ if (p[0] != 0x0A)
+ VG_(message)(Vg_DebugMsg,
+ "?! restarting over syscall at %#llx %02x %02x\n",
+ arch->vex.guest_IA, p[0], p[1]);
+
+ vg_assert(p[0] == 0x0A);
+ }
#else
# error "ML_(fixup_guest_state_to_restart_syscall): unknown plat"
#endif