Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1882117/?format=api
{ "id": 1882117, "url": "http://patchwork.ozlabs.org/api/patches/1882117/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20240103173349.398526-41-alex.bennee@linaro.org/", "project": { "id": 14, "url": "http://patchwork.ozlabs.org/api/projects/14/?format=api", "name": "QEMU Development", "link_name": "qemu-devel", "list_id": "qemu-devel.nongnu.org", "list_email": "qemu-devel@nongnu.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20240103173349.398526-41-alex.bennee@linaro.org>", "list_archive_url": null, "date": "2024-01-03T17:33:46", "name": "[v2,40/43] contrib/plugins: extend execlog to track register changes", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "8c04b8daf590eaa93aadfb41a2d6ce479dc97402", "submitter": { "id": 39532, "url": "http://patchwork.ozlabs.org/api/people/39532/?format=api", "name": "Alex Bennée", "email": "alex.bennee@linaro.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20240103173349.398526-41-alex.bennee@linaro.org/mbox/", "series": [ { "id": 388742, "url": "http://patchwork.ozlabs.org/api/series/388742/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=388742", "date": "2024-01-03T17:33:08", "name": "testing and plugin updates for 9.0 (pre-PR)", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/388742/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1882117/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1882117/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256\n header.s=google header.b=Dmj9yqBH;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)" ], "Received": [ "from lists.gnu.org (lists.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4T4xqf6nBTz1ydb\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 4 Jan 2024 04:42:06 +1100 (AEDT)", "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1rL5DX-0007yt-D9; Wed, 03 Jan 2024 12:39:47 -0500", "from eggs.gnu.org ([2001:470:142:3::10])\n by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <alex.bennee@linaro.org>)\n id 1rL5DV-0007uN-KP\n for qemu-devel@nongnu.org; Wed, 03 Jan 2024 12:39:45 -0500", "from mail-wr1-x42c.google.com ([2a00:1450:4864:20::42c])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.90_1) (envelope-from <alex.bennee@linaro.org>)\n id 1rL5D4-0000nJ-29\n for qemu-devel@nongnu.org; Wed, 03 Jan 2024 12:39:45 -0500", "by mail-wr1-x42c.google.com with SMTP id\n ffacd0b85a97d-32f8441dfb5so10215749f8f.0\n for <qemu-devel@nongnu.org>; Wed, 03 Jan 2024 09:39:17 -0800 (PST)", "from draig.lan ([85.9.250.243]) by smtp.gmail.com with ESMTPSA id\n a16-20020a056000101000b003366a9cb0d1sm31080983wrx.92.2024.01.03.09.39.09\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 03 Jan 2024 09:39:13 -0800 (PST)", "from draig.lan (localhost [IPv6:::1])\n by draig.lan (Postfix) with ESMTP id 6B2135F9D5;\n Wed, 3 Jan 2024 17:33:53 +0000 (GMT)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=linaro.org; s=google; t=1704303556; x=1704908356; darn=nongnu.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=6qYxYpnr0vzCXiIKNDoO95XioKhgHwYSQEn7vMTXP0k=;\n b=Dmj9yqBH0R9BNNEJZQN+FNhibX59WBNR3Code1eBTJenUa25jXSHbtf/Mf0IKX8MZe\n 6XCrym3EOptamH3G/VRfvXTab4yOa7VfOiXHr2c4D86w/Dk19JaYmvLP5DkFpdlfUcBd\n n5zQxqRocv+qN4aStvKE8zYkwPUe5zUueok/eZB4lKjPDGSvLFnyUQSXYhoKlivHHA3Y\n zLBt0Arf3oDaXQMU3/8DkBk624NJzpje9MfCfhPvvp3cCcMX2DTZ0kKtiipMNFsR232F\n tl4q5leS2u6C2kEDIuTDbmYVR04GPG0bXNy9IAoXKc3eLbdH75SJXNqgQChsM1dmRDOM\n dxvw==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1704303556; x=1704908356;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc\n :subject:date:message-id:reply-to;\n bh=6qYxYpnr0vzCXiIKNDoO95XioKhgHwYSQEn7vMTXP0k=;\n b=KiPtBdpRKp3+Q04iYjl98o2I1A8Q+UvBXVbgdHwAjaN7fPV3kxttUZuH0D9a5rQpCi\n OZH8lRqLLlGF5YhWEybJqYnIeqcyTZ/qC1AIXHHh0Xk9RYIOQxSPU+AlFEgDBT+Atz+r\n HMGGAkVbNTE6LidZlcGEpao2fHvawB3TyV6D019NyiGHOJbxFaHcTZXWm70QDIAhb30p\n DmFG8Pn7ATamWMHeqwDNnIMq0hVnPVlL+Bj5tY8/NSbBhx4nRuSZAi6d63y3mgC7JqQV\n BxsrAsHnhMZ5+ehfz9ThrB7RU7Ek7FQiFFyNiv1db8A/OCqMTtrXIzju5op2KLzyXDb2\n 5asw==", "X-Gm-Message-State": "AOJu0Yx9xvjnrjKWIbutZPdJ785TITLTcaa7mx4TZXTeSdehL7B+s7F8\n OPxhTcHABALb6YF3FrP0OpS+T/+2y1914A==", "X-Google-Smtp-Source": "\n AGHT+IFirHy9EDbCpJhUcCOWZ36HyZDOq8CLVldsPYnvJBVFXEf2kuTpqZW9jVagG31llrW0iPzfwg==", "X-Received": "by 2002:adf:e747:0:b0:336:6722:19f with SMTP id\n c7-20020adfe747000000b003366722019fmr10341379wrn.29.1704303556598;\n Wed, 03 Jan 2024 09:39:16 -0800 (PST)", "From": "=?utf-8?q?Alex_Benn=C3=A9e?= <alex.bennee@linaro.org>", "To": "qemu-devel@nongnu.org", "Cc": "qemu-s390x@nongnu.org, qemu-ppc@nongnu.org,\n Richard Henderson <richard.henderson@linaro.org>,\n Song Gao <gaosong@loongson.cn>,\n =?utf-8?q?Marc-Andr=C3=A9_Lureau?= <marcandre.lureau@redhat.com>,\n David Hildenbrand <david@redhat.com>, Aurelien Jarno <aurelien@aurel32.net>,\n Yoshinori Sato <ysato@users.sourceforge.jp>,\n Yanan Wang <wangyanan55@huawei.com>, Bin Meng <bin.meng@windriver.com>,\n Laurent Vivier <lvivier@redhat.com>, Michael Rolnik <mrolnik@gmail.com>,\n Alexandre Iooss <erdnaxe@crans.org>, David Woodhouse <dwmw2@infradead.org>,\n Laurent Vivier <laurent@vivier.eu>, Paolo Bonzini <pbonzini@redhat.com>,\n Brian Cain <bcain@quicinc.com>,\n Daniel Henrique Barboza <danielhb413@gmail.com>,\n Beraldo Leal <bleal@redhat.com>, Paul Durrant <paul@xen.org>,\n Mahmoud Mandour <ma.mandourr@gmail.com>, Thomas Huth <thuth@redhat.com>,\n Liu Zhiwei <zhiwei_liu@linux.alibaba.com>, Cleber Rosa <crosa@redhat.com>,\n kvm@vger.kernel.org, Peter Maydell <peter.maydell@linaro.org>,\n Wainer dos Santos Moschetta <wainersm@redhat.com>, =?utf-8?q?Alex_Benn?=\n\t=?utf-8?q?=C3=A9e?= <alex.bennee@linaro.org>, qemu-arm@nongnu.org,\n Weiwei Li <liwei1518@gmail.com>,\n =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= <philmd@linaro.org>,\n John Snow <jsnow@redhat.com>,\n Daniel Henrique Barboza <dbarboza@ventanamicro.com>,\n Nicholas Piggin <npiggin@gmail.com>, Palmer Dabbelt <palmer@dabbelt.com>,\n Marcel Apfelbaum <marcel.apfelbaum@gmail.com>,\n Ilya Leoshkevich <iii@linux.ibm.com>,\n =?utf-8?q?C=C3=A9dric_Le_Goater?= <clg@kaod.org>,\n \"Edgar E. Iglesias\" <edgar.iglesias@gmail.com>,\n Eduardo Habkost <eduardo@habkost.net>,\n Pierrick Bouvier <pierrick.bouvier@linaro.org>, qemu-riscv@nongnu.org,\n Alistair Francis <alistair.francis@wdc.com>,\n Akihiko Odaki <akihiko.odaki@daynix.com>", "Subject": "[PATCH v2 40/43] contrib/plugins: extend execlog to track register\n changes", "Date": "Wed, 3 Jan 2024 17:33:46 +0000", "Message-Id": "<20240103173349.398526-41-alex.bennee@linaro.org>", "X-Mailer": "git-send-email 2.39.2", "In-Reply-To": "<20240103173349.398526-1-alex.bennee@linaro.org>", "References": "<20240103173349.398526-1-alex.bennee@linaro.org>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=UTF-8", "Content-Transfer-Encoding": "8bit", "Received-SPF": "pass client-ip=2a00:1450:4864:20::42c;\n envelope-from=alex.bennee@linaro.org; helo=mail-wr1-x42c.google.com", "X-Spam_score_int": "-20", "X-Spam_score": "-2.1", "X-Spam_bar": "--", "X-Spam_report": "(-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001,\n T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no", "X-Spam_action": "no action", "X-BeenThere": "qemu-devel@nongnu.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "<qemu-devel.nongnu.org>", "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>", "List-Archive": "<https://lists.nongnu.org/archive/html/qemu-devel>", "List-Post": "<mailto:qemu-devel@nongnu.org>", "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>", "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>", "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org", "Sender": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org" }, "content": "With the new plugin register API we can now track changes to register\nvalues. Currently the implementation is fairly dumb which will slow\ndown if a large number of register values are being tracked. This\ncould be improved by only instrumenting instructions which mention\nregisters we are interested in tracking.\n\nExample usage:\n\n ./qemu-aarch64 -D plugin.log -d plugin \\\n -cpu max,sve256=on \\\n -plugin contrib/plugins/libexeclog.so,reg=sp,reg=z\\* \\\n ./tests/tcg/aarch64-linux-user/sha512-sve\n\nwill display in the execlog any changes to the stack pointer (sp) and\nthe SVE Z registers.\n\nSigned-off-by: Alex Bennée <alex.bennee@linaro.org>\nCc: Akihiko Odaki <akihiko.odaki@daynix.com>\nBased-On: <20231025093128.33116-19-akihiko.odaki@daynix.com>\n\n---\nv3\n - prefix 0x to register value\nv2\n - we now do the glob-like search in the plugin itself.\n - fix some erroneous cpus->cpu\n\nvAJB:\n\nChanges for the new API with a simpler glob based \"reg\" specifier\nwhich can be specified multiple times.\n---\n docs/devel/tcg-plugins.rst | 9 +-\n contrib/plugins/execlog.c | 189 ++++++++++++++++++++++++++++---------\n 2 files changed, 153 insertions(+), 45 deletions(-)", "diff": "diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst\nindex 81dcd43a612..3a0962723d7 100644\n--- a/docs/devel/tcg-plugins.rst\n+++ b/docs/devel/tcg-plugins.rst\n@@ -497,6 +497,14 @@ arguments if required::\n $ qemu-system-arm $(QEMU_ARGS) \\\n -plugin ./contrib/plugins/libexeclog.so,ifilter=st1w,afilter=0x40001808 -d plugin\n \n+This plugin can also dump registers when they change value. Specify the name of the\n+registers with multiple ``reg`` options. You can also use glob style matching if you wish::\n+\n+ $ qemu-system-arm $(QEMU_ARGS) \\\n+ -plugin ./contrib/plugins/libexeclog.so,reg=\\*_el2,reg=sp -d plugin\n+\n+Be aware that each additional register to check will slow down execution quite considerably.\n+\n - contrib/plugins/cache.c\n \n Cache modelling plugin that measures the performance of a given L1 cache\n@@ -583,4 +591,3 @@ The following API is generated from the inline documentation in\n include the full kernel-doc annotations.\n \n .. kernel-doc:: include/qemu/qemu-plugin.h\n-\ndiff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c\nindex f262e5555eb..c20e88a6941 100644\n--- a/contrib/plugins/execlog.c\n+++ b/contrib/plugins/execlog.c\n@@ -1,7 +1,7 @@\n /*\n * Copyright (C) 2021, Alexandre Iooss <erdnaxe@crans.org>\n *\n- * Log instruction execution with memory access.\n+ * Log instruction execution with memory access and register changes\n *\n * License: GNU GPL, version 2 or later.\n * See the COPYING file in the top-level directory.\n@@ -15,30 +15,29 @@\n \n #include <qemu-plugin.h>\n \n+typedef struct {\n+ struct qemu_plugin_register *handle;\n+ GByteArray *last;\n+ GByteArray *new;\n+ const char *name;\n+} Register;\n+\n+typedef struct CPU {\n+ /* Store last executed instruction on each vCPU as a GString */\n+ GString *last_exec;\n+ /* Ptr array of Register */\n+ GPtrArray *registers;\n+} CPU;\n+\n QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;\n \n-/* Store last executed instruction on each vCPU as a GString */\n-static GPtrArray *last_exec;\n+static CPU *cpus;\n+static int num_cpus;\n static GRWLock expand_array_lock;\n \n static GPtrArray *imatches;\n static GArray *amatches;\n-\n-/*\n- * Expand last_exec array.\n- *\n- * As we could have multiple threads trying to do this we need to\n- * serialise the expansion under a lock.\n- */\n-static void expand_last_exec(int cpu_index)\n-{\n- g_rw_lock_writer_lock(&expand_array_lock);\n- while (cpu_index >= last_exec->len) {\n- GString *s = g_string_new(NULL);\n- g_ptr_array_add(last_exec, s);\n- }\n- g_rw_lock_writer_unlock(&expand_array_lock);\n-}\n+static GPtrArray *rmatches;\n \n /**\n * Add memory read or write information to current instruction log\n@@ -50,8 +49,8 @@ static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t info,\n \n /* Find vCPU in array */\n g_rw_lock_reader_lock(&expand_array_lock);\n- g_assert(cpu_index < last_exec->len);\n- s = g_ptr_array_index(last_exec, cpu_index);\n+ g_assert(cpu_index < num_cpus);\n+ s = cpus[cpu_index].last_exec;\n g_rw_lock_reader_unlock(&expand_array_lock);\n \n /* Indicate type of memory access */\n@@ -77,28 +76,46 @@ static void vcpu_mem(unsigned int cpu_index, qemu_plugin_meminfo_t info,\n */\n static void vcpu_insn_exec(unsigned int cpu_index, void *udata)\n {\n- GString *s;\n+ CPU *cpu;\n \n- /* Find or create vCPU in array */\n g_rw_lock_reader_lock(&expand_array_lock);\n- if (cpu_index >= last_exec->len) {\n- g_rw_lock_reader_unlock(&expand_array_lock);\n- expand_last_exec(cpu_index);\n- g_rw_lock_reader_lock(&expand_array_lock);\n- }\n- s = g_ptr_array_index(last_exec, cpu_index);\n+ g_assert(cpu_index < num_cpus);\n+ cpu = &cpus[cpu_index];\n g_rw_lock_reader_unlock(&expand_array_lock);\n \n /* Print previous instruction in cache */\n- if (s->len) {\n- qemu_plugin_outs(s->str);\n+ if (cpu->last_exec->len) {\n+ if (cpu->registers) {\n+ for (int n = 0; n < cpu->registers->len; n++) {\n+ Register *reg = cpu->registers->pdata[n];\n+ int sz;\n+\n+ g_byte_array_set_size(reg->new, 0);\n+ sz = qemu_plugin_read_register(cpu_index, reg->handle, reg->new);\n+ g_assert(sz == reg->last->len);\n+\n+ if (memcmp(reg->last->data, reg->new->data, sz)) {\n+ GByteArray *temp = reg->last;\n+ g_string_append_printf(cpu->last_exec, \", %s -> 0x\", reg->name);\n+ /* TODO: handle BE properly */\n+ for (int i = sz; i >= 0; i--) {\n+ g_string_append_printf(cpu->last_exec, \"%02x\",\n+ reg->new->data[i]);\n+ }\n+ reg->last = reg->new;\n+ reg->new = temp;\n+ }\n+ }\n+ }\n+\n+ qemu_plugin_outs(cpu->last_exec->str);\n qemu_plugin_outs(\"\\n\");\n }\n \n /* Store new instruction in cache */\n /* vcpu_mem will add memory access information to last_exec */\n- g_string_printf(s, \"%u, \", cpu_index);\n- g_string_append(s, (char *)udata);\n+ g_string_printf(cpus[cpu_index].last_exec, \"%u, \", cpu_index);\n+ g_string_append(cpus[cpu_index].last_exec, (char *)udata);\n }\n \n /**\n@@ -167,8 +184,10 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)\n QEMU_PLUGIN_MEM_RW, NULL);\n \n /* Register callback on instruction */\n- qemu_plugin_register_vcpu_insn_exec_cb(insn, vcpu_insn_exec,\n- QEMU_PLUGIN_CB_NO_REGS, output);\n+ qemu_plugin_register_vcpu_insn_exec_cb(\n+ insn, vcpu_insn_exec,\n+ rmatches ? QEMU_PLUGIN_CB_R_REGS : QEMU_PLUGIN_CB_NO_REGS,\n+ output);\n \n /* reset skip */\n skip = (imatches || amatches);\n@@ -177,17 +196,86 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)\n }\n }\n \n+static Register *init_vcpu_register(int vcpu_index,\n+ qemu_plugin_reg_descriptor *desc)\n+{\n+ Register *reg = g_new0(Register, 1);\n+ int r;\n+\n+ reg->handle = desc->handle;\n+ reg->name = g_strdup(desc->name);\n+ reg->last = g_byte_array_new();\n+ reg->new = g_byte_array_new();\n+\n+ /* read the initial value */\n+ r = qemu_plugin_read_register(vcpu_index, reg->handle, reg->last);\n+ g_assert(r > 0);\n+ return reg;\n+}\n+\n+static registers_init(int vcpu_index)\n+{\n+ GPtrArray *registers = g_ptr_array_new();\n+ g_autoptr(GArray) reg_list = qemu_plugin_get_registers(vcpu_index);\n+\n+ if (reg_list && reg_list->len) {\n+ /*\n+ * Go through each register in the complete list and\n+ * see if we want to track it.\n+ */\n+ for (int r = 0; r < reg_list->len; r++) {\n+ qemu_plugin_reg_descriptor *rd = &g_array_index(\n+ reg_list, qemu_plugin_reg_descriptor, r);\n+ for (int p = 0; p < rmatches->len; p++) {\n+ g_autoptr(GPatternSpec) pat = g_pattern_spec_new(rmatches->pdata[p]);\n+ if (g_pattern_match_string(pat, rd->name)) {\n+ Register *reg = init_vcpu_register(vcpu_index, rd);\n+ g_ptr_array_add(registers, reg);\n+ }\n+ }\n+ }\n+ }\n+ cpus[num_cpus].registers = registers;\n+}\n+\n+/*\n+ * Initialise a new vcpu/thread with:\n+ * - last_exec tracking data\n+ * - list of tracked registers\n+ * - initial value of registers\n+ *\n+ * As we could have multiple threads trying to do this we need to\n+ * serialise the expansion under a lock.\n+ */\n+static void vcpu_init(qemu_plugin_id_t id, unsigned int vcpu_index)\n+{\n+ g_rw_lock_writer_lock(&expand_array_lock);\n+\n+ if (vcpu_index >= num_cpus) {\n+ cpus = g_realloc_n(cpus, vcpu_index + 1, sizeof(*cpus));\n+ while (vcpu_index >= num_cpus) {\n+ cpus[num_cpus].last_exec = g_string_new(NULL);\n+\n+ /* Any registers to track? */\n+ if (rmatches && rmatches->len) {\n+ registers_init(vcpu_index);\n+ }\n+ num_cpus++;\n+ }\n+ }\n+\n+ g_rw_lock_writer_unlock(&expand_array_lock);\n+}\n+\n /**\n * On plugin exit, print last instruction in cache\n */\n static void plugin_exit(qemu_plugin_id_t id, void *p)\n {\n guint i;\n- GString *s;\n- for (i = 0; i < last_exec->len; i++) {\n- s = g_ptr_array_index(last_exec, i);\n- if (s->str) {\n- qemu_plugin_outs(s->str);\n+ for (i = 0; i < num_cpus; i++) {\n+ if (cpus[i].last_exec->str) {\n+ qemu_plugin_outs(cpus[i].last_exec->str);\n qemu_plugin_outs(\"\\n\");\n }\n }\n@@ -212,6 +300,18 @@ static void parse_vaddr_match(char *match)\n g_array_append_val(amatches, v);\n }\n \n+/*\n+ * We have to wait until vCPUs are started before we can check the\n+ * patterns find anything.\n+ */\n+static void add_regpat(char *regpat)\n+{\n+ if (!rmatches) {\n+ rmatches = g_ptr_array_new();\n+ }\n+ g_ptr_array_add(rmatches, g_strdup(regpat));\n+}\n+\n /**\n * Install the plugin\n */\n@@ -224,9 +324,7 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,\n * we don't know the size before emulation.\n */\n if (info->system_emulation) {\n- last_exec = g_ptr_array_sized_new(info->system.max_vcpus);\n- } else {\n- last_exec = g_ptr_array_new();\n+ cpus = g_new(CPU, info->system.max_vcpus);\n }\n \n for (int i = 0; i < argc; i++) {\n@@ -236,13 +334,16 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,\n parse_insn_match(tokens[1]);\n } else if (g_strcmp0(tokens[0], \"afilter\") == 0) {\n parse_vaddr_match(tokens[1]);\n+ } else if (g_strcmp0(tokens[0], \"reg\") == 0) {\n+ add_regpat(tokens[1]);\n } else {\n fprintf(stderr, \"option parsing failed: %s\\n\", opt);\n return -1;\n }\n }\n \n- /* Register translation block and exit callbacks */\n+ /* Register init, translation block and exit callbacks */\n+ qemu_plugin_register_vcpu_init_cb(id, vcpu_init);\n qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);\n qemu_plugin_register_atexit_cb(id, plugin_exit, NULL);\n \n", "prefixes": [ "v2", "40/43" ] }