diff mbox series

[v3,5/6] monitor: adding info tb and tbs to monitor

Message ID 20190702210017.4275-5-vandersonmr2@gmail.com
State New
Headers show
Series None | expand

Commit Message

vandersonmr July 2, 2019, 9 p.m. UTC
adding options to list tbs by some metric and
investigate their code.

Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
---
 hmp-commands-info.hx | 22 ++++++++++++++
 monitor/misc.c       | 69 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+)

Comments

Alex Bennée July 4, 2019, 4:36 p.m. UTC | #1
vandersonmr <vandersonmr2@gmail.com> writes:

> adding options to list tbs by some metric and
> investigate their code.
>
> Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
> ---
>  hmp-commands-info.hx | 22 ++++++++++++++
>  monitor/misc.c       | 69 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 91 insertions(+)
>
> diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
> index c59444c461..0b8c0de95d 100644
> --- a/hmp-commands-info.hx
> +++ b/hmp-commands-info.hx
> @@ -288,6 +288,28 @@ ETEXI
>          .params     = "",
>          .help       = "show dynamic compiler info",
>          .cmd        = hmp_info_jit,
> +    {

Ahh this is the breakage:

},
{

> +        .name       = "tbs",
> +        .args_type  = "number:i?,sortedby:s?",
> +        .params     = "[number sortedby]",
> +        .help       = "show a [number] translated blocks sorted by [sortedby]"
> +                      "sortedby opts: hotness hg",
> +        .cmd        = hmp_info_tbs,
> +    },
> +    {
> +        .name       = "tb",
> +        .args_type  = "id:i,flags:s?",
> +        .params     = "id [log1[,...] flags]",
> +        .help       = "show information about one translated block by id",
> +        .cmd        = hmp_info_tb,
> +    },
> +    {
> +        .name       = "coverset",
> +        .args_type  = "number:i?",
> +        .params     = "[number]",
> +        .help       = "show hottest translated blocks neccesary to cover"
> +                      "[number]% of the execution count",
> +        .cmd        = hmp_info_coverset,
>      },
>  #endif
>
> diff --git a/monitor/misc.c b/monitor/misc.c
> index bf9faceb86..1fb4d75871 100644
> --- a/monitor/misc.c
> +++ b/monitor/misc.c
> @@ -469,6 +469,75 @@ static void hmp_info_jit(Monitor *mon, const QDict *qdict)
>      dump_drift_info();
>  }
>
> +static void hmp_info_tbs(Monitor *mon, const QDict *qdict)
> +{
> +    int n;
> +    const char *s = NULL;
> +    if (!tcg_enabled()) {
> +        error_report("TB information is only available with accel=tcg");
> +        return;
> +    }
> +    if (!tb_ctx.tb_stats.map) {
> +        error_report("no TB information recorded");
> +        return;
> +    }
> +
> +    n = qdict_get_try_int(qdict, "number", 10);
> +    s = qdict_get_try_str(qdict, "sortedby");
> +
> +    int sortedby = 0;
> +    if (s == NULL || strcmp(s, "hotness") == 0) {
> +        sortedby = SORT_BY_HOTNESS;
> +    } else if (strcmp(s, "hg") == 0) {
> +        sortedby = SORT_BY_HG;
> +    }
> +
> +    dump_tbs_info(n, sortedby, true);
> +}
> +
> +static void hmp_info_tb(Monitor *mon, const QDict *qdict)
> +{
> +    const int id = qdict_get_int(qdict, "id");
> +    const char *flags = qdict_get_try_str(qdict, "flags");
> +    int mask;
> +
> +    if (!tcg_enabled()) {
> +        error_report("TB information is only available with accel=tcg");
> +        return;
> +    }
> +
> +    mask = flags ? qemu_str_to_log_mask(flags) : CPU_LOG_TB_IN_ASM;
> +
> +    if (!mask) {
> +        help_cmd(mon, "log");
> +        return;
> +    }
> +
> +    dump_tb_info(id, mask, true);
> +}
> +
> +static void hmp_info_coverset(Monitor *mon, const QDict *qdict)
> +{
> +    int n;
> +    if (!tcg_enabled()) {
> +        error_report("TB information is only available with accel=tcg");
> +        return;
> +    }
> +    if (!qemu_loglevel_mask(CPU_LOG_HOT_TBS)) {
> +        error_report("TB information not being recorded");
> +        return;
> +    }
> +
> +    n = qdict_get_try_int(qdict, "number", 90);
> +
> +    if (n < 0 || n > 100) {
> +        error_report("Coverset percentage should be between 0 and 100");
> +        return;
> +    }
> +
> +    dump_coverset_info(n, true);
> +}
> +
>  static void hmp_info_opcount(Monitor *mon, const QDict *qdict)
>  {
>      dump_opcount_info();


--
Alex Bennée
Markus Armbruster July 5, 2019, 1:54 p.m. UTC | #2
vandersonmr <vandersonmr2@gmail.com> writes:

> adding options to list tbs by some metric and
> investigate their code.

What's "tbs"?

Why is listing them useful?

What do you mean by "some metric"?

What do you mean by "and investigate their code?"

> Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>
> ---
>  hmp-commands-info.hx | 22 ++++++++++++++
>  monitor/misc.c       | 69 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 91 insertions(+)
>
> diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
> index c59444c461..0b8c0de95d 100644
> --- a/hmp-commands-info.hx
> +++ b/hmp-commands-info.hx
> @@ -288,6 +288,28 @@ ETEXI
>          .params     = "",
>          .help       = "show dynamic compiler info",
>          .cmd        = hmp_info_jit,
> +    {
> +        .name       = "tbs",
> +        .args_type  = "number:i?,sortedby:s?",
> +        .params     = "[number sortedby]",
> +        .help       = "show a [number] translated blocks sorted by [sortedby]"
> +                      "sortedby opts: hotness hg",

Your use of [square brackets] in .help is unusual.  Please try to have
your commands' help blend into the existing help.

> +        .cmd        = hmp_info_tbs,
> +    },
> +    {
> +        .name       = "tb",
> +        .args_type  = "id:i,flags:s?",
> +        .params     = "id [log1[,...] flags]",
> +        .help       = "show information about one translated block by id",
> +        .cmd        = hmp_info_tb,
> +    },
> +    {
> +        .name       = "coverset",
> +        .args_type  = "number:i?",
> +        .params     = "[number]",
> +        .help       = "show hottest translated blocks neccesary to cover"
> +                      "[number]% of the execution count",

When a parameter takes a percentage, "number" is a suboptimal name :)

> +        .cmd        = hmp_info_coverset,
>      },
>  #endif
>  

