{"id":2225826,"url":"http://patchwork.ozlabs.org/api/patches/2225826/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20260421162912.3295598-6-jim.shu@sifive.com/","project":{"id":14,"url":"http://patchwork.ozlabs.org/api/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":"","list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<20260421162912.3295598-6-jim.shu@sifive.com>","list_archive_url":null,"date":"2026-04-21T16:29:12","name":"[v2,5/5] accel/tcg: Support IOMMU lazy translation in CPU TLB","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"ed432d4d5f9482bc8226f577e2309e9e68c909d5","submitter":{"id":83153,"url":"http://patchwork.ozlabs.org/api/people/83153/?format=json","name":"Jim Shu","email":"jim.shu@sifive.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20260421162912.3295598-6-jim.shu@sifive.com/mbox/","series":[{"id":500851,"url":"http://patchwork.ozlabs.org/api/series/500851/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/list/?series=500851","date":"2026-04-21T16:29:09","name":"Defer the IOMMU translation and support access_type","version":2,"mbox":"http://patchwork.ozlabs.org/series/500851/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2225826/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2225826/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\tdkim=pass (2048-bit key;\n unprotected) header.d=sifive.com header.i=@sifive.com header.a=rsa-sha256\n header.s=google header.b=HCRV6hRE;\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=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists1p.gnu.org (lists1p.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 4g0SXk2KsWz1yJy\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 02:31:18 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wFDzG-0000S1-3A; Tue, 21 Apr 2026 12:30:10 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <jim.shu@sifive.com>)\n id 1wFDzA-0000Da-BO\n for qemu-devel@nongnu.org; Tue, 21 Apr 2026 12:30:05 -0400","from mail-pj1-x1035.google.com ([2607:f8b0:4864:20::1035])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.90_1) (envelope-from <jim.shu@sifive.com>)\n id 1wFDz6-0005lV-Uf\n for qemu-devel@nongnu.org; Tue, 21 Apr 2026 12:30:03 -0400","by mail-pj1-x1035.google.com with SMTP id\n 98e67ed59e1d1-35fb0bb27e7so2900387a91.1\n for <qemu-devel@nongnu.org>; Tue, 21 Apr 2026 09:29:57 -0700 (PDT)","from hsinchu26.internal.sifive.com ([210.176.154.34])\n by smtp.gmail.com with ESMTPSA id\n 98e67ed59e1d1-36140ff2e1esm13529470a91.8.2026.04.21.09.29.48\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 21 Apr 2026 09:29:54 -0700 (PDT)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=sifive.com; s=google; t=1776788995; x=1777393795; 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=W9nxX3vo27aPKXMM9uM/grMyQNuhei9Pxu0QSoOCOso=;\n b=HCRV6hRE+TZv4rGgPHHAbwA+0bffRitB503IP08HgkdJIUA3/ndxg1y5D2Fa4tdoZF\n DTQcnp5UhO7E0MMqfPunjVJven5g+Gf1Vb8KlbF65+0B6d06/5Kudl3cC5ddBeSLtEnw\n rPtbfUY+t68g5pOJqs1qvoA0a0so6/Exa6GjTpDw6YZFu+kkR4/NJBJX+oRd0OfdjqMn\n eD89o0JoO1fjExfTIm1Ohe/evlrPc1ueWiesaXnFbf5br2Uw5xqNkE0VRat4NHXz/Rgv\n 8haedtXMhNta8WyI17KMpbmXRFcG5ccpHIbyjYEw75tUq2H7iV13U4GZ/E/vb8KyXNjX\n CB/A==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776788995; x=1777393795;\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=W9nxX3vo27aPKXMM9uM/grMyQNuhei9Pxu0QSoOCOso=;\n b=fJ6PwLUA3XhCj3qvQHIW9iVE262llqtsIhtMzIau6CIwVDZ1g+pOI4nYjxqGnNS952\n OrSrO7dcYwDHTmBO1M21xxMniaehzykbXlLh3AVckxHKPjCKo+WgyIZovXjhpbrjACj0\n Um+lAB6063T0MCVQy1Eo5taZkr4wiYCaU/UopczPny+ySqmJ2FmzraElDNc/74ZS+M22\n F2uvIf+N4NRJMcWHrZOB9iOO2wMAwhgmz3MXGRwuWiPjFfN8G1D7wfdk+pOJh5FIMwzO\n m3noGZq4RSCAKs4mRJhBJo2ka1sUrPxZItVhlst2KQySdOuAwf3Cfof9LumtmvcnoY1h\n xyvQ==","X-Gm-Message-State":"AOJu0YzZ2oOojF89JTmb1L1JYEpvuBz8UJK8+B8iMrswkxXCjuiJUaEq\n dDPVj7te0JCSUWbK4ICO8JpSNPzIHTzCgpkvGF67IDLsmalGeLu+e4hx7svpHVw+yTtqKyhZGTE\n U/fRxRZ+sleCEf+tW5fm2UUl+31BcvZtzP0Ljox1JHLiOrrT9i8nTRlLclmyG6C2ywFZJQPIneg\n 4fDiztXeB/ZqnrePD2cQ0iPMijo4umF4aPrlU/dPQ0","X-Gm-Gg":"AeBDieu6FMfbRQ+jZIn+5ECoRf2OgDQq49hQXP+UlOZRhEtQFbZRcIdz1vkJZofX0j5\n qK+iOck36Safa3OpVPkKsUn1/KCRGXVtil7T7y3Ue6k/qWxVmxrqPdzSXJKqmQxwqGGrlhILr6S\n wfAUyy4TMzmhp22DzY9Yn0hY7jSIr/jYs+KnNw5OcdwiS7mIAh627qruU/wgqwiPPVEJR/XhBSp\n bCpUyyGYVP0e9rbvljm8TmZ4RTzLkS/jk/rNFTgf0UYBN0LOo4w/B3fiZIZkXxpvV2J17Ec7jpM\n Efag7OsRKsvIYi8k6zIQUIlhoAg5hDhDDM9xrlWi2U53L9FU77SWnU4GbLPEEX7adjqIL4tH0dt\n PNh9qy0qr5R4n+eZc3Lpk9C1JhS+dL9Rfd+ToO47maA2fZErp1zWH5CyVxcPHt8SazLtzszvVF3\n SdWJgpdcEQgd9m/1+sYxtgxtyjD/KbPoJFI65YDPdSgvif88EQ8dBh2qE=","X-Received":"by 2002:a17:90b:4ecc:b0:35b:e553:9cc2 with SMTP id\n 98e67ed59e1d1-361404b9802mr18174499a91.26.1776788994782;\n Tue, 21 Apr 2026 09:29:54 -0700 (PDT)","From":"Jim Shu <jim.shu@sifive.com>","To":"qemu-devel@nongnu.org,\n\tqemu-riscv@nongnu.org","Cc":"Richard Henderson <richard.henderson@linaro.org>,\n Paolo Bonzini <pbonzini@redhat.com>,\n =?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= <philmd@linaro.org>,\n Marcel Apfelbaum <marcel.apfelbaum@gmail.com>,\n Yanan Wang <wangyanan55@huawei.com>, Zhao Liu <zhao1.liu@intel.com>,\n Peter Xu <peterx@redhat.com>, Michael Rolnik <mrolnik@gmail.com>,\n Helge Deller <deller@gmx.de>, Song Gao <gaosong@loongson.cn>,\n Laurent Vivier <laurent@vivier.eu>,\n \"Edgar E. Iglesias\" <edgar.iglesias@gmail.com>,\n Aurelien Jarno <aurelien@aurel32.net>, Jiaxun Yang <jiaxun.yang@flygoat.com>,\n Aleksandar Rikalo <arikalo@gmail.com>, Stafford Horne <shorne@gmail.com>,\n Nicholas Piggin <npiggin@gmail.com>, Chinmay Rath <rathc@linux.ibm.com>,\n Glenn Miles <milesg@linux.ibm.com>, Palmer Dabbelt <palmer@dabbelt.com>,\n Alistair Francis <alistair.francis@wdc.com>, Weiwei Li <liwei1518@gmail.com>,\n Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>,\n Liu Zhiwei <zhiwei_liu@linux.alibaba.com>,\n Chao Liu <chao.liu.zevorn@gmail.com>,\n Yoshinori Sato <yoshinori.sato@nifty.com>,\n Ilya Leoshkevich <iii@linux.ibm.com>, David Hildenbrand <david@kernel.org>,\n Cornelia Huck <cohuck@redhat.com>, Eric Farman <farman@linux.ibm.com>,\n Matthew Rosato <mjrosato@linux.ibm.com>,\n Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>,\n Artyom Tarasenko <atar4qemu@gmail.com>,\n Bastian Koppelmann <kbastian@rumtueddeln.de>,\n Max Filippov <jcmvbkbc@gmail.com>,\n qemu-ppc@nongnu.org (open list:PowerPC TCG CPUs),\n qemu-s390x@nongnu.org (open list:S390 TCG CPUs), Jim Shu <jim.shu@sifive.com>","Subject":"[PATCH v2 5/5] accel/tcg: Support IOMMU lazy translation in CPU TLB","Date":"Wed, 22 Apr 2026 00:29:12 +0800","Message-ID":"<20260421162912.3295598-6-jim.shu@sifive.com>","X-Mailer":"git-send-email 2.43.0","In-Reply-To":"<20260421162912.3295598-1-jim.shu@sifive.com>","References":"<20260421162912.3295598-1-jim.shu@sifive.com>","MIME-Version":"1.0","Content-Transfer-Encoding":"8bit","Received-SPF":"pass client-ip=2607:f8b0:4864:20::1035;\n envelope-from=jim.shu@sifive.com; helo=mail-pj1-x1035.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 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":"tlb_set_page_full() no longer translates IOMMU region, but only stores\nuntranslated IOMMU region in the CPUTLBEntryFull. Then, when CPU uses\nCPUTLBEntryFull in the slow path. it should perform the lazy translation\nvia tlb_translate_iommu().\n\nThe untranslated IOMMU region in TLB always requires to run in the slow\npath to trigger the lazy translation, so the IOMMU region will contain a\nnew TLB flag, TLB_IOMMU, to force the slow path. Lazy translation will\noverwrite the TLB flags to the flags of the translated region. The host\nmemory region from IOMMU region can still run in the fast path to\naccelerate the performance.\n\nSigned-off-by: Jim Shu <jim.shu@sifive.com>\n---\n accel/tcg/cputlb.c       | 66 ++++++++++++++++++++++++++++++++++------\n include/exec/tlb-flags.h |  4 ++-\n 2 files changed, 60 insertions(+), 10 deletions(-)","diff":"diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c\nindex 5735f632896..7a44ae8238b 100644\n--- a/accel/tcg/cputlb.c\n+++ b/accel/tcg/cputlb.c\n@@ -1034,7 +1034,7 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx,\n     hwaddr iotlb, xlat, sz, paddr_page;\n     vaddr addr_page;\n     int asidx, wp_flags, prot;\n-    bool is_ram, is_romd;\n+    bool is_ram, is_romd, is_iommu;\n \n     assert_cpu_is_self(cpu);\n \n@@ -1049,29 +1049,38 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx,\n \n     prot = full->prot;\n     asidx = cpu_asidx_from_attrs(cpu, full->attrs);\n-    section = address_space_translate_for_iotlb_late(cpu, asidx, paddr_page,\n-                                                     &xlat, &sz, full->attrs,\n-                                                     &prot);\n+\n+    /*\n+     * Use the early translation to check if it is an IOMMU region.\n+     * This function stops at IOMMU regions without translating through them.\n+     */\n+    section = address_space_translate_for_iotlb_early(cpu, asidx, paddr_page,\n+                                                      &xlat, &sz, full->attrs,\n+                                                      &prot);\n     assert(sz >= TARGET_PAGE_SIZE);\n \n     tlb_debug(\"vaddr=%016\" VADDR_PRIx \" paddr=0x\" HWADDR_FMT_plx\n               \" prot=%x idx=%d\\n\",\n               addr, full->phys_addr, prot, mmu_idx);\n \n+    is_iommu = memory_region_is_iommu(section->mr);\n+    is_ram = memory_region_is_ram(section->mr);\n+    is_romd = memory_region_is_romd(section->mr);\n+\n+    full->is_iommu = is_iommu;\n+    full->iommu_last_at = MMU_ACCESS_COUNT;\n+\n     read_flags = full->tlb_fill_flags;\n     if (full->lg_page_size < TARGET_PAGE_BITS) {\n         /* Repeat the MMU check and TLB fill on every access.  */\n         read_flags |= TLB_INVALID_MASK;\n     }\n \n-    is_ram = memory_region_is_ram(section->mr);\n-    is_romd = memory_region_is_romd(section->mr);\n-\n     if (is_ram || is_romd) {\n         /* RAM and ROMD both have associated host memory. */\n         addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat;\n     } else {\n-        /* I/O does not; force the host address to NULL. */\n+        /* I/O and IOMMU does not; force the host address to NULL. */\n         addend = 0;\n     }\n \n@@ -1090,6 +1099,15 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx,\n                 write_flags |= TLB_NOTDIRTY;\n             }\n         }\n+    } else if (is_iommu) {\n+        /* IOMMU */\n+        iotlb = xlat;\n+        /*\n+         * If IOMMU region is not translated, any access will go to\n+         * the slow path and do the lazy IOMMU translation.\n+         */\n+        read_flags |= TLB_IOMMU;\n+        write_flags |= TLB_IOMMU;\n     } else {\n         /* I/O or ROMD */\n         iotlb = xlat;\n@@ -1568,6 +1586,11 @@ static int probe_access_internal(CPUState *cpu, vaddr addr,\n     flags &= tlb_addr;\n \n     *pfull = full = &cpu->neg.tlb.d[mmu_idx].fulltlb[index];\n+\n+    if (full->is_iommu) {\n+        tlb_translate_iommu(cpu, mmu_idx, addr, access_type, full);\n+    }\n+\n     flags |= full->slow_flags[access_type];\n \n     /* Fold all \"mmio-like\" bits into TLB_MMIO.  This is not RAM.  */\n@@ -1760,6 +1783,11 @@ bool tlb_plugin_lookup(CPUState *cpu, vaddr addr, int mmu_idx,\n     }\n \n     full = &cpu->neg.tlb.d[mmu_idx].fulltlb[index];\n+\n+    if (full->is_iommu) {\n+        tlb_translate_iommu(cpu, mmu_idx, addr, access_type, full);\n+    }\n+\n     data->phys_addr = full->phys_addr | (addr & ~TARGET_PAGE_MASK);\n \n     /* We must have an iotlb entry for MMIO */\n@@ -1833,6 +1861,11 @@ static bool mmu_lookup1(CPUState *cpu, MMULookupPageData *data, MemOp memop,\n     }\n \n     full = &cpu->neg.tlb.d[mmu_idx].fulltlb[index];\n+\n+    if (full->is_iommu) {\n+        tlb_translate_iommu(cpu, mmu_idx, addr, access_type, full);\n+    }\n+\n     flags = tlb_addr & (TLB_FLAGS_MASK & ~TLB_FORCE_SLOW);\n     flags |= full->slow_flags[access_type];\n \n@@ -1944,6 +1977,11 @@ static bool mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,\n         if (mmu_lookup1(cpu, &l->page[1], 0, l->mmu_idx, type, ra)) {\n             uintptr_t index = tlb_index(cpu, l->mmu_idx, addr);\n             l->page[0].full = &cpu->neg.tlb.d[l->mmu_idx].fulltlb[index];\n+\n+            if (l->page[0].full->is_iommu) {\n+                tlb_translate_iommu(cpu, l->mmu_idx, addr, type,\n+                                    l->page[0].full);\n+            }\n         }\n \n         flags = l->page[0].flags | l->page[1].flags;\n@@ -2001,6 +2039,17 @@ static void *atomic_mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,\n         tlb_addr = tlb_addr_write(tlbe) & ~TLB_INVALID_MASK;\n     }\n \n+    full = &cpu->neg.tlb.d[mmu_idx].fulltlb[index];\n+\n+    if (full->is_iommu) {\n+        /*\n+         * Do IOMMU lazy translation before accessing addr_idx and TLB flags.\n+         * Generate TLB flags for both read and write.\n+         */\n+        tlb_translate_iommu(cpu, mmu_idx, addr, MMU_DATA_LOAD, full);\n+        tlb_translate_iommu(cpu, mmu_idx, addr, MMU_DATA_STORE, full);\n+    }\n+\n     /*\n      * Let the guest notice RMW on a write-only page.\n      * We have just verified that the page is writable.\n@@ -2035,7 +2084,6 @@ static void *atomic_mmu_lookup(CPUState *cpu, vaddr addr, MemOpIdx oi,\n     }\n \n     /* Finish collecting tlb flags for both read and write. */\n-    full = &cpu->neg.tlb.d[mmu_idx].fulltlb[index];\n     tlb_addr |= tlbe->addr_read;\n     tlb_addr &= TLB_FLAGS_MASK & ~TLB_FORCE_SLOW;\n     tlb_addr |= full->slow_flags[MMU_DATA_STORE];\ndiff --git a/include/exec/tlb-flags.h b/include/exec/tlb-flags.h\nindex 357e79095c9..d78f1c3dc64 100644\n--- a/include/exec/tlb-flags.h\n+++ b/include/exec/tlb-flags.h\n@@ -52,10 +52,12 @@\n #define TLB_DISCARD_WRITE    (1 << 3)\n /* Set if TLB entry is an IO callback.  */\n #define TLB_MMIO             (1 << 4)\n+/* Set if TLB entry is a IOMMU region which requires lazy translation. */\n+#define TLB_IOMMU            (1 << 5)\n \n #define TLB_SLOW_FLAGS_MASK \\\n     (TLB_BSWAP | TLB_WATCHPOINT | TLB_CHECK_ALIGNED | \\\n-     TLB_DISCARD_WRITE | TLB_MMIO)\n+     TLB_DISCARD_WRITE | TLB_MMIO | TLB_IOMMU)\n \n /*\n  * Flags stored in CPUTLBEntry.addr_idx[x].\n","prefixes":["v2","5/5"]}