mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-04 02:18:37 +00:00
Merge patch from JeremyF:
39-lock-prefix Add a new UInstr LOCK to represent a "lock" prefix in the instruction stream. This has the same semantics as NOP, but allows a skin to tell whether a group of UInstrs associated with an x86 instruction are meant to be locked. HELGRIND: uses the LOCK UInstr to automatically take and release a special __BUS_HARDWARE_LOCK__ around locked instructions. This only works properly if all instructions touching a given address are locked (even reads). git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1310
This commit is contained in:
parent
ef4e9cecd5
commit
18b7ed0c53
@ -1752,7 +1752,7 @@ UCodeBlock* SK_(instrument)(UCodeBlock* cb_in, Addr orig_addr)
|
||||
u_in = &cb_in->instrs[i];
|
||||
|
||||
switch (u_in->opcode) {
|
||||
case NOP: case CALLM_E: case CALLM_S:
|
||||
case NOP: case LOCK: case CALLM_E: case CALLM_S:
|
||||
break;
|
||||
|
||||
/* For memory-ref instrs, copy the data_addr into a temporary to be
|
||||
|
||||
@ -731,7 +731,7 @@ UCodeBlock* SK_(instrument)(UCodeBlock* cb_in, Addr orig_addr)
|
||||
if (instrumented_Jcond) sk_assert(u_in->opcode == JMP);
|
||||
|
||||
switch (u_in->opcode) {
|
||||
case NOP: case CALLM_E: case CALLM_S:
|
||||
case NOP: case LOCK: case CALLM_E: case CALLM_S:
|
||||
break;
|
||||
|
||||
/* For memory-ref instrs, copy the data_addr into a temporary to be
|
||||
|
||||
@ -1981,7 +1981,7 @@ static void emitUInstr ( UCodeBlock* cb, Int i, RRegSet regs_live_before )
|
||||
old_emitted_code_used = emitted_code_used;
|
||||
|
||||
switch (u->opcode) {
|
||||
case NOP: case CALLM_S: case CALLM_E: break;
|
||||
case NOP: case LOCK: case CALLM_S: case CALLM_E: break;
|
||||
|
||||
case INCEIP: {
|
||||
/* Note: Redundant INCEIP merging. A potentially useful
|
||||
|
||||
@ -3254,6 +3254,7 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
|
||||
/* Skip a LOCK prefix. */
|
||||
if (getUChar(eip) == 0xF0) {
|
||||
/* VG_(printf)("LOCK LOCK LOCK LOCK LOCK \n"); */
|
||||
uInstr0(cb, LOCK, 0);
|
||||
eip++;
|
||||
}
|
||||
|
||||
|
||||
@ -476,6 +476,7 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u )
|
||||
case GETSEG: return LIT0 && SZ2 && CC0 && Se1 && TR2 && N3 && XOTHER;
|
||||
case USESEG: return LIT0 && SZ0 && CC0 && TR1 && TR2 && N3 && XOTHER;
|
||||
case NOP: return LIT0 && SZ0 && CC0 && N1 && N2 && N3 && XOTHER;
|
||||
case LOCK: return LIT0 && SZ0 && CC0 && N1 && N2 && N3 && XOTHER;
|
||||
case GETF: return LIT0 && SZ42 && CCr && TR1 && N2 && N3 && XOTHER;
|
||||
case PUTF: return LIT0 && SZ42 && CCw && TR1 && N2 && N3 && XOTHER;
|
||||
case GET: return LIT0 && SZi && CC0 && AS1 && TR2 && N3 && XOTHER;
|
||||
@ -799,6 +800,7 @@ Char* VG_(name_UOpcode) ( Bool upper, Opcode opc )
|
||||
case LEA1: return "LEA1";
|
||||
case LEA2: return "LEA2";
|
||||
case NOP: return "NOP";
|
||||
case LOCK: return "LOCK";
|
||||
case GET: return "GET";
|
||||
case PUT: return "PUT";
|
||||
case GETF: return "GETF";
|
||||
@ -919,7 +921,7 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness )
|
||||
VG_(pp_UOperand)(u, 2, 4, False);
|
||||
break;
|
||||
|
||||
case NOP:
|
||||
case NOP: case LOCK:
|
||||
break;
|
||||
|
||||
case FPU_W:
|
||||
@ -1092,7 +1094,7 @@ Int VG_(get_reg_usage) ( UInstr* u, Tag tag, RegUse* arr )
|
||||
case LEA2: RD(1); RD(2); WR(3); break;
|
||||
|
||||
case NOP: case FPU: case INCEIP: case CALLM_S: case CALLM_E:
|
||||
case CLEAR: case CALLM: break;
|
||||
case CLEAR: case CALLM: case LOCK: break;
|
||||
|
||||
case CCALL:
|
||||
if (u->argc > 0) RD(1);
|
||||
@ -1225,6 +1227,7 @@ Int maybe_uinstrReadsArchReg ( UInstr* u )
|
||||
case LEA1:
|
||||
case LEA2:
|
||||
case NOP:
|
||||
case LOCK:
|
||||
case PUT:
|
||||
case LOAD:
|
||||
case STORE:
|
||||
|
||||
@ -1732,6 +1732,9 @@ static void eraser_mem_help_write_2(Addr a, UInt val) REGPARM(2);
|
||||
static void eraser_mem_help_write_4(Addr a, UInt val) REGPARM(2);
|
||||
static void eraser_mem_help_write_N(Addr a, UInt size) REGPARM(2);
|
||||
|
||||
static void bus_lock(void);
|
||||
static void bus_unlock(void);
|
||||
|
||||
static
|
||||
void eraser_pre_mem_read(CorePart part, ThreadState* tst,
|
||||
Char* s, UInt base, UInt size )
|
||||
@ -1863,6 +1866,7 @@ UCodeBlock* SK_(instrument) ( UCodeBlock* cb_in, Addr not_used )
|
||||
Int t_size = INVALID_TEMPREG;
|
||||
Int ntemps;
|
||||
Bool *stackref = NULL;
|
||||
Bool locked = False; /* lock prefix */
|
||||
|
||||
cb = VG_(alloc_UCodeBlock)();
|
||||
cb->nextTemp = cb_in->nextTemp;
|
||||
@ -1883,6 +1887,21 @@ UCodeBlock* SK_(instrument) ( UCodeBlock* cb_in, Addr not_used )
|
||||
case NOP: case CALLM_S: case CALLM_E:
|
||||
break;
|
||||
|
||||
case LOCK:
|
||||
locked = True;
|
||||
uInstr0(cb, CCALL, 0);
|
||||
uCCall(cb, (Addr)bus_lock, 0, 0, False);
|
||||
break;
|
||||
|
||||
case JMP: case INCEIP:
|
||||
if (locked) {
|
||||
uInstr0(cb, CCALL, 0);
|
||||
uCCall(cb, (Addr)bus_unlock, 0, 0, False);
|
||||
}
|
||||
locked = False;
|
||||
VG_(copy_UInstr)(cb, u_in);
|
||||
break;
|
||||
|
||||
case GET:
|
||||
sk_assert(u_in->tag1 == ArchReg);
|
||||
sk_assert(u_in->tag2 == TempReg);
|
||||
@ -2935,6 +2954,21 @@ static void hg_thread_join(ThreadId joiner, ThreadId joinee)
|
||||
clearTLS(joinee);
|
||||
}
|
||||
|
||||
static Int __BUS_HARDWARE_LOCK__;
|
||||
|
||||
static void bus_lock(void)
|
||||
{
|
||||
ThreadId tid = VG_(get_current_tid)();
|
||||
eraser_pre_mutex_lock(tid, &__BUS_HARDWARE_LOCK__);
|
||||
eraser_post_mutex_lock(tid, &__BUS_HARDWARE_LOCK__);
|
||||
}
|
||||
|
||||
static void bus_unlock(void)
|
||||
{
|
||||
ThreadId tid = VG_(get_current_tid)();
|
||||
eraser_post_mutex_unlock(tid, &__BUS_HARDWARE_LOCK__);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------*/
|
||||
/*--- Client requests ---*/
|
||||
/*--------------------------------------------------------------------*/
|
||||
@ -3030,6 +3064,9 @@ void SK_(pre_clo_init)(VgDetails* details, VgNeeds* needs, VgTrackEvents* track)
|
||||
VG_(register_compact_helper)((Addr) & eraser_mem_help_write_4);
|
||||
VG_(register_noncompact_helper)((Addr) & eraser_mem_help_write_N);
|
||||
|
||||
VG_(register_noncompact_helper)((Addr) & bus_lock);
|
||||
VG_(register_noncompact_helper)((Addr) & bus_unlock);
|
||||
|
||||
for(i = 0; i < LOCKSET_HASH_SZ; i++)
|
||||
lockset_hash[i] = NULL;
|
||||
|
||||
|
||||
@ -492,6 +492,8 @@ typedef
|
||||
enum {
|
||||
NOP, /* Null op */
|
||||
|
||||
LOCK, /* Indicate the existance of a LOCK prefix (functionally NOP) */
|
||||
|
||||
/* Moving values around */
|
||||
GET, PUT, /* simulated register <--> TempReg */
|
||||
GETF, PUTF, /* simulated %eflags <--> TempReg */
|
||||
|
||||
@ -162,7 +162,7 @@ UCodeBlock* SK_(instrument)(UCodeBlock* cb_in, Addr orig_addr)
|
||||
u = &cb_in->instrs[i];
|
||||
|
||||
switch (u->opcode) {
|
||||
case NOP: case CALLM_S: case CALLM_E:
|
||||
case NOP: case LOCK: case CALLM_S: case CALLM_E:
|
||||
break;
|
||||
|
||||
case INCEIP:
|
||||
|
||||
@ -541,6 +541,7 @@ static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in )
|
||||
|
||||
switch (u_in->opcode) {
|
||||
|
||||
case LOCK:
|
||||
case NOP:
|
||||
break;
|
||||
|
||||
@ -1260,6 +1261,7 @@ static void vg_propagate_definedness ( UCodeBlock* cb )
|
||||
|
||||
/* Deal with these quickly. */
|
||||
case NOP:
|
||||
case LOCK:
|
||||
case INCEIP:
|
||||
break;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user