Standard request for new HMP commands without corresponding QMP
commands: please state in the commit message why the QMP command is not
worthwhile.

HMP commands without a QMP equivalent are okay if their functionality
makes no sense in QMP, or is of use only for human users.

Example for "makes no sense in QMP": setting the current CPU, because a
QMP monitor doesn't have a current CPU.

Examples for "is of use only for human users": HMP command "help", the
integrated pocket calculator.

Debugging commands are kind of borderline.  Debugging is commonly a
human activity, where HMP is just fine.  However, humans create tools to
assist with their activities, and then QMP is useful.  While I wouldn't
encourage HMP-only for the debugging use case, I wouldn't veto it.

Your (overly terse!) commit message and help texts make me guess the
commands are for gathering statistics.  Statistics can have debugging
uses.  But they often have non-debugging uses as well.  What use cases
can you imagine for these commands?

[...]
Alex Bennée July 5, 2019, 2:36 p.m. UTC | #3
Markus Armbruster <armbru@redhat.com> writes:

> vandersonmr <vandersonmr2@gmail.com> writes:
>
<snip>

I'll leave Vanderson to address your other comments.

>
> Debugging commands are kind of borderline.  Debugging is commonly a
> human activity, where HMP is just fine.  However, humans create tools to
> assist with their activities, and then QMP is useful.  While I wouldn't
> encourage HMP-only for the debugging use case, I wouldn't veto it.
>
> Your (overly terse!) commit message and help texts make me guess the
> commands are for gathering statistics.  Statistics can have debugging
> uses.  But they often have non-debugging uses as well.  What use cases
> can you imagine for these commands?

