tcg: Prepare TB invalidation for lockless TB lookup

When invalidating a translation block, set an invalid flag into the
TranslationBlock structure first. It is also necessary to check whether
the target TB is still valid after acquiring 'tb_lock' but before calling
tb_add_jump() since TB lookup is to be performed out of 'tb_lock' in
future. Note that we don't have to check 'last_tb'; an already invalidated
TB will not be executed anyway and it is thus safe to patch it.

Backports commit 6d21e4208f382dd8ca1f7995a6dd9ea7ca281163 from qemu
This commit is contained in:
Paolo Bonzini 2018-02-26 01:48:06 -05:00 committed by Lioncash
parent c0dda5fbe9
commit 30845ae475
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
3 changed files with 7 additions and 1 deletions

View file

@ -214,7 +214,7 @@ static inline TranslationBlock *tb_find_fast(CPUState *cpu,
/* Check if translation buffer has been flushed */ /* Check if translation buffer has been flushed */
if (cpu->tb_flushed) { if (cpu->tb_flushed) {
cpu->tb_flushed = false; cpu->tb_flushed = false;
} else { } else if (!tb->invalid) {
tb_add_jump(last_tb, tb_exit, tb); tb_add_jump(last_tb, tb_exit, tb);
} }
} }

View file

@ -224,6 +224,9 @@ struct TranslationBlock {
#define CF_LAST_IO 0x8000 /* Last insn may be an IO access. */ #define CF_LAST_IO 0x8000 /* Last insn may be an IO access. */
#define CF_NOCACHE 0x10000 /* To be freed after execution */ #define CF_NOCACHE 0x10000 /* To be freed after execution */
#define CF_USE_ICOUNT 0x20000 #define CF_USE_ICOUNT 0x20000
#define CF_IGNORE_ICOUNT 0x40000 /* Do not generate icount code */
uint16_t invalid;
void *tc_ptr; /* pointer to the translated code */ void *tc_ptr; /* pointer to the translated code */
uint8_t *tc_search; /* pointer to search data */ uint8_t *tc_search; /* pointer to search data */

View file

@ -836,6 +836,7 @@ static TranslationBlock *tb_alloc(struct uc_struct *uc, target_ulong pc)
tb = &tcg_ctx->tb_ctx.tbs[tcg_ctx->tb_ctx.nb_tbs++]; tb = &tcg_ctx->tb_ctx.tbs[tcg_ctx->tb_ctx.nb_tbs++];
tb->pc = pc; tb->pc = pc;
tb->cflags = 0; tb->cflags = 0;
tb->invalid = false;
return tb; return tb;
} }
@ -1076,6 +1077,8 @@ void tb_phys_invalidate(struct uc_struct *uc,
uint32_t h; uint32_t h;
tb_page_addr_t phys_pc; tb_page_addr_t phys_pc;
atomic_set(&tb->invalid, true);
/* remove the TB from the hash list */ /* remove the TB from the hash list */
phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK); phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
h = tb_hash_func(phys_pc, tb->pc, tb->flags); h = tb_hash_func(phys_pc, tb->pc, tb->flags);