All of lore.kernel.org
 help / color / mirror / Atom feed
From: Richard Henderson <richard.henderson@linaro.org>
To: Matt Turner <mattst88@gmail.com>, qemu-devel@nongnu.org
Cc: pbonzini@redhat.com, philmd@oss.qualcomm.com,
	alex.bennee@linaro.org, zhao1.liu@intel.com
Subject: Re: [PATCH v4 5/9] accel/tcg: give the TB jump cache a second base pointer for generated code
Date: Thu, 27 Aug 2026 13:03:44 -0700	[thread overview]
Message-ID: <0a19da5b-e50f-447e-9630-37f951cc94db@linaro.org> (raw)
In-Reply-To: <20260827050241.3713332-6-mattst88@gmail.com>

On 8/26/26 22:02, Matt Turner wrote:
> +/*
> + * The inline jump cache probe reads cpu->tb_jmp_cache_probe and takes the
> + * slow path when the entry it finds has a NULL tb.  Pointing the probe at a
> + * region that is all zeroes therefore forces every indirect dispatch into
> + * helper_lookup_tb_ptr(), which does the full lookup the inline probe only
> + * approximates.  The real jump cache is untouched, so no contents are lost
> + * and recovery is a single store.
> + *
> + * Only ever read from, and only one entry per dispatch, so one shared
> + * zero-filled cache is enough for every CPU.  Not const: that would put a
> + * megabyte of zeroes in .rodata and so in the binary, where .bss costs
> + * nothing on disk and only faults in the handful of pages a poisoned run
> + * happens to probe.
> + */
> +static CPUJumpCache tb_jmp_cache_poison;

Hmm.  Maybe we should mmap it at startup then, because while we're not 
supposed to be writing into this, it would be nice to enforce that.

> +/*
> + * Poison @cpu's probe, from any thread.  Called when a breakpoint is
> + * inserted, which is what makes the poison take effect at the dispatch
> + * after the insert rather than whenever @cpu next reaches its main loop:
> + * a vCPU chaining indirectly need never reach it, and would run past a
> + * breakpoint another thread had just set.
> + *
> + * A plain store is enough.  The value only ever costs a slow path that is
> + * correct on its own, and the generated code re-reads the base on every
> + * dispatch.  Un-poisoning is tcg_cpu_sync_jmp_cache()'s job.
> + */
> +void tcg_cpu_poison_jmp_cache(CPUState *cpu)
> +{
> +    if (qatomic_read(&cpu->tb_jmp_cache_probe) != NULL) {
> +        qatomic_set(&cpu->tb_jmp_cache_probe, &tb_jmp_cache_poison);
> +    }
> +}

Why do we need to check for NULL?

