get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2217950/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2217950,
    "url": "http://patchwork.ozlabs.org/api/patches/2217950/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260331040659.401397-3-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-3-tangtao1634@phytium.com.cn>",
    "list_archive_url": null,
    "date": "2026-03-31T04:06:57",
    "name": "[2/4] tests/qtest: Add libqtest attrs helpers for memory accesses",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "f47cb626e229022f32131042f81f89b868add532",
    "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-3-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/2217950/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2217950/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-7; 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 4flF3L3vNgz1yGT\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 31 Mar 2026 15:08: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 1w7QOe-0001CB-V9; Tue, 31 Mar 2026 00:08:09 -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-00010F-MG; Tue, 31 Mar 2026 00:07:52 -0400",
            "from zg8tmtyylji0my4xnjqumte4.icoremail.net ([162.243.164.118])\n by eggs.gnu.org with esmtp (Exim 4.90_1)\n (envelope-from <tangtao1634@phytium.com.cn>)\n id 1w7QOK-0002F6-42; Tue, 31 Mar 2026 00:07:51 -0400",
            "from prodtpl.icoremail.net (unknown [10.12.1.20])\n by hzbj-icmmx-7 (Coremail) with SMTP id AQAAfwCnrmKHSMtpeojBCA--.71S2;\n Tue, 31 Mar 2026 12:07:35 +0800 (CST)",
            "from phytium.com.cn (unknown [218.76.62.144])\n by mail (Coremail) with SMTP id AQAAf8DwSJR6SMtpYqQHAA--.18366S5;\n Tue, 31 Mar 2026 12:07:34 +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 2/4] tests/qtest: Add libqtest attrs helpers for memory\n accesses",
        "Date": "Tue, 31 Mar 2026 12:06:57 +0800",
        "Message-Id": "<20260331040659.401397-3-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--.18366S5",
        "X-CM-SenderInfo": "pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQALBWnKzfEBsQAAsg",
        "X-Coremail-Antispam": "1Uk129KBjvAXoWfZw1xtw1kAw17Zw1xJrW5KFg_yoW8try3uo\n WrtF1jq34DXwnxZrW09ryxGr9rXw47Cr15Xwn8t3WUKas3Grn09a13KanxZa4j9F1rGrWU\n XFZ7XrW5WrWIyFZ7n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf\n J3UbIjqfuFe4nvWSU8nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UU\n UUUUUUU==",
        "Received-SPF": "pass client-ip=162.243.164.118;\n envelope-from=tangtao1634@phytium.com.cn;\n helo=zg8tmtyylji0my4xnjqumte4.icoremail.net",
        "X-Spam_score_int": "-5",
        "X-Spam_score": "-0.6",
        "X-Spam_bar": "/",
        "X-Spam_report": "(-0.6 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_LOW=-0.7,\n RCVD_IN_MSPIKE_H4=-0.01, RCVD_IN_MSPIKE_WL=-0.01,\n RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=1, RCVD_IN_VALIDITY_RPBL_BLOCKED=1,\n SPF_HELO_NONE=0.001, SPF_PASS=-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": "Expose libqtest APIs for qtest memory commands with optional attrs:\n- qtest_{read,write}{b,w,l,q}_attrs()\n- qtest_mem{read,write,set}_attrs()\n- qtest_buf{read,write}_attrs()\n\nKeep the existing libqtest memory access helpers as wrappers passing\nNULL attrs, so current users remain unchanged.\n\nAlso add matching libqtest-single shortcut wrappers for the *_attrs\nhelpers.\n\nRefactor libqtest response parsing by splitting qtest_rsp_args() into a\nraw tokenizing helper, qtest_rsp_words(), and the existing OK-checking\nwrapper. Add qtest_raw_cmd() on top of qtest_rsp_words() so tests can\nsend raw qtest protocol commands and inspect non-OK responses such as\nERR and FAIL.\n\nSigned-off-by: Tao Tang <tangtao1634@phytium.com.cn>\nReviewed-by: Chao Liu <chao.liu.zevorn@gmail.com>\n---\n tests/qtest/libqtest-single.h | 156 +++++++++++++++++++++\n tests/qtest/libqtest.c        | 246 ++++++++++++++++++++++++++--------\n tests/qtest/libqtest.h        | 177 ++++++++++++++++++++++++\n 3 files changed, 524 insertions(+), 55 deletions(-)",
    "diff": "diff --git a/tests/qtest/libqtest-single.h b/tests/qtest/libqtest-single.h\nindex 851724cbcb..2812b86bd4 100644\n--- a/tests/qtest/libqtest-single.h\n+++ b/tests/qtest/libqtest-single.h\n@@ -291,6 +291,162 @@ static inline void memwrite(uint64_t addr, const void *data, size_t size)\n     qtest_memwrite(global_qtest, addr, data, size);\n }\n \n+/**\n+ * writeb_attrs:\n+ * @addr: Guest address to write to.\n+ * @value: Value being written.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Writes an 8-bit value to guest memory with optional transaction attributes.\n+ */\n+static inline void writeb_attrs(uint64_t addr, uint8_t value, const char *attrs)\n+{\n+    qtest_writeb_attrs(global_qtest, addr, value, attrs);\n+}\n+\n+/**\n+ * writew_attrs:\n+ * @addr: Guest address to write to.\n+ * @value: Value being written.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Writes a 16-bit value to guest memory with optional transaction attributes.\n+ */\n+static inline void writew_attrs(uint64_t addr, uint16_t value,\n+                                const char *attrs)\n+{\n+    qtest_writew_attrs(global_qtest, addr, value, attrs);\n+}\n+\n+/**\n+ * writel_attrs:\n+ * @addr: Guest address to write to.\n+ * @value: Value being written.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Writes a 32-bit value to guest memory with optional transaction attributes.\n+ */\n+static inline void writel_attrs(uint64_t addr, uint32_t value,\n+                                const char *attrs)\n+{\n+    qtest_writel_attrs(global_qtest, addr, value, attrs);\n+}\n+\n+/**\n+ * writeq_attrs:\n+ * @addr: Guest address to write to.\n+ * @value: Value being written.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Writes a 64-bit value to guest memory with optional transaction attributes.\n+ */\n+static inline void writeq_attrs(uint64_t addr, uint64_t value,\n+                                const char *attrs)\n+{\n+    qtest_writeq_attrs(global_qtest, addr, value, attrs);\n+}\n+\n+/**\n+ * readb_attrs:\n+ * @addr: Guest address to read from.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Reads an 8-bit value from guest memory with optional transaction attributes.\n+ *\n+ * Returns: Value read.\n+ */\n+static inline uint8_t readb_attrs(uint64_t addr, const char *attrs)\n+{\n+    return qtest_readb_attrs(global_qtest, addr, attrs);\n+}\n+\n+/**\n+ * readw_attrs:\n+ * @addr: Guest address to read from.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Reads a 16-bit value from guest memory with optional transaction attributes.\n+ *\n+ * Returns: Value read.\n+ */\n+static inline uint16_t readw_attrs(uint64_t addr, const char *attrs)\n+{\n+    return qtest_readw_attrs(global_qtest, addr, attrs);\n+}\n+\n+/**\n+ * readl_attrs:\n+ * @addr: Guest address to read from.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Reads a 32-bit value from guest memory with optional transaction attributes.\n+ *\n+ * Returns: Value read.\n+ */\n+static inline uint32_t readl_attrs(uint64_t addr, const char *attrs)\n+{\n+    return qtest_readl_attrs(global_qtest, addr, attrs);\n+}\n+\n+/**\n+ * readq_attrs:\n+ * @addr: Guest address to read from.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Reads a 64-bit value from guest memory with optional transaction attributes.\n+ *\n+ * Returns: Value read.\n+ */\n+static inline uint64_t readq_attrs(uint64_t addr, const char *attrs)\n+{\n+    return qtest_readq_attrs(global_qtest, addr, attrs);\n+}\n+\n+/**\n+ * memread_attrs:\n+ * @addr: Guest address to read from.\n+ * @data: Pointer to where memory contents will be stored.\n+ * @size: Number of bytes to read.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Read guest memory into a buffer with optional transaction attributes.\n+ */\n+static inline void memread_attrs(uint64_t addr, void *data, size_t size,\n+                                 const char *attrs)\n+{\n+    qtest_memread_attrs(global_qtest, addr, data, size, attrs);\n+}\n+\n+/**\n+ * memwrite_attrs:\n+ * @addr: Guest address to write to.\n+ * @data: Pointer to the bytes that will be written to guest memory.\n+ * @size: Number of bytes to write.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Write a buffer to guest memory with optional transaction attributes.\n+ */\n+static inline void memwrite_attrs(uint64_t addr, const void *data, size_t size,\n+                                  const char *attrs)\n+{\n+    qtest_memwrite_attrs(global_qtest, addr, data, size, attrs);\n+}\n+\n+/**\n+ * memset_attrs:\n+ * @addr: Guest address to write to.\n+ * @pattern: Byte pattern to fill the guest memory region with.\n+ * @size: Number of bytes to write.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Write a pattern to guest memory with optional transaction attributes.\n+ */\n+static inline void memset_attrs(uint64_t addr, uint8_t pattern, size_t size,\n+                                const char *attrs)\n+{\n+    qtest_memset_attrs(global_qtest, addr, pattern, size, attrs);\n+}\n+\n /**\n  * clock_step_next:\n  *\ndiff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c\nindex 051faf31e1..b67786f1ad 100644\n--- a/tests/qtest/libqtest.c\n+++ b/tests/qtest/libqtest.c\n@@ -747,11 +747,10 @@ static GString *qtest_client_socket_recv_line(QTestState *s)\n     return line;\n }\n \n-static gchar **qtest_rsp_args(QTestState *s, int expected_args)\n+static gchar **qtest_rsp_words(QTestState *s)\n {\n     GString *line;\n     gchar **words;\n-    int i;\n \n redo:\n     line = s->ops.recv_line(s);\n@@ -781,6 +780,15 @@ redo:\n     }\n \n     g_assert(words[0] != NULL);\n+\n+    return words;\n+}\n+\n+static gchar **qtest_rsp_args(QTestState *s, int expected_args)\n+{\n+    gchar **words = qtest_rsp_words(s);\n+    int i;\n+\n     g_assert_cmpstr(words[0], ==, \"OK\");\n \n     for (i = 0; i < expected_args; i++) {\n@@ -790,6 +798,21 @@ redo:\n     return words;\n }\n \n+gchar **qtest_raw_cmd(QTestState *s, const char *fmt, ...)\n+{\n+    va_list ap;\n+    gchar *str;\n+\n+    va_start(ap, fmt);\n+    str = g_strdup_vprintf(fmt, ap);\n+    va_end(ap);\n+\n+    s->ops.send(s, str);\n+    g_free(str);\n+\n+    return qtest_rsp_words(s);\n+}\n+\n static void qtest_rsp(QTestState *s)\n {\n     gchar **words = qtest_rsp_args(s, 0);\n@@ -1232,66 +1255,44 @@ uint32_t qtest_inl(QTestState *s, uint16_t addr)\n     return qtest_big_endian(s) ? bswap32(v) : v;\n }\n \n-static void qtest_write(QTestState *s, const char *cmd, uint64_t addr,\n-                        uint64_t value)\n-{\n-    qtest_sendf(s, \"%s 0x%\" PRIx64 \" 0x%\" PRIx64 \"\\n\", cmd, addr, value);\n-    qtest_rsp(s);\n-}\n-\n void qtest_writeb(QTestState *s, uint64_t addr, uint8_t value)\n {\n-    qtest_write(s, \"writeb\", addr, value);\n+    qtest_writeb_attrs(s, addr, value, NULL);\n }\n \n void qtest_writew(QTestState *s, uint64_t addr, uint16_t value)\n {\n-    qtest_write(s, \"writew\", addr, value);\n+    qtest_writew_attrs(s, addr, value, NULL);\n }\n \n void qtest_writel(QTestState *s, uint64_t addr, uint32_t value)\n {\n-    qtest_write(s, \"writel\", addr, value);\n+    qtest_writel_attrs(s, addr, value, NULL);\n }\n \n void qtest_writeq(QTestState *s, uint64_t addr, uint64_t value)\n {\n-    qtest_write(s, \"writeq\", addr, value);\n-}\n-\n-static uint64_t qtest_read(QTestState *s, const char *cmd, uint64_t addr)\n-{\n-    gchar **args;\n-    int ret;\n-    uint64_t value;\n-\n-    qtest_sendf(s, \"%s 0x%\" PRIx64 \"\\n\", cmd, addr);\n-    args = qtest_rsp_args(s, 2);\n-    ret = qemu_strtou64(args[1], NULL, 0, &value);\n-    g_assert(!ret);\n-    g_strfreev(args);\n-\n-    return value;\n+    qtest_writeq_attrs(s, addr, value, NULL);\n }\n \n uint8_t qtest_readb(QTestState *s, uint64_t addr)\n {\n-    return qtest_read(s, \"readb\", addr);\n+    return qtest_readb_attrs(s, addr, NULL);\n }\n \n uint16_t qtest_readw(QTestState *s, uint64_t addr)\n {\n-    return qtest_read(s, \"readw\", addr);\n+    return qtest_readw_attrs(s, addr, NULL);\n }\n \n uint32_t qtest_readl(QTestState *s, uint64_t addr)\n {\n-    return qtest_read(s, \"readl\", addr);\n+    return qtest_readl_attrs(s, addr, NULL);\n }\n \n uint64_t qtest_readq(QTestState *s, uint64_t addr)\n {\n-    return qtest_read(s, \"readq\", addr);\n+    return qtest_readq_attrs(s, addr, NULL);\n }\n \n static int hex2nib(char ch)\n@@ -1309,23 +1310,7 @@ static int hex2nib(char ch)\n \n void qtest_memread(QTestState *s, uint64_t addr, void *data, size_t size)\n {\n-    uint8_t *ptr = data;\n-    gchar **args;\n-    size_t i;\n-\n-    if (!size) {\n-        return;\n-    }\n-\n-    qtest_sendf(s, \"read 0x%\" PRIx64 \" 0x%zx\\n\", addr, size);\n-    args = qtest_rsp_args(s, 2);\n-\n-    for (i = 0; i < size; i++) {\n-        ptr[i] = hex2nib(args[1][2 + (i * 2)]) << 4;\n-        ptr[i] |= hex2nib(args[1][2 + (i * 2) + 1]);\n-    }\n-\n-    g_strfreev(args);\n+    qtest_memread_attrs(s, addr, data, size, NULL);\n }\n \n uint64_t qtest_rtas_call(QTestState *s, const char *name,\n@@ -1390,23 +1375,58 @@ void qtest_add_data_func(const char *str, const void *data,\n }\n \n void qtest_bufwrite(QTestState *s, uint64_t addr, const void *data, size_t size)\n+{\n+    qtest_bufwrite_attrs(s, addr, data, size, NULL);\n+}\n+\n+void qtest_bufread(QTestState *s, uint64_t addr, void *data, size_t size)\n+{\n+    qtest_bufread_attrs(s, addr, data, size, NULL);\n+}\n+\n+void qtest_memwrite(QTestState *s, uint64_t addr, const void *data, size_t size)\n+{\n+    qtest_memwrite_attrs(s, addr, data, size, NULL);\n+}\n+\n+void qtest_memset(QTestState *s, uint64_t addr, uint8_t pattern, size_t size)\n+{\n+    qtest_memset_attrs(s, addr, pattern, size, NULL);\n+}\n+\n+static bool qtest_has_attrs(const char *attrs)\n+{\n+    return attrs && attrs[0];\n+}\n+\n+void qtest_bufwrite_attrs(QTestState *s, uint64_t addr, const void *data,\n+                          size_t size, const char *attrs)\n {\n     gchar *bdata;\n \n     bdata = g_base64_encode(data, size);\n     qtest_sendf(s, \"b64write 0x%\" PRIx64 \" 0x%zx \", addr, size);\n     s->ops.send(s, bdata);\n+    if (qtest_has_attrs(attrs)) {\n+        s->ops.send(s, \" \");\n+        s->ops.send(s, attrs);\n+    }\n     s->ops.send(s, \"\\n\");\n     qtest_rsp(s);\n     g_free(bdata);\n }\n \n-void qtest_bufread(QTestState *s, uint64_t addr, void *data, size_t size)\n+void qtest_bufread_attrs(QTestState *s, uint64_t addr, void *data, size_t size,\n+                         const char *attrs)\n {\n     gchar **args;\n     size_t len;\n \n-    qtest_sendf(s, \"b64read 0x%\" PRIx64 \" 0x%zx\\n\", addr, size);\n+    if (qtest_has_attrs(attrs)) {\n+        qtest_sendf(s, \"b64read 0x%\" PRIx64 \" 0x%zx %s\\n\", addr, size, attrs);\n+    } else {\n+        qtest_sendf(s, \"b64read 0x%\" PRIx64 \" 0x%zx\\n\", addr, size);\n+    }\n     args = qtest_rsp_args(s, 2);\n \n     g_base64_decode_inplace(args[1], &len);\n@@ -1420,7 +1440,111 @@ void qtest_bufread(QTestState *s, uint64_t addr, void *data, size_t size)\n     g_strfreev(args);\n }\n \n-void qtest_memwrite(QTestState *s, uint64_t addr, const void *data, size_t size)\n+static void qtest_write_attrs(QTestState *s, const char *cmd,\n+                              uint64_t addr, uint64_t value,\n+                              const char *attrs)\n+{\n+    if (qtest_has_attrs(attrs)) {\n+        qtest_sendf(s, \"%s 0x%\" PRIx64 \" 0x%\" PRIx64 \" %s\\n\",\n+                    cmd, addr, value, attrs);\n+    } else {\n+        qtest_sendf(s, \"%s 0x%\" PRIx64 \" 0x%\" PRIx64 \"\\n\", cmd, addr, value);\n+    }\n+    qtest_rsp(s);\n+}\n+\n+static uint64_t qtest_read_attrs(QTestState *s, const char *cmd,\n+                                 uint64_t addr, const char *attrs)\n+{\n+    gchar **args;\n+    int ret;\n+    uint64_t value;\n+\n+    if (qtest_has_attrs(attrs)) {\n+        qtest_sendf(s, \"%s 0x%\" PRIx64 \" %s\\n\", cmd, addr, attrs);\n+    } else {\n+        qtest_sendf(s, \"%s 0x%\" PRIx64 \"\\n\", cmd, addr);\n+    }\n+    args = qtest_rsp_args(s, 2);\n+    ret = qemu_strtou64(args[1], NULL, 0, &value);\n+    g_assert(!ret);\n+    g_strfreev(args);\n+\n+    return value;\n+}\n+\n+void qtest_writeb_attrs(QTestState *s, uint64_t addr, uint8_t value,\n+                        const char *attrs)\n+{\n+    qtest_write_attrs(s, \"writeb\", addr, value, attrs);\n+}\n+\n+void qtest_writew_attrs(QTestState *s, uint64_t addr, uint16_t value,\n+                        const char *attrs)\n+{\n+    qtest_write_attrs(s, \"writew\", addr, value, attrs);\n+}\n+\n+void qtest_writel_attrs(QTestState *s, uint64_t addr, uint32_t value,\n+                        const char *attrs)\n+{\n+    qtest_write_attrs(s, \"writel\", addr, value, attrs);\n+}\n+\n+void qtest_writeq_attrs(QTestState *s, uint64_t addr, uint64_t value,\n+                        const char *attrs)\n+{\n+    qtest_write_attrs(s, \"writeq\", addr, value, attrs);\n+}\n+\n+uint8_t qtest_readb_attrs(QTestState *s, uint64_t addr, const char *attrs)\n+{\n+    return qtest_read_attrs(s, \"readb\", addr, attrs);\n+}\n+\n+uint16_t qtest_readw_attrs(QTestState *s, uint64_t addr, const char *attrs)\n+{\n+    return qtest_read_attrs(s, \"readw\", addr, attrs);\n+}\n+\n+uint32_t qtest_readl_attrs(QTestState *s, uint64_t addr, const char *attrs)\n+{\n+    return qtest_read_attrs(s, \"readl\", addr, attrs);\n+}\n+\n+uint64_t qtest_readq_attrs(QTestState *s, uint64_t addr, const char *attrs)\n+{\n+    return qtest_read_attrs(s, \"readq\", addr, attrs);\n+}\n+\n+void qtest_memread_attrs(QTestState *s, uint64_t addr, void *data,\n+                         size_t size, const char *attrs)\n+{\n+    uint8_t *ptr = data;\n+    gchar **args;\n+    size_t i;\n+\n+    if (!size) {\n+        return;\n+    }\n+\n+    if (qtest_has_attrs(attrs)) {\n+        qtest_sendf(s, \"read 0x%\" PRIx64 \" 0x%zx %s\\n\", addr, size, attrs);\n+    } else {\n+        qtest_sendf(s, \"read 0x%\" PRIx64 \" 0x%zx\\n\", addr, size);\n+    }\n+    args = qtest_rsp_args(s, 2);\n+\n+    for (i = 0; i < size; i++) {\n+        ptr[i] = hex2nib(args[1][2 + (i * 2)]) << 4;\n+        ptr[i] |= hex2nib(args[1][2 + (i * 2) + 1]);\n+    }\n+\n+    g_strfreev(args);\n+}\n+\n+void qtest_memwrite_attrs(QTestState *s, uint64_t addr, const void *data,\n+                          size_t size, const char *attrs)\n {\n     const uint8_t *ptr = data;\n     size_t i;\n@@ -1436,14 +1560,26 @@ void qtest_memwrite(QTestState *s, uint64_t addr, const void *data, size_t size)\n         sprintf(&enc[i * 2], \"%02x\", ptr[i]);\n     }\n \n-    qtest_sendf(s, \"write 0x%\" PRIx64 \" 0x%zx 0x%s\\n\", addr, size, enc);\n+    if (qtest_has_attrs(attrs)) {\n+        qtest_sendf(s, \"write 0x%\" PRIx64 \" 0x%zx 0x%s %s\\n\",\n+                    addr, size, enc, attrs);\n+    } else {\n+        qtest_sendf(s, \"write 0x%\" PRIx64 \" 0x%zx 0x%s\\n\", addr, size, enc);\n+    }\n     qtest_rsp(s);\n     g_free(enc);\n }\n \n-void qtest_memset(QTestState *s, uint64_t addr, uint8_t pattern, size_t size)\n+void qtest_memset_attrs(QTestState *s, uint64_t addr, uint8_t pattern,\n+                        size_t size, const char *attrs)\n {\n-    qtest_sendf(s, \"memset 0x%\" PRIx64 \" 0x%zx 0x%02x\\n\", addr, size, pattern);\n+    if (qtest_has_attrs(attrs)) {\n+        qtest_sendf(s, \"memset 0x%\" PRIx64 \" 0x%zx 0x%02x %s\\n\",\n+                    addr, size, pattern, attrs);\n+    } else {\n+        qtest_sendf(s, \"memset 0x%\" PRIx64 \" 0x%zx 0x%02x\\n\",\n+                    addr, size, pattern);\n+    }\n     qtest_rsp(s);\n }\n \ndiff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h\nindex 9c118c89ca..cee74cf2a4 100644\n--- a/tests/qtest/libqtest.h\n+++ b/tests/qtest/libqtest.h\n@@ -239,6 +239,19 @@ void qtest_qmp_send(QTestState *s, const char *fmt, ...)\n void qtest_qmp_send_raw(QTestState *s, const char *fmt, ...)\n     G_GNUC_PRINTF(2, 3);\n \n+/**\n+ * qtest_raw_cmd:\n+ * @s: #QTestState instance to operate on.\n+ * @fmt: raw qtest protocol text to send, formatted like sprintf().\n+ *\n+ * Sends a raw qtest command and returns the response split on spaces.\n+ * The response is not required to start with ``OK``; callers can inspect\n+ * ``args[0]`` for ``OK``, ``ERR``, or ``FAIL`` and must free the returned\n+ * vector with g_strfreev().\n+ */\n+gchar **qtest_raw_cmd(QTestState *s, const char *fmt, ...)\n+    G_GNUC_PRINTF(2, 3);\n+\n /**\n  * qtest_socket_server:\n  * @socket_path: the UNIX domain socket path\n@@ -671,6 +684,20 @@ uint64_t qtest_csr_call(QTestState *s, const char *name,\n  */\n void qtest_bufread(QTestState *s, uint64_t addr, void *data, size_t size);\n \n+/**\n+ * qtest_bufread_attrs:\n+ * @s: #QTestState instance to operate on.\n+ * @addr: Guest address to read from.\n+ * @data: Pointer to where memory contents will be stored.\n+ * @size: Number of bytes to read.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Read guest memory into a buffer and receive using a base64 encoding with\n+ * optional transaction attributes.\n+ */\n+void qtest_bufread_attrs(QTestState *s, uint64_t addr, void *data, size_t size,\n+                         const char *attrs);\n+\n /**\n  * qtest_memwrite:\n  * @s: #QTestState instance to operate on.\n@@ -694,6 +721,21 @@ void qtest_memwrite(QTestState *s, uint64_t addr, const void *data, size_t size)\n void qtest_bufwrite(QTestState *s, uint64_t addr,\n                     const void *data, size_t size);\n \n+/**\n+ * qtest_bufwrite_attrs:\n+ * @s: #QTestState instance to operate on.\n+ * @addr: Guest address to write to.\n+ * @data: Pointer to the bytes that will be written to guest memory.\n+ * @size: Number of bytes to write.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Write a buffer to guest memory and transmit using a base64 encoding with\n+ * optional transaction attributes.\n+ */\n+void qtest_bufwrite_attrs(QTestState *s, uint64_t addr,\n+                          const void *data, size_t size,\n+                          const char *attrs);\n+\n /**\n  * qtest_memset:\n  * @s: #QTestState instance to operate on.\n@@ -705,6 +747,141 @@ void qtest_bufwrite(QTestState *s, uint64_t addr,\n  */\n void qtest_memset(QTestState *s, uint64_t addr, uint8_t patt, size_t size);\n \n+/**\n+ * qtest_writeb_attrs:\n+ * @s: #QTestState instance to operate on.\n+ * @addr: Guest address to write to.\n+ * @value: Value being written.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Writes an 8-bit value to guest memory with optional transaction attributes.\n+ */\n+void qtest_writeb_attrs(QTestState *s, uint64_t addr, uint8_t value,\n+                        const char *attrs);\n+\n+/**\n+ * qtest_writew_attrs:\n+ * @s: #QTestState instance to operate on.\n+ * @addr: Guest address to write to.\n+ * @value: Value being written.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Writes a 16-bit value to guest memory with optional transaction attributes.\n+ */\n+void qtest_writew_attrs(QTestState *s, uint64_t addr, uint16_t value,\n+                        const char *attrs);\n+\n+/**\n+ * qtest_writel_attrs:\n+ * @s: #QTestState instance to operate on.\n+ * @addr: Guest address to write to.\n+ * @value: Value being written.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Writes a 32-bit value to guest memory with optional transaction attributes.\n+ */\n+void qtest_writel_attrs(QTestState *s, uint64_t addr, uint32_t value,\n+                        const char *attrs);\n+\n+/**\n+ * qtest_writeq_attrs:\n+ * @s: #QTestState instance to operate on.\n+ * @addr: Guest address to write to.\n+ * @value: Value being written.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Writes a 64-bit value to guest memory with optional transaction attributes.\n+ */\n+void qtest_writeq_attrs(QTestState *s, uint64_t addr, uint64_t value,\n+                        const char *attrs);\n+\n+/**\n+ * qtest_readb_attrs:\n+ * @s: #QTestState instance to operate on.\n+ * @addr: Guest address to read from.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Reads an 8-bit value from guest memory with optional transaction attributes.\n+ *\n+ * Returns: Value read.\n+ */\n+uint8_t qtest_readb_attrs(QTestState *s, uint64_t addr, const char *attrs);\n+\n+/**\n+ * qtest_readw_attrs:\n+ * @s: #QTestState instance to operate on.\n+ * @addr: Guest address to read from.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Reads a 16-bit value from guest memory with optional transaction attributes.\n+ *\n+ * Returns: Value read.\n+ */\n+uint16_t qtest_readw_attrs(QTestState *s, uint64_t addr, const char *attrs);\n+\n+/**\n+ * qtest_readl_attrs:\n+ * @s: #QTestState instance to operate on.\n+ * @addr: Guest address to read from.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Reads a 32-bit value from guest memory with optional transaction attributes.\n+ *\n+ * Returns: Value read.\n+ */\n+uint32_t qtest_readl_attrs(QTestState *s, uint64_t addr, const char *attrs);\n+\n+/**\n+ * qtest_readq_attrs:\n+ * @s: #QTestState instance to operate on.\n+ * @addr: Guest address to read from.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Reads a 64-bit value from guest memory with optional transaction attributes.\n+ *\n+ * Returns: Value read.\n+ */\n+uint64_t qtest_readq_attrs(QTestState *s, uint64_t addr, const char *attrs);\n+\n+/**\n+ * qtest_memread_attrs:\n+ * @s: #QTestState instance to operate on.\n+ * @addr: Guest address to read from.\n+ * @data: Pointer to where memory contents will be stored.\n+ * @size: Number of bytes to read.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Read guest memory into a buffer with optional transaction attributes.\n+ */\n+void qtest_memread_attrs(QTestState *s, uint64_t addr, void *data, size_t size,\n+                         const char *attrs);\n+\n+/**\n+ * qtest_memwrite_attrs:\n+ * @s: #QTestState instance to operate on.\n+ * @addr: Guest address to write to.\n+ * @data: Pointer to the bytes that will be written to guest memory.\n+ * @size: Number of bytes to write.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Write a buffer to guest memory with optional transaction attributes.\n+ */\n+void qtest_memwrite_attrs(QTestState *s, uint64_t addr, const void *data,\n+                          size_t size, const char *attrs);\n+\n+/**\n+ * qtest_memset_attrs:\n+ * @s: #QTestState instance to operate on.\n+ * @addr: Guest address to write to.\n+ * @patt: Byte pattern to fill the guest memory region with.\n+ * @size: Number of bytes to write.\n+ * @attrs: Optional transaction attributes string.\n+ *\n+ * Write a pattern to guest memory with optional transaction attributes.\n+ */\n+void qtest_memset_attrs(QTestState *s, uint64_t addr, uint8_t patt, size_t size,\n+                        const char *attrs);\n+\n /**\n  * qtest_clock_step_next:\n  * @s: #QTestState instance to operate on.\n",
    "prefixes": [
        "2/4"
    ]
}