From: "Alex Bennée" <alex.bennee@linaro.org>
To: Nikolay Igotti <igotti@gmail.com>
Cc: Riku Voipio <riku.voipio@iki.fi>,
"Emilio G. Cota" <cota@braap.org>,
Laurent Vivier <laurent@vivier.eu>,
QEMU Developers <qemu-devel@nongnu.org>
Subject: Re: [PATCH 3/3] plugins: avoid failing plugin when CPU is inited several times
Date: Tue, 12 May 2020 20:35:00 +0100 [thread overview]
Message-ID: <873685eyl7.fsf@linaro.org> (raw)
In-Reply-To: <CAEme+7E+d4Obmc=6bDcZgP5oEx9F57qe9RE2X=iFw+Yo=+i9_A@mail.gmail.com>
Nikolay Igotti <igotti@gmail.com> writes:
> --- counter.c
>
> #include <assert.h>
> #include <pthread.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <unistd.h>
>
> #include <glib.h>
>
> #include <qemu-plugin.h>
>
> QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
>
> // Files with descriptors after this one are intercepted for instruction
> counting marks.
> #define CATCH_BASE 0xcafebabe
>
> static uint64_t insn_count = 0;
> static pthread_t counting = false;
> static pthread_t counting_for = 0;
> static bool on_every_close = false;
>
> static void vcpu_insn_exec_before(unsigned int cpu_index, void *udata)
> {
> if (counting && pthread_self() == counting_for)
> insn_count++;
> }
>
> static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
> {
> size_t n = qemu_plugin_tb_n_insns(tb);
> size_t i;
>
> for (i = 0; i < n; i++) {
> struct qemu_plugin_insn *insn = qemu_plugin_tb_get_insn(tb, i);
>
> // TODO: do this call only on first insn in bb.
> qemu_plugin_register_vcpu_insn_exec_cb(
> insn, vcpu_insn_exec_before, QEMU_PLUGIN_CB_NO_REGS, NULL);
> }
> }
>
> static void print_insn_count(void) {
> g_autofree gchar *out = g_strdup_printf("executed %" PRIu64 "
> instructions\n", insn_count);
> qemu_plugin_outs(out);
> }
>
> static void vcpu_syscall(qemu_plugin_id_t id, unsigned int vcpu_index,
> int64_t num, uint64_t a1, uint64_t a2,
> uint64_t a3, uint64_t a4, uint64_t a5,
> uint64_t a6, uint64_t a7, uint64_t a8)
> {
> // We put our listener on fd reads in range [CATCH_BASE, CATCH_BASE + 1]
> if (num == 0) { // sys_read
> switch (a1)
> {
> case CATCH_BASE + 0:
> counting = true;
> counting_for = pthread_self();
> insn_count = 0;
> break;
> case CATCH_BASE + 1: {
> counting = false;
> counting_for = 0;
> if (a3 == 8) {
> // In case of user emulation in QEMU, addresses are 1:1
> translated, so we can tell the caller
> // number of executed instructions by just writing into
> the buffer argument of read.
> *(uint64_t*)a2 = insn_count;
Hmm this was certainly unintentional - is it the host or guest address
you are messing with here? I wouldn't count on it pointing where you
think and relying on it to pass information back to the instrumented
guest.
Anyway I have a replication - we are trying to insert the same id into
the plugin cpu index hash table twice.
> }
> print_insn_count();
> break;
> }
> default:
> break;
> }
> }
> if (num == 3 && on_every_close) { // sys_close
> print_insn_count();
> }
> }
>
> QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
> const qemu_info_t *info,
> int argc, char **argv)
> {
> int i;
> for (i = 0; i < argc; i++) {
> if (!strcmp(argv[i], "on_every_close")) {
> on_every_close = true;
> counting = true;
> counting_for = pthread_self();
> }
> }
>
> qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
> qemu_plugin_register_vcpu_syscall_cb(id, vcpu_syscall);
> return 0;
> }
>
> --- test.c
>
> #include <stdint.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <pthread.h>
>
> #define CATCH_BASE 0xcafebabe
>
> static void start_counting() {
> char buf;
> int rv = read(CATCH_BASE, &buf, 1);
> (void)rv;
> }
>
> static void end_counting() {
> uint64_t counter = 0;
> int rv = read(CATCH_BASE + 1, &counter, sizeof(counter));
> (void)rv;
> printf("We got %lld from TCG\n", counter);
> }
>
> int global = 0;
>
> typedef struct {
> int delay;
> } ThreadArg;
>
> static void* thread_fn(void* varg) {
> ThreadArg* arg = varg;
> usleep(arg->delay);
> free(arg);
> return NULL;
> }
>
> int main(int argc, char** argv) {
> int i;
> int repeat = 100;
> #define THREAD_NUM 10
> pthread_t threads[THREAD_NUM];
>
> if (argc > 1) {
> repeat = atoi(argv[1]);
> }
>
> for (i = 0; i < THREAD_NUM; i++) {
> ThreadArg* arg = calloc(sizeof(ThreadArg), 1);
> arg->delay = i * 100;
> pthread_create(threads + i, NULL, thread_fn, arg);
> }
>
> start_counting();
> for (i = 0; i < repeat; i++) {
> global += i;
> }
> end_counting();
>
> for (i = 0; i < THREAD_NUM; i++) {
> pthread_join(threads[i], NULL);
> }
>
> return 0;
> }
>
> On Tue, May 12, 2020 at 3:55 AM Emilio G. Cota <cota@braap.org> wrote:
>
>> On Mon, May 11, 2020 at 18:53:19 +0300, Nikolay Igotti wrote:
>> > Attached to the mail counter.c when running with attached test.c compiled
>> > to Linux standalone binary shows failing assert, unless the patch is
>> > applied.
>>
>> I didn't get the attachment. Can you paste the code at the end of your
>> reply?
>>
>> Thanks,
>> Emilio
>>
--
Alex Bennée
next prev parent reply other threads:[~2020-05-12 19:42 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-04-20 9:15 [PATCH 3/3] plugins: avoid failing plugin when CPU is inited several times Nikolay Igotti
2020-04-20 9:51 ` Laurent Vivier
2020-04-20 10:04 ` Nikolay Igotti
2020-05-09 23:00 ` Emilio G. Cota
2020-05-11 15:53 ` Nikolay Igotti
2020-05-12 0:55 ` Emilio G. Cota
2020-05-12 8:38 ` Nikolay Igotti
2020-05-12 19:35 ` Alex Bennée [this message]
2020-05-12 20:11 ` Alex Bennée
2020-05-24 14:11 ` Emilio G. Cota
2020-04-20 10:11 ` Peter Maydell
2020-04-20 10:18 ` Nikolay Igotti
2020-04-20 10:30 ` Peter Maydell
2020-04-20 15:07 ` Alex Bennée
2020-04-20 16:14 ` Nikolay Igotti
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=873685eyl7.fsf@linaro.org \
--to=alex.bennee@linaro.org \
--cc=cota@braap.org \
--cc=igotti@gmail.com \
--cc=laurent@vivier.eu \
--cc=qemu-devel@nongnu.org \
--cc=riku.voipio@iki.fi \
/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).