From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id F11D7C2D0CD for ; Wed, 21 May 2025 09:44:33 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uHfzJ-0002jm-PY; Wed, 21 May 2025 05:43:49 -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 1uHfzE-0002d1-Ih for qemu-devel@nongnu.org; Wed, 21 May 2025 05:43:44 -0400 Received: from mail-pf1-x434.google.com ([2607:f8b0:4864:20::434]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1uHfzB-0001bl-TW for qemu-devel@nongnu.org; Wed, 21 May 2025 05:43:44 -0400 Received: by mail-pf1-x434.google.com with SMTP id d2e1a72fcca58-742c46611b6so4772200b3a.1 for ; Wed, 21 May 2025 02:43:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1747820619; x=1748425419; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=iOOmy0NnOkTG9aWPPbTXqcQiNJ8PCIOZVYoxmQs26tY=; b=JHGZH/aIt4Vc2J8NDM50JaCZayckQdXUpPu8MBRFxnosTL55u77mnTT6Vjx/HMA7Dq 5/IYitbIm5afc6sWrv4m5SfslaKuM9ouxSUSZ+WDvKTaBunfOKnkqx5KL6Gw8F3rvJOS EMzQgVRxDBHaWUxHKASwbODsQm93AKlEED6wqcB4fFu87dfzp1Vtv/AmX1FI7xxokF9g 4UojoMuWuaS1Y5/dRW1w8h+DRgzRYK509ObSNUgliPjsFWaR9Ynlihg+MTWlpaoqnpvV gxEW+R6zOirVxOF5IylT0rNQ9bbK8XTJZYEA9GcDy5qlNIINF5VFip/6Q8n7G2gIlkvL y2ig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747820619; x=1748425419; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=iOOmy0NnOkTG9aWPPbTXqcQiNJ8PCIOZVYoxmQs26tY=; b=tGtCe2NNrLhWgjsEKDfObjiDL4HMx/FAtBr6iKAUveO8+8okhy6vfS225cO9ZCnlV6 +MxOQ2o58TXEQCcYBbIUNA2vHtwt21Lq9EdUYb04rAwnqfIDxrBZNr2T8it6gaPWLAVp 3QGLxe1yuyfZVAoytRY/3DRkFyPijhfIlvCHZ5e6J7AbH/8WcIlbOeXh6niCdBeGgZVb 8JwjX/1pgHNIB1qHu3+M4TUpBUsTVf/wlxrONLtjCj4lWDYJhF/WnbQw5LguY3K9STD5 ngjytGP0qMEsLrAF0w0DqbHnAPf1QFzvXoNBKSpfX1zEhktlaHdM0ppBXPz1jQ4Yl5+F wi0A== X-Gm-Message-State: AOJu0YyrXpUS5688j7wGKB2S5/uz1ZsEU94GJIInlfTnQF6d15UeyDrq wGAYUEbXXNlMJN1lhC+gSPY8Ofg+2lWZjCxbWoJTaBuOIOTSHdQQ2YHJQPhDGaEjJ1Q= X-Gm-Gg: ASbGncup9d7Y4Tj17R979aYj8EN8lYAlGrU+GXq1WFTJ4JFreMgos1si/eSJN+eEpeQ WY7KQ8+CBNYPs6KslV9WPK+Py3fvkx/sMe36zyPP1cuBq7NHitUK26i3N1biLPcfmGlU2huzahK uDL3Qna4mDCciepwuDE+9RgNvAMWGb2whvo3lzf3t7j2cq01VmEBomVEJof8s6E+ubbN9X0bh+8 Qe6DX1NXjU1El/Pf+g3whwvXIBq3lRjFy+IycnGcCTv3G20wacyuGhvKL3C9BG34QPnboiQn6L/ /AjaiNF7+VRcbDXofjbZ9aZZB93fhyKh3v8qTy4ffTFc3iNw7bk= X-Google-Smtp-Source: AGHT+IH8VLO4EukNIkob08vR4bW8Hgu3TyQWMGDTSUZxfWrdN3kDpJfZLtJsYG8ecMEluQltD50cCw== X-Received: by 2002:a05:6a00:1d88:b0:736:546c:eb69 with SMTP id d2e1a72fcca58-742accc5783mr22699960b3a.9.1747820618661; Wed, 21 May 2025 02:43:38 -0700 (PDT) Received: from shemhazi.lan ([50.46.174.34]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-742a9829b87sm9255668b3a.114.2025.05.21.02.43.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 May 2025 02:43:38 -0700 (PDT) From: Rowan Hart To: qemu-devel@nongnu.org Cc: Pierrick Bouvier , Alexandre Iooss , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Eduardo Habkost , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Mahmoud Mandour , Paolo Bonzini , novafacing Subject: [PATCH v3 5/8] Add memory hardware address read/write API Date: Wed, 21 May 2025 02:43:29 -0700 Message-ID: <20250521094333.4075796-6-rowanbhart@gmail.com> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250521094333.4075796-1-rowanbhart@gmail.com> References: <20250521094333.4075796-1-rowanbhart@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Received-SPF: pass client-ip=2607:f8b0:4864:20::434; envelope-from=rowanbhart@gmail.com; helo=mail-pf1-x434.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, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-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: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: novafacing Signed-off-by: novafacing Signed-off-by: Rowan Hart --- include/qemu/qemu-plugin.h | 96 +++++++++++++++++++++++++++++++++++ plugins/api.c | 100 +++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) diff --git a/include/qemu/qemu-plugin.h b/include/qemu/qemu-plugin.h index eff8430b4a..d4f229abd9 100644 --- a/include/qemu/qemu-plugin.h +++ b/include/qemu/qemu-plugin.h @@ -1014,6 +1014,102 @@ QEMU_PLUGIN_API bool qemu_plugin_write_memory_vaddr(uint64_t addr, GByteArray *data); +/** + * enum qemu_plugin_hwaddr_operation_result - result of a memory operation + * + * @QEMU_PLUGIN_HWADDR_OPERATION_OK: hwaddr operation succeeded + * @QEMU_PLUGIN_HWADDR_OPERATION_ERROR: unexpected error occurred + * @QEMU_PLUGIN_HWADDR_OPERATION_DEVICE_ERROR: error in memory device + * @QEMU_PLUGIN_HWADDR_OPERATION_ACCESS_DENIED: permission error + * @QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS: address was invalid + * @QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS_SPACE: invalid address space + */ +enum qemu_plugin_hwaddr_operation_result { + QEMU_PLUGIN_HWADDR_OPERATION_OK, + QEMU_PLUGIN_HWADDR_OPERATION_ERROR, + QEMU_PLUGIN_HWADDR_OPERATION_DEVICE_ERROR, + QEMU_PLUGIN_HWADDR_OPERATION_ACCESS_DENIED, + QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS, + QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS_SPACE, +}; + +/** + * qemu_plugin_read_memory_hwaddr() - read from memory using a hardware address + * + * @as_idx: The index of the address space to read from + * @addr: A physical address to read from + * @data: A byte array to store data into + * @len: The number of bytes to read, starting from @addr + * + * @len bytes of data is read starting at @addr and stored into @data. If @data + * is not large enough to hold @len bytes, it will be expanded to the necessary + * size, reallocating if necessary. @len must be greater than 0. + * + * This function does not ensure writes are flushed prior to reading, so + * callers should take care when calling this function in plugin callbacks to + * avoid attempting to read data which may not yet be written and should use + * the memory callback API instead. + * + * This function is only valid for softmmu targets. + * + * Returns a qemu_plugin_hwaddr_operation_result indicating the result of the + * operation. + */ +QEMU_PLUGIN_API +enum qemu_plugin_hwaddr_operation_result +qemu_plugin_read_memory_hwaddr(unsigned int as_idx, uint64_t addr, + GByteArray *data, size_t len); + +/** + * qemu_plugin_write_memory_hwaddr() - write to memory using a hardware address + * + * @as_idx: The index of the address space to write to + * @addr: A physical address to write to + * @data: A byte array containing the data to write + * + * The contents of @data will be written to memory starting at the hardware + * address @addr. + * + * This function does not guarantee consistency of writes, nor does it ensure + * that pending writes are flushed either before or after the write takes place, + * so callers should take care when calling this function in plugin callbacks to + * avoid depending on the existence of data written using this function which + * may be overwritten afterward. In addition, this function requires that the + * pages containing the address are not locked. Practically, this means that you + * should not write instruction memory in a current translation block inside a + * callback registered with qemu_plugin_register_vcpu_tb_trans_cb. + * + * You can, for example, write instruction memory in a current translation block + * in a callback registered with qemu_plugin_register_vcpu_tb_exec_cb, although + * be aware that the write will not be flushed until after the translation block + * has finished executing. In general, this function should be used to write + * data memory or to patch code at a known address, not in a current translation + * block. + * + * This function is only valid for softmmu targets. + * + * Returns a qemu_plugin_hwaddr_operation_result indicating the result of the + * operation. + */ +QEMU_PLUGIN_API +enum qemu_plugin_hwaddr_operation_result +qemu_plugin_write_memory_hwaddr(unsigned int as_idx, uint64_t addr, + GByteArray *data); + +/** + * qemu_plugin_translate_vaddr() - translate a virtual address to a physical one + * + * @vaddr: virtual address to translate + * @hwaddr: pointer to store the physical address + * + * This function is only valid in vCPU context (i.e. in callbacks) and is only + * valid for softmmu targets. + * + * Returns true on success and false on failure. + */ +QEMU_PLUGIN_API +bool qemu_plugin_translate_vaddr(uint64_t vaddr, uint64_t *hwaddr); + /** * qemu_plugin_scoreboard_new() - alloc a new scoreboard * diff --git a/plugins/api.c b/plugins/api.c index 19c10bb39e..5983768783 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -569,6 +569,106 @@ bool qemu_plugin_write_memory_vaddr(uint64_t addr, GByteArray *data) return true; } +enum qemu_plugin_hwaddr_operation_result +qemu_plugin_read_memory_hwaddr(unsigned int as_idx, hwaddr addr, + GByteArray *data, size_t len) +{ +#ifdef CONFIG_SOFTMMU + CPUState *cpu = current_cpu; + + if (len == 0 || as_idx >= cpu->cpu_ases_count) { + return QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS_SPACE; + } + + g_byte_array_set_size(data, len); + + AddressSpace *as = cpu_get_address_space(cpu, as_idx); + + if (as == NULL) { + return QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS_SPACE; + } + + MemTxResult res = address_space_rw(as, addr, + MEMTXATTRS_UNSPECIFIED, data->data, + data->len, false); + + switch (res) { + case MEMTX_OK: + return QEMU_PLUGIN_HWADDR_OPERATION_OK; + case MEMTX_ERROR: + return QEMU_PLUGIN_HWADDR_OPERATION_DEVICE_ERROR; + case MEMTX_DECODE_ERROR: + return QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS; + case MEMTX_ACCESS_ERROR: + return QEMU_PLUGIN_HWADDR_OPERATION_ACCESS_DENIED; + default: + return QEMU_PLUGIN_HWADDR_OPERATION_ERROR; + } +#else + return QEMU_PLUGIN_HWADDR_OPERATION_ERROR; +#endif +} + +enum qemu_plugin_hwaddr_operation_result +qemu_plugin_write_memory_hwaddr(unsigned int as_idx, hwaddr addr, + GByteArray *data) +{ +#ifdef CONFIG_SOFTMMU + CPUState *cpu = current_cpu; + + if (data->len == 0 || as_idx >= cpu->cpu_ases_count) { + return QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS_SPACE; + } + + AddressSpace *as = cpu_get_address_space(cpu, as_idx); + + if (as == NULL) { + return QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS_SPACE; + } + + qemu_plugin_outs("Got cpu address space...\n"); + + MemTxResult res = address_space_rw(as, addr, + MEMTXATTRS_UNSPECIFIED, data->data, + data->len, true); + switch (res) { + case MEMTX_OK: + return QEMU_PLUGIN_HWADDR_OPERATION_OK; + case MEMTX_ERROR: + return QEMU_PLUGIN_HWADDR_OPERATION_DEVICE_ERROR; + case MEMTX_DECODE_ERROR: + return QEMU_PLUGIN_HWADDR_OPERATION_INVALID_ADDRESS; + case MEMTX_ACCESS_ERROR: + return QEMU_PLUGIN_HWADDR_OPERATION_ACCESS_DENIED; + default: + return QEMU_PLUGIN_HWADDR_OPERATION_ERROR; + } +#else + return QEMU_PLUGIN_HWADDR_OPERATION_ERROR; +#endif +} + +bool qemu_plugin_translate_vaddr(uint64_t vaddr, uint64_t *hwaddr) +{ +#ifdef CONFIG_SOFTMMU + g_assert(current_cpu); + + CPUState *cpu = current_cpu; + + uint64_t res = cpu_get_phys_page_debug(cpu, vaddr); + + if (res == (uint64_t)-1) { + return false; + } + + *hwaddr = res | (vaddr & ~TARGET_PAGE_MASK); + + return true; +#else + return false; +#endif +} + struct qemu_plugin_scoreboard *qemu_plugin_scoreboard_new(size_t element_size) { return plugin_scoreboard_new(element_size); -- 2.49.0