From: Sergey Fedorov <serge.fdrv@gmail.com>
To: Peter Maydell <peter.maydell@linaro.org>
Cc: "QEMU Developers" <qemu-devel@nongnu.org>,
"Blue Swirl" <blauwirbel@gmail.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Riku Voipio" <riku.voipio@iki.fi>,
"Alex Bennée" <alex.bennee@linaro.org>,
"Richard Henderson" <rth@twiddle.net>
Subject: Re: [Qemu-devel] tcg: How 'CPUState::current_tb' is used?
Date: Tue, 3 May 2016 12:56:06 +0300 [thread overview]
Message-ID: <572875B6.5090705@gmail.com> (raw)
In-Reply-To: <CAFEAcA8UF5w=uFtdjNvL=1cfcnZNEAHwXjjrVHvJtkhkW9kCjw@mail.gmail.com>
On 03/05/16 03:02, Peter Maydell wrote:
> On 2 May 2016 at 21:18, Sergey Fedorov <serge.fdrv@gmail.com> wrote:
>> On 02/05/16 22:54, Sergey Fedorov wrote:
>>
>> Hi,
>>
>> I can't figure out how this field is used. The comment says it's "Currently
>> executing TB", but actually it's the first TB in a chain of TBs executed.
>> Grep shows the only place it is really checked is
>> tb_invalidate_phys_page_range(). That code seems to be introduced long ago
>> in:
>>
>> commit ea1c18022edd0e2c45552d6fc2da6e15a3486b33
>> Author: bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>
>> Date: Mon Jun 14 18:56:36 2004 +0000
>>
>> fixed self modifying code in case of asynchronous interrupt
>>
>>
>> I suspect it's only related to user emulation. But I would appreciate if
>> someone could give me an idea of how this really works :)
>>
>>
>> UPD: 'CPUState::current_tb' was used in that version of QEMU by this code:
>>
>> /* mask must never be zero, except for A20 change call */
>> void cpu_interrupt(CPUState *env, int mask)
>> {
>> TranslationBlock *tb;
>> static int interrupt_lock;
>>
>> env->interrupt_request |= mask;
>> /* if the cpu is currently executing code, we must unlink it and
>> all the potentially executing TB */
>> tb = env->current_tb;
>> if (tb && !testandset(&interrupt_lock)) {
>> env->current_tb = NULL;
>> tb_reset_jump_recursive(tb);
>> interrupt_lock = 0;
>> }
>> }
>>
>>
>> cpu_interrupt() has changed almost completely since that time. I'm wondering
>> if checking 'cpu->current_tb' by this code in
>> tb_invalidate_phys_page_range() still makes any sense:
>>
>> if (cpu->interrupt_request && cpu->current_tb) {
>> cpu_interrupt(cpu, cpu->interrupt_request);
>> }
>>
>>
>> BTW, I'm not sure about the purpose of this piece of code either :)
> I think it's now obsolete. When cpu_interrupt() worked
> by unlinking the TB being executed and all the ones that it
> chained to, then (as you see in the code you quote) cpu_interrupt()
> only did actual work if env->current_tb was set. The code in
> tb_invalidate_phys_page_range() doesn't want that work to happen
> while it's in tb_phys_invalidate() [it would have tried to
> modify the TB graph in the signal handler in the middle of
> tb_phys_invalidate also modifying the graph and corrupted it],
> so it sets cpu->current_tb to NULL to suppress this. However
> that then meant that if we had an asynchronous interrupt
> (ie executed cpu_interrupt() in a signal handler) it would
> have done nothing, so the tb_invalidate_phys_page_range()
> code now has to say "if we did get an interrupt, do the work
> now" after it restores the current_tb pointer.
>
> Since cpu_interrupt() no longer does complicated TB graph
> modification it now does it unconditionally, so the work
> done by tb_invalidate_phys_page_range() to clear cpu->current_tb
> is unnecessary and so is the extra call to cpu_interrupt()
> afterwards.
>
> So I think the current_tb field can be deleted, and so
> can the code fragments
> /* we need to do that to handle the case where a signal
> occurs while doing tb_phys_invalidate() */
> saved_tb = NULL;
> if (cpu != NULL) {
> saved_tb = cpu->current_tb;
> cpu->current_tb = NULL;
> }
>
> and
> if (cpu != NULL) {
> cpu->current_tb = saved_tb;
> if (cpu->interrupt_request && cpu->current_tb) {
> cpu_interrupt(cpu, cpu->interrupt_request);
> }
> }
>
> because with our current code a signal and resulting
> call to cpu_interrupt() is perfectly safe even if it
> happens while we're executing tb_phys_invalidate().
Thank you for the detailed explanation. Now, in the morning, I can see
it :) I'll prepare a patch for this.
Kind regards,
Sergey
prev parent reply other threads:[~2016-05-03 9:56 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-02 19:54 [Qemu-devel] tcg: How CPUState::current_tb is used? Sergey Fedorov
2016-05-02 20:18 ` [Qemu-devel] tcg: How 'CPUState::current_tb' " Sergey Fedorov
2016-05-03 0:02 ` Peter Maydell
2016-05-03 9:56 ` Sergey Fedorov [this message]
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=572875B6.5090705@gmail.com \
--to=serge.fdrv@gmail.com \
--cc=alex.bennee@linaro.org \
--cc=blauwirbel@gmail.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
--cc=riku.voipio@iki.fi \
--cc=rth@twiddle.net \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).