So this is all really aimed at making TCG go faster - but before we can
make it go faster we need better tools for seeing where the time is
being spent and examining the code that we generate. So I expect the
main users of this functionality will be QEMU developers.

That said I can see a good rationale for supporting QMP because it is
more amenable to automation. However this is early days so I would
caution about exposing this stuff too early least we bake in a woolly
API.

The other wrinkle is we do have to take control of the emulator to
safely calculate some of the numbers we output. This essentially means
the HMP commands are asynchronous - we kick of safe work which waits
until all vCPU threads are stopped before we go through the records and
add up numbers. This is fine for the HMP because we just output to the
monitor FD when we are ready. I assume for QMP commands there is more
housekeeping to do? Can QMP commands wait for a response to be
calculated by another thread? Are there any existing commands that have
to support this sort of pattern?

>
> [...]


--
Alex Bennée
Markus Armbruster July 6, 2019, 6:09 a.m. UTC | #4
Cc: Marc-André, who has patches that might be useful here.

Alex Bennée <alex.bennee@linaro.org> writes:

> Markus Armbruster <armbru@redhat.com> writes:
>
>> vandersonmr <vandersonmr2@gmail.com> writes:
>>
> <snip>
>
> I'll leave Vanderson to address your other comments.
>
>>
>> Debugging commands are kind of borderline.  Debugging is commonly a
>> human activity, where HMP is just fine.  However, humans create tools to
>> assist with their activities, and then QMP is useful.  While I wouldn't
>> encourage HMP-only for the debugging use case, I wouldn't veto it.
>>
>> Your (overly terse!) commit message and help texts make me guess the
>> commands are for gathering statistics.  Statistics can have debugging
>> uses.  But they often have non-debugging uses as well.  What use cases
>> can you imagine for these commands?
>
> So this is all really aimed at making TCG go faster - but before we can
> make it go faster we need better tools for seeing where the time is
> being spent and examining the code that we generate. So I expect the
> main users of this functionality will be QEMU developers.
>
> That said I can see a good rationale for supporting QMP because it is
> more amenable to automation. However this is early days so I would
> caution about exposing this stuff too early least we bake in a woolly
> API.

Development tools should exempt themselves from QMP's interface
stability promise: prefix the command names with 'x-'.

> The other wrinkle is we do have to take control of the emulator to
> safely calculate some of the numbers we output. This essentially means
> the HMP commands are asynchronous - we kick of safe work which waits
> until all vCPU threads are stopped before we go through the records and
> add up numbers. This is fine for the HMP because we just output to the
> monitor FD when we are ready. I assume for QMP commands there is more
> housekeeping to do? Can QMP commands wait for a response to be
> calculated by another thread? Are there any existing commands that have
> to support this sort of pattern?

Let me clarify "synchronous" to avoid confusion.

Both QMP and HMP commands are synchronous protocols in the sense that
commands are executed one after the other, without overlap.  When a
client sends multiple commands, it can assume that each one starts only
after the previous one completed.

Both HMP and QMP commands execute synchronously in the sense that the
command runs to completion without ever yielding the thread.  Any
blocking operations put the thread to sleep (but see below).

HMP runs in the main thread.  Putting the main thread to sleep is
generally undesirable.

QMP used to run in the main thread, too.  Nowadays, the QMP core runs in
an I/O thread shared by all monitors, and dispatches commands to the
main thread.  Moving command execution out of the main thread as well
requires careful review of the command's code for hidden assumptions.
Major project.

Fine print: OOB commands are a special case, but I doubt you want to
know more.

Fine print: certain character devices can't support use of an I/O
thread; QMP runs in the main thread then.  The ones you want to use with
QMP all support I/O threads.

You wrote "we kick of safe work which waits until all vCPU threads are
stopped before we go through the records and add up numbers [...] we
just output to the monitor FD".  Does this mean the HMP command kicks
off the work, terminates, and some time later something else prints
results to the monitor?  How much later?