> +
> +/*
> + * Called from the main loop, which is the only context that can establish
> + * that no reason to be poisoned is left.  Cheap enough to call every time
> + * round: the common case is a load, a compare and no store at all.
> + */
> +void tcg_cpu_sync_jmp_cache(CPUState *cpu)
> +{
> +    CPUJumpCache *want;
> +
> +    if (qatomic_read(&cpu->tb_jmp_cache_probe) == NULL) {
> +        return;  /* not realized, or already unrealized */
> +    }

If this function is only called by the main loop, we shouldn't have to 
deal with either unrealized state.

> +
> +    want = tcg_cpu_may_dispatch(cpu)
> +           ? cpu->tb_jmp_cache
> +           : &tb_jmp_cache_poison;
> +
> +    if (qatomic_read(&cpu->tb_jmp_cache_probe) != want) {
> +        qatomic_set(&cpu->tb_jmp_cache_probe, want);
> +
> +        if (want == cpu->tb_jmp_cache) {
> +            /*
> +             * Un-poisoning races a concurrent tcg_cpu_poison_jmp_cache():
> +             * the reason may have appeared after tcg_cpu_may_dispatch() read
> +             * it, and the poison may have landed before the store above.
> +             * Order that store against the re-read below, so that the race
> +             * is lost in the safe direction.
> +             */
> +            smp_mb();
> +            if (!tcg_cpu_may_dispatch(cpu)) {
> +                tcg_cpu_poison_jmp_cache(cpu);

Why do we need to check for breakpoints twice?
I don't think I understand this race.

I'm not familiar with how gdbstub interacts with user threads, but this 
feels overly complicated.  Up to and including needing to poison the 
jump cache just for adding a breakpoint.

I suspect what we need is to add a CF_NO_GOTO_JC flag that suppresses 
the inline jump cache, which is set whenever any breakpoint exists, 
which falls back to the helper, which checks for breakpoints.

Conveniently, you've already shown how to adjust tcg_cflags from 
gdbstub.  :-)


r~



  reply	other threads:[~2026-08-27 20:04 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-22 19:08 [PATCH v3 0/7] accel/tcg: cut per-block dispatch overhead Matt Turner
2026-08-22 19:08 ` [PATCH v3 1/7] accel/tcg: fold the dynamic cflags into CPUState::tcg_cflags Matt Turner
2026-08-25 21:47   ` Richard Henderson
2026-08-27  4:57     ` Matt Turner
2026-08-26  7:46   ` Alex Bennée
2026-08-27  4:57     ` Matt Turner
2026-08-22 19:08 ` [PATCH v3 2/7] accel/tcg: enlarge the TB jump cache to 64K entries Matt Turner
2026-08-25 21:50   ` Richard Henderson
2026-08-27  4:57     ` Matt Turner
2026-08-22 19:08 ` [PATCH v3 3/7] accel/tcg: skip the can_do_io stores in user-only builds Matt Turner
2026-08-22 19:08 ` [PATCH v3 4/7] RFC: tcg: probe the TB jump cache inline instead of calling a helper Matt Turner
2026-08-25 22:28   ` Richard Henderson
2026-08-27  5:00     ` Matt Turner
2026-08-22 19:08 ` [PATCH v3 5/7] RFC: accel/tcg: allow cross-page goto_tb chaining in user-only builds Matt Turner
2026-08-26  7:51   ` Alex Bennée
2026-08-27  4:57     ` Matt Turner
2026-08-22 19:08 ` [PATCH v3 6/7] RFC: accel/tcg: poison the jump cache instead of polling for indirect exits Matt Turner
2026-08-22 19:08 ` [PATCH v3 7/7] RFC: tcg: fold a guest displacement into the host addressing mode Matt Turner
2026-08-25 22:52   ` Richard Henderson
2026-08-27  4:57     ` Matt Turner
2026-08-27  5:02 ` [PATCH v4 0/9] accel/tcg: cut per-block dispatch overhead Matt Turner
2026-09-01  3:47   ` [PATCH v5 " Matt Turner
2026-09-01  3:48     ` [PATCH v5 1/9] accel/tcg: fold the dynamic cflags into CPUState::tcg_cflags Matt Turner
2026-09-01  3:48     ` [PATCH v5 2/9] accel/tcg: enlarge the TB jump cache to 64K entries Matt Turner
2026-09-01  3:48     ` [PATCH v5 3/9] accel/tcg: skip the can_do_io stores in user-only builds Matt Turner
2026-09-01  3:48     ` [PATCH v5 4/9] tcg: add tcg_gen_goto_jc_{i32,i64,tl}() Matt Turner
2026-09-01  3:48     ` [PATCH v5 5/9] accel/tcg: add CF_NO_GOTO_JC, set while a breakpoint is present Matt Turner
2026-09-01  3:48     ` [PATCH v5 6/9] RFC: tcg: probe the TB jump cache inline instead of calling a helper Matt Turner
2026-09-01  3:48     ` [PATCH v5 7/9] RFC: accel/tcg: allow cross-page goto_tb chaining in user-only builds Matt Turner
2026-09-01  3:48     ` [PATCH v5 8/9] RFC: accel/tcg: poison the jump cache instead of polling for indirect exits Matt Turner
2026-09-01  3:48     ` [PATCH v5 9/9] RFC: tcg: fold a guest displacement into the host addressing mode Matt Turner
2026-08-27  5:02 ` [PATCH v4 1/9] accel/tcg: fold the dynamic cflags into CPUState::tcg_cflags Matt Turner
2026-08-27 18:51   ` Richard Henderson
2026-08-27  5:02 ` [PATCH v4 2/9] accel/tcg: enlarge the TB jump cache to 64K entries Matt Turner
2026-08-27  5:02 ` [PATCH v4 3/9] accel/tcg: skip the can_do_io stores in user-only builds Matt Turner
2026-08-27  5:02 ` [PATCH v4 4/9] tcg: pass the destination to tcg_gen_lookup_and_goto_ptr() Matt Turner
2026-08-27 23:12   ` Richard Henderson
2026-09-01  2:55     ` Matt Turner
2026-08-27  5:02 ` [PATCH v4 5/9] accel/tcg: give the TB jump cache a second base pointer for generated code Matt Turner
2026-08-27 20:03   ` Richard Henderson [this message]
2026-09-01  2:55     ` Matt Turner
2026-08-27  5:02 ` [PATCH v4 6/9] RFC: tcg: probe the TB jump cache inline instead of calling a helper Matt Turner
2026-08-27 23:34   ` Richard Henderson
2026-09-01  2:55     ` Matt Turner
2026-08-27  5:02 ` [PATCH v4 7/9] RFC: accel/tcg: allow cross-page goto_tb chaining in user-only builds Matt Turner
2026-08-27  5:02 ` [PATCH v4 8/9] RFC: accel/tcg: poison the jump cache instead of polling for indirect exits Matt Turner
2026-08-27  5:02 ` [PATCH v4 9/9] RFC: tcg: fold a guest displacement into the host addressing mode Matt Turner

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=0a19da5b-e50f-447e-9630-37f951cc94db@linaro.org \
    --to=richard.henderson@linaro.org \
    --cc=alex.bennee@linaro.org \
    --cc=mattst88@gmail.com \
    --cc=pbonzini@redhat.com \
    --cc=philmd@oss.qualcomm.com \
    --cc=qemu-devel@nongnu.org \
    --cc=zhao1.liu@intel.com \
    /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.