- ISA 3.1 support is now complete
- ISA 3.0 support for the darn instruction added.
+ - ISA 3.0 support for the vector system call instruction scv added.
* ==================== TOOL CHANGES ====================
423963 Error in child thread when CLONE_PIDFD is used
429375 PPC ISA 3.1 support is missing, part 9
+431157 PPC_FEATURE2_SCV needs to be masked in AT_HWCAP2
433801 PPC ISA 3.1 support is missing, part 10 (ISA 3.1 support complete)
433863 s390x: memcheck/tests/s390x/{cds,cs,csg} failures
434840 PPC64 darn instruction not supported
#endif /* ndef __VEX_GUEST_PPC_DEFS_H */
+/* SCV flag defines. Must be consistently defined here and in
+ coregrind/pub_core_syscall.h,in the do_syscall_WRK() assembly code in
+ coregrind/m_syscall.c and coregrind/m_syswrap/syscall-ppc64le-linux.S
+ code. */
+#define SC_FLAG 1
+#define SCV_FLAG 2
+
/*---------------------------------------------------------------*/
/*--- end guest_ppc_defs.h ---*/
/*---------------------------------------------------------------*/
#define OFFB_ACC_7_r1 offsetofPPCGuestState(guest_ACC_7_r1)
#define OFFB_ACC_7_r2 offsetofPPCGuestState(guest_ACC_7_r2)
#define OFFB_ACC_7_r3 offsetofPPCGuestState(guest_ACC_7_r3)
+#define OFFB_syscall_flag offsetofPPCGuestState(guest_syscall_flag)
/*------------------------------------------------------------*/
return mkexpr(val);
}
+static void put_syscall_flag( IRExpr* src )
+{
+ /* Need to pass a flag indicating if the system call is using the sc or
+ scv instructions. Because Valgrind does an end-of-block after the
+ system call, the contents of a gpr can not be saved and restored after
+ the system call. A custom guest state register guest_syscall_flag is
+ used to pass the flag so the guest state is not disturbed. */
+
+ stmt( IRStmt_Put( offsetofPPCGuestState(guest_syscall_flag), src ) );
+}
+
+
/*-----------------------------------------------------------*/
/* Helpers to access VSX Accumulator register file
*-----------------------------------------------------------*/
/*
System Linkage Instructions
*/
+
static Bool dis_syslink ( UInt prefix, UInt theInstr,
const VexAbiInfo* abiinfo, DisResult* dres )
{
/* There is no prefixed version of these instructions. */
PREFIX_CHECK
- if (theInstr != 0x44000002) { // sc
- if (theInstr != 0x44000001) // scv
- vex_printf("dis_syslink(ppc)(theInstr)\n");
+ if ((theInstr != 0x44000002) // sc
+ && (theInstr != 0x44000001)) { // scv
+ vex_printf("dis_syslink(ppc)(theInstr)\n");
return False;
}
- // sc (System Call, PPC32 p504)
- DIP("sc\n");
+ /* The PPC syscall uses guest_GPR9 to pass a flag to indicate which
+ system call instruction is to be used. Arg7 = SC_FLAG for the sc
+ instruction; Arg7 = SCV_FLAG for the scv instruction. */
+ if (theInstr == 0x44000002) {
+ // sc (System Call, PPC32 p504)
+ DIP("sc\n");
+ put_syscall_flag( mkU32(SC_FLAG) );
+ } else if (theInstr == 0x44000001) {
+ // scv
+ DIP("scv\n");
+ put_syscall_flag( mkU32(SCV_FLAG) );
+ } else {
+ /* Unknown instruction */
+ return False;
+ }
/* Copy CIA into the IP_AT_SYSCALL pseudo-register, so that on Darwin
Valgrind can back the guest up to this instruction if it needs
goto decode_failure;
/* System Linkage Instructions */
- case 0x11: // sc
- if (dis_syslink( prefix, theInstr, abiinfo, &dres)) goto decode_success;
+ case 0x11: // sc, scv
+ if (dis_syslink( prefix, theInstr, abiinfo, &dres))
+ goto decode_success;
goto decode_failure;
/* Trap Instructions */
#define VEX_HWCAPS_PPC64_ISA2_07 (1<<20) /* ISA 2.07 -- e.g., mtvsrd */
#define VEX_HWCAPS_PPC64_ISA3_0 (1<<22) /* ISA 3.0 -- e.g., cnttzw */
#define VEX_HWCAPS_PPC64_ISA3_1 (1<<23) /* ISA 3.1 -- e.g., brh */
+#define VEX_HWCAPS_PPC64_SCV (1<<24) /* ISA 3.0, Kernel supports scv
+ instruction. */
/* s390x: Hardware capability encoding
/* 1924 */ U128 guest_ACC_7_r3;
/* Padding to make it have an 16-aligned size */
- /* 1940 */ UInt padding2;
-// /* 1944 */ UInt padding3;
-// /* 1948 */ UInt padding4;
+ /* 1940 */ UInt guest_syscall_flag;
+ /* 1944 * UInt padding2; */
}
VexGuestPPC32State;
/* 2192 */ U128 guest_ACC_7_r2;
/* 2208 */ U128 guest_ACC_7_r3;
+ /* 2224 */ UInt guest_syscall_flag;
+ /* 2228 */ UInt padding1;
+ /* 2232 */ UInt padding2;
+ /* 2236 */ UInt padding3;
/* Padding to make it have an 16-aligned size */
/* 2222 UInt padding0; */
}
Bool auxv_2_07, hw_caps_2_07;
Bool auxv_3_0, hw_caps_3_0;
Bool auxv_3_1, hw_caps_3_1;
+ Bool auxv_scv_supported, hw_caps_scv_supported;
/* The HWCAP2 field may contain an arch_2_07 entry that indicates
* if the processor is compliant with the 2.07 ISA. (i.e. Power 8
ADD PUBLIC LINK WHEN AVAILABLE
*/
+
+ /* Check for SCV support */
+ auxv_scv_supported = (auxv->u.a_val & 0x00100000ULL)
+ == 0x00100000ULL;
+ hw_caps_scv_supported =
+ (vex_archinfo->hwcaps & VEX_HWCAPS_PPC64_SCV)
+ == VEX_HWCAPS_PPC64_SCV;
+
+ /* Verify the scv_supported setting in HWCAP2 matches the setting
+ in VEX HWCAPS.
+ */
+ vg_assert(auxv_scv_supported == hw_caps_scv_supported);
+
/* ISA 3.1 */
auxv_3_1 = (auxv->u.a_val & 0x00040000ULL) == 0x00040000ULL;
hw_caps_3_1 = (vex_archinfo->hwcaps & VEX_HWCAPS_PPC64_ISA3_1)
| 0x04000000ULL /* TAR */
| 0x04000000ULL /* VEC_CRYPTO */
| 0x00800000ULL /* ARCH_3_00 */
+ | 0x00100000ULL /* PPC_FEATURE2_SCV */
| 0x00400000ULL /* HAS_IEEE128 */
| 0x00200000ULL /* PPC_FEATURE2_DARN */
| 0x00040000ULL); /* ARCH_3_1 */
volatile Bool have_F, have_V, have_FX, have_GX, have_VX, have_DFP;
volatile Bool have_isa_2_07, have_isa_3_0, have_isa_3_1;
+ volatile Bool have_scv_support;
Int r;
/* This is a kludge. Really we ought to back-convert saved_act
__asm__ __volatile__(".long 0x7f1401b6"); /* brh RA, RS */
}
+ /* Check if Host supports scv instruction */
+ have_scv_support = True;
+ if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
+ have_scv_support = False;
+ } else {
+ /* Set r0 to 13 for the system time call. Don't want to make a random
+ system call. */
+ __asm__ __volatile__(".long 0x7c000278"); /* clear r0 */
+ __asm__ __volatile__(".long 0x6009000d"); /* set r0 to 13 */
+ __asm__ __volatile__(".long 0x44000001"); /* scv */
+ }
+
/* determine dcbz/dcbzl sizes while we still have the signal
* handlers registered */
find_ppc_dcbz_sz(&vai);
if (have_isa_2_07) vai.hwcaps |= VEX_HWCAPS_PPC64_ISA2_07;
if (have_isa_3_0) vai.hwcaps |= VEX_HWCAPS_PPC64_ISA3_0;
if (have_isa_3_1) vai.hwcaps |= VEX_HWCAPS_PPC64_ISA3_1;
+ if (have_scv_support) vai.hwcaps |= VEX_HWCAPS_PPC64_SCV;
VG_(machine_get_cache_info)(&vai);
{
ULong err = (uc->uc_mcontext.gp_regs[VKI_PT_CCR] >> 28) & 1;
ULong r3 = uc->uc_mcontext.gp_regs[VKI_PT_R3];
+ ThreadId tid = VG_(lwpid_to_vgtid)(VG_(gettid)());
+ ThreadState *tst = VG_(get_ThreadState)(tid);
+
if (err) r3 &= 0xFF;
- return VG_(mk_SysRes_ppc64_linux)( r3, err );
+ return VG_(mk_SysRes_ppc64_linux)( r3, err,
+ tst->arch.vex.guest_syscall_flag);
}
# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \
{ (srP)->r_pc = (uc)->uc_mcontext.gp_regs[VKI_PT_NIP]; \
return res;
}
-/* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */
-SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) {
+/* As per ppc32 version, for the sc instruction cr0.so must be in
+ l.s.b. of 2nd arg.
+ For the scv 0 instruction, the return value indicates failure if
+ it is -4095..-1 (i.e., it is >= -MAX_ERRNO (-4095) as an unsigned
+ comparison), in which case the error value is the negated return value. */
+SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so, UInt flag ) {
SysRes res;
- res._isError = (cr0so & 1) != 0;
- res._val = val;
+
+ if (flag == SC_FLAG) {
+ /* sc instruction */
+ res._isError = (cr0so & 1) != 0;
+ res._val = val;
+ } else if (flag == SCV_FLAG) {
+ /* scv instruction */
+ if ( (Long)val >= -4095 && (Long)val <= -1) {
+ res._isError = True;
+ res._val = (ULong)(-val);
+ } else {
+ res._isError = False;
+ res._val = (ULong)(val);
+ }
+ } else
+ vg_assert(0);
return res;
}
" addi 2,2,.TOC.-0b@l\n"
" .localentry do_syscall_WRK, .-do_syscall_WRK\n"
"#endif" "\n"
+/* Check which system call instruction to issue*/
+" ld 8, 56(3)\n" /* arg 7 holds sc/scv flag */
+" cmpdi 8,1\n" /* check sc/scv flag not equal to SC_FLAG*/
+" bne issue_scv\n"
+
+/* setup and issue the sc instruction */
" std 3,-16(1)\n" /* stash arg */
" ld 8, 48(3)\n" /* sc arg 6 */
" ld 7, 40(3)\n" /* sc arg 5 */
" srwi 3,3,28\n"
" andi. 3,3,1\n"
" std 3,8(5)\n" /* argblock[1] = cr0.s0 & 1 */
+" blr\n" /* return */
+
+/* setup to do scv instruction */
+"issue_scv: "
+/* The scv instruction requires a new stack frame */
+" stdu 1,-80(1)\n"
+" std 27,40(1)\n" /* save r27 to stack frame */
+" mflr 27\n" /* Get link register */
+" std 27,16(1)\n" /* Save link register */
+
+/* setup and issue the scv instruction */
+" std 3,-16(1)\n" /* stash arg */
+" ld 8, 48(3)\n" /* sc arg 6 */
+" ld 7, 40(3)\n" /* sc arg 5 */
+" ld 6, 32(3)\n" /* sc arg 4 */
+" ld 5, 24(3)\n" /* sc arg 3 */
+" ld 4, 16(3)\n" /* sc arg 2 */
+" ld 0, 0(3)\n" /* sc number */
+" ld 3, 8(3)\n" /* sc arg 1 */
+" scv 0\n"
+" ld 5,-16(1)\n" /* reacquire argblock ptr (r5 is caller-save) */
+" std 3,0(5)\n" /* argblock[0] = r3 */
+
+/* pop off stack frame */
+" ld 27,16(1)\n" /* Fetch LR from frame */
+" mtlr 27\n" /* restore LR */
+" ld 27,40(1)\n" /* restore r27 from stack frame */
+" addi 1,1,80\n"
" blr\n"
" .size do_syscall_WRK, .-do_syscall_WRK\n"
);
return VG_(mk_SysRes_ppc32_linux)( val, cr0so );
# elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
- ULong argblock[7];
+ ULong argblock[8];
+ /* PPC system calls have at most 6 arguments. The Valgrind infrastructure
+ supports 8 system call arguments. Argument 7 is used on PPC LE to pass
+ the flag indicating if the sc or scv instruction should be used for the
+ system call. */
argblock[0] = sysno;
argblock[1] = a1;
argblock[2] = a2;
argblock[4] = a4;
argblock[5] = a5;
argblock[6] = a6;
+ argblock[7] = a7;
do_syscall_WRK( &argblock[0] );
- return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1] );
+ return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1], a7 );
# elif defined(VGP_arm_linux)
UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno);
Int o_sysno;
# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
|| defined(VGP_ppc32_linux) \
- || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
|| defined(VGP_arm_linux) || defined(VGP_s390x_linux) \
|| defined(VGP_arm64_linux) \
|| defined(VGP_nanomips_linux)
Int o_arg6;
Int uu_arg7;
Int uu_arg8;
+# elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
+ Int o_arg1;
+ Int o_arg2;
+ Int o_arg3;
+ Int o_arg4;
+ Int o_arg5;
+ Int o_arg6;
+ Int o_arg7;
+ Int uu_arg8;
# elif defined(VGP_mips32_linux)
Int o_arg1;
Int o_arg2;
Int sigsetSzB) // r7
*/
/* from vki_arch.h */
+
+/* SCV flag defines. Must be consistently defined here and in
+ coregrind/pub_core_syscall.h,in the do_syscall_WRK() assembly code in
+ coregrind/m_syscall.c and coregrind/m_syswrap/syscall-ppcle-linux.S code.
+*/
+#define SC_FLAG 1
+#define SCV_FLAG 2
+
#define VKI_SIG_SETMASK 2
.align 2
std 30,64(1)
std 29,56(1)
std 28,48(1)
+ std 27,40(1) /* save r27 to stack frame */
+ mflr 27 /* Get link register */
+ std 27,16(1) /* Save link register */
+ std 9,32(1) /* save gpr 9 */
mr 31,3 /* syscall number */
mr 30,4 /* guest_state */
mr 29,6 /* postmask */
ld 6,OFFSET_ppc64_GPR6(30)
ld 7,OFFSET_ppc64_GPR7(30)
ld 8,OFFSET_ppc64_GPR8(30)
+ ld 9,OFFSET_ppc64_GPR9(30) /* get flag for sc or scv inst */
mr 0,31 /* syscall number */
+ cmpdi 9,SC_FLAG
+ bne 8f /* jump to scv call if gpr9 != 0 */
+ /* If you change the code between labels 2 and 3, you need to update
+ the corresponding ppc64le calculations for blksys_restart and
+ blksys_complete in function getSyscallArgsFromGuestState in file
+ syswrap-main.c. */
2: sc /* do the syscall */
+ b 3f /* jump over scv call */
+8: scv 0
/* put the result back in the threadstate */
3: std 3,OFFSET_ppc64_GPR3(30) /* gst->GPR3 = sc result */
+
/* copy cr0.so back to simulated state */
mfcr 5 /* r5 = CR */
rlwinm 5,5,4,31,31 /* r5 = (CR >> 28) & 1 */
+ ld 9,OFFSET_ppc64_GPR9(30)
+ cmpdi 9,SC_FLAG
+ bne 4f /* scv does not change CR */
stb 5,OFFSET_ppc64_CR0_0(30) /* gst->CR0.SO = cr0.so */
/* block signals again */
ld 29,56(1)
ld 30,64(1)
ld 31,72(1)
+ ld 9,32(1)
+ ld 27,16(1) /* Fetch LR from frame */
+ mtlr 27 /* restore LR */
+ ld 27,40(1) /* restore r27 from stack frame */
addi 1,1,80
blr
#elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
ULong word64;
UInt old_cr = LibVEX_GuestPPC64_get_CR( &ctst->arch.vex );
+ UInt flag = ctst->arch.vex.guest_syscall_flag;
/* %r3 = 0 */
ctst->arch.vex.guest_GPR3 = 0;
/* %cr0.so = 0 */
/* VG_(printf)("word64 = 0x%llx\n", word64); */
res = VG_(mk_SysRes_ppc64_linux)
(/*val*/(UInt)(word64 & 0xFFFFFFFFULL),
- /*errflag*/ (UInt)((word64 >> (32+28)) & 1));
+ /*errflag*/ (UInt)((word64 >> (32+28)) & 1), flag);
#elif defined(VGP_s390x_linux)
ULong r2;
ctst->arch.vex.guest_r2 = 0;
canonical->arg4 = gst->guest_GPR6;
canonical->arg5 = gst->guest_GPR7;
canonical->arg6 = gst->guest_GPR8;
- canonical->arg7 = 0;
+ /* ISA 3.0 adds the scv system call instruction.
+ The PPC syscalls have at most 6 args. Arg 7 is being used to pass a
+ flag to indicate which system call instruction is to be used.
+ Arg7 = SC_FLAG for the sc instruction; Arg7 = SCV_FLAG for the scv
+ instruction. The guest register guest_syscall_flag was created to pass
+ the flag so the actual guest state would not be changed. */
+ canonical->arg7 = gst->guest_syscall_flag;
canonical->arg8 = 0;
+#if defined(VGP_ppc64be_linux)
+ /* The sc instruction is currently only supported on LE systems. */
+ vg_assert(gst->guest_syscall_flag == SC_FLAG);
+#endif
+
#elif defined(VGP_arm_linux)
VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla;
canonical->sysno = gst->guest_R7;
gst->guest_GPR6 = canonical->arg4;
gst->guest_GPR7 = canonical->arg5;
gst->guest_GPR8 = canonical->arg6;
+ gst->guest_GPR9 = canonical->arg7;
#elif defined(VGP_arm_linux)
VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla;
canonical->what = SsComplete;
# elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
+ /* There is a Valgrind specific guest state register guest_syscall_flag
+ that is set to zero to indicate if the sc instruction was used or one
+ if the scv instruction was used for the system call. */
VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla;
UInt cr = LibVEX_GuestPPC64_get_CR( gst );
UInt cr0so = (cr >> 28) & 1;
- canonical->sres = VG_(mk_SysRes_ppc64_linux)( gst->guest_GPR3, cr0so );
+ UInt flag = gst->guest_syscall_flag;
+
+ canonical->sres = VG_(mk_SysRes_ppc64_linux)( gst->guest_GPR3, cr0so, flag );
canonical->what = SsComplete;
# elif defined(VGP_arm_linux)
# elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
VexGuestPPC64State* gst = (VexGuestPPC64State*)gst_vanilla;
UInt old_cr = LibVEX_GuestPPC64_get_CR(gst);
+ UInt flag = gst->guest_syscall_flag;
+
vg_assert(canonical->what == SsComplete);
- if (sr_isError(canonical->sres)) {
- /* set CR0.SO */
- LibVEX_GuestPPC64_put_CR( old_cr | (1<<28), gst );
- gst->guest_GPR3 = sr_Err(canonical->sres);
+ if (flag == SC_FLAG) {
+ /* sc syscall */
+ if (sr_isError(canonical->sres)) {
+ /* set CR0.SO */
+ LibVEX_GuestPPC64_put_CR( old_cr | (1<<28), gst );
+ gst->guest_GPR3 = sr_Err(canonical->sres);
+ } else {
+ /* clear CR0.SO */
+ LibVEX_GuestPPC64_put_CR( old_cr & ~(1<<28), gst );
+ gst->guest_GPR3 = sr_Res(canonical->sres);
+ }
+ VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
+ OFFSET_ppc64_GPR3, sizeof(UWord) );
+ VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
+ OFFSET_ppc64_CR0_0, sizeof(UChar) );
} else {
- /* clear CR0.SO */
- LibVEX_GuestPPC64_put_CR( old_cr & ~(1<<28), gst );
- gst->guest_GPR3 = sr_Res(canonical->sres);
+ /* scv system call instruction */
+ if (sr_isError(canonical->sres))
+ gst->guest_GPR3 = - (Long)canonical->sres._val;
+ else
+ gst->guest_GPR3 = canonical->sres._val;
+
+ VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
+ OFFSET_ppc64_GPR3, sizeof(UWord) );
}
- VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
- OFFSET_ppc64_GPR3, sizeof(UWord) );
- VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
- OFFSET_ppc64_CR0_0, sizeof(UChar) );
# elif defined(VGP_arm_linux)
VexGuestARMState* gst = (VexGuestARMState*)gst_vanilla;
layout->o_arg4 = OFFSET_ppc64_GPR6;
layout->o_arg5 = OFFSET_ppc64_GPR7;
layout->o_arg6 = OFFSET_ppc64_GPR8;
- layout->uu_arg7 = -1; /* impossible value */
+ layout->o_arg7 = OFFSET_ppc64_GPR9;
layout->uu_arg8 = -1; /* impossible value */
#elif defined(VGP_arm_linux)
back over a syscall.
sc == 44 00 00 02
+ or
+ scv == 44 00 00 01
*/
{
UChar *p = (UChar *)arch->vex.guest_CIA;
- if (p[3] != 0x44 || p[2] != 0x0 || p[1] != 0x0 || p[0] != 0x02)
+ if (!(p[3] == 0x44 && p[2] == 0x0 && p[1] == 0x0
+ && (p[0] == 0x01 || p[0] == 0x02)))
VG_(message)(Vg_DebugMsg,
"?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
arch->vex.guest_CIA, p[3], p[2], p[1], p[0]);
- vg_assert(p[3] == 0x44 && p[2] == 0x0 && p[1] == 0x0 && p[0] == 0x2);
+ vg_assert(p[3] == 0x44 && p[2] == 0x0 && p[1] == 0x0
+ && (p[0] == 0x1 || p[0] == 0x2));
}
#elif defined(VGP_arm_linux)
= ip < ML_(blksys_setup) || ip >= ML_(blksys_finished);
in_setup_to_restart
= ip >= ML_(blksys_setup) && ip < ML_(blksys_restart);
+
+#if defined(VGP_ppc64le_linux)
+ /* Starting with ISA 3.0, Power supports two system call instructions sc
+ and scv. The code in file syscall-ppc64[be|le]-linux.S uses an input
+ to call the requested system call. The definitions for blksys_restart
+ and blksys_complete must account for being at either of the two system
+ calls and account for the branch to lable 3 if the sc instruction was
+ called. at_restart is true if the ip is at either system call
+ instruction. in_complete_to_committed is true if the ip is between
+ blksys_complete and blksys_committed OR at the branch after the sc
+ instruction. The scv instruction is currently only supported on LE. */
+ at_restart
+ = (ip == ML_(blksys_restart)) || ((ip-8) == ML_(blksys_restart));
+ in_complete_to_committed
+ = (ip >= ML_(blksys_complete) && ip < ML_(blksys_committed)) ||
+ ((ip+8) == ML_(blksys_complete));
+#else
at_restart
= ip == ML_(blksys_restart);
in_complete_to_committed
= ip >= ML_(blksys_complete) && ip < ML_(blksys_committed);
+#endif
+
in_committed_to_finished
= ip >= ML_(blksys_committed) && ip < ML_(blksys_finished);
# elif defined(VGO_darwin)
#include "pub_core_basics.h" // VG_ macro
+/* PPC64 supports two system call instructions. The flags are used to
+ identify which of the two system call instructions sc or scv is to be
+ used. The following flags must be consistently defined here and in
+ VEX/priv/guest_ppc_defs.h, in the do_syscall_WRK() assembly code
+ below and coregrind/m_syswrap/syscall-ppcle-linux.S code. */
+#define SC_FLAG 1
+#define SCV_FLAG 2
+
//--------------------------------------------------------------------
// PURPOSE: This module contains the code for actually executing syscalls.
//--------------------------------------------------------------------
/* Macros make life easier. */
-#define vgPlain_do_syscall0(s) VG_(do_syscall)((s),0,0,0,0,0,0,0,0)
+#if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
+/* PPC64 uses the 7th argument to pass a flag indicating if the sc or scv
+ instruction is to be used for the system call. Need to set the flag to the
+ sc instruction by default. */
+#define A7 SC_FLAG
+#else
+#define A7 0
+#endif
+
+#define vgPlain_do_syscall0(s) VG_(do_syscall)((s),0,0,0,0,0,0,A7,0)
+
#define vgPlain_do_syscall1(s,a) VG_(do_syscall)((s),(a),\
- 0,0,0,0,0,0,0)
+ 0,0,0,0,0,A7,0)
#define vgPlain_do_syscall2(s,a,b) VG_(do_syscall)((s),(a),(b),\
- 0,0,0,0,0,0)
+ 0,0,0,0,A7,0)
#define vgPlain_do_syscall3(s,a,b,c) VG_(do_syscall)((s),(a),(b),(c),\
- 0,0,0,0,0)
+ 0,0,0,A7,0)
#define vgPlain_do_syscall4(s,a,b,c,d) VG_(do_syscall)((s),(a),(b),(c),\
- (d),0,0,0,0)
+ (d),0,0,A7,0)
#define vgPlain_do_syscall5(s,a,b,c,d,e) VG_(do_syscall)((s),(a),(b),(c),\
- (d),(e),0,0,0)
+ (d),(e),0,A7,0)
#define vgPlain_do_syscall6(s,a,b,c,d,e,f) VG_(do_syscall)((s),(a),(b),(c),\
- (d),(e),(f),0,0)
+ (d),(e),(f),A7,0)
#define vgPlain_do_syscall7(s,a,b,c,d,e,f,g) VG_(do_syscall)((s),(a),(b),(c),\
(d),(e),(f),(g),0)
#define vgPlain_do_syscall8(s,a,b,c,d,e,f,g,h) VG_(do_syscall)((s),(a),(b),(c),\
extern SysRes VG_(mk_SysRes_x86_linux) ( Int val );
extern SysRes VG_(mk_SysRes_amd64_linux) ( Long val );
extern SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so );
-extern SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so );
+extern SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so, UInt flag );
extern SysRes VG_(mk_SysRes_arm_linux) ( Int val );
extern SysRes VG_(mk_SysRes_arm64_linux) ( Long val );
extern SysRes VG_(mk_SysRes_x86_darwin) ( UChar scclass, Bool isErr,
extern const HChar* VG_(strerror) ( UWord errnum );
-
#endif // __PUB_CORE_SYSCALL_H
/*--------------------------------------------------------------------*/
return 0+ GOF(ACC_7_r2);
if (o >= GOF(ACC_7_r3) && o+sz <= GOF(ACC_7_r3)+SZB(ACC_7_r3))
return 0+ GOF(ACC_7_r3);
+ if (o == GOF(syscall_flag) && sz == 4) return -1;
VG_(printf)("MC_(get_otrack_shadow_offset)(ppc64)(off=%d,sz=%d)\n",
offset,szB);
test_isa_3_1_AT.vgtest test_isa_3_1_AT.stderr.exp test_isa_3_1_AT.stdout.exp \
subnormal_test.stderr.exp subnormal_test.stdout.exp \
subnormal_test.vgtest test_darn_inst.stderr.exp \
- test_darn_inst.stdout.exp test_darn_inst.vgtest
+ test_darn_inst.stdout.exp test_darn_inst.vgtest \
+ scv_test.stderr.exp scv_test.stdout.exp scv_test.vgtest
check_PROGRAMS = \
allexec \
subnormal_test test_darn_inst \
test_tm test_touch_tm data-cache-instructions \
power6_mf_gpr std_reg_imm \
- twi_tdi tw_td power6_bcmp
+ twi_tdi tw_td power6_bcmp scv_test
# lmw, stmw, lswi, lswx, stswi, stswx compile (and run) only on big endian.
if VGCONF_PLATFORMS_INCLUDE_PPC64BE_LINUX
--- /dev/null
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <asm/unistd.h>
+#include <sys/auxv.h>
+
+
+#define ASM_INPUT_0 "0" (r0)
+
+#define INTERNAL_SYSCALL_SCV(name, nr) \
+ ({ \
+ register long int r0 __asm__ ("r0"); \
+ register long int r3 __asm__ ("r3"); \
+ register long int r4 __asm__ ("r4"); \
+ register long int r5 __asm__ ("r5"); \
+ register long int r6 __asm__ ("r6"); \
+ register long int r7 __asm__ ("r7"); \
+ register long int r8 __asm__ ("r8"); \
+ r0=name; \
+ __asm__ __volatile__ \
+ ("scv 0\n\t" \
+ "0:" \
+ : "=&r" (r0), \
+ "=&r" (r3), "=&r" (r4), "=&r" (r5), \
+ "=&r" (r6), "=&r" (r7), "=&r" (r8) \
+ : ASM_INPUT_##nr \
+ : "r9", "r10", "r11", "r12", \
+ "cr0", "cr1", "cr5", "cr6", "cr7", "xer", \
+ "lr", "ctr", "memory"); \
+ r3; \
+ })
+
+#define INTERNAL_SYSCALL_SC(name, nr) \
+ ({ \
+ register long int r0 __asm__ ("r0"); \
+ register long int r3 __asm__ ("r3"); \
+ register long int r4 __asm__ ("r4"); \
+ register long int r5 __asm__ ("r5"); \
+ register long int r6 __asm__ ("r6"); \
+ register long int r7 __asm__ ("r7"); \
+ register long int r8 __asm__ ("r8"); \
+ r0=name; \
+ __asm__ __volatile__ \
+ ("sc\n\t" \
+ "mfcr %0\n\t" \
+ "0:" \
+ : "=&r" (r0), \
+ "=&r" (r3), "=&r" (r4), "=&r" (r5), \
+ "=&r" (r6), "=&r" (r7), "=&r" (r8) \
+ : ASM_INPUT_##nr \
+ : "r9", "r10", "r11", "r12", \
+ "xer", "cr0", "ctr", "memory"); \
+ r0 & (1 << 28) ? -r3 : r3; \
+ })
+
+#define PPC_FEATURE2_SCV 0x00100000 /* scv syscall enabled */
+
+int
+main(void)
+{
+ int result;
+ unsigned long hwcaps2_val;
+
+ result = INTERNAL_SYSCALL_SC(__NR_gettid, 0);
+
+ if (result < 0) {
+ printf("The sc instruction test unexpectedly failed\n");
+ exit (-1);
+ }
+
+ hwcaps2_val = getauxval(AT_HWCAP2);
+
+ if ((hwcaps2_val & PPC_FEATURE2_SCV) == PPC_FEATURE2_SCV) {
+ /* system supports the scv instruction */
+ result = INTERNAL_SYSCALL_SCV(__NR_gettid, 0);
+
+ if (result < 0) {
+ printf("The scv instruction test unexpectedly failed\n");
+ exit (-1);
+ }
+ }
+
+ printf("Success\n");
+ return 0;
+}
--- /dev/null
+prereq:
+prog: scv_test