From: "Pavel Dovgalyuk" <dovgaluk@ispras.ru>
To: 'Richard Henderson' <richard.henderson@linaro.org>,
qemu-devel@nongnu.org
Cc: peter.maydell@linaro.org, "'Emilio G. Cota'" <cota@braap.org>
Subject: Re: [Qemu-devel] [PULL, 14/18] translate-all: discard TB when tb_link_page returns an existing matching TB
Date: Fri, 29 Jun 2018 10:25:03 +0300 [thread overview]
Message-ID: <000601d40f7a$4be320b0$e3a96210$@ru> (raw)
In-Reply-To: <20180614193147.29680-15-richard.henderson@linaro.org>
This patch breaks record/replay.
I run execution recording of the WindowsXP machine with the following script:
./bin/qemu-system-i386 -d in_asm,exec -D xp_save.log -global apic-common.vapic=off \
-icount shift=7,rr=record,rrfile=xp0.replay \
-drive file=./images/xp_sp2.qcow2,if=none,id=img-direct,snapshot \
-drive driver=blkreplay,if=none,image=img-direct,id=img-replay \
-device ide-hd,drive=img-replay -net none -m 512M
QEMU fails at some moment. Here are the contents of the log:
----------------
IN:
0x806ee2d0: 33 c0 xorl %eax, %eax
0x806ee2d2: 8a c1 movb %cl, %al
0x806ee2d4: 33 c9 xorl %ecx, %ecx
0x806ee2d6: 8a 88 58 e2 6e 80 movb -0x7f911da8(%eax), %cl
0x806ee2dc: 89 0d 80 00 fe ff movl %ecx, 0xfffe0080
0x806ee2e2: a1 80 00 fe ff movl 0xfffe0080, %eax
0x806ee2e7: c3 retl
Trace 0: 0x7fdc103b16a0 [00000000/806ee2d0/0x4000b0]
qemu: fatal: cpu_io_recompile: could not find TB for pc=0x7fec24fde2de
EAX=00000001 EBX=00006901 ECX=0000003d EDX=00000ffc
ESI=040d78c0 EDI=0000031f EBP=f878fc60 ESP=f878fc54
EIP=806ee2d0 EFL=00000202 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=0
....
Pavel Dovgalyuk
> -----Original Message-----
> From: Richard Henderson [mailto:richard.henderson@linaro.org]
> Sent: Thursday, June 14, 2018 10:32 PM
> To: qemu-devel@nongnu.org
> Cc: peter.maydell@linaro.org; Emilio G. Cota
> Subject: [PULL, 14/18] translate-all: discard TB when tb_link_page returns an existing
> matching TB
>
> From: "Emilio G. Cota" <cota@braap.org>
>
> Use the recently-gained QHT feature of returning the matching TB if it
> already exists. This allows us to get rid of the lookup we perform
> right after acquiring tb_lock.
>
> Suggested-by: Richard Henderson <richard.henderson@linaro.org>
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> Signed-off-by: Emilio G. Cota <cota@braap.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> accel/tcg/cpu-exec.c | 14 ++-------
> accel/tcg/translate-all.c | 50 +++++++++++++++++++++++++++------
> docs/devel/multi-thread-tcg.txt | 3 ++
> 3 files changed, 46 insertions(+), 21 deletions(-)
>
> diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
> index d75c35380a..45f6ebc65e 100644
> --- a/accel/tcg/cpu-exec.c
> +++ b/accel/tcg/cpu-exec.c
> @@ -245,10 +245,7 @@ void cpu_exec_step_atomic(CPUState *cpu)
> if (tb == NULL) {
> mmap_lock();
> tb_lock();
> - tb = tb_htable_lookup(cpu, pc, cs_base, flags, cf_mask);
> - if (likely(tb == NULL)) {
> - tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
> - }
> + tb = tb_gen_code(cpu, pc, cs_base, flags, cflags);
> tb_unlock();
> mmap_unlock();
> }
> @@ -398,14 +395,7 @@ static inline TranslationBlock *tb_find(CPUState *cpu,
> tb_lock();
> acquired_tb_lock = true;
>
> - /* There's a chance that our desired tb has been translated while
> - * taking the locks so we check again inside the lock.
> - */
> - tb = tb_htable_lookup(cpu, pc, cs_base, flags, cf_mask);
> - if (likely(tb == NULL)) {
> - /* if no translated code available, then translate it now */
> - tb = tb_gen_code(cpu, pc, cs_base, flags, cf_mask);
> - }
> + tb = tb_gen_code(cpu, pc, cs_base, flags, cf_mask);
>
> mmap_unlock();
> /* We add the TB in the virtual pc hash table for the fast lookup */
> diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
> index c75298d08a..2585e6fd3e 100644
> --- a/accel/tcg/translate-all.c
> +++ b/accel/tcg/translate-all.c
> @@ -1581,18 +1581,30 @@ static inline void tb_page_add(PageDesc *p, TranslationBlock *tb,
> * (-1) to indicate that only one page contains the TB.
> *
> * Called with mmap_lock held for user-mode emulation.
> + *
> + * Returns a pointer @tb, or a pointer to an existing TB that matches @tb.
> + * Note that in !user-mode, another thread might have already added a TB
> + * for the same block of guest code that @tb corresponds to. In that case,
> + * the caller should discard the original @tb, and use instead the returned TB.
> */
> -static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
> - tb_page_addr_t phys_page2)
> +static TranslationBlock *
> +tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
> + tb_page_addr_t phys_page2)
> {
> PageDesc *p;
> PageDesc *p2 = NULL;
> + void *existing_tb = NULL;
> uint32_t h;
>
> assert_memory_lock();
>
> /*
> * Add the TB to the page list, acquiring first the pages's locks.
> + * We keep the locks held until after inserting the TB in the hash table,
> + * so that if the insertion fails we know for sure that the TBs are still
> + * in the page descriptors.
> + * Note that inserting into the hash table first isn't an option, since
> + * we can only insert TBs that are fully initialized.
> */
> page_lock_pair(&p, phys_pc, &p2, phys_page2, 1);
> tb_page_add(p, tb, 0, phys_pc & TARGET_PAGE_MASK);
> @@ -1602,21 +1614,33 @@ static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
> tb->page_addr[1] = -1;
> }
>
> + /* add in the hash table */
> + h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags & CF_HASH_MASK,
> + tb->trace_vcpu_dstate);
> + qht_insert(&tb_ctx.htable, tb, h, &existing_tb);
> +
> + /* remove TB from the page(s) if we couldn't insert it */
> + if (unlikely(existing_tb)) {
> + tb_page_remove(p, tb);
> + invalidate_page_bitmap(p);
> + if (p2) {
> + tb_page_remove(p2, tb);
> + invalidate_page_bitmap(p2);
> + }
> + tb = existing_tb;
> + }
> +
> if (p2) {
> page_unlock(p2);
> }
> page_unlock(p);
>
> - /* add in the hash table */
> - h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags & CF_HASH_MASK,
> - tb->trace_vcpu_dstate);
> - qht_insert(&tb_ctx.htable, tb, h, NULL);
> -
> #ifdef CONFIG_USER_ONLY
> if (DEBUG_TB_CHECK_GATE) {
> tb_page_check();
> }
> #endif
> + return tb;
> }
>
> /* Called with mmap_lock held for user mode emulation. */
> @@ -1625,7 +1649,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
> uint32_t flags, int cflags)
> {
> CPUArchState *env = cpu->env_ptr;
> - TranslationBlock *tb;
> + TranslationBlock *tb, *existing_tb;
> tb_page_addr_t phys_pc, phys_page2;
> target_ulong virt_page2;
> tcg_insn_unit *gen_code_buf;
> @@ -1773,7 +1797,15 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
> * memory barrier is required before tb_link_page() makes the TB visible
> * through the physical hash table and physical page list.
> */
> - tb_link_page(tb, phys_pc, phys_page2);
> + existing_tb = tb_link_page(tb, phys_pc, phys_page2);
> + /* if the TB already exists, discard what we just translated */
> + if (unlikely(existing_tb != tb)) {
> + uintptr_t orig_aligned = (uintptr_t)gen_code_buf;
> +
> + orig_aligned -= ROUND_UP(sizeof(*tb), qemu_icache_linesize);
> + atomic_set(&tcg_ctx->code_gen_ptr, orig_aligned);
> + return existing_tb;
> + }
> tcg_tb_insert(tb);
> return tb;
> }
> diff --git a/docs/devel/multi-thread-tcg.txt b/docs/devel/multi-thread-tcg.txt
> index faf8918b23..faf09c6069 100644
> --- a/docs/devel/multi-thread-tcg.txt
> +++ b/docs/devel/multi-thread-tcg.txt
> @@ -140,6 +140,9 @@ to atomically insert new elements.
> The lookup caches are updated atomically and the lookup hash uses QHT
> which is designed for concurrent safe lookup.
>
> +Parallel code generation is supported. QHT is used at insertion time
> +as the synchronization point across threads, thereby ensuring that we only
> +keep track of a single TranslationBlock for each guest code block.
>
> Memory maps and TLBs
> --------------------
next prev parent reply other threads:[~2018-06-29 7:25 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-14 19:31 [Qemu-devel] [PULL 00/18] tcg queued patches Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 01/18] tcg/i386: Use byte form of xgetbv instruction Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 02/18] qht: require a default comparison function Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 03/18] qht: return existing entry when qht_insert fails Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 04/18] tcg: track TBs with per-region BST's Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 05/18] tcg: move tb_ctx.tb_phys_invalidate_count to tcg_ctx Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 06/18] translate-all: iterate over TBs in a page with PAGE_FOR_EACH_TB Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 07/18] translate-all: make l1_map lockless Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 08/18] translate-all: remove hole in PageDesc Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 09/18] translate-all: work page-by-page in tb_invalidate_phys_range_1 Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 10/18] translate-all: move tb_invalidate_phys_page_range up in the file Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 11/18] translate-all: use per-page locking in !user-mode Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 12/18] translate-all: add page_locked assertions Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 13/18] translate-all: introduce assert_no_pages_locked Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 14/18] translate-all: discard TB when tb_link_page returns an existing matching TB Richard Henderson
2018-06-29 7:25 ` Pavel Dovgalyuk [this message]
2018-06-29 18:48 ` [Qemu-devel] [PULL, " Emilio G. Cota
2018-07-02 5:52 ` Pavel Dovgalyuk
2018-07-02 19:52 ` Emilio G. Cota
2018-07-03 5:38 ` Pavel Dovgalyuk
2018-07-04 19:38 ` Emilio G. Cota
2018-07-05 5:51 ` Pavel Dovgalyuk
2018-06-14 19:31 ` [Qemu-devel] [PULL 15/18] translate-all: protect TB jumps with a per-destination-TB lock Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 16/18] cputlb: remove tb_lock from tlb_flush functions Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 17/18] translate-all: remove tb_lock mention from cpu_restore_state_from_tb Richard Henderson
2018-06-14 19:31 ` [Qemu-devel] [PULL 18/18] tcg: remove tb_lock Richard Henderson
2018-06-15 10:41 ` [Qemu-devel] [PULL 00/18] tcg queued patches Peter Maydell
2018-06-15 14:01 ` Emilio G. Cota
2018-06-15 17:54 ` Richard Henderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='000601d40f7a$4be320b0$e3a96210$@ru' \
--to=dovgaluk@ispras.ru \
--cc=cota@braap.org \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.