Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2217953/?format=api
{ "id": 2217953, "url": "http://patchwork.ozlabs.org/api/patches/2217953/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260331040659.401397-2-tangtao1634@phytium.com.cn/", "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": "<20260331040659.401397-2-tangtao1634@phytium.com.cn>", "list_archive_url": null, "date": "2026-03-31T04:06:56", "name": "[1/4] tests/qtest: Add attrs support to qtest server memory commands", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "8a8fd151c8abe072fe62ef97fe319c1820ba51bd", "submitter": { "id": 91412, "url": "http://patchwork.ozlabs.org/api/people/91412/?format=api", "name": "Tao Tang", "email": "tangtao1634@phytium.com.cn" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260331040659.401397-2-tangtao1634@phytium.com.cn/mbox/", "series": [ { "id": 498122, "url": "http://patchwork.ozlabs.org/api/series/498122/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=498122", "date": "2026-03-31T04:06:55", "name": "tests/qtest: Add memory-access attributes (secure/space)", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/498122/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2217953/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2217953/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 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)", "hzbj-icmmx-6; spf=neutral smtp.mail=tangtao163\n 4@phytium.com.cn;" ], "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 4flF4T51Xdz1xtJ\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 31 Mar 2026 15:09:29 +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 1w7QOZ-0001BC-WB; Tue, 31 Mar 2026 00:08:04 -0400", "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 <tangtao1634@phytium.com.cn>)\n id 1w7QON-000102-DI; Tue, 31 Mar 2026 00:07:51 -0400", "from sgoci-sdnproxy-4.icoremail.net ([129.150.39.64])\n by eggs.gnu.org with esmtp (Exim 4.90_1)\n (envelope-from <tangtao1634@phytium.com.cn>)\n id 1w7QOI-0002F2-MM; Tue, 31 Mar 2026 00:07:51 -0400", "from prodtpl.icoremail.net (unknown [10.12.1.20])\n by hzbj-icmmx-6 (Coremail) with SMTP id AQAAfwDn7qKFSMtpdcg9AA--.20365S2;\n Tue, 31 Mar 2026 12:07:33 +0800 (CST)", "from phytium.com.cn (unknown [218.76.62.144])\n by mail (Coremail) with SMTP id AQAAf8DwSJR6SMtpYqQHAA--.18366S4;\n Tue, 31 Mar 2026 12:07:28 +0800 (CST)" ], "From": "Tao Tang <tangtao1634@phytium.com.cn>", "To": "Fabiano Rosas <farosas@suse.de>, Laurent Vivier <lvivier@redhat.com>,\n Paolo Bonzini <pbonzini@redhat.com>", "Cc": "qemu-devel@nongnu.org, qemu-arm@nongnu.org,\n Peter Maydell <peter.maydell@linaro.org>,\n Chen Baozi <chenbaozi@phytium.com.cn>,\n Pierrick Bouvier <pierrick.bouvier@linaro.org>,\n Chao Liu <chao.liu.zevorn@gmail.com>, Tao Tang <tangtao1634@phytium.com.cn>", "Subject": "[PATCH 1/4] tests/qtest: Add attrs support to qtest server memory\n commands", "Date": "Tue, 31 Mar 2026 12:06:56 +0800", "Message-Id": "<20260331040659.401397-2-tangtao1634@phytium.com.cn>", "X-Mailer": "git-send-email 2.34.1", "In-Reply-To": "<20260331040659.401397-1-tangtao1634@phytium.com.cn>", "References": "<20260331040659.401397-1-tangtao1634@phytium.com.cn>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-CM-TRANSID": "AQAAf8DwSJR6SMtpYqQHAA--.18366S4", "X-CM-SenderInfo": "pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQAKBWnJfH8GCQACsg", "X-Coremail-Antispam": "1Uk129KBjvAXoW3uryrCryftrykCrW3tw4DCFg_yoW8Wry7Zo\n WfKFnIya4Ut3Z7Cr929r1DJ34DXay5ur1DAwsYywn8Kay8Wryq9a98JFsxWa4jqayrGryk\n X3WfXr4fXFy0v397n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf\n J3UbIjqfuFe4nvWSU8nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UU\n UUUUUUU==", "Received-SPF": "pass client-ip=129.150.39.64;\n envelope-from=tangtao1634@phytium.com.cn; helo=sgoci-sdnproxy-4.icoremail.net", "X-Spam_score_int": "1", "X-Spam_score": "0.1", "X-Spam_bar": "/", "X-Spam_report": "(0.1 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_MSPIKE_H3=-0.01,\n RCVD_IN_MSPIKE_WL=-0.01, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=1,\n RCVD_IN_VALIDITY_RPBL_BLOCKED=1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001,\n WEIRD_QUOTING=0.001 autolearn=no 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 development <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": "Extend qtest memory access commands to accept an optional attrs argument.\n\nSupported attrs:\n- secure (x86/Arm)\n- space=non-secure|secure|root|realm (Arm-only)\n\nFor memory commands, parse attrs, select the corresponding AddressSpace\nwith cpu_asidx_from_attrs(), and issue accesses with the matching\nMemTxAttrs.\n\nCover scalar and bulk memory commands, including:\n- read{b,w,l,q} / write{b,w,l,q}\n- read / write\n- b64read / b64write\n- memset\n\nAlso reject invalid attrs and excessive arguments, and document the new\ncommand forms in qtest.c, and use qtest_send_memtx_error() to return\nERR for memory access failures.\n\nPreserve legacy no-attrs semantics for compatibility: those commands\ncontinue to ignore MemTxResult and return OK.\n\nSigned-off-by: Tao Tang <tangtao1634@phytium.com.cn>\n---\n system/qtest.c | 420 +++++++++++++++++++++++++++++++++++++++++++------\n 1 file changed, 368 insertions(+), 52 deletions(-)", "diff": "diff --git a/system/qtest.c b/system/qtest.c\nindex cf90cd53ad..f330c158d0 100644\n--- a/system/qtest.c\n+++ b/system/qtest.c\n@@ -22,6 +22,7 @@\n #include \"hw/core/qdev.h\"\n #include \"hw/core/irq.h\"\n #include \"hw/core/cpu.h\"\n+#include \"hw/arm/arm-security.h\"\n #include \"qemu/accel.h\"\n #include \"system/cpu-timers.h\"\n #include \"qemu/config-file.h\"\n@@ -113,6 +114,14 @@ static void *qtest_server_send_opaque;\n * PIO and memory access:\n * \"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\n *\n+ * Memory access commands allow specifying memory transaction attributes,\n+ * which is useful for testing devices that behave differently based on\n+ * security state (e.g., Arm TrustZone/CCA or System Management Mode in x86).\n+ *\n+ * Only the following attributes are supported by the qtest server:\n+ * ``secure`` sets MemTxAttrs.secure=1 (x86/Arm).\n+ * ``space=...`` is Arm-specific and accepts: non-secure, secure, root, realm.\n+ *\n * .. code-block:: none\n *\n * > outb ADDR VALUE\n@@ -208,6 +217,36 @@ static void *qtest_server_send_opaque;\n * > memset ADDR SIZE VALUE\n * < OK\n *\n+ * Memory commands accept an optional ATTRS argument after their existing\n+ * operands:\n+ *\n+ * .. code-block:: none\n+ *\n+ * > read{b,w,l,q} ADDR [ATTRS]\n+ * > write{b,w,l,q} ADDR VALUE [ATTRS]\n+ * > read ADDR SIZE [ATTRS]\n+ * > write ADDR SIZE DATA [ATTRS]\n+ * > b64read ADDR SIZE [ATTRS]\n+ * > b64write ADDR SIZE B64_DATA [ATTRS]\n+ * > memset ADDR SIZE VALUE [ATTRS]\n+ *\n+ * Representative examples:\n+ *\n+ * .. code-block:: none\n+ *\n+ * > readl ADDR secure\n+ * < OK VALUE\n+ *\n+ * .. code-block:: none\n+ *\n+ * > b64read ADDR SIZE space=root\n+ * < OK B64_DATA\n+ *\n+ * .. code-block:: none\n+ *\n+ * > writeq ADDR VALUE space=realm\n+ * < OK\n+ *\n * ADDR, SIZE, VALUE are all integers parsed with strtoul() with a base of 0.\n * For 'memset' a zero size is permitted and does nothing.\n *\n@@ -353,6 +392,141 @@ static void qtest_install_gpio_out_intercept(DeviceState *dev, const char *name,\n *disconnected = qdev_intercept_gpio_out(dev, icpt, name, n);\n }\n \n+static bool qtest_parse_mem_attrs(CharFrontend *chr, const char *arg,\n+ MemTxAttrs *attrs)\n+{\n+ if (!arg) {\n+ *attrs = MEMTXATTRS_UNSPECIFIED;\n+ return true;\n+ }\n+\n+ if (strcmp(arg, \"secure\") == 0) {\n+ *attrs = (MemTxAttrs){ .secure = 1 };\n+ return true;\n+ }\n+\n+ if (strncmp(arg, \"space=\", 6) == 0) {\n+ const char *space = arg + 6;\n+ ARMSecuritySpace sec_space;\n+\n+ if (!target_arm() && !target_aarch64()) {\n+ qtest_send(chr, \"ERR space=<...> is Arm-specific\\n\");\n+ return false;\n+ }\n+\n+ if (strcmp(space, \"non-secure\") == 0) {\n+ sec_space = ARMSS_NonSecure;\n+ } else if (strcmp(space, \"secure\") == 0) {\n+ sec_space = ARMSS_Secure;\n+ } else if (strcmp(space, \"root\") == 0) {\n+ sec_space = ARMSS_Root;\n+ } else if (strcmp(space, \"realm\") == 0) {\n+ sec_space = ARMSS_Realm;\n+ } else {\n+ qtest_send(chr, \"ERR invalid space value. Valid space: \"\n+ \"secure/non-secure/root/realm\\n\");\n+ return false;\n+ }\n+\n+ *attrs = (MemTxAttrs){\n+ .space = sec_space,\n+ .secure = arm_space_is_secure(sec_space),\n+ };\n+ return true;\n+ }\n+\n+ qtest_send(chr, \"ERR invalid attrs argument\\n\");\n+ return false;\n+}\n+\n+static bool qtest_get_mem_as(CharFrontend *chr, MemTxAttrs attrs,\n+ AddressSpace **as)\n+{\n+ int asidx;\n+\n+ /*\n+ * cpu_asidx_from_attrs mainly uses attrs to call ->asidx_from_attrs. We use\n+ * first_cpu as it's readily available.\n+ */\n+\n+ asidx = cpu_asidx_from_attrs(first_cpu, attrs);\n+ *as = cpu_get_address_space(first_cpu, asidx);\n+ if (!*as) {\n+ qtest_send(chr, \"ERR address space unavailable for attrs\\n\");\n+ return false;\n+ }\n+\n+ return true;\n+}\n+\n+static void qtest_send_memtx_error(CharFrontend *chr, MemTxResult result)\n+{\n+ qtest_sendf(chr, \"ERR memory access failed 0x%x\\n\", result);\n+}\n+\n+static MemTxResult qtest_write_sized(AddressSpace *as, uint64_t addr,\n+ MemTxAttrs attrs, uint64_t value,\n+ char size)\n+{\n+ switch (size) {\n+ case 'b': {\n+ uint8_t data = value;\n+ return address_space_write(as, addr, attrs, &data, 1);\n+ }\n+ case 'w': {\n+ uint16_t data = value;\n+ tswap16s(&data);\n+ return address_space_write(as, addr, attrs, &data, 2);\n+ }\n+ case 'l': {\n+ uint32_t data = value;\n+ tswap32s(&data);\n+ return address_space_write(as, addr, attrs, &data, 4);\n+ }\n+ case 'q': {\n+ uint64_t data = value;\n+ tswap64s(&data);\n+ return address_space_write(as, addr, attrs, &data, 8);\n+ }\n+ default:\n+ g_assert_not_reached();\n+ }\n+}\n+\n+static MemTxResult qtest_read_sized(AddressSpace *as, uint64_t addr,\n+ MemTxAttrs attrs, char size,\n+ uint64_t *value)\n+{\n+ switch (size) {\n+ case 'b': {\n+ uint8_t data = 0;\n+ MemTxResult result = address_space_read(as, addr, attrs, &data, 1);\n+ *value = data;\n+ return result;\n+ }\n+ case 'w': {\n+ uint16_t data = 0;\n+ MemTxResult result = address_space_read(as, addr, attrs, &data, 2);\n+ *value = tswap16(data);\n+ return result;\n+ }\n+ case 'l': {\n+ uint32_t data = 0;\n+ MemTxResult result = address_space_read(as, addr, attrs, &data, 4);\n+ *value = tswap32(data);\n+ return result;\n+ }\n+ case 'q': {\n+ uint64_t data = 0;\n+ MemTxResult result = address_space_read(as, addr, attrs, &data, 8);\n+ *value = tswap64(data);\n+ return result;\n+ }\n+ default:\n+ g_assert_not_reached();\n+ }\n+}\n+\n static void qtest_process_command(CharFrontend *chr, gchar **words)\n {\n const gchar *command;\n@@ -510,33 +684,38 @@ static void qtest_process_command(CharFrontend *chr, gchar **words)\n strcmp(words[0], \"writeq\") == 0) {\n uint64_t addr;\n uint64_t value;\n+ bool has_attrs;\n+ MemTxResult result;\n+ MemTxAttrs attrs;\n+ AddressSpace *as;\n int ret;\n \n g_assert(words[1] && words[2]);\n+ if (words[3] && words[4]) {\n+ qtest_send(chr, \"ERR too many arguments\\n\");\n+ return;\n+ }\n ret = qemu_strtou64(words[1], NULL, 0, &addr);\n g_assert(ret == 0);\n ret = qemu_strtou64(words[2], NULL, 0, &value);\n g_assert(ret == 0);\n+ has_attrs = words[3] != NULL;\n+ if (!has_attrs) {\n+ qtest_write_sized(first_cpu->as, addr,\n+ MEMTXATTRS_UNSPECIFIED,\n+ value, words[0][5]);\n+ qtest_send(chr, \"OK\\n\");\n+ return;\n+ }\n+ if (!qtest_parse_mem_attrs(chr, words[3], &attrs) ||\n+ !qtest_get_mem_as(chr, attrs, &as)) {\n+ return;\n+ }\n \n- if (words[0][5] == 'b') {\n- uint8_t data = value;\n- address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,\n- &data, 1);\n- } else if (words[0][5] == 'w') {\n- uint16_t data = value;\n- tswap16s(&data);\n- address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,\n- &data, 2);\n- } else if (words[0][5] == 'l') {\n- uint32_t data = value;\n- tswap32s(&data);\n- address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,\n- &data, 4);\n- } else if (words[0][5] == 'q') {\n- uint64_t data = value;\n- tswap64s(&data);\n- address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,\n- &data, 8);\n+ result = qtest_write_sized(as, addr, attrs, value, words[0][5]);\n+ if (result != MEMTX_OK) {\n+ qtest_send_memtx_error(chr, result);\n+ return;\n }\n qtest_send(chr, \"OK\\n\");\n } else if (strcmp(words[0], \"readb\") == 0 ||\n@@ -544,51 +723,83 @@ static void qtest_process_command(CharFrontend *chr, gchar **words)\n strcmp(words[0], \"readl\") == 0 ||\n strcmp(words[0], \"readq\") == 0) {\n uint64_t addr;\n- uint64_t value = UINT64_C(-1);\n+ uint64_t value = 0;\n+ bool has_attrs;\n+ MemTxResult result;\n+ MemTxAttrs attrs;\n+ AddressSpace *as;\n int ret;\n \n g_assert(words[1]);\n+ if (words[2] && words[3]) {\n+ qtest_send(chr, \"ERR too many arguments\\n\");\n+ return;\n+ }\n ret = qemu_strtou64(words[1], NULL, 0, &addr);\n g_assert(ret == 0);\n+ has_attrs = words[2] != NULL;\n+ if (!has_attrs) {\n+ qtest_read_sized(first_cpu->as, addr,\n+ MEMTXATTRS_UNSPECIFIED,\n+ words[0][4], &value);\n+ qtest_sendf(chr, \"OK 0x%016\" PRIx64 \"\\n\", value);\n+ return;\n+ }\n+ if (!qtest_parse_mem_attrs(chr, words[2], &attrs) ||\n+ !qtest_get_mem_as(chr, attrs, &as)) {\n+ return;\n+ }\n \n- if (words[0][4] == 'b') {\n- uint8_t data;\n- address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,\n- &data, 1);\n- value = data;\n- } else if (words[0][4] == 'w') {\n- uint16_t data;\n- address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,\n- &data, 2);\n- value = tswap16(data);\n- } else if (words[0][4] == 'l') {\n- uint32_t data;\n- address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,\n- &data, 4);\n- value = tswap32(data);\n- } else if (words[0][4] == 'q') {\n- address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,\n- &value, 8);\n- tswap64s(&value);\n+ result = qtest_read_sized(as, addr, attrs, words[0][4], &value);\n+ if (result != MEMTX_OK) {\n+ qtest_send_memtx_error(chr, result);\n+ return;\n }\n qtest_sendf(chr, \"OK 0x%016\" PRIx64 \"\\n\", value);\n } else if (strcmp(words[0], \"read\") == 0) {\n g_autoptr(GString) enc = NULL;\n uint64_t addr, len;\n uint8_t *data;\n+ bool has_attrs;\n+ MemTxResult result;\n+ MemTxAttrs attrs;\n+ AddressSpace *as;\n int ret;\n \n g_assert(words[1] && words[2]);\n+ if (words[3] && words[4]) {\n+ qtest_send(chr, \"ERR too many arguments\\n\");\n+ return;\n+ }\n ret = qemu_strtou64(words[1], NULL, 0, &addr);\n g_assert(ret == 0);\n ret = qemu_strtou64(words[2], NULL, 0, &len);\n g_assert(ret == 0);\n /* We'd send garbage to libqtest if len is 0 */\n g_assert(len);\n+ has_attrs = words[3] != NULL;\n+ if (!has_attrs) {\n+ data = g_malloc0(len);\n+ address_space_read(first_cpu->as, addr,\n+ MEMTXATTRS_UNSPECIFIED,\n+ data, len);\n+ enc = qemu_hexdump_line(NULL, data, len, 0, 0);\n+ qtest_sendf(chr, \"OK 0x%s\\n\", enc->str);\n+ g_free(data);\n+ return;\n+ }\n+ if (!qtest_parse_mem_attrs(chr, words[3], &attrs) ||\n+ !qtest_get_mem_as(chr, attrs, &as)) {\n+ return;\n+ }\n \n data = g_malloc(len);\n- address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,\n- len);\n+ result = address_space_read(as, addr, attrs, data, len);\n+ if (result != MEMTX_OK) {\n+ g_free(data);\n+ qtest_send_memtx_error(chr, result);\n+ return;\n+ }\n \n enc = qemu_hexdump_line(NULL, data, len, 0, 0);\n \n@@ -599,17 +810,45 @@ static void qtest_process_command(CharFrontend *chr, gchar **words)\n uint64_t addr, len;\n uint8_t *data;\n gchar *b64_data;\n+ bool has_attrs;\n+ MemTxResult result;\n+ MemTxAttrs attrs;\n+ AddressSpace *as;\n int ret;\n \n g_assert(words[1] && words[2]);\n+ if (words[3] && words[4]) {\n+ qtest_send(chr, \"ERR too many arguments\\n\");\n+ return;\n+ }\n ret = qemu_strtou64(words[1], NULL, 0, &addr);\n g_assert(ret == 0);\n ret = qemu_strtou64(words[2], NULL, 0, &len);\n g_assert(ret == 0);\n+ has_attrs = words[3] != NULL;\n+ if (!has_attrs) {\n+ data = g_malloc0(len);\n+ address_space_read(first_cpu->as, addr,\n+ MEMTXATTRS_UNSPECIFIED,\n+ data, len);\n+ b64_data = g_base64_encode(data, len);\n+ qtest_sendf(chr, \"OK %s\\n\", b64_data);\n+ g_free(data);\n+ g_free(b64_data);\n+ return;\n+ }\n+ if (!qtest_parse_mem_attrs(chr, words[3], &attrs) ||\n+ !qtest_get_mem_as(chr, attrs, &as)) {\n+ return;\n+ }\n \n data = g_malloc(len);\n- address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,\n- len);\n+ result = address_space_read(as, addr, attrs, data, len);\n+ if (result != MEMTX_OK) {\n+ g_free(data);\n+ qtest_send_memtx_error(chr, result);\n+ return;\n+ }\n b64_data = g_base64_encode(data, len);\n qtest_sendf(chr, \"OK %s\\n\", b64_data);\n \n@@ -619,13 +858,22 @@ static void qtest_process_command(CharFrontend *chr, gchar **words)\n uint64_t addr, len, i;\n uint8_t *data;\n size_t data_len;\n+ bool has_attrs;\n+ MemTxResult result;\n+ MemTxAttrs attrs;\n+ AddressSpace *as;\n int ret;\n \n g_assert(words[1] && words[2] && words[3]);\n+ if (words[4] && words[5]) {\n+ qtest_send(chr, \"ERR too many arguments\\n\");\n+ return;\n+ }\n ret = qemu_strtou64(words[1], NULL, 0, &addr);\n g_assert(ret == 0);\n ret = qemu_strtou64(words[2], NULL, 0, &len);\n g_assert(ret == 0);\n+ has_attrs = words[4] != NULL;\n \n data_len = strlen(words[3]);\n if (data_len < 3) {\n@@ -642,46 +890,100 @@ static void qtest_process_command(CharFrontend *chr, gchar **words)\n data[i] = 0;\n }\n }\n- address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,\n- len);\n+ if (!has_attrs) {\n+ address_space_write(first_cpu->as, addr,\n+ MEMTXATTRS_UNSPECIFIED,\n+ data, len);\n+ g_free(data);\n+ qtest_send(chr, \"OK\\n\");\n+ return;\n+ }\n+ if (!qtest_parse_mem_attrs(chr, words[4], &attrs) ||\n+ !qtest_get_mem_as(chr, attrs, &as)) {\n+ g_free(data);\n+ return;\n+ }\n+ result = address_space_write(as, addr, attrs, data, len);\n g_free(data);\n+ if (result != MEMTX_OK) {\n+ qtest_send_memtx_error(chr, result);\n+ return;\n+ }\n \n qtest_send(chr, \"OK\\n\");\n } else if (strcmp(words[0], \"memset\") == 0) {\n uint64_t addr, len;\n- uint8_t *data;\n unsigned long pattern;\n+ bool has_attrs;\n+ MemTxResult result;\n+ MemTxAttrs attrs;\n+ AddressSpace *as;\n int ret;\n \n g_assert(words[1] && words[2] && words[3]);\n+ if (words[4] && words[5]) {\n+ qtest_send(chr, \"ERR too many arguments\\n\");\n+ return;\n+ }\n ret = qemu_strtou64(words[1], NULL, 0, &addr);\n g_assert(ret == 0);\n ret = qemu_strtou64(words[2], NULL, 0, &len);\n g_assert(ret == 0);\n ret = qemu_strtoul(words[3], NULL, 0, &pattern);\n g_assert(ret == 0);\n+ has_attrs = words[4] != NULL;\n+ if (!has_attrs) {\n+ if (len) {\n+ uint8_t *data = g_malloc(len);\n+\n+ memset(data, pattern, len);\n+ address_space_write(first_cpu->as, addr,\n+ MEMTXATTRS_UNSPECIFIED,\n+ data, len);\n+ g_free(data);\n+ }\n+ qtest_send(chr, \"OK\\n\");\n+ return;\n+ }\n+ if (!qtest_parse_mem_attrs(chr, words[4], &attrs) ||\n+ !qtest_get_mem_as(chr, attrs, &as)) {\n+ return;\n+ }\n \n if (len) {\n- data = g_malloc(len);\n+ uint8_t *data = g_malloc(len);\n+\n memset(data, pattern, len);\n- address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED,\n- data, len);\n+ result = address_space_write(as, addr, attrs, data, len);\n g_free(data);\n+ if (result != MEMTX_OK) {\n+ qtest_send_memtx_error(chr, result);\n+ return;\n+ }\n }\n \n qtest_send(chr, \"OK\\n\");\n- } else if (strcmp(words[0], \"b64write\") == 0) {\n+ } else if (strcmp(words[0], \"b64write\") == 0) {\n uint64_t addr, len;\n uint8_t *data;\n size_t data_len;\n gsize out_len;\n+ bool has_attrs;\n+ MemTxResult result;\n+ MemTxAttrs attrs;\n+ AddressSpace *as;\n int ret;\n \n g_assert(words[1] && words[2] && words[3]);\n+ if (words[4] && words[5]) {\n+ qtest_send(chr, \"ERR too many arguments\\n\");\n+ return;\n+ }\n ret = qemu_strtou64(words[1], NULL, 0, &addr);\n g_assert(ret == 0);\n ret = qemu_strtou64(words[2], NULL, 0, &len);\n g_assert(ret == 0);\n+ has_attrs = words[4] != NULL;\n \n data_len = strlen(words[3]);\n if (data_len < 3) {\n@@ -697,8 +999,22 @@ static void qtest_process_command(CharFrontend *chr, gchar **words)\n out_len = MIN(out_len, len);\n }\n \n- address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, data,\n- len);\n+ if (!has_attrs) {\n+ address_space_write(first_cpu->as, addr,\n+ MEMTXATTRS_UNSPECIFIED,\n+ data, len);\n+ qtest_send(chr, \"OK\\n\");\n+ return;\n+ }\n+ if (!qtest_parse_mem_attrs(chr, words[4], &attrs) ||\n+ !qtest_get_mem_as(chr, attrs, &as)) {\n+ return;\n+ }\n+ result = address_space_write(as, addr, attrs, data, len);\n+ if (result != MEMTX_OK) {\n+ qtest_send_memtx_error(chr, result);\n+ return;\n+ }\n \n qtest_send(chr, \"OK\\n\");\n } else if (strcmp(words[0], \"endianness\") == 0) {\n", "prefixes": [ "1/4" ] }