If "later" is actually "soon", for a suitable value of "soon",
Marc-André's work on "asynchronous" QMP might be pertinent.  I put
"asynchronous" in scare quotes, because of the confusion it has caused.
My current understanding (Marc-André, please correct me if wrong): it
lets QMP commands to block without putting their thread to sleep.  It
does not make QMP an asynchronous protocol.

If "later" need not be "soon", read on.

In QMP, there are two established ways to do potentially long-running
work.  Both ways use a command that kicks off the work, then terminates
without waiting for it to complete.

The first way is traditional: pair the kick off command with a query
command and optionally an event.

When the work completes, it fires off the event.  The event is broadcast
to all QMP monitors (we could implement unicast if we have a compelling
use case).

The query command reports whether the work has completed, and if yes,
the work's results, if any.

You need the event if you want to avoid polling.

Even with an event, you still need a query command.  If your management
application loses its QMP connection temporarily, you can miss the
event.  You want to poll on reconnect, with the query command.

If more than one instance of the work can be pending at any one time,
event and query need to identify the instance somehow.  This is
completely ad hoc.

The second way is a full-blown "job".  This provides more control: you
can cancel, pause, resume, ...  It also provides a job ID.  More
featureful and more structured.

Jobs have grown out of block jobs.  I'd love to see some uses outside
the block subsystem.

Hope this helps!
vandersonmr July 8, 2019, 2:51 a.m. UTC | #5
Markus,

Thank you for your comments! Based on your questions and suggestions of
writing a more complete explanation in my commits, I decided to start to
describe our whole work on the wiki:
https://wiki.qemu.org/Internships/ProjectIdeas/TCGCodeQuality
I will update and expand it weekly, so I can link and cite it in future
patches to give a better whole vision for anyone interested.

Btw, thank you for your QMP tips, I will discuss with Alex how to address
it in our approach.

[]'s
Vanderson M. Rosario


On Sat, Jul 6, 2019 at 3:09 AM Markus Armbruster <armbru@redhat.com> wrote:

> Cc: Marc-André, who has patches that might be useful here.
>
> Alex Bennée <alex.bennee@linaro.org> writes:
>
> > Markus Armbruster <armbru@redhat.com> writes:
> >
> >> vandersonmr <vandersonmr2@gmail.com> writes:
> >>
> > <snip>
> >
> > I'll leave Vanderson to address your other comments.
> >
> >>
> >> Debugging commands are kind of borderline.  Debugging is commonly a
> >> human activity, where HMP is just fine.  However, humans create tools to
> >> assist with their activities, and then QMP is useful.  While I wouldn't
> >> encourage HMP-only for the debugging use case, I wouldn't veto it.
> >>
> >> Your (overly terse!) commit message and help texts make me guess the
> >> commands are for gathering statistics.  Statistics can have debugging
> >> uses.  But they often have non-debugging uses as well.  What use cases
> >> can you imagine for these commands?
> >
> > So this is all really aimed at making TCG go faster - but before we can
> > make it go faster we need better tools for seeing where the time is
> > being spent and examining the code that we generate. So I expect the
> > main users of this functionality will be QEMU developers.
> >
> > That said I can see a good rationale for supporting QMP because it is
> > more amenable to automation. However this is early days so I would
> > caution about exposing this stuff too early least we bake in a woolly
> > API.
>
> Development tools should exempt themselves from QMP's interface
> stability promise: prefix the command names with 'x-'.
>
> > The other wrinkle is we do have to take control of the emulator to
> > safely calculate some of the numbers we output. This essentially means
> > the HMP commands are asynchronous - we kick of safe work which waits
> > until all vCPU threads are stopped before we go through the records and
> > add up numbers. This is fine for the HMP because we just output to the
> > monitor FD when we are ready. I assume for QMP commands there is more
> > housekeeping to do? Can QMP commands wait for a response to be
> > calculated by another thread? Are there any existing commands that have
> > to support this sort of pattern?
>
> Let me clarify "synchronous" to avoid confusion.
>
> Both QMP and HMP commands are synchronous protocols in the sense that
> commands are executed one after the other, without overlap.  When a
> client sends multiple commands, it can assume that each one starts only
> after the previous one completed.
>
> Both HMP and QMP commands execute synchronously in the sense that the
> command runs to completion without ever yielding the thread.  Any
> blocking operations put the thread to sleep (but see below).
>
> HMP runs in the main thread.  Putting the main thread to sleep is
> generally undesirable.
>
> QMP used to run in the main thread, too.  Nowadays, the QMP core runs in
> an I/O thread shared by all monitors, and dispatches commands to the
> main thread.  Moving command execution out of the main thread as well
> requires careful review of the command's code for hidden assumptions.
> Major project.
>
> Fine print: OOB commands are a special case, but I doubt you want to
> know more.
>
> Fine print: certain character devices can't support use of an I/O
> thread; QMP runs in the main thread then.  The ones you want to use with
> QMP all support I/O threads.
>
> You wrote "we kick of safe work which waits until all vCPU threads are
> stopped before we go through the records and add up numbers [...] we
> just output to the monitor FD".  Does this mean the HMP command kicks
> off the work, terminates, and some time later something else prints
> results to the monitor?  How much later?
>
> If "later" is actually "soon", for a suitable value of "soon",
> Marc-André's work on "asynchronous" QMP might be pertinent.  I put
> "asynchronous" in scare quotes, because of the confusion it has caused.
> My current understanding (Marc-André, please correct me if wrong): it
> lets QMP commands to block without putting their thread to sleep.  It
> does not make QMP an asynchronous protocol.
>
> If "later" need not be "soon", read on.
>
> In QMP, there are two established ways to do potentially long-running
> work.  Both ways use a command that kicks off the work, then terminates
> without waiting for it to complete.
>
> The first way is traditional: pair the kick off command with a query
> command and optionally an event.
>
> When the work completes, it fires off the event.  The event is broadcast
> to all QMP monitors (we could implement unicast if we have a compelling
> use case).
>
> The query command reports whether the work has completed, and if yes,
> the work's results, if any.
>
> You need the event if you want to avoid polling.
>
> Even with an event, you still need a query command.  If your management
> application loses its QMP connection temporarily, you can miss the
> event.  You want to poll on reconnect, with the query command.
>
> If more than one instance of the work can be pending at any one time,
> event and query need to identify the instance somehow.  This is
> completely ad hoc.
>
> The second way is a full-blown "job".  This provides more control: you
> can cancel, pause, resume, ...  It also provides a job ID.  More
> featureful and more structured.
>
> Jobs have grown out of block jobs.  I'd love to see some uses outside
> the block subsystem.
>
> Hope this helps!
>
Marc-André Lureau July 8, 2019, 4:49 a.m. UTC | #6
Hi

