From nobody Thu Apr 2 01:30:51 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1774272783368456.95730615582136; Mon, 23 Mar 2026 06:33:03 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w4fOX-0000Yx-Be; Mon, 23 Mar 2026 09:32:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1w4fOQ-0000W3-FD; Mon, 23 Mar 2026 09:32:30 -0400 Received: from zg8tmja5ljk3lje4ms43mwaa.icoremail.net ([209.97.181.73]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w4fOM-00028b-Aj; Mon, 23 Mar 2026 09:32:30 -0400 Received: from prodtpl.icoremail.net (unknown [10.12.1.20]) by hzbj-icmmx-6 (Coremail) with SMTP id AQAAfwB3faHgQMFppc8VAA--.8098S2; Mon, 23 Mar 2026 21:32:16 +0800 (CST) Received: from phytium.com.cn (unknown [218.76.62.144]) by mail (Coremail) with SMTP id AQAAf8DwwZLcQMFp0nsEAA--.10052S4; Mon, 23 Mar 2026 21:32:13 +0800 (CST) From: Tao Tang To: Fabiano Rosas , Laurent Vivier , Paolo Bonzini Cc: qemu-devel@nongnu.org, qemu-arm@nongnu.org, Peter Maydell , Chen Baozi , Pierrick Bouvier , Chao Liu , Tao Tang Subject: [RFC v3 1/4] tests/qtest: Add attrs support to qtest server memory commands Date: Mon, 23 Mar 2026 21:32:07 +0800 Message-Id: <20260323133210.1523868-2-tangtao1634@phytium.com.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260323133210.1523868-1-tangtao1634@phytium.com.cn> References: <20260323133210.1523868-1-tangtao1634@phytium.com.cn> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAf8DwwZLcQMFp0nsEAA--.10052S4 X-CM-SenderInfo: pwdqw3tdrrljuu6sx5pwlxzhxfrphubq/1tbiAQADBWnAQfgOxgAAsf Authentication-Results: hzbj-icmmx-6; spf=neutral smtp.mail=tangtao163 4@phytium.com.cn; X-Coremail-Antispam: 1Uk129KBjvAXoW3uryrCrW7XFW8KF4xWr4fuFg_yoW8AFy5uo WftF1qvasrt3WxCr929r1DA34DJay5uw1DAwsYyw15Ka48uryq9a98JFs8Xayjqa1rCr97 Xw4ftr4fZFyIv3yDn29KB7ZKAUJUUUU5529EdanIXcx71UUUUU7KY7ZEXasCq-sGcSsGvf J3UbIjqfuFe4nvWSU8nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2KfnxnUUI43ZEXa7xR_UU UUUUUUU== Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=209.97.181.73; envelope-from=tangtao1634@phytium.com.cn; helo=zg8tmja5ljk3lje4ms43mwaa.icoremail.net X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, RCVD_IN_VALIDITY_SAFE_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, WEIRD_QUOTING=0.001 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 development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1774272791193154100 Content-Type: text/plain; charset="utf-8" Extend qtest memory access commands to accept an optional attrs argument. Supported attrs: - secure (x86/Arm) - space=3Dnon-secure|secure|root|realm (Arm-only) For memory commands, parse attrs, select the corresponding AddressSpace with cpu_asidx_from_attrs(), and issue accesses with the matching MemTxAttrs. Cover scalar and bulk memory commands, including: - read{b,w,l,q} / write{b,w,l,q} - read / write - b64read / b64write - memset Also reject invalid attrs and excessive arguments, and document the new command forms in qtest.c, and use qtest_send_memtx_error() to return ERR for memory access failures. Signed-off-by: Tao Tang --- system/qtest.c | 517 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 463 insertions(+), 54 deletions(-) diff --git a/system/qtest.c b/system/qtest.c index cf90cd53ad..30c2a95020 100644 --- a/system/qtest.c +++ b/system/qtest.c @@ -22,6 +22,7 @@ #include "hw/core/qdev.h" #include "hw/core/irq.h" #include "hw/core/cpu.h" +#include "hw/arm/arm-security.h" #include "qemu/accel.h" #include "system/cpu-timers.h" #include "qemu/config-file.h" @@ -113,6 +114,14 @@ static void *qtest_server_send_opaque; * PIO and memory access: * """""""""""""""""""""" * + * Memory access commands allow specifying memory transaction attributes, + * which is useful for testing devices that behave differently based on + * security state (e.g., Arm TrustZone/CCA or System Management Mode in x8= 6). + * + * Only the following attributes are supported by the qtest server: + * ``secure`` sets MemTxAttrs.secure=3D1 (x86/Arm). + * ``space=3D...`` is Arm-specific and accepts: non-secure, secure, root, = realm. + * * .. code-block:: none * * > outb ADDR VALUE @@ -150,13 +159,42 @@ static void *qtest_server_send_opaque; * * .. code-block:: none * + * > writeb ADDR VALUE secure + * < OK + * + * .. code-block:: none + * + * > writeb ADDR VALUE space=3Drealm + * < OK + * + * .. code-block:: none + * * > writew ADDR VALUE * < OK * * .. code-block:: none * + * > writew ADDR VALUE secure + * < OK + * + * .. code-block:: none + * + * > writew ADDR VALUE space=3Drealm + * < OK + * + * .. code-block:: none + * * > writel ADDR VALUE * < OK + * .. code-block:: none + * + * > writel ADDR VALUE secure + * < OK + * + * .. code-block:: none + * + * > writel ADDR VALUE space=3Droot + * < OK * * .. code-block:: none * @@ -165,49 +203,147 @@ static void *qtest_server_send_opaque; * * .. code-block:: none * + * > writeq ADDR VALUE secure + * < OK + * + * .. code-block:: none + * + * > writeq ADDR VALUE space=3Dnon-secure + * < OK + * + * .. code-block:: none + * * > readb ADDR * < OK VALUE * * .. code-block:: none * + * > readb ADDR secure + * < OK VALUE + * + * .. code-block:: none + * + * > readb ADDR space=3Droot + * < OK VALUE + * + * .. code-block:: none + * * > readw ADDR * < OK VALUE * * .. code-block:: none * + * > readw ADDR secure + * < OK VALUE + * + * .. code-block:: none + * + * > readw ADDR space=3Droot + * < OK VALUE + * + * .. code-block:: none + * * > readl ADDR * < OK VALUE * * .. code-block:: none * + * > readl ADDR secure + * < OK VALUE + * + * .. code-block:: none + * + * > readl ADDR space=3Droot + * < OK VALUE + * + * .. code-block:: none + * * > readq ADDR * < OK VALUE * * .. code-block:: none * + * > readq ADDR secure + * < OK VALUE + * + * .. code-block:: none + * + * > readq ADDR space=3Droot + * < OK VALUE + * + * .. code-block:: none + * * > read ADDR SIZE * < OK DATA * * .. code-block:: none * + * > read ADDR SIZE secure + * < OK DATA + * + * .. code-block:: none + * + * > read ADDR SIZE space=3Droot + * < OK DATA + * + * .. code-block:: none + * * > write ADDR SIZE DATA * < OK * * .. code-block:: none * + * > write ADDR SIZE DATA secure + * < OK + * + * .. code-block:: none + * + * > write ADDR SIZE DATA space=3Droot + * < OK + * + * .. code-block:: none + * * > b64read ADDR SIZE * < OK B64_DATA * * .. code-block:: none * + * > b64read ADDR SIZE secure + * < OK B64_DATA + * + * .. code-block:: none + * + * > b64read ADDR SIZE space=3Droot + * < OK B64_DATA + * + * .. code-block:: none + * * > b64write ADDR SIZE B64_DATA * < OK + * .. code-block:: none + * + * > b64write ADDR SIZE B64_DATA secure + * < OK + * .. code-block:: none + * + * > b64write ADDR SIZE B64_DATA space=3Droot + * < OK * * .. code-block:: none * * > memset ADDR SIZE VALUE * < OK * + * .. code-block:: none + * + * > memset ADDR SIZE VALUE secure + * < OK + * + * .. code-block:: none + * + * > memset ADDR SIZE VALUE space=3Droot + * < OK + * * ADDR, SIZE, VALUE are all integers parsed with strtoul() with a base of= 0. * For 'memset' a zero size is permitted and does nothing. * @@ -353,6 +489,141 @@ static void qtest_install_gpio_out_intercept(DeviceSt= ate *dev, const char *name, *disconnected =3D qdev_intercept_gpio_out(dev, icpt, name, n); } =20 +static bool qtest_parse_mem_attrs(CharFrontend *chr, const char *arg, + MemTxAttrs *attrs) +{ + if (!arg) { + *attrs =3D MEMTXATTRS_UNSPECIFIED; + return true; + } + + if (strcmp(arg, "secure") =3D=3D 0) { + *attrs =3D (MemTxAttrs){ .secure =3D 1 }; + return true; + } + + if (strncmp(arg, "space=3D", 6) =3D=3D 0) { + const char *space =3D arg + 6; + ARMSecuritySpace sec_space; + + if (!target_arm() && !target_aarch64()) { + qtest_send(chr, "ERR space=3D<...> is Arm-specific\n"); + return false; + } + + if (strcmp(space, "non-secure") =3D=3D 0) { + sec_space =3D ARMSS_NonSecure; + } else if (strcmp(space, "secure") =3D=3D 0) { + sec_space =3D ARMSS_Secure; + } else if (strcmp(space, "root") =3D=3D 0) { + sec_space =3D ARMSS_Root; + } else if (strcmp(space, "realm") =3D=3D 0) { + sec_space =3D ARMSS_Realm; + } else { + qtest_send(chr, "ERR invalid space value. Valid space: " + "secure/non-secure/root/realm\n"); + return false; + } + + *attrs =3D (MemTxAttrs){ + .space =3D sec_space, + .secure =3D arm_space_is_secure(sec_space), + }; + return true; + } + + qtest_send(chr, "ERR invalid attrs argument\n"); + return false; +} + +static bool qtest_get_mem_as(CharFrontend *chr, MemTxAttrs attrs, + AddressSpace **as) +{ + int asidx; + + /* + * cpu_asidx_from_attrs mainly uses attrs to call ->asidx_from_attrs. = We use + * first_cpu as it's readily available. + */ + + asidx =3D cpu_asidx_from_attrs(first_cpu, attrs); + *as =3D cpu_get_address_space(first_cpu, asidx); + if (!*as) { + qtest_send(chr, "ERR address space unavailable for attrs\n"); + return false; + } + + return true; +} + +static void qtest_send_memtx_error(CharFrontend *chr, MemTxResult result) +{ + qtest_sendf(chr, "ERR memory access failed 0x%x\n", result); +} + +static MemTxResult qtest_write_sized(AddressSpace *as, uint64_t addr, + MemTxAttrs attrs, uint64_t value, + char size) +{ + switch (size) { + case 'b': { + uint8_t data =3D value; + return address_space_write(as, addr, attrs, &data, 1); + } + case 'w': { + uint16_t data =3D value; + tswap16s(&data); + return address_space_write(as, addr, attrs, &data, 2); + } + case 'l': { + uint32_t data =3D value; + tswap32s(&data); + return address_space_write(as, addr, attrs, &data, 4); + } + case 'q': { + uint64_t data =3D value; + tswap64s(&data); + return address_space_write(as, addr, attrs, &data, 8); + } + default: + g_assert_not_reached(); + } +} + +static MemTxResult qtest_read_sized(AddressSpace *as, uint64_t addr, + MemTxAttrs attrs, char size, + uint64_t *value) +{ + switch (size) { + case 'b': { + uint8_t data =3D 0; + MemTxResult result =3D address_space_read(as, addr, attrs, &data, = 1); + *value =3D data; + return result; + } + case 'w': { + uint16_t data =3D 0; + MemTxResult result =3D address_space_read(as, addr, attrs, &data, = 2); + *value =3D tswap16(data); + return result; + } + case 'l': { + uint32_t data =3D 0; + MemTxResult result =3D address_space_read(as, addr, attrs, &data, = 4); + *value =3D tswap32(data); + return result; + } + case 'q': { + uint64_t data =3D 0; + MemTxResult result =3D address_space_read(as, addr, attrs, &data, = 8); + *value =3D tswap64(data); + return result; + } + default: + g_assert_not_reached(); + } +} + static void qtest_process_command(CharFrontend *chr, gchar **words) { const gchar *command; @@ -510,33 +781,38 @@ static void qtest_process_command(CharFrontend *chr, = gchar **words) strcmp(words[0], "writeq") =3D=3D 0) { uint64_t addr; uint64_t value; + bool has_attrs; + MemTxResult result; + MemTxAttrs attrs; + AddressSpace *as; int ret; =20 g_assert(words[1] && words[2]); + if (words[3] && words[4]) { + qtest_send(chr, "ERR too many arguments\n"); + return; + } ret =3D qemu_strtou64(words[1], NULL, 0, &addr); g_assert(ret =3D=3D 0); ret =3D qemu_strtou64(words[2], NULL, 0, &value); g_assert(ret =3D=3D 0); + has_attrs =3D words[3] !=3D NULL; + if (!has_attrs) { + qtest_write_sized(first_cpu->as, addr, + MEMTXATTRS_UNSPECIFIED, + value, words[0][5]); + qtest_send(chr, "OK\n"); + return; + } + if (!qtest_parse_mem_attrs(chr, words[3], &attrs) || + !qtest_get_mem_as(chr, attrs, &as)) { + return; + } =20 - if (words[0][5] =3D=3D 'b') { - uint8_t data =3D value; - address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIE= D, - &data, 1); - } else if (words[0][5] =3D=3D 'w') { - uint16_t data =3D value; - tswap16s(&data); - address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIE= D, - &data, 2); - } else if (words[0][5] =3D=3D 'l') { - uint32_t data =3D value; - tswap32s(&data); - address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIE= D, - &data, 4); - } else if (words[0][5] =3D=3D 'q') { - uint64_t data =3D value; - tswap64s(&data); - address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIE= D, - &data, 8); + result =3D qtest_write_sized(as, addr, attrs, value, words[0][5]); + if (result !=3D MEMTX_OK) { + qtest_send_memtx_error(chr, result); + return; } qtest_send(chr, "OK\n"); } else if (strcmp(words[0], "readb") =3D=3D 0 || @@ -544,51 +820,83 @@ static void qtest_process_command(CharFrontend *chr, = gchar **words) strcmp(words[0], "readl") =3D=3D 0 || strcmp(words[0], "readq") =3D=3D 0) { uint64_t addr; - uint64_t value =3D UINT64_C(-1); + uint64_t value =3D 0; + bool has_attrs; + MemTxResult result; + MemTxAttrs attrs; + AddressSpace *as; int ret; =20 g_assert(words[1]); + if (words[2] && words[3]) { + qtest_send(chr, "ERR too many arguments\n"); + return; + } ret =3D qemu_strtou64(words[1], NULL, 0, &addr); g_assert(ret =3D=3D 0); + has_attrs =3D words[2] !=3D NULL; + if (!has_attrs) { + qtest_read_sized(first_cpu->as, addr, + MEMTXATTRS_UNSPECIFIED, + words[0][4], &value); + qtest_sendf(chr, "OK 0x%016" PRIx64 "\n", value); + return; + } + if (!qtest_parse_mem_attrs(chr, words[2], &attrs) || + !qtest_get_mem_as(chr, attrs, &as)) { + return; + } =20 - if (words[0][4] =3D=3D 'b') { - uint8_t data; - address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, - &data, 1); - value =3D data; - } else if (words[0][4] =3D=3D 'w') { - uint16_t data; - address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, - &data, 2); - value =3D tswap16(data); - } else if (words[0][4] =3D=3D 'l') { - uint32_t data; - address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, - &data, 4); - value =3D tswap32(data); - } else if (words[0][4] =3D=3D 'q') { - address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, - &value, 8); - tswap64s(&value); + result =3D qtest_read_sized(as, addr, attrs, words[0][4], &value); + if (result !=3D MEMTX_OK) { + qtest_send_memtx_error(chr, result); + return; } qtest_sendf(chr, "OK 0x%016" PRIx64 "\n", value); } else if (strcmp(words[0], "read") =3D=3D 0) { g_autoptr(GString) enc =3D NULL; uint64_t addr, len; uint8_t *data; + bool has_attrs; + MemTxResult result; + MemTxAttrs attrs; + AddressSpace *as; int ret; =20 g_assert(words[1] && words[2]); + if (words[3] && words[4]) { + qtest_send(chr, "ERR too many arguments\n"); + return; + } ret =3D qemu_strtou64(words[1], NULL, 0, &addr); g_assert(ret =3D=3D 0); ret =3D qemu_strtou64(words[2], NULL, 0, &len); g_assert(ret =3D=3D 0); /* We'd send garbage to libqtest if len is 0 */ g_assert(len); + has_attrs =3D words[3] !=3D NULL; + if (!has_attrs) { + data =3D g_malloc0(len); + address_space_read(first_cpu->as, addr, + MEMTXATTRS_UNSPECIFIED, + data, len); + enc =3D qemu_hexdump_line(NULL, data, len, 0, 0); + qtest_sendf(chr, "OK 0x%s\n", enc->str); + g_free(data); + return; + } + if (!qtest_parse_mem_attrs(chr, words[3], &attrs) || + !qtest_get_mem_as(chr, attrs, &as)) { + return; + } =20 data =3D g_malloc(len); - address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, da= ta, - len); + result =3D address_space_read(as, addr, attrs, data, len); + if (result !=3D MEMTX_OK) { + g_free(data); + qtest_send_memtx_error(chr, result); + return; + } =20 enc =3D qemu_hexdump_line(NULL, data, len, 0, 0); =20 @@ -599,17 +907,45 @@ static void qtest_process_command(CharFrontend *chr, = gchar **words) uint64_t addr, len; uint8_t *data; gchar *b64_data; + bool has_attrs; + MemTxResult result; + MemTxAttrs attrs; + AddressSpace *as; int ret; =20 g_assert(words[1] && words[2]); + if (words[3] && words[4]) { + qtest_send(chr, "ERR too many arguments\n"); + return; + } ret =3D qemu_strtou64(words[1], NULL, 0, &addr); g_assert(ret =3D=3D 0); ret =3D qemu_strtou64(words[2], NULL, 0, &len); g_assert(ret =3D=3D 0); + has_attrs =3D words[3] !=3D NULL; + if (!has_attrs) { + data =3D g_malloc0(len); + address_space_read(first_cpu->as, addr, + MEMTXATTRS_UNSPECIFIED, + data, len); + b64_data =3D g_base64_encode(data, len); + qtest_sendf(chr, "OK %s\n", b64_data); + g_free(data); + g_free(b64_data); + return; + } + if (!qtest_parse_mem_attrs(chr, words[3], &attrs) || + !qtest_get_mem_as(chr, attrs, &as)) { + return; + } =20 data =3D g_malloc(len); - address_space_read(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, da= ta, - len); + result =3D address_space_read(as, addr, attrs, data, len); + if (result !=3D MEMTX_OK) { + g_free(data); + qtest_send_memtx_error(chr, result); + return; + } b64_data =3D g_base64_encode(data, len); qtest_sendf(chr, "OK %s\n", b64_data); =20 @@ -619,13 +955,22 @@ static void qtest_process_command(CharFrontend *chr, = gchar **words) uint64_t addr, len, i; uint8_t *data; size_t data_len; + bool has_attrs; + MemTxResult result; + MemTxAttrs attrs; + AddressSpace *as; int ret; =20 g_assert(words[1] && words[2] && words[3]); + if (words[4] && words[5]) { + qtest_send(chr, "ERR too many arguments\n"); + return; + } ret =3D qemu_strtou64(words[1], NULL, 0, &addr); g_assert(ret =3D=3D 0); ret =3D qemu_strtou64(words[2], NULL, 0, &len); g_assert(ret =3D=3D 0); + has_attrs =3D words[4] !=3D NULL; =20 data_len =3D strlen(words[3]); if (data_len < 3) { @@ -642,46 +987,96 @@ static void qtest_process_command(CharFrontend *chr, = gchar **words) data[i] =3D 0; } } - address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, d= ata, - len); + if (!has_attrs) { + address_space_write(first_cpu->as, addr, + MEMTXATTRS_UNSPECIFIED, + data, len); + g_free(data); + qtest_send(chr, "OK\n"); + return; + } + if (!qtest_parse_mem_attrs(chr, words[4], &attrs) || + !qtest_get_mem_as(chr, attrs, &as)) { + g_free(data); + return; + } + result =3D address_space_write(as, addr, attrs, data, len); g_free(data); + if (result !=3D MEMTX_OK) { + qtest_send_memtx_error(chr, result); + return; + } =20 qtest_send(chr, "OK\n"); } else if (strcmp(words[0], "memset") =3D=3D 0) { uint64_t addr, len; - uint8_t *data; unsigned long pattern; + bool has_attrs; + MemTxResult result; + MemTxAttrs attrs; + AddressSpace *as; int ret; =20 g_assert(words[1] && words[2] && words[3]); + if (words[4] && words[5]) { + qtest_send(chr, "ERR too many arguments\n"); + return; + } ret =3D qemu_strtou64(words[1], NULL, 0, &addr); g_assert(ret =3D=3D 0); ret =3D qemu_strtou64(words[2], NULL, 0, &len); g_assert(ret =3D=3D 0); ret =3D qemu_strtoul(words[3], NULL, 0, &pattern); g_assert(ret =3D=3D 0); + has_attrs =3D words[4] !=3D NULL; + if (!has_attrs) { + if (len) { + uint8_t *data =3D g_malloc(len); + + memset(data, pattern, len); + address_space_write(first_cpu->as, addr, + MEMTXATTRS_UNSPECIFIED, + data, len); + g_free(data); + } + qtest_send(chr, "OK\n"); + return; + } + if (!qtest_parse_mem_attrs(chr, words[4], &attrs) || + !qtest_get_mem_as(chr, attrs, &as)) { + return; + } =20 if (len) { - data =3D g_malloc(len); - memset(data, pattern, len); - address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIE= D, - data, len); - g_free(data); + result =3D address_space_set(as, addr, pattern, len, attrs); + if (result !=3D MEMTX_OK) { + qtest_send_memtx_error(chr, result); + return; + } } =20 qtest_send(chr, "OK\n"); - } else if (strcmp(words[0], "b64write") =3D=3D 0) { + } else if (strcmp(words[0], "b64write") =3D=3D 0) { uint64_t addr, len; uint8_t *data; size_t data_len; gsize out_len; + bool has_attrs; + MemTxResult result; + MemTxAttrs attrs; + AddressSpace *as; int ret; =20 g_assert(words[1] && words[2] && words[3]); + if (words[4] && words[5]) { + qtest_send(chr, "ERR too many arguments\n"); + return; + } ret =3D qemu_strtou64(words[1], NULL, 0, &addr); g_assert(ret =3D=3D 0); ret =3D qemu_strtou64(words[2], NULL, 0, &len); g_assert(ret =3D=3D 0); + has_attrs =3D words[4] !=3D NULL; =20 data_len =3D strlen(words[3]); if (data_len < 3) { @@ -697,8 +1092,22 @@ static void qtest_process_command(CharFrontend *chr, = gchar **words) out_len =3D MIN(out_len, len); } =20 - address_space_write(first_cpu->as, addr, MEMTXATTRS_UNSPECIFIED, d= ata, - len); + if (!has_attrs) { + address_space_write(first_cpu->as, addr, + MEMTXATTRS_UNSPECIFIED, + data, len); + qtest_send(chr, "OK\n"); + return; + } + if (!qtest_parse_mem_attrs(chr, words[4], &attrs) || + !qtest_get_mem_as(chr, attrs, &as)) { + return; + } + result =3D address_space_write(as, addr, attrs, data, len); + if (result !=3D MEMTX_OK) { + qtest_send_memtx_error(chr, result); + return; + } =20 qtest_send(chr, "OK\n"); } else if (strcmp(words[0], "endianness") =3D=3D 0) { --=20 2.34.1