Skip to content

Commit

Permalink
translate-all: exit from tb_phys_invalidate if qht_remove fails
Browse files Browse the repository at this point in the history
Two or more threads might race while invalidating the same TB. We currently
do not check for this at all despite taking tb_lock, which means we would
wrongly invalidate the same TB more than once. This bug has actually been
hit by users: I recently saw a report on IRC, although I have yet to see
the corresponding test case.

Fix this by using qht_remove as the synchronization point; if it fails,
that means the TB has already been invalidated, and therefore there
is nothing left to do in tb_phys_invalidate.

Note that this solution works now that we still have tb_lock, and will
continue working once we remove tb_lock.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Emilio G. Cota <cota@braap.org>
Message-Id: <1508445114-4717-1-git-send-email-cota@braap.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
cota authored and rth7680 committed Oct 24, 2017
1 parent 1c2adb9 commit cc68948
Showing 1 changed file with 3 additions and 1 deletion.
4 changes: 3 additions & 1 deletion accel/tcg/translate-all.c
Expand Up @@ -1079,7 +1079,9 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags & CF_HASH_MASK,
tb->trace_vcpu_dstate);
qht_remove(&tb_ctx.htable, tb, h);
if (!qht_remove(&tb_ctx.htable, tb, h)) {
return;
}

/* remove the TB from the page list */
if (tb->page_addr[0] != page_addr) {
Expand Down

0 comments on commit cc68948

Please sign in to comment.