On Sat, Jul 6, 2019 at 10:09 AM Markus Armbruster <armbru@redhat.com> wrote:
>
> Cc: Marc-André, who has patches that might be useful here.
>
> Alex Bennée <alex.bennee@linaro.org> writes:
>
> > Markus Armbruster <armbru@redhat.com> writes:
> >
> >> vandersonmr <vandersonmr2@gmail.com> writes:
> >>
> > <snip>
> >
> > I'll leave Vanderson to address your other comments.
> >
> >>
> >> Debugging commands are kind of borderline.  Debugging is commonly a
> >> human activity, where HMP is just fine.  However, humans create tools to
> >> assist with their activities, and then QMP is useful.  While I wouldn't
> >> encourage HMP-only for the debugging use case, I wouldn't veto it.
> >>
> >> Your (overly terse!) commit message and help texts make me guess the
> >> commands are for gathering statistics.  Statistics can have debugging
> >> uses.  But they often have non-debugging uses as well.  What use cases
> >> can you imagine for these commands?
> >
> > So this is all really aimed at making TCG go faster - but before we can
> > make it go faster we need better tools for seeing where the time is
> > being spent and examining the code that we generate. So I expect the
> > main users of this functionality will be QEMU developers.
> >
> > That said I can see a good rationale for supporting QMP because it is
> > more amenable to automation. However this is early days so I would
> > caution about exposing this stuff too early least we bake in a woolly
> > API.
>
> Development tools should exempt themselves from QMP's interface
> stability promise: prefix the command names with 'x-'.
>
> > The other wrinkle is we do have to take control of the emulator to
> > safely calculate some of the numbers we output. This essentially means
> > the HMP commands are asynchronous - we kick of safe work which waits
> > until all vCPU threads are stopped before we go through the records and
> > add up numbers. This is fine for the HMP because we just output to the
> > monitor FD when we are ready. I assume for QMP commands there is more
> > housekeeping to do? Can QMP commands wait for a response to be
> > calculated by another thread? Are there any existing commands that have
> > to support this sort of pattern?
>
> Let me clarify "synchronous" to avoid confusion.
>
> Both QMP and HMP commands are synchronous protocols in the sense that
> commands are executed one after the other, without overlap.  When a
> client sends multiple commands, it can assume that each one starts only
> after the previous one completed.
>
> Both HMP and QMP commands execute synchronously in the sense that the
> command runs to completion without ever yielding the thread.  Any
> blocking operations put the thread to sleep (but see below).
>
> HMP runs in the main thread.  Putting the main thread to sleep is
> generally undesirable.
>
> QMP used to run in the main thread, too.  Nowadays, the QMP core runs in
> an I/O thread shared by all monitors, and dispatches commands to the
> main thread.  Moving command execution out of the main thread as well
> requires careful review of the command's code for hidden assumptions.
> Major project.
>
> Fine print: OOB commands are a special case, but I doubt you want to
> know more.
>
> Fine print: certain character devices can't support use of an I/O
> thread; QMP runs in the main thread then.  The ones you want to use with
> QMP all support I/O threads.
>
> You wrote "we kick of safe work which waits until all vCPU threads are
> stopped before we go through the records and add up numbers [...] we
> just output to the monitor FD".  Does this mean the HMP command kicks
> off the work, terminates, and some time later something else prints
> results to the monitor?  How much later?
>
> If "later" is actually "soon", for a suitable value of "soon",
> Marc-André's work on "asynchronous" QMP might be pertinent.  I put
> "asynchronous" in scare quotes, because of the confusion it has caused.
> My current understanding (Marc-André, please correct me if wrong): it
> lets QMP commands to block without putting their thread to sleep.  It
> does not make QMP an asynchronous protocol.

In "[PATCH v4 00/20] monitor: add asynchronous command type", I
propose a way to defer monitor commands (both QMP and HMP). This
allows the main loop to reenter, and when the work is completed,
return the command. During that time, no other commands are accepted
(except OOB), effectively "blocking" the monitor.

The series probably doesn't apply cleanly anymore, I'll rebase and resubmit it.

>
> If "later" need not be "soon", read on.
>
> In QMP, there are two established ways to do potentially long-running
> work.  Both ways use a command that kicks off the work, then terminates
> without waiting for it to complete.
>
> The first way is traditional: pair the kick off command with a query
> command and optionally an event.
>
> When the work completes, it fires off the event.  The event is broadcast
> to all QMP monitors (we could implement unicast if we have a compelling
> use case).
>
> The query command reports whether the work has completed, and if yes,
> the work's results, if any.
>
> You need the event if you want to avoid polling.
>
> Even with an event, you still need a query command.  If your management
> application loses its QMP connection temporarily, you can miss the
> event.  You want to poll on reconnect, with the query command.
>
> If more than one instance of the work can be pending at any one time,
> event and query need to identify the instance somehow.  This is
> completely ad hoc.
>
> The second way is a full-blown "job".  This provides more control: you
> can cancel, pause, resume, ...  It also provides a job ID.  More
> featureful and more structured.
>
> Jobs have grown out of block jobs.  I'd love to see some uses outside
> the block subsystem.
>
> Hope this helps!
Dr. David Alan Gilbert July 9, 2019, 9:57 a.m. UTC | #7
* vandersonmr (vandersonmr2@gmail.com) wrote:
> adding options to list tbs by some metric and
> investigate their code.
> 
> Signed-off-by: Vanderson M. do Rosario <vandersonmr2@gmail.com>

As Markus said you need a short justification that it's for debug etc
to justify HMP only; it doesn't need to be huge, but we should have it.

> ---
>  hmp-commands-info.hx | 22 ++++++++++++++
>  monitor/misc.c       | 69 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 91 insertions(+)
> 
> diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
> index c59444c461..0b8c0de95d 100644
> --- a/hmp-commands-info.hx
> +++ b/hmp-commands-info.hx
> @@ -288,6 +288,28 @@ ETEXI
>          .params     = "",
>          .help       = "show dynamic compiler info",
>          .cmd        = hmp_info_jit,
> +    {
> +        .name       = "tbs",
> +        .args_type  = "number:i?,sortedby:s?",
> +        .params     = "[number sortedby]",
> +        .help       = "show a [number] translated blocks sorted by [sortedby]"
> +                      "sortedby opts: hotness hg",

If this is showing 'number' blocks then I think it should be called
'count'

> +        .cmd        = hmp_info_tbs,
> +    },
> +    {
> +        .name       = "tb",
> +        .args_type  = "id:i,flags:s?",
> +        .params     = "id [log1[,...] flags]",
> +        .help       = "show information about one translated block by id",
> +        .cmd        = hmp_info_tb,

That doesn't say what those flags are for; qemu has lots of flags for
different things; I think you're  saying it's some log flag?

> +    },
> +    {
> +        .name       = "coverset",
> +        .args_type  = "number:i?",
> +        .params     = "[number]",
> +        .help       = "show hottest translated blocks neccesary to cover"
> +                      "[number]% of the execution count",
> +        .cmd        = hmp_info_coverset,
>      },

That 'number' should be something like 'percent' or 'coverage'
>  #endif
>  
> diff --git a/monitor/misc.c b/monitor/misc.c
> index bf9faceb86..1fb4d75871 100644
> --- a/monitor/misc.c
> +++ b/monitor/misc.c
> @@ -469,6 +469,75 @@ static void hmp_info_jit(Monitor *mon, const QDict *qdict)
>      dump_drift_info();
>  }
>  
> +static void hmp_info_tbs(Monitor *mon, const QDict *qdict)
> +{
> +    int n;
> +    const char *s = NULL;
> +    if (!tcg_enabled()) {
> +        error_report("TB information is only available with accel=tcg");
> +        return;
> +    }
> +    if (!tb_ctx.tb_stats.map) {
> +        error_report("no TB information recorded");
> +        return;
> +    }
> +
> +    n = qdict_get_try_int(qdict, "number", 10);
> +    s = qdict_get_try_str(qdict, "sortedby");

No need to use single characters; sortedby_str  is fine for
example.

> +    int sortedby = 0;
> +    if (s == NULL || strcmp(s, "hotness") == 0) {
> +        sortedby = SORT_BY_HOTNESS;
> +    } else if (strcmp(s, "hg") == 0) {
> +        sortedby = SORT_BY_HG;
> +    }

You should error if there's another word in 's'

> +    dump_tbs_info(n, sortedby, true);
> +}
> +
> +static void hmp_info_tb(Monitor *mon, const QDict *qdict)
> +{
> +    const int id = qdict_get_int(qdict, "id");
> +    const char *flags = qdict_get_try_str(qdict, "flags");
> +    int mask;
> +
> +    if (!tcg_enabled()) {
> +        error_report("TB information is only available with accel=tcg");
> +        return;
> +    }
> +
> +    mask = flags ? qemu_str_to_log_mask(flags) : CPU_LOG_TB_IN_ASM;
> +
> +    if (!mask) {
> +        help_cmd(mon, "log");

That's not obvious - I'd perfer you said something like
     Unable to parse log flags, see 'help log'

> +        return;
> +    }
> +
> +    dump_tb_info(id, mask, true);
> +}
> +
> +static void hmp_info_coverset(Monitor *mon, const QDict *qdict)
> +{
> +    int n;
> +    if (!tcg_enabled()) {
> +        error_report("TB information is only available with accel=tcg");
> +        return;
> +    }
> +    if (!qemu_loglevel_mask(CPU_LOG_HOT_TBS)) {
> +        error_report("TB information not being recorded");
> +        return;
> +    }
> +
> +    n = qdict_get_try_int(qdict, "number", 90);
> +
> +    if (n < 0 || n > 100) {
> +        error_report("Coverset percentage should be between 0 and 100");
> +        return;
> +    }
> +
> +    dump_coverset_info(n, true);
> +}
> +
>  static void hmp_info_opcount(Monitor *mon, const QDict *qdict)
>  {
>      dump_opcount_info();
> -- 
> 2.22.0
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
diff mbox series

Patch

diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx
index c59444c461..0b8c0de95d 100644
--- a/hmp-commands-info.hx
+++ b/hmp-commands-info.hx
@@ -288,6 +288,28 @@  ETEXI
         .params     = "",
         .help       = "show dynamic compiler info",
         .cmd        = hmp_info_jit,
+    {
+        .name       = "tbs",
+        .args_type  = "number:i?,sortedby:s?",
+        .params     = "[number sortedby]",
+        .help       = "show a [number] translated blocks sorted by [sortedby]"
+                      "sortedby opts: hotness hg",
+        .cmd        = hmp_info_tbs,
+    },
+    {
+        .name       = "tb",
+        .args_type  = "id:i,flags:s?",
+        .params     = "id [log1[,...] flags]",
+        .help       = "show information about one translated block by id",
+        .cmd        = hmp_info_tb,
+    },
+    {
+        .name       = "coverset",
+        .args_type  = "number:i?",
+        .params     = "[number]",
+        .help       = "show hottest translated blocks neccesary to cover"
+                      "[number]% of the execution count",
+        .cmd        = hmp_info_coverset,
     },
 #endif
 
diff --git a/monitor/misc.c b/monitor/misc.c
index bf9faceb86..1fb4d75871 100644
--- a/monitor/misc.c
+++ b/monitor/misc.c
@@ -469,6 +469,75 @@  static void hmp_info_jit(Monitor *mon, const QDict *qdict)
     dump_drift_info();
 }
 
+static void hmp_info_tbs(Monitor *mon, const QDict *qdict)
+{
+    int n;
+    const char *s = NULL;
+    if (!tcg_enabled()) {
+        error_report("TB information is only available with accel=tcg");
+        return;
+    }
+    if (!tb_ctx.tb_stats.map) {
+        error_report("no TB information recorded");
+        return;
+    }
+
+    n = qdict_get_try_int(qdict, "number", 10);
+    s = qdict_get_try_str(qdict, "sortedby");
+
+    int sortedby = 0;
+    if (s == NULL || strcmp(s, "hotness") == 0) {
+        sortedby = SORT_BY_HOTNESS;
+    } else if (strcmp(s, "hg") == 0) {
+        sortedby = SORT_BY_HG;
+    }
+
+    dump_tbs_info(n, sortedby, true);
+}
+
+static void hmp_info_tb(Monitor *mon, const QDict *qdict)
+{
+    const int id = qdict_get_int(qdict, "id");
+    const char *flags = qdict_get_try_str(qdict, "flags");
+    int mask;
+
+    if (!tcg_enabled()) {
+        error_report("TB information is only available with accel=tcg");
+        return;
+    }
+
+    mask = flags ? qemu_str_to_log_mask(flags) : CPU_LOG_TB_IN_ASM;
+
+    if (!mask) {
+        help_cmd(mon, "log");
+        return;
+    }
+
+    dump_tb_info(id, mask, true);
+}
+
+static void hmp_info_coverset(Monitor *mon, const QDict *qdict)
+{
+    int n;
+    if (!tcg_enabled()) {
+        error_report("TB information is only available with accel=tcg");
+        return;
+    }
+    if (!qemu_loglevel_mask(CPU_LOG_HOT_TBS)) {
+        error_report("TB information not being recorded");
+        return;
+    }
+
+    n = qdict_get_try_int(qdict, "number", 90);
+
+    if (n < 0 || n > 100) {
+        error_report("Coverset percentage should be between 0 and 100");
+        return;
+    }
+
+    dump_coverset_info(n, true);
+}
+
 static void hmp_info_opcount(Monitor *mon, const QDict *qdict)
 {
     dump_opcount_info();