{"id":2175187,"url":"http://patchwork.ozlabs.org/api/1.0/patches/2175187/?format=json","project":{"id":14,"url":"http://patchwork.ozlabs.org/api/1.0/projects/14/?format=json","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":""},"msgid":"<20251217143150.94463-8-philmd@linaro.org>","date":"2025-12-17T14:31:43","name":"[07/14] system/memory: Split MemoryRegionCache API to 'memory_cached.h'","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"bc27e28e232c667f30853d2d1a7460126ddf5aa0","submitter":{"id":85046,"url":"http://patchwork.ozlabs.org/api/1.0/people/85046/?format=json","name":"Philippe Mathieu-Daudé","email":"philmd@linaro.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20251217143150.94463-8-philmd@linaro.org/mbox/","series":[{"id":485701,"url":"http://patchwork.ozlabs.org/api/1.0/series/485701/?format=json","date":"2025-12-17T14:31:37","name":"system/memory: Clean ups around address_space_ldst() endian variants","version":1,"mbox":"http://patchwork.ozlabs.org/series/485701/mbox/"}],"check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2175187/checks/","tags":{},"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=VveX+igS;\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 4dWbvF1wSdz1xty\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 18 Dec 2025 01:35:53 +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 1vVsaX-00021L-VO; Wed, 17 Dec 2025 09:33:13 -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 <philmd@linaro.org>) id 1vVsaG-0001k6-Or\n for qemu-devel@nongnu.org; Wed, 17 Dec 2025 09:32:58 -0500","from mail-wm1-x32b.google.com ([2a00:1450:4864:20::32b])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.90_1) (envelope-from <philmd@linaro.org>) id 1vVsaB-0007C6-CI\n for qemu-devel@nongnu.org; Wed, 17 Dec 2025 09:32:53 -0500","by mail-wm1-x32b.google.com with SMTP id\n 5b1f17b1804b1-47796a837c7so43028935e9.0\n for <qemu-devel@nongnu.org>; Wed, 17 Dec 2025 06:32:49 -0800 (PST)","from localhost.localdomain (88-187-86-199.subs.proxad.net.\n [88.187.86.199]) by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-47bd9cc37f0sm30740305e9.4.2025.12.17.06.32.44\n (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256);\n Wed, 17 Dec 2025 06:32:44 -0800 (PST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=linaro.org; s=google; t=1765981967; x=1766586767; 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=6YAsph7okBK8AuJ8n8nNBWNPp4wOy6eiaeIdpcOIdYY=;\n b=VveX+igSFvrtusPx/FyTD/Y9PBxYGuqxcK62/ua6hafa6f4wE6U7pZ6IoqG171W3PK\n BIQe69Iyd1iQcfDIMX5ZRbkmH5qc4jklZiYhUuQXGI/q9X5ZyA/7dLvzguYTidsaGp6k\n bY2AsnX0G4V4/3hqNIwD4E7Wo+1KFGcJz5DgIDuciueNPTyUS/R7HYj42NgB0z01aqdJ\n p+97Y2/4oXyWlwq5Fog1+RZzKRtIV83GBT5SF2n3Byf4mdDxKR60pZwPcKvQrqAUHyEu\n uTzRu5K0V9QYBD69k+yyvj9KIzzcPkRo8H5vo9Z85GH80+aBvGSUpWyvtwn0Flx9wurL\n dqJA==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20230601; t=1765981967; x=1766586767;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=6YAsph7okBK8AuJ8n8nNBWNPp4wOy6eiaeIdpcOIdYY=;\n b=G+4XbykJl5tH3WoQkwWRrsu7h2V6zLZY3MN7GH6sWRTHhA5y8geBjiO9BLEz2ySW12\n sJDQSmRXccmmZNX8yiu8TzUxxLENPYGzroxueCq+ef+Q9gQqgQg0K/W0V7xf9CCmZ4hj\n DJHL+S1tefFLrTgn3fttXuyhLZ9NLV3CHD83oAWVxYFIxXe32N7xJz8dnllUkgfuj8GL\n Fhsx3ZyU9GDCfHH0dKN9tsoVYbgf+bbSRQ2DiCoyAMq5hUmN5x1CAS0S2G2Fi+zB/av2\n XGRgsmmPjmkHxZbJ1xu7Kt9lkcrwsYFMoxo6tmajZTzkBqHS9RMzPmAVWKKhMkZxM8wE\n EkWQ==","X-Gm-Message-State":"AOJu0Yzq8pi/rophYum+IqFOEb+fIihyPnrsebgLDw4RuGVKRzIEyj5Y\n yu0TK1bmv6/BWACcpdGyB99tnJJYv0aiZMqfhTPbC9OSZeQ7TkCbpx6D2wt7NyWHMe4mIbW48Je\n rhbWdXmsU8w==","X-Gm-Gg":"AY/fxX489ecfxo61Vm4c1BXGt3BSKU5YMNFKEume35kv2UiwlUG+IR/KUrNhE1U0L1j\n 3z3F8HKmo6Ge/W1Rh9nqS+q8tiMKMXLTYJgNFpKR1VMOuApsX+tWnvqAS25k0gFY3gjJuXQzhuG\n 3FHvNcCJJOwleb6eK3STgq12NAY9kbDbXewHAbURqaDvIvl2fhT0VWsJEfIPWSLeZO4U1pbnW5P\n mkXdIzE6xZtenW+OQXcMgXmwl1dEib6JMIFvampF69HmAzzA9NitWGeo7hKMNZ/YuoSf5TDr9sE\n mZai8glNJf5mna44Q8I8nxSUYiKhX0FqD9AFJN5WEWf2RPXuLzoE+iMNekJrvLKky+8IkfnAAkp\n 83U4ShXrE6qs20o52BNOib8vaJ4y1Y+5J8dfAd5L7x2uEvD+mHFAXCmbC9YY8fefelAeczs6yPD\n f/FjKsDDchbec1zNaQRL0c7/B6+B1mtNjYPK+fSg3SuYlkeTgr0gj2Eg49lLJi","X-Google-Smtp-Source":"\n AGHT+IFf79uMo8hEMhvgn211ETxm0/XeKA7EJwP8+cGqkOr1q7YBaCl5QACRDU32If929/+b35/BzQ==","X-Received":"by 2002:a05:600c:6748:b0:479:2f95:5179 with SMTP id\n 5b1f17b1804b1-47a8f8c380emr172015875e9.15.1765981967082;\n Wed, 17 Dec 2025 06:32:47 -0800 (PST)","From":"=?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= <philmd@linaro.org>","To":"qemu-devel@nongnu.org","Cc":"=?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= <philmd@linaro.org>,\n Anton Johansson <anjo@rev.ng>, qemu-arm@nongnu.org,\n Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>,\n Paolo Bonzini <pbonzini@redhat.com>, \"Michael S. Tsirkin\" <mst@redhat.com>,\n Artyom Tarasenko <atar4qemu@gmail.com>,\n Peter Maydell <peter.maydell@linaro.org>,\n David Hildenbrand <david@kernel.org>, Peter Xu <peterx@redhat.com>","Subject":"[PATCH 07/14] system/memory: Split MemoryRegionCache API to\n 'memory_cached.h'","Date":"Wed, 17 Dec 2025 15:31:43 +0100","Message-ID":"<20251217143150.94463-8-philmd@linaro.org>","X-Mailer":"git-send-email 2.52.0","In-Reply-To":"<20251217143150.94463-1-philmd@linaro.org>","References":"<20251217143150.94463-1-philmd@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::32b;\n envelope-from=philmd@linaro.org; helo=mail-wm1-x32b.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,\n SPF_PASS=-0.001 autolearn=unavailable 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":"We have 115 direct inclusions of \"system/memory.h\", and 91 headers\nin include/ use it: hundreds of files have to process it.\nHowever only one single header really uses the MemoryRegionCache\nAPI: \"hw/virtio/virtio-access.h\". Split it out to a new header,\navoiding processing unused inlined functions hundreds of times.\n\nSigned-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>\n---\n MAINTAINERS                       |   1 +\n include/hw/virtio/virtio-access.h |   1 +\n include/system/memory.h           | 185 --------------------------\n include/system/memory_cached.h    | 207 ++++++++++++++++++++++++++++++\n system/physmem.c                  |   1 +\n 5 files changed, 210 insertions(+), 185 deletions(-)\n create mode 100644 include/system/memory_cached.h","diff":"diff --git a/MAINTAINERS b/MAINTAINERS\nindex 63e9ba521bc..c299b84d418 100644\n--- a/MAINTAINERS\n+++ b/MAINTAINERS\n@@ -3255,6 +3255,7 @@ S: Supported\n F: include/system/ioport.h\n F: include/exec/memop.h\n F: include/system/memory.h\n+F: include/system/memory_cached.h\n F: include/system/physmem.h\n F: include/system/ram_addr.h\n F: include/system/ramblock.h\ndiff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h\nindex 07aae69042a..3ea3acfe05a 100644\n--- a/include/hw/virtio/virtio-access.h\n+++ b/include/hw/virtio/virtio-access.h\n@@ -17,6 +17,7 @@\n #define QEMU_VIRTIO_ACCESS_H\n \n #include \"exec/hwaddr.h\"\n+#include \"system/memory_cached.h\"\n #include \"hw/virtio/virtio.h\"\n #include \"hw/virtio/virtio-bus.h\"\n \ndiff --git a/include/system/memory.h b/include/system/memory.h\nindex e69171de05a..90f375df5df 100644\n--- a/include/system/memory.h\n+++ b/include/system/memory.h\n@@ -2855,140 +2855,6 @@ MemTxResult address_space_write_rom(AddressSpace *as, hwaddr addr,\n #define ARG1_DECL    AddressSpace *as\n #include \"exec/memory_ldst_phys.h.inc\"\n \n-struct MemoryRegionCache {\n-    uint8_t *ptr;\n-    hwaddr xlat;\n-    hwaddr len;\n-    FlatView *fv;\n-    MemoryRegionSection mrs;\n-    bool is_write;\n-};\n-\n-/* address_space_ld*_cached: load from a cached #MemoryRegion\n- * address_space_st*_cached: store into a cached #MemoryRegion\n- *\n- * These functions perform a load or store of the byte, word,\n- * longword or quad to the specified address.  The address is\n- * a physical address in the AddressSpace, but it must lie within\n- * a #MemoryRegion that was mapped with address_space_cache_init.\n- *\n- * The _le suffixed functions treat the data as little endian;\n- * _be indicates big endian; no suffix indicates \"same endianness\n- * as guest CPU\".\n- *\n- * The \"guest CPU endianness\" accessors are deprecated for use outside\n- * target-* code; devices should be CPU-agnostic and use either the LE\n- * or the BE accessors.\n- *\n- * @cache: previously initialized #MemoryRegionCache to be accessed\n- * @addr: address within the address space\n- * @val: data value, for stores\n- * @attrs: memory transaction attributes\n- * @result: location to write the success/failure of the transaction;\n- *   if NULL, this information is discarded\n- */\n-\n-#define SUFFIX       _cached_slow\n-#define ARG1         cache\n-#define ARG1_DECL    MemoryRegionCache *cache\n-#include \"exec/memory_ldst.h.inc\"\n-\n-/* Inline fast path for direct RAM access.  */\n-static inline uint8_t address_space_ldub_cached(MemoryRegionCache *cache,\n-    hwaddr addr, MemTxAttrs attrs, MemTxResult *result)\n-{\n-    assert(addr < cache->len);\n-    if (likely(cache->ptr)) {\n-        return ldub_p(cache->ptr + addr);\n-    } else {\n-        return address_space_ldub_cached_slow(cache, addr, attrs, result);\n-    }\n-}\n-\n-static inline void address_space_stb_cached(MemoryRegionCache *cache,\n-    hwaddr addr, uint8_t val, MemTxAttrs attrs, MemTxResult *result)\n-{\n-    assert(addr < cache->len);\n-    if (likely(cache->ptr)) {\n-        stb_p(cache->ptr + addr, val);\n-    } else {\n-        address_space_stb_cached_slow(cache, addr, val, attrs, result);\n-    }\n-}\n-\n-#define ENDIANNESS\n-#include \"exec/memory_ldst_cached.h.inc\"\n-\n-#define ENDIANNESS   _le\n-#include \"exec/memory_ldst_cached.h.inc\"\n-\n-#define ENDIANNESS   _be\n-#include \"exec/memory_ldst_cached.h.inc\"\n-\n-#define SUFFIX       _cached\n-#define ARG1         cache\n-#define ARG1_DECL    MemoryRegionCache *cache\n-#include \"exec/memory_ldst_phys.h.inc\"\n-\n-/* address_space_cache_init: prepare for repeated access to a physical\n- * memory region\n- *\n- * @cache: #MemoryRegionCache to be filled\n- * @as: #AddressSpace to be accessed\n- * @addr: address within that address space\n- * @len: length of buffer\n- * @is_write: indicates the transfer direction\n- *\n- * Will only work with RAM, and may map a subset of the requested range by\n- * returning a value that is less than @len.  On failure, return a negative\n- * errno value.\n- *\n- * Because it only works with RAM, this function can be used for\n- * read-modify-write operations.  In this case, is_write should be %true.\n- *\n- * Note that addresses passed to the address_space_*_cached functions\n- * are relative to @addr.\n- */\n-int64_t address_space_cache_init(MemoryRegionCache *cache,\n-                                 AddressSpace *as,\n-                                 hwaddr addr,\n-                                 hwaddr len,\n-                                 bool is_write);\n-\n-/**\n- * address_space_cache_init_empty: Initialize empty #MemoryRegionCache\n- *\n- * @cache: The #MemoryRegionCache to operate on.\n- *\n- * Initializes #MemoryRegionCache structure without memory region attached.\n- * Cache initialized this way can only be safely destroyed, but not used.\n- */\n-static inline void address_space_cache_init_empty(MemoryRegionCache *cache)\n-{\n-    cache->mrs.mr = NULL;\n-    /* There is no real need to initialize fv, but it makes Coverity happy. */\n-    cache->fv = NULL;\n-}\n-\n-/**\n- * address_space_cache_invalidate: complete a write to a #MemoryRegionCache\n- *\n- * @cache: The #MemoryRegionCache to operate on.\n- * @addr: The first physical address that was written, relative to the\n- * address that was passed to @address_space_cache_init.\n- * @access_len: The number of bytes that were written starting at @addr.\n- */\n-void address_space_cache_invalidate(MemoryRegionCache *cache,\n-                                    hwaddr addr,\n-                                    hwaddr access_len);\n-\n-/**\n- * address_space_cache_destroy: free a #MemoryRegionCache\n- *\n- * @cache: The #MemoryRegionCache whose memory should be released.\n- */\n-void address_space_cache_destroy(MemoryRegionCache *cache);\n-\n void address_space_flush_icache_range(AddressSpace *as, hwaddr addr, hwaddr len);\n \n /* address_space_get_iotlb_entry: translate an address into an IOTLB\n@@ -3116,14 +2982,6 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr,\n                                    MemoryRegion *mr);\n void *qemu_map_ram_ptr(RAMBlock *ram_block, ram_addr_t addr);\n \n-/* Internal functions, part of the implementation of address_space_read_cached\n- * and address_space_write_cached.  */\n-MemTxResult address_space_read_cached_slow(MemoryRegionCache *cache,\n-                                           hwaddr addr, void *buf, hwaddr len);\n-MemTxResult address_space_write_cached_slow(MemoryRegionCache *cache,\n-                                            hwaddr addr, const void *buf,\n-                                            hwaddr len);\n-\n int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr);\n bool prepare_mmio_access(MemoryRegion *mr);\n \n@@ -3201,49 +3059,6 @@ MemTxResult address_space_read(AddressSpace *as, hwaddr addr,\n     return result;\n }\n \n-/**\n- * address_space_read_cached: read from a cached RAM region\n- *\n- * @cache: Cached region to be addressed\n- * @addr: address relative to the base of the RAM region\n- * @buf: buffer with the data transferred\n- * @len: length of the data transferred\n- */\n-static inline MemTxResult\n-address_space_read_cached(MemoryRegionCache *cache, hwaddr addr,\n-                          void *buf, hwaddr len)\n-{\n-    assert(addr < cache->len && len <= cache->len - addr);\n-    fuzz_dma_read_cb(cache->xlat + addr, len, cache->mrs.mr);\n-    if (likely(cache->ptr)) {\n-        memcpy(buf, cache->ptr + addr, len);\n-        return MEMTX_OK;\n-    } else {\n-        return address_space_read_cached_slow(cache, addr, buf, len);\n-    }\n-}\n-\n-/**\n- * address_space_write_cached: write to a cached RAM region\n- *\n- * @cache: Cached region to be addressed\n- * @addr: address relative to the base of the RAM region\n- * @buf: buffer with the data transferred\n- * @len: length of the data transferred\n- */\n-static inline MemTxResult\n-address_space_write_cached(MemoryRegionCache *cache, hwaddr addr,\n-                           const void *buf, hwaddr len)\n-{\n-    assert(addr < cache->len && len <= cache->len - addr);\n-    if (likely(cache->ptr)) {\n-        memcpy(cache->ptr + addr, buf, len);\n-        return MEMTX_OK;\n-    } else {\n-        return address_space_write_cached_slow(cache, addr, buf, len);\n-    }\n-}\n-\n /**\n  * address_space_set: Fill address space with a constant byte.\n  *\ndiff --git a/include/system/memory_cached.h b/include/system/memory_cached.h\nnew file mode 100644\nindex 00000000000..1a07774b6ad\n--- /dev/null\n+++ b/include/system/memory_cached.h\n@@ -0,0 +1,207 @@\n+/*\n+ * Physical memory management API\n+ *\n+ * Copyright 2011 Red Hat, Inc. and/or its affiliates\n+ *\n+ * Authors:\n+ *  Avi Kivity <avi@redhat.com>\n+ *\n+ * SPDX-License-Identifier: GPL-2.0-or-later\n+ */\n+\n+#ifndef SYSTEM_MEMORY_CACHED_H\n+#define SYSTEM_MEMORY_CACHED_H\n+\n+#include \"exec/hwaddr.h\"\n+#include \"system/memory.h\"\n+\n+struct MemoryRegionCache {\n+    uint8_t *ptr;\n+    hwaddr xlat;\n+    hwaddr len;\n+    FlatView *fv;\n+    MemoryRegionSection mrs;\n+    bool is_write;\n+};\n+\n+/**\n+ * address_space_ld*_cached: load from a cached #MemoryRegion\n+ * address_space_st*_cached: store into a cached #MemoryRegion\n+ *\n+ * These functions perform a load or store of the byte, word,\n+ * longword or quad to the specified address.  The address is\n+ * a physical address in the AddressSpace, but it must lie within\n+ * a #MemoryRegion that was mapped with address_space_cache_init.\n+ *\n+ * The _le suffixed functions treat the data as little endian;\n+ * _be indicates big endian; no suffix indicates \"same endianness\n+ * as guest CPU\".\n+ *\n+ * The \"guest CPU endianness\" accessors are deprecated for use outside\n+ * target-* code; devices should be CPU-agnostic and use either the LE\n+ * or the BE accessors.\n+ *\n+ * @cache: previously initialized #MemoryRegionCache to be accessed\n+ * @addr: address within the address space\n+ * @val: data value, for stores\n+ * @attrs: memory transaction attributes\n+ * @result: location to write the success/failure of the transaction;\n+ *          if NULL, this information is discarded\n+ */\n+\n+#define SUFFIX       _cached_slow\n+#define ARG1         cache\n+#define ARG1_DECL    MemoryRegionCache *cache\n+#include \"exec/memory_ldst.h.inc\"\n+\n+/* Inline fast path for direct RAM access.  */\n+static inline uint8_t address_space_ldub_cached(MemoryRegionCache *cache,\n+    hwaddr addr, MemTxAttrs attrs, MemTxResult *result)\n+{\n+    assert(addr < cache->len);\n+    if (likely(cache->ptr)) {\n+        return ldub_p(cache->ptr + addr);\n+    } else {\n+        return address_space_ldub_cached_slow(cache, addr, attrs, result);\n+    }\n+}\n+\n+static inline void address_space_stb_cached(MemoryRegionCache *cache,\n+    hwaddr addr, uint8_t val, MemTxAttrs attrs, MemTxResult *result)\n+{\n+    assert(addr < cache->len);\n+    if (likely(cache->ptr)) {\n+        stb_p(cache->ptr + addr, val);\n+    } else {\n+        address_space_stb_cached_slow(cache, addr, val, attrs, result);\n+    }\n+}\n+\n+#define ENDIANNESS\n+#include \"exec/memory_ldst_cached.h.inc\"\n+\n+#define ENDIANNESS   _le\n+#include \"exec/memory_ldst_cached.h.inc\"\n+\n+#define ENDIANNESS   _be\n+#include \"exec/memory_ldst_cached.h.inc\"\n+\n+#define SUFFIX       _cached\n+#define ARG1         cache\n+#define ARG1_DECL    MemoryRegionCache *cache\n+#include \"exec/memory_ldst_phys.h.inc\"\n+\n+/**\n+ * address_space_cache_init: prepare for repeated access to a physical\n+ *                           memory region\n+ *\n+ * @cache: #MemoryRegionCache to be filled\n+ * @as: #AddressSpace to be accessed\n+ * @addr: address within that address space\n+ * @len: length of buffer\n+ * @is_write: indicates the transfer direction\n+ *\n+ * Will only work with RAM, and may map a subset of the requested range by\n+ * returning a value that is less than @len.  On failure, return a negative\n+ * errno value.\n+ *\n+ * Because it only works with RAM, this function can be used for\n+ * read-modify-write operations.  In this case, is_write should be %true.\n+ *\n+ * Note that addresses passed to the address_space_*_cached functions\n+ * are relative to @addr.\n+ */\n+int64_t address_space_cache_init(MemoryRegionCache *cache,\n+                                 AddressSpace *as,\n+                                 hwaddr addr,\n+                                 hwaddr len,\n+                                 bool is_write);\n+\n+/**\n+ * address_space_cache_init_empty: Initialize empty #MemoryRegionCache\n+ *\n+ * @cache: The #MemoryRegionCache to operate on.\n+ *\n+ * Initializes #MemoryRegionCache structure without memory region attached.\n+ * Cache initialized this way can only be safely destroyed, but not used.\n+ */\n+static inline void address_space_cache_init_empty(MemoryRegionCache *cache)\n+{\n+    cache->mrs.mr = NULL;\n+    /* There is no real need to initialize fv, but it makes Coverity happy. */\n+    cache->fv = NULL;\n+}\n+\n+/**\n+ * address_space_cache_invalidate: complete a write to a #MemoryRegionCache\n+ *\n+ * @cache: The #MemoryRegionCache to operate on.\n+ * @addr: The first physical address that was written, relative to the\n+ * address that was passed to @address_space_cache_init.\n+ * @access_len: The number of bytes that were written starting at @addr.\n+ */\n+void address_space_cache_invalidate(MemoryRegionCache *cache,\n+                                    hwaddr addr,\n+                                    hwaddr access_len);\n+\n+/**\n+ * address_space_cache_destroy: free a #MemoryRegionCache\n+ *\n+ * @cache: The #MemoryRegionCache whose memory should be released.\n+ */\n+void address_space_cache_destroy(MemoryRegionCache *cache);\n+\n+/*\n+ * Internal functions, part of the implementation of address_space_read_cached\n+ * and address_space_write_cached.\n+ */\n+MemTxResult address_space_read_cached_slow(MemoryRegionCache *cache,\n+                                           hwaddr addr, void *buf, hwaddr len);\n+MemTxResult address_space_write_cached_slow(MemoryRegionCache *cache,\n+                                            hwaddr addr, const void *buf,\n+                                            hwaddr len);\n+\n+/**\n+ * address_space_read_cached: read from a cached RAM region\n+ *\n+ * @cache: Cached region to be addressed\n+ * @addr: address relative to the base of the RAM region\n+ * @buf: buffer with the data transferred\n+ * @len: length of the data transferred\n+ */\n+static inline MemTxResult\n+address_space_read_cached(MemoryRegionCache *cache, hwaddr addr,\n+                          void *buf, hwaddr len)\n+{\n+    assert(addr < cache->len && len <= cache->len - addr);\n+    fuzz_dma_read_cb(cache->xlat + addr, len, cache->mrs.mr);\n+    if (likely(cache->ptr)) {\n+        memcpy(buf, cache->ptr + addr, len);\n+        return MEMTX_OK;\n+    } else {\n+        return address_space_read_cached_slow(cache, addr, buf, len);\n+    }\n+}\n+\n+/**\n+ * address_space_write_cached: write to a cached RAM region\n+ *\n+ * @cache: Cached region to be addressed\n+ * @addr: address relative to the base of the RAM region\n+ * @buf: buffer with the data transferred\n+ * @len: length of the data transferred\n+ */\n+static inline MemTxResult\n+address_space_write_cached(MemoryRegionCache *cache, hwaddr addr,\n+                           const void *buf, hwaddr len)\n+{\n+    assert(addr < cache->len && len <= cache->len - addr);\n+    if (likely(cache->ptr)) {\n+        memcpy(cache->ptr + addr, buf, len);\n+        return MEMTX_OK;\n+    } else {\n+        return address_space_write_cached_slow(cache, addr, buf, len);\n+    }\n+}\n+\n+#endif\ndiff --git a/system/physmem.c b/system/physmem.c\nindex d8465f085bd..853a8c00aa2 100644\n--- a/system/physmem.c\n+++ b/system/physmem.c\n@@ -53,6 +53,7 @@\n #include \"qemu/memalign.h\"\n #include \"qemu/memfd.h\"\n #include \"system/memory.h\"\n+#include \"system/memory_cached.h\"\n #include \"system/ioport.h\"\n #include \"system/dma.h\"\n #include \"system/hostmem.h\"\n","prefixes":["07/14"]}