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:
Julian Seward 2002-11-13 22:42:13 +00:00
parent ef4e9cecd5
commit 18b7ed0c53
9 changed files with 51 additions and 6 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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++;
}

View File

@ -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:

View File

@ -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;

View File

@ -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 */

View File

@ -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:

View File

@ -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;