From nobody Tue Apr 7 07:34:15 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1773546208; cv=none; d=zohomail.com; s=zohoarc; b=jjpkCyS2OgCUxnn6m/ZBCQdTkIMVmYvSCx3SF2vpBiqb65ou9AGvuKZ5zLNCw5iiz4A0jR8nCd/anYpY++xyXcZ0zykptytlI8aO3ifVzeULtmRhhe65uYanao7qwZxKrb5HnOZfAZuJ/CU6eaPMtUf9sd2+vW8OUK47sMr0DgA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773546208; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=XVVM+w5YtEgVuUumx4wLK/FVrEJ2UWwyHA2kIqW+YD4=; b=Y/icQoxfSsuZxFlnAmO9oX4J7XIC4q3Ik305MHmu0Ea/N1QIH+CAPR7NLjsDm5mHBF+2N3+bfz4GuEVB/WQyzs4zGGBzdhrZtSJfBqgGD7PHEtL6HYypqL50EvPeauHBF2E6eF9qfQgmeU3Lfdd6+VOgQ2piIc7FGs4J4bGK2uI= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773546208635417.20558043900587; Sat, 14 Mar 2026 20:43:28 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w1cMD-0004oq-IX; Sat, 14 Mar 2026 23:41:37 -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 1w1cMB-0004no-JJ for qemu-devel@nongnu.org; Sat, 14 Mar 2026 23:41:35 -0400 Received: from mail-dy1-x132e.google.com ([2607:f8b0:4864:20::132e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w1cM9-0003Uf-1W for qemu-devel@nongnu.org; Sat, 14 Mar 2026 23:41:35 -0400 Received: by mail-dy1-x132e.google.com with SMTP id 5a478bee46e88-2b4520f6b32so5139305eec.0 for ; Sat, 14 Mar 2026 20:41:32 -0700 (PDT) Received: from 192.168.7.2 ([189.6.247.75]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2beab3eec8fsm8886424eec.13.2026.03.14.20.41.28 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 14 Mar 2026 20:41:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773546091; x=1774150891; 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=XVVM+w5YtEgVuUumx4wLK/FVrEJ2UWwyHA2kIqW+YD4=; b=bOtbVI/b2FrcplVuUGT8nKaxMnSUDEGIWjljXRyy/4re0pYTBLd+9v5hASJHDJKD+V TR/HWPcZ1oKihnLTAXbAn0nvTACwvNhOS5qYpunujGQS3ity1vBb3hGzXLgi+V+uR9T2 Ubgfi4W1UyU+A4whuD1UcSCTKdzjBkL7cpz3eB+baJGEip89rZA01Yvr27nJfKBq5dhz wjKSke4G+IptTb7WAEu/v/P8kMalzGmbmBszQL+poADs+oTcI53wO2D9hwEDqP1AMBcv CnJ7V74XBx5h1YX1LU4eZ5n6pqSwuHwmisYFvYfqXES/SC0spA9qCW+HcCt5vUCT1rkk HM0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773546091; x=1774150891; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=XVVM+w5YtEgVuUumx4wLK/FVrEJ2UWwyHA2kIqW+YD4=; b=nX8H+thNf7zWs9UovjGPltC+oYurJbozulcIKdcyVvwCUouYEwEPteNFnAHyILIo6Y oUMCzVynVsZ0shGM6Y6dAjoBv4GAc9Lpe5wxFM62CajSLUh4JVLbKjT2PmVHSXVOLVlW +7UbltH0eWjOk3jE3FBsnCnzWMl81YqhkjvsaQ0u7A0Rm3b4QByivH9WIK6nXnI9GONe zDWZuT9cuDoalzGgqjQhOkeQAeSMuFsiiJBFL4/VhpMOjTxcYl+VukvNd3qDUNUQ5jFH ihzfjToIekKKLrClNUg/KV6xIB+P5Mw2QCk6Rr5K5gqbQBqT46cOjOMTLHUkV+xopFzp bJ9g== X-Gm-Message-State: AOJu0Yz+a46wQbAZxbeoKkmXPShWq9nCJJCXddrzL6/c5EjCyLoTrh0n x6bFlqYqJEUiCiGdCHXtvGzommWR9doYP83d4LkCIbEMQnvLmzPMNI9Yhi0tQePY X-Gm-Gg: ATEYQzxjjQ04rSYAxpM+zN818WcFayGGzVT90RqnSsatusuUj06wsUjdE5qMGNQdwae oc10OHXvACkS8GNvIN7f3UgJUw9fQKSWeui01qK+H/ZQB2J4jXPhk7pKkmcQpWKEJgshU3iVk2o uZPyND2MO62uwME5fySIrfERBRaQNbSZzuTE5jtoNaWeOComsbXAGG3TP02mQ1tM+EFZX4BpvMD QdKx4KYow10bHqdtfTn0ZZ4s68CSi6iL0hGvzG0i/gUiCYsBdvpJ7M9XgqrZMRbTmwpbMZV/WPS WAGF1D13GMMLmNEOX934DBmZWxl/95erkMsL5TxZnPWfKhMkDdxj1fC8WcdKFucsy1t8fnl4WPQ KiKvSONIvWAWiztY7771o9euaJ8LxrInMSqyzG/080wa+o7jqMI6kpeleCDhqTnZDpcaHeSuEms Dgi2LjtfY0ngbE6raXKn8GTHa1m6Ah4FKbNvgoeyA= X-Received: by 2002:a05:693c:6286:b0:2be:b2cf:cd34 with SMTP id 5a478bee46e88-2beb2cfda25mr2238322eec.18.1773546090983; Sat, 14 Mar 2026 20:41:30 -0700 (PDT) From: Lucas Amaral To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, agraf@csgraf.de, Lucas Amaral Subject: [PATCH v3 1/6] target/arm/emulate: add ISV=0 emulation library with load/store immediate Date: Sun, 15 Mar 2026 00:41:18 -0300 Message-ID: <20260315034123.41921-2-lucaaamaral@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260315034123.41921-1-lucaaamaral@gmail.com> References: <20260313021850.42379-1-lucaaamaral@gmail.com> <20260315034123.41921-1-lucaaamaral@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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=2607:f8b0:4864:20::132e; envelope-from=lucaaamaral@gmail.com; helo=mail-dy1-x132e.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, FSL_HELO_BARE_IP_2=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, 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 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-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773546211774154100 Add a shared emulation library for AArch64 load/store instructions that cause ISV=3D0 data aborts under hardware virtualization (HVF, WHPX). When the Instruction Syndrome Valid bit is clear, the hypervisor cannot determine the faulting instruction's target register or access size from the syndrome alone. This library fetches and decodes the instruction using a decodetree-generated decoder, then emulates it by accessing the vCPU's register file (CPUARMState) and memory (cpu_memory_rw_debug) directly. This patch establishes the framework and adds load/store single with immediate addressing =E2=80=94 the most common ISV=3D0 trigger. Subsequent patches add register-offset, pair, exclusive, and atomic instructions. Instruction coverage: - STR/LDR (GPR): unscaled, post-indexed, unprivileged, pre-indexed, unsigned offset =E2=80=94 all sizes (8/16/32/64-bit), sign/zero extensi= on - STR/LDR (SIMD/FP): same addressing modes, 8-128 bit elements - PRFM: prefetch treated as NOP - DC cache maintenance (SYS CRn=3DC7): NOP on MMIO This library uses its own a64-ldst.decode rather than sharing target/arm/tcg/a64.decode. TCG's trans_* functions are a compiler: they emit IR ops into a translation block for later execution. This library's trans_* functions are an interpreter: they execute directly against the vCPU register file and memory. The decodetree-generated dispatcher calls trans_* by name, so both cannot coexist in the same translation unit. Decode patterns are kept consistent with TCG's where possible. Signed-off-by: Lucas Amaral --- target/arm/emulate/a64-ldst.decode | 129 ++++++++++++++++ target/arm/emulate/arm_emulate.c | 226 +++++++++++++++++++++++++++++ target/arm/emulate/arm_emulate.h | 30 ++++ target/arm/emulate/meson.build | 6 + target/arm/meson.build | 1 + 5 files changed, 392 insertions(+) create mode 100644 target/arm/emulate/a64-ldst.decode create mode 100644 target/arm/emulate/arm_emulate.c create mode 100644 target/arm/emulate/arm_emulate.h create mode 100644 target/arm/emulate/meson.build diff --git a/target/arm/emulate/a64-ldst.decode b/target/arm/emulate/a64-ld= st.decode new file mode 100644 index 00000000..c887dcba --- /dev/null +++ b/target/arm/emulate/a64-ldst.decode @@ -0,0 +1,129 @@ +# AArch64 load/store instruction patterns for ISV=3D0 emulation +# +# Copyright (c) 2026 Lucas Amaral +# +# SPDX-License-Identifier: GPL-2.0-or-later + +### Argument sets + +# Load/store immediate (unscaled, pre/post-index, unprivileged, unsigned o= ffset) +# 'u' flag: 0 =3D 9-bit signed immediate (byte offset), 1 =3D 12-bit unsig= ned (needs << sz) +&ldst_imm rt rn imm sz sign w p unpriv ext u + +### Format templates + +# Load/store immediate (9-bit signed) +@ldst_imm .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm u=3D0 unp= riv=3D0 p=3D0 w=3D0 +@ldst_imm_pre .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm u=3D0 unp= riv=3D0 p=3D0 w=3D1 +@ldst_imm_post .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm u=3D0 unp= riv=3D0 p=3D1 w=3D1 +@ldst_imm_user .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm u=3D0 unp= riv=3D1 p=3D0 w=3D0 + +# Load/store unsigned offset (12-bit, handler scales by << sz) +@ldst_uimm .. ... . .. .. imm:12 rn:5 rt:5 &ldst_imm u=3D1 unp= riv=3D0 p=3D0 w=3D0 + +### Load/store register =E2=80=94 unscaled immediate (LDUR/STUR) + +# GPR +STR_i sz:2 111 0 00 00 0 ......... 00 ..... ..... @ldst_imm s= ign=3D0 ext=3D0 +LDR_i 00 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm s= ign=3D0 ext=3D1 sz=3D0 +LDR_i 01 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm s= ign=3D0 ext=3D1 sz=3D1 +LDR_i 10 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm s= ign=3D0 ext=3D1 sz=3D2 +LDR_i 11 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm s= ign=3D0 ext=3D0 sz=3D3 +LDR_i 00 111 0 00 10 0 ......... 00 ..... ..... @ldst_imm s= ign=3D1 ext=3D0 sz=3D0 +LDR_i 01 111 0 00 10 0 ......... 00 ..... ..... @ldst_imm s= ign=3D1 ext=3D0 sz=3D1 +LDR_i 10 111 0 00 10 0 ......... 00 ..... ..... @ldst_imm s= ign=3D1 ext=3D0 sz=3D2 +LDR_i 00 111 0 00 11 0 ......... 00 ..... ..... @ldst_imm s= ign=3D1 ext=3D1 sz=3D0 +LDR_i 01 111 0 00 11 0 ......... 00 ..... ..... @ldst_imm s= ign=3D1 ext=3D1 sz=3D1 + +# SIMD/FP +STR_v_i sz:2 111 1 00 00 0 ......... 00 ..... ..... @ldst_imm s= ign=3D0 ext=3D0 +STR_v_i 00 111 1 00 10 0 ......... 00 ..... ..... @ldst_imm s= ign=3D0 ext=3D0 sz=3D4 +LDR_v_i sz:2 111 1 00 01 0 ......... 00 ..... ..... @ldst_imm s= ign=3D0 ext=3D0 +LDR_v_i 00 111 1 00 11 0 ......... 00 ..... ..... @ldst_imm s= ign=3D0 ext=3D0 sz=3D4 + +### Load/store register =E2=80=94 post-indexed + +# GPR +STR_i sz:2 111 0 00 00 0 ......... 01 ..... ..... @ldst_imm_p= ost sign=3D0 ext=3D0 +LDR_i 00 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_p= ost sign=3D0 ext=3D1 sz=3D0 +LDR_i 01 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_p= ost sign=3D0 ext=3D1 sz=3D1 +LDR_i 10 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_p= ost sign=3D0 ext=3D1 sz=3D2 +LDR_i 11 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_p= ost sign=3D0 ext=3D0 sz=3D3 +LDR_i 00 111 0 00 10 0 ......... 01 ..... ..... @ldst_imm_p= ost sign=3D1 ext=3D0 sz=3D0 +LDR_i 01 111 0 00 10 0 ......... 01 ..... ..... @ldst_imm_p= ost sign=3D1 ext=3D0 sz=3D1 +LDR_i 10 111 0 00 10 0 ......... 01 ..... ..... @ldst_imm_p= ost sign=3D1 ext=3D0 sz=3D2 +LDR_i 00 111 0 00 11 0 ......... 01 ..... ..... @ldst_imm_p= ost sign=3D1 ext=3D1 sz=3D0 +LDR_i 01 111 0 00 11 0 ......... 01 ..... ..... @ldst_imm_p= ost sign=3D1 ext=3D1 sz=3D1 + +# SIMD/FP +STR_v_i sz:2 111 1 00 00 0 ......... 01 ..... ..... @ldst_imm_p= ost sign=3D0 ext=3D0 +STR_v_i 00 111 1 00 10 0 ......... 01 ..... ..... @ldst_imm_p= ost sign=3D0 ext=3D0 sz=3D4 +LDR_v_i sz:2 111 1 00 01 0 ......... 01 ..... ..... @ldst_imm_p= ost sign=3D0 ext=3D0 +LDR_v_i 00 111 1 00 11 0 ......... 01 ..... ..... @ldst_imm_p= ost sign=3D0 ext=3D0 sz=3D4 + +### Load/store register =E2=80=94 unprivileged + +# GPR only (no SIMD/FP unprivileged forms) +STR_i sz:2 111 0 00 00 0 ......... 10 ..... ..... @ldst_imm_u= ser sign=3D0 ext=3D0 +LDR_i 00 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_u= ser sign=3D0 ext=3D1 sz=3D0 +LDR_i 01 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_u= ser sign=3D0 ext=3D1 sz=3D1 +LDR_i 10 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_u= ser sign=3D0 ext=3D1 sz=3D2 +LDR_i 11 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_u= ser sign=3D0 ext=3D0 sz=3D3 +LDR_i 00 111 0 00 10 0 ......... 10 ..... ..... @ldst_imm_u= ser sign=3D1 ext=3D0 sz=3D0 +LDR_i 01 111 0 00 10 0 ......... 10 ..... ..... @ldst_imm_u= ser sign=3D1 ext=3D0 sz=3D1 +LDR_i 10 111 0 00 10 0 ......... 10 ..... ..... @ldst_imm_u= ser sign=3D1 ext=3D0 sz=3D2 +LDR_i 00 111 0 00 11 0 ......... 10 ..... ..... @ldst_imm_u= ser sign=3D1 ext=3D1 sz=3D0 +LDR_i 01 111 0 00 11 0 ......... 10 ..... ..... @ldst_imm_u= ser sign=3D1 ext=3D1 sz=3D1 + +### Load/store register =E2=80=94 pre-indexed + +# GPR +STR_i sz:2 111 0 00 00 0 ......... 11 ..... ..... @ldst_imm_p= re sign=3D0 ext=3D0 +LDR_i 00 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_p= re sign=3D0 ext=3D1 sz=3D0 +LDR_i 01 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_p= re sign=3D0 ext=3D1 sz=3D1 +LDR_i 10 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_p= re sign=3D0 ext=3D1 sz=3D2 +LDR_i 11 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_p= re sign=3D0 ext=3D0 sz=3D3 +LDR_i 00 111 0 00 10 0 ......... 11 ..... ..... @ldst_imm_p= re sign=3D1 ext=3D0 sz=3D0 +LDR_i 01 111 0 00 10 0 ......... 11 ..... ..... @ldst_imm_p= re sign=3D1 ext=3D0 sz=3D1 +LDR_i 10 111 0 00 10 0 ......... 11 ..... ..... @ldst_imm_p= re sign=3D1 ext=3D0 sz=3D2 +LDR_i 00 111 0 00 11 0 ......... 11 ..... ..... @ldst_imm_p= re sign=3D1 ext=3D1 sz=3D0 +LDR_i 01 111 0 00 11 0 ......... 11 ..... ..... @ldst_imm_p= re sign=3D1 ext=3D1 sz=3D1 + +# SIMD/FP +STR_v_i sz:2 111 1 00 00 0 ......... 11 ..... ..... @ldst_imm_p= re sign=3D0 ext=3D0 +STR_v_i 00 111 1 00 10 0 ......... 11 ..... ..... @ldst_imm_p= re sign=3D0 ext=3D0 sz=3D4 +LDR_v_i sz:2 111 1 00 01 0 ......... 11 ..... ..... @ldst_imm_p= re sign=3D0 ext=3D0 +LDR_v_i 00 111 1 00 11 0 ......... 11 ..... ..... @ldst_imm_p= re sign=3D0 ext=3D0 sz=3D4 + +### PRFM =E2=80=94 unscaled immediate: prefetch is a NOP + +NOP 11 111 0 00 10 0 --------- 00 ----- ----- + +### Load/store register =E2=80=94 unsigned offset + +# GPR +STR_i sz:2 111 0 01 00 ............ ..... ..... @ldst_uimm= sign=3D0 ext=3D0 +LDR_i 00 111 0 01 01 ............ ..... ..... @ldst_uimm= sign=3D0 ext=3D1 sz=3D0 +LDR_i 01 111 0 01 01 ............ ..... ..... @ldst_uimm= sign=3D0 ext=3D1 sz=3D1 +LDR_i 10 111 0 01 01 ............ ..... ..... @ldst_uimm= sign=3D0 ext=3D1 sz=3D2 +LDR_i 11 111 0 01 01 ............ ..... ..... @ldst_uimm= sign=3D0 ext=3D0 sz=3D3 +LDR_i 00 111 0 01 10 ............ ..... ..... @ldst_uimm= sign=3D1 ext=3D0 sz=3D0 +LDR_i 01 111 0 01 10 ............ ..... ..... @ldst_uimm= sign=3D1 ext=3D0 sz=3D1 +LDR_i 10 111 0 01 10 ............ ..... ..... @ldst_uimm= sign=3D1 ext=3D0 sz=3D2 +LDR_i 00 111 0 01 11 ............ ..... ..... @ldst_uimm= sign=3D1 ext=3D1 sz=3D0 +LDR_i 01 111 0 01 11 ............ ..... ..... @ldst_uimm= sign=3D1 ext=3D1 sz=3D1 + +# PRFM =E2=80=94 unsigned offset +NOP 11 111 0 01 10 ------------ ----- ----- + +# SIMD/FP +STR_v_i sz:2 111 1 01 00 ............ ..... ..... @ldst_uimm= sign=3D0 ext=3D0 +STR_v_i 00 111 1 01 10 ............ ..... ..... @ldst_uimm= sign=3D0 ext=3D0 sz=3D4 +LDR_v_i sz:2 111 1 01 01 ............ ..... ..... @ldst_uimm= sign=3D0 ext=3D0 +LDR_v_i 00 111 1 01 11 ............ ..... ..... @ldst_uimm= sign=3D0 ext=3D0 sz=3D4 + +### System instructions =E2=80=94 DC cache maintenance + +# SYS with CRn=3DC7 covers all data cache operations (DC CIVAC, CVAC, etc.= ). +# On MMIO regions, cache maintenance is a harmless no-op. +NOP 1101 0101 0000 1 --- 0111 ---- --- ----- diff --git a/target/arm/emulate/arm_emulate.c b/target/arm/emulate/arm_emul= ate.c new file mode 100644 index 00000000..2b4e2a9e --- /dev/null +++ b/target/arm/emulate/arm_emulate.c @@ -0,0 +1,226 @@ +/* + * AArch64 instruction emulation for ISV=3D0 data aborts + * + * Copyright (c) 2026 Lucas Amaral + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "arm_emulate.h" +#include "target/arm/cpu.h" +#include "exec/cpu-common.h" + +/* Named "DisasContext" as required by the decodetree code generator */ +typedef struct { + CPUState *cpu; + CPUARMState *env; + ArmEmulResult result; +} DisasContext; + +#include "decode-a64-ldst.c.inc" + +/* GPR data access (Rt, Rs, Rt2) -- register 31 =3D XZR */ + +static uint64_t gpr_read(DisasContext *ctx, int reg) +{ + if (reg =3D=3D 31) { + return 0; /* XZR */ + } + return ctx->env->xregs[reg]; +} + +static void gpr_write(DisasContext *ctx, int reg, uint64_t val) +{ + if (reg =3D=3D 31) { + return; /* XZR -- discard */ + } + ctx->env->xregs[reg] =3D val; + ctx->cpu->vcpu_dirty =3D true; +} + +/* Base register access (Rn) -- register 31 =3D SP */ + +static uint64_t base_read(DisasContext *ctx, int rn) +{ + return ctx->env->xregs[rn]; +} + +static void base_write(DisasContext *ctx, int rn, uint64_t val) +{ + ctx->env->xregs[rn] =3D val; + ctx->cpu->vcpu_dirty =3D true; +} + +/* SIMD/FP register access */ + +static void fpreg_read(DisasContext *ctx, int reg, void *buf, int size) +{ + memcpy(buf, &ctx->env->vfp.zregs[reg], size); +} + +static void fpreg_write(DisasContext *ctx, int reg, const void *buf, int s= ize) +{ + memset(&ctx->env->vfp.zregs[reg], 0, sizeof(ctx->env->vfp.zregs[reg])); + memcpy(&ctx->env->vfp.zregs[reg], buf, size); + ctx->cpu->vcpu_dirty =3D true; +} + +/* Memory access wrappers */ + +static int mem_read(DisasContext *ctx, uint64_t va, void *buf, int size) +{ + int ret =3D cpu_memory_rw_debug(ctx->cpu, va, buf, size, false); + if (ret !=3D 0) { + ctx->result =3D ARM_EMUL_ERR_MEM; + } + return ret; +} + +static int mem_write(DisasContext *ctx, uint64_t va, const void *buf, int = size) +{ + int ret =3D cpu_memory_rw_debug(ctx->cpu, va, (void *)buf, size, true); + if (ret !=3D 0) { + ctx->result =3D ARM_EMUL_ERR_MEM; + } + return ret; +} + +/* Sign/zero extension helpers */ + +static uint64_t sign_extend(uint64_t val, int from_bits) +{ + int shift =3D 64 - from_bits; + return (int64_t)(val << shift) >> shift; +} + +/* Apply sign/zero extension */ +static uint64_t load_extend(uint64_t val, int sz, int sign, int ext) +{ + int data_bits =3D 8 << sz; + + if (sign) { + val =3D sign_extend(val, data_bits); + if (ext) { + /* Sign-extend to 32 bits (W register) */ + val &=3D 0xFFFFFFFF; + } + } else if (ext) { + /* Zero-extend to 32 bits (W register) */ + val &=3D 0xFFFFFFFF; + } + return val; +} + +/* Load/store single -- immediate (GPR) (DDI 0487 C3.3.8 -- C3.3.13) */ + +static bool trans_STR_i(DisasContext *ctx, arg_ldst_imm *a) +{ + int esize =3D (a->sz <=3D 3) ? (1 << a->sz) : 16; + int64_t offset =3D a->u ? ((int64_t)(uint64_t)a->imm << a->sz) + : (int64_t)a->imm; + uint64_t base =3D base_read(ctx, a->rn); + uint64_t va =3D a->p ? base : base + offset; + + uint64_t val =3D gpr_read(ctx, a->rt); + if (mem_write(ctx, va, &val, esize) !=3D 0) { + return true; + } + + if (a->w) { + base_write(ctx, a->rn, base + offset); + } + return true; +} + +static bool trans_LDR_i(DisasContext *ctx, arg_ldst_imm *a) +{ + int esize =3D (a->sz <=3D 3) ? (1 << a->sz) : 16; + int64_t offset =3D a->u ? ((int64_t)(uint64_t)a->imm << a->sz) + : (int64_t)a->imm; + uint64_t base =3D base_read(ctx, a->rn); + uint64_t va =3D a->p ? base : base + offset; + uint64_t val =3D 0; + + if (mem_read(ctx, va, &val, esize) !=3D 0) { + return true; + } + + val =3D load_extend(val, a->sz, a->sign, a->ext); + gpr_write(ctx, a->rt, val); + + if (a->w) { + base_write(ctx, a->rn, base + offset); + } + return true; +} + +/* + * Load/store single -- immediate (SIMD/FP) + * STR_v_i / LDR_v_i (DDI 0487 C3.3.10) + */ + +static bool trans_STR_v_i(DisasContext *ctx, arg_ldst_imm *a) +{ + int esize =3D (a->sz <=3D 3) ? (1 << a->sz) : 16; + int64_t offset =3D a->u ? ((int64_t)(uint64_t)a->imm << a->sz) + : (int64_t)a->imm; + uint64_t base =3D base_read(ctx, a->rn); + uint64_t va =3D a->p ? base : base + offset; + uint8_t buf[16]; + + fpreg_read(ctx, a->rt, buf, esize); + if (mem_write(ctx, va, buf, esize) !=3D 0) { + return true; + } + + if (a->w) { + base_write(ctx, a->rn, base + offset); + } + return true; +} + +static bool trans_LDR_v_i(DisasContext *ctx, arg_ldst_imm *a) +{ + int esize =3D (a->sz <=3D 3) ? (1 << a->sz) : 16; + int64_t offset =3D a->u ? ((int64_t)(uint64_t)a->imm << a->sz) + : (int64_t)a->imm; + uint64_t base =3D base_read(ctx, a->rn); + uint64_t va =3D a->p ? base : base + offset; + uint8_t buf[16]; + + if (mem_read(ctx, va, buf, esize) !=3D 0) { + return true; + } + + fpreg_write(ctx, a->rt, buf, esize); + + if (a->w) { + base_write(ctx, a->rn, base + offset); + } + return true; +} + +/* PRFM, DC cache maintenance -- treated as NOP */ +static bool trans_NOP(DisasContext *ctx, arg_NOP *a) +{ + (void)ctx; + (void)a; + return true; +} + +/* Entry point */ + +ArmEmulResult arm_emul_insn(CPUArchState *env, uint32_t insn) +{ + DisasContext ctx =3D { + .cpu =3D env_cpu(env), + .env =3D env, + .result =3D ARM_EMUL_OK, + }; + + if (!decode_a64_ldst(&ctx, insn)) { + return ARM_EMUL_UNHANDLED; + } + + return ctx.result; +} diff --git a/target/arm/emulate/arm_emulate.h b/target/arm/emulate/arm_emul= ate.h new file mode 100644 index 00000000..7fe29839 --- /dev/null +++ b/target/arm/emulate/arm_emulate.h @@ -0,0 +1,30 @@ +/* + * AArch64 instruction emulation library + * + * Copyright (c) 2026 Lucas Amaral + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef ARM_EMULATE_H +#define ARM_EMULATE_H + +#include "qemu/osdep.h" + +/** + * ArmEmulResult - return status from arm_emul_insn() + */ +typedef enum { + ARM_EMUL_OK, /* Instruction emulated successfully */ + ARM_EMUL_UNHANDLED, /* Instruction not recognized by decoder */ + ARM_EMUL_ERR_MEM, /* Memory access failed */ +} ArmEmulResult; + +/** + * arm_emul_insn - decode and emulate one AArch64 instruction + * + * Caller must synchronize CPU state and fetch @insn before calling. + */ +ArmEmulResult arm_emul_insn(CPUArchState *env, uint32_t insn); + +#endif /* ARM_EMULATE_H */ diff --git a/target/arm/emulate/meson.build b/target/arm/emulate/meson.build new file mode 100644 index 00000000..c0b38dd1 --- /dev/null +++ b/target/arm/emulate/meson.build @@ -0,0 +1,6 @@ +gen_a64_ldst =3D decodetree.process('a64-ldst.decode', + extra_args: ['--static-decode=3Ddecode_a64_ldst']) + +arm_common_system_ss.add(when: 'TARGET_AARCH64', if_true: [ + gen_a64_ldst, files('arm_emulate.c') +]) diff --git a/target/arm/meson.build b/target/arm/meson.build index 6e0e504a..a4b2291b 100644 --- a/target/arm/meson.build +++ b/target/arm/meson.build @@ -57,6 +57,7 @@ arm_common_system_ss.add(files( 'vfp_fpscr.c', )) =20 +subdir('emulate') subdir('hvf') subdir('whpx') =20 --=20 2.52.0 From nobody Tue Apr 7 07:34:15 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1773546186; cv=none; d=zohomail.com; s=zohoarc; b=T0YdvSt7Dq04wuCE8WyL4zVa/hwzgNv7WWrVoLZ2bmFY923CrblQcuaLPj1cqDUYOMWO030l2l0N+iBqggHl7lcMQCHnZ33l2LtUl3bQ8mlFPph4hjHzbEhZefQWKbPLJwHSNFrLrVnWORPy8PF2MCA5kgim5oFI0xJYGR1LViw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773546186; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=LbSg1MD18V9IGLdbKDVPJ9yDLz9GZTVkv2Dyy41T4fY=; b=RC0vEbJwnHoGkJSWdYK1B4N0CHmA0p95S0Yc9g7BNoLp/LWUIonKRfgSdAbI5z31Ut5+SSIgXf7pBnd2A9t8epXfgXbLY5KgxVpCsNqIitu+9tGDwNimBMfemuV3GsslMxFt2dZ7bzGZJDpFIP5DemoX9A1Fb8bVdrjnK8OoB9U= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773546186663543.6920420028704; Sat, 14 Mar 2026 20:43:06 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w1cMF-0004pj-8L; Sat, 14 Mar 2026 23:41:39 -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 1w1cMC-0004o8-Uy for qemu-devel@nongnu.org; Sat, 14 Mar 2026 23:41:36 -0400 Received: from mail-dy1-x1332.google.com ([2607:f8b0:4864:20::1332]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w1cMA-0003XX-Ra for qemu-devel@nongnu.org; Sat, 14 Mar 2026 23:41:36 -0400 Received: by mail-dy1-x1332.google.com with SMTP id 5a478bee46e88-2be27fa54feso4422098eec.0 for ; Sat, 14 Mar 2026 20:41:34 -0700 (PDT) Received: from 192.168.7.2 ([189.6.247.75]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2beab3eec8fsm8886424eec.13.2026.03.14.20.41.31 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 14 Mar 2026 20:41:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773546093; x=1774150893; 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=LbSg1MD18V9IGLdbKDVPJ9yDLz9GZTVkv2Dyy41T4fY=; b=ISgkRcfeb/U5I7D1R/PB6ieZlddDPdRjUuw80ZeJFJMNZkYwhMzy+X8Xknge8IYoQa jDh+w8CPrX5Yt5GX7c/kbq/sTLD+QC+TW6+AAdf/WFG22oQFyPNkoG9gar8ZU+68FzYE 45w0CkvIJQDpSIZiCemuAEgSuNk12yrPa07NazUPj6GhYaltejwflZZZY6UAMijtj/gf 1fyNPYH9UHsfNxXYiwuES+8FNRhfoPeF9+2BzSkQJbI9klOE6t3WwBGqPuyt+aLLh5TG 3q1HRiZnLoubAjr0xEGdDSVpPddUgJEPnVmm2NCEHYBE2okS5AC/arOT57e5xo8yfBSV T9iQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773546093; x=1774150893; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=LbSg1MD18V9IGLdbKDVPJ9yDLz9GZTVkv2Dyy41T4fY=; b=FE71vhSrqYUwRUXQhxF0hUvTWaD5rWsbuIArSg8RH3TDyPiCg1u6bu1drc6wzK+2N9 iL6YmeSbpQTuOiVt2EizjOLizgBfwIs+mDJkIsBZ1KyQMAl5oZiZTaSLS5M3+zL9Ls7c PRfAgeY4CSio18412qZcgS8MmFFQBQQAVzrLSI3tjvDdSSUqLbCmg/qmefNrMJazTR9G XZ/WIMj8iuv7uutaMya+TnfRfaSGsfB+ZUVNlWMm6XIc5zjFm8TKKn8bRjNVVK9wMHiy H4ghxSi7IVHGHr0nv03MM4mw3QvmM6+QVz/+fIQvhRWSL3HayIRmBOPYfQPKhLG/k2of USzw== X-Gm-Message-State: AOJu0YymZeE4WFyI65+lNcFTAeIwiW3UdYGZLtCuDO3Y1QS3nPKh0ElM ZLTEL2OmBVQREYy1X+dJQfcQIVbc3avI2XaSMA3eCzHxIGUPYmJt348eKGN/tYk+ X-Gm-Gg: ATEYQzxC8u25ATxGy9TL3qsQrHT8vWk+bsExeDD/pL9ztTVYEPA24Nf6BSLak46fSWt 4eDlOJx/SxrM2sbd7L+dHgsMU5Lv0s+K1YBOBTFmw6y6v1qzR3qswJ/vcT2mvXLgmxaOwbydGuD Sud/WbE26MQskBxDTBXH8/msJ5WeVGjBOETXjca09zpYQOrcPfImavYhXr/V7q8AWeGQaFK/fma uCB/w5Wk8/HmzwV5Qrlxz7RVLFqlOLXReGvB1/fgLbAkIhBNQhT1Sirz/L9CfWOqs6Ufa4LMhNw amCOaNwjieJEtWNZY8MxCh6Ym4YTQHqTx972SwapPWNTTo8iGVJKxjO90F5ZLYRR+5vA+uBLalp 3YUcJaAZ4wMTQ1gVrlzBj2FqVlRvj1FN9VG5cN5AqzJTvb2GXoIBbgGwECGqjfo/rMS0z1XMdFA JSIKK5gofyp+8PdIL5cXEzO3cuPvmOMP5b1S3IA0A= X-Received: by 2002:a05:7300:230b:b0:2be:1f58:32a6 with SMTP id 5a478bee46e88-2bea555a8aamr3584887eec.33.1773546093154; Sat, 14 Mar 2026 20:41:33 -0700 (PDT) From: Lucas Amaral To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, agraf@csgraf.de, Lucas Amaral Subject: [PATCH v3 2/6] target/arm/emulate: add load/store register offset Date: Sun, 15 Mar 2026 00:41:19 -0300 Message-ID: <20260315034123.41921-3-lucaaamaral@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260315034123.41921-1-lucaaamaral@gmail.com> References: <20260313021850.42379-1-lucaaamaral@gmail.com> <20260315034123.41921-1-lucaaamaral@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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=2607:f8b0:4864:20::1332; envelope-from=lucaaamaral@gmail.com; helo=mail-dy1-x1332.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, FSL_HELO_BARE_IP_2=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, 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 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-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773546188556158500 Add emulation for load/store register offset addressing mode (DDI 0487 C3.3.9). The offset register value is extended via UXTB/UXTH/UXTW/UXTX/SXTB/SXTH/SXTW/SXTX and optionally shifted by the element size. Instruction coverage: - STR/LDR (GPR): register offset with extend, all sizes - STR/LDR (SIMD/FP): register offset with extend, 8-128 bit - PRFM register offset: NOP Signed-off-by: Lucas Amaral --- target/arm/emulate/a64-ldst.decode | 29 ++++++++ target/arm/emulate/arm_emulate.c | 103 +++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) diff --git a/target/arm/emulate/a64-ldst.decode b/target/arm/emulate/a64-ld= st.decode index c887dcba..af6babe1 100644 --- a/target/arm/emulate/a64-ldst.decode +++ b/target/arm/emulate/a64-ldst.decode @@ -10,6 +10,9 @@ # 'u' flag: 0 =3D 9-bit signed immediate (byte offset), 1 =3D 12-bit unsig= ned (needs << sz) &ldst_imm rt rn imm sz sign w p unpriv ext u =20 +# Load/store register offset +&ldst rm rn rt sign ext sz opt s + ### Format templates =20 # Load/store immediate (9-bit signed) @@ -21,6 +24,9 @@ # Load/store unsigned offset (12-bit, handler scales by << sz) @ldst_uimm .. ... . .. .. imm:12 rn:5 rt:5 &ldst_imm u=3D1 unp= riv=3D0 p=3D0 w=3D0 =20 +# Load/store register offset +@ldst .. ... . .. .. . rm:5 opt:3 s:1 .. rn:5 rt:5 &ldst + ### Load/store register =E2=80=94 unscaled immediate (LDUR/STUR) =20 # GPR @@ -122,6 +128,29 @@ STR_v_i 00 111 1 01 10 ............ ..... ....= . @ldst_uimm sign=3D LDR_v_i sz:2 111 1 01 01 ............ ..... ..... @ldst_uimm= sign=3D0 ext=3D0 LDR_v_i 00 111 1 01 11 ............ ..... ..... @ldst_uimm= sign=3D0 ext=3D0 sz=3D4 =20 +### Load/store register =E2=80=94 register offset + +# GPR +STR sz:2 111 0 00 00 1 ..... ... . 10 ..... ..... @ldst sign= =3D0 ext=3D0 +LDR 00 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign= =3D0 ext=3D1 sz=3D0 +LDR 01 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign= =3D0 ext=3D1 sz=3D1 +LDR 10 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign= =3D0 ext=3D1 sz=3D2 +LDR 11 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign= =3D0 ext=3D0 sz=3D3 +LDR 00 111 0 00 10 1 ..... ... . 10 ..... ..... @ldst sign= =3D1 ext=3D0 sz=3D0 +LDR 01 111 0 00 10 1 ..... ... . 10 ..... ..... @ldst sign= =3D1 ext=3D0 sz=3D1 +LDR 10 111 0 00 10 1 ..... ... . 10 ..... ..... @ldst sign= =3D1 ext=3D0 sz=3D2 +LDR 00 111 0 00 11 1 ..... ... . 10 ..... ..... @ldst sign= =3D1 ext=3D1 sz=3D0 +LDR 01 111 0 00 11 1 ..... ... . 10 ..... ..... @ldst sign= =3D1 ext=3D1 sz=3D1 + +# PRFM =E2=80=94 register offset +NOP 11 111 0 00 10 1 ----- -1- - 10 ----- ----- + +# SIMD/FP +STR_v sz:2 111 1 00 00 1 ..... ... . 10 ..... ..... @ldst sign= =3D0 ext=3D0 +STR_v 00 111 1 00 10 1 ..... ... . 10 ..... ..... @ldst sign= =3D0 ext=3D0 sz=3D4 +LDR_v sz:2 111 1 00 01 1 ..... ... . 10 ..... ..... @ldst sign= =3D0 ext=3D0 +LDR_v 00 111 1 00 11 1 ..... ... . 10 ..... ..... @ldst sign= =3D0 ext=3D0 sz=3D4 + ### System instructions =E2=80=94 DC cache maintenance =20 # SYS with CRn=3DC7 covers all data cache operations (DC CIVAC, CVAC, etc.= ). diff --git a/target/arm/emulate/arm_emulate.c b/target/arm/emulate/arm_emul= ate.c index 2b4e2a9e..0e77cf33 100644 --- a/target/arm/emulate/arm_emulate.c +++ b/target/arm/emulate/arm_emulate.c @@ -200,6 +200,109 @@ static bool trans_LDR_v_i(DisasContext *ctx, arg_ldst= _imm *a) return true; } =20 +/* Register offset extension (DDI 0487 C6.2.131) */ + +static uint64_t extend_reg(uint64_t val, int option, int shift) +{ + switch (option) { + case 0: /* UXTB */ + val =3D (uint8_t)val; + break; + case 1: /* UXTH */ + val =3D (uint16_t)val; + break; + case 2: /* UXTW */ + val =3D (uint32_t)val; + break; + case 3: /* UXTX / LSL */ + break; + case 4: /* SXTB */ + val =3D (int64_t)(int8_t)val; + break; + case 5: /* SXTH */ + val =3D (int64_t)(int16_t)val; + break; + case 6: /* SXTW */ + val =3D (int64_t)(int32_t)val; + break; + case 7: /* SXTX */ + break; + } + return val << shift; +} + +/* + * Load/store single -- register offset (GPR) + * STR / LDR (DDI 0487 C3.3.9) + */ + +static bool trans_STR(DisasContext *ctx, arg_ldst *a) +{ + int esize =3D (a->sz <=3D 3) ? (1 << a->sz) : 16; + int shift =3D a->s ? a->sz : 0; + uint64_t rm_val =3D gpr_read(ctx, a->rm); + uint64_t offset =3D extend_reg(rm_val, a->opt, shift); + uint64_t va =3D base_read(ctx, a->rn) + offset; + + uint64_t val =3D gpr_read(ctx, a->rt); + mem_write(ctx, va, &val, esize); + return true; +} + +static bool trans_LDR(DisasContext *ctx, arg_ldst *a) +{ + int esize =3D (a->sz <=3D 3) ? (1 << a->sz) : 16; + int shift =3D a->s ? a->sz : 0; + uint64_t rm_val =3D gpr_read(ctx, a->rm); + uint64_t offset =3D extend_reg(rm_val, a->opt, shift); + uint64_t va =3D base_read(ctx, a->rn) + offset; + uint64_t val =3D 0; + + if (mem_read(ctx, va, &val, esize) !=3D 0) { + return true; + } + + val =3D load_extend(val, a->sz, a->sign, a->ext); + gpr_write(ctx, a->rt, val); + return true; +} + +/* + * Load/store single -- register offset (SIMD/FP) + * STR_v / LDR_v (DDI 0487 C3.3.10) + */ + +static bool trans_STR_v(DisasContext *ctx, arg_ldst *a) +{ + int esize =3D (a->sz <=3D 3) ? (1 << a->sz) : 16; + int shift =3D a->s ? a->sz : 0; + uint64_t rm_val =3D gpr_read(ctx, a->rm); + uint64_t offset =3D extend_reg(rm_val, a->opt, shift); + uint64_t va =3D base_read(ctx, a->rn) + offset; + uint8_t buf[16]; + + fpreg_read(ctx, a->rt, buf, esize); + mem_write(ctx, va, buf, esize); + return true; +} + +static bool trans_LDR_v(DisasContext *ctx, arg_ldst *a) +{ + int esize =3D (a->sz <=3D 3) ? (1 << a->sz) : 16; + int shift =3D a->s ? a->sz : 0; + uint64_t rm_val =3D gpr_read(ctx, a->rm); + uint64_t offset =3D extend_reg(rm_val, a->opt, shift); + uint64_t va =3D base_read(ctx, a->rn) + offset; + uint8_t buf[16]; + + if (mem_read(ctx, va, buf, esize) !=3D 0) { + return true; + } + + fpreg_write(ctx, a->rt, buf, esize); + return true; +} + /* PRFM, DC cache maintenance -- treated as NOP */ static bool trans_NOP(DisasContext *ctx, arg_NOP *a) { --=20 2.52.0 From nobody Tue Apr 7 07:34:15 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1773546176; cv=none; d=zohomail.com; s=zohoarc; b=hcq0Y+11fQJSVbMldftkt1eNKQQCBMdhxBFscHsbrX/+pX5h4tWjeKJCWX5ZFZQ99RxqNJMGEq13ZLkUW39es8e9if+lVZagYPGgzzHvsHRJlW6jP75uTEQRnT7bMG+G/Re9pfQZnYATYXIn8SnjUso9xLYhpfuw7XB9L074CxI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773546176; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=YiOMf28ORrB2Me6DhKc96H6bxpOo6A6fc0FUbQxuhYQ=; b=bAWvp7mOCZSz1yrOajjvg08nDxJ4mYsk+Eocmu2ECAMERFTdUL1a06Au3/JstIWHU6Pi14Zfyr3NNsr8ZEgsXpvwu5qRET5OwGtUW5fQKi/r6Z2Jww1WrLN/dCg+tGn78RVRAsNxFTupzk6yV9nj9JLhIAVtP/Cpnubc+FdeAmA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773546176083373.4758178147772; Sat, 14 Mar 2026 20:42:56 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w1cMF-0004po-N4; Sat, 14 Mar 2026 23:41:39 -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 1w1cME-0004pU-Qk for qemu-devel@nongnu.org; Sat, 14 Mar 2026 23:41:38 -0400 Received: from mail-dy1-x132e.google.com ([2607:f8b0:4864:20::132e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w1cMC-0003am-Un for qemu-devel@nongnu.org; Sat, 14 Mar 2026 23:41:38 -0400 Received: by mail-dy1-x132e.google.com with SMTP id 5a478bee46e88-2bea8220c38so1541487eec.1 for ; Sat, 14 Mar 2026 20:41:36 -0700 (PDT) Received: from 192.168.7.2 ([189.6.247.75]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2beab3eec8fsm8886424eec.13.2026.03.14.20.41.33 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 14 Mar 2026 20:41:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773546095; x=1774150895; 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=YiOMf28ORrB2Me6DhKc96H6bxpOo6A6fc0FUbQxuhYQ=; b=K1ski8BufnwHXxX1l2jrDQhu3SAz88+ClpN/zhcU5ijOILMD53wgYxl6cQ2U0xfQ37 9iPKY1eRhxj98nDHtMICkOI+0alruuBUY1rfjQWDxq2QLkIcvMmAamgL5HvsU2nLKDcU VR9fnbnuGvZn0YXV9v0qLlWORRefhFv14gYng7XAu6CtneZvVK3ABqQ3m+M8rN8BuZpR EauITPr2+pFzHNB0swkiekeNerY14ek0KpG4gVPh963iaQ5n+q92Ggmpdx0eCUa2RmbH vCjmX8+JfgPBbOteAzG12PpSx2E+/bPErQvB6OoI3C5AX4Yu3VpWyTEbqGGYhnTElUOQ SHkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773546095; x=1774150895; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=YiOMf28ORrB2Me6DhKc96H6bxpOo6A6fc0FUbQxuhYQ=; b=IqA4nLL7TM2bPEzXYVX1CR9UZgoWrHci8b2qfoc3UKcJVsLM2DDKFupaEVt7egfd7h sfjp2KHnjQTHRnOlMLf1wfYdiB94G3zx+bRhSKexR2XBlLJ84Lgt89y9dnzKicUGDg75 uIBisVZ3lxuN9+DjDpiO4BJZadqnxk7TjbGRWM0o1JTSVo4vqOX7E7b2ElrkJF0KmCH9 vgktGUpU4d+bPHmu0Mq7hBLxX91EIYx/mKXpeRlUi5zIK0bGUKxQfn+qnRBveG0r9tNT MfXWXMcHxH7FN24FJlKuzFeIWvpNy0T6Rk3JWqcAOc5VfQh9FWJaicfahuYJw+TVUKMG Ijjw== X-Gm-Message-State: AOJu0YzGl+FH6KJ6bhYe+39211VYloZ5FuDbaLgNOpgP7zTH4TYESlbs otAKqsBeHbkMKPYZL3cit/yaGehVqxCGfBndd0inr4zj1dPnf9r4k5figVSauoHO X-Gm-Gg: ATEYQzzshWCSQa7/dvrFA0JbuSaPIWR5/G+7tpPiaLe9wmUOCP2WVQJ6TSd2DMXzWHj 01YEXM59vpxnfnGtZCNsnPNoCWnwLcupBEMhbR/KZdnZwCzUiPp2F7yczd1B89Ci961R0mdvnN5 5YgczVxlyDjioejHrYdvWmAAddWweFL9yfhvQy+zykLsNuNQIrX9ME+dyKGHnCC06bLI5lgg14m DobErvju2RTPqBmKP/QWvcu7nb/agu2UK4gp/n6ZFTt2877RYiB7tFa+4l7mNVjk8xYMzDGT397 DU+csZXfxqd/MvYNdrt+HLMdmwByFc8n2MBryLKjnS02no6ZmHN7U56LeGa5EWZBSZ6nIwC1Quo aeSnvhEfy+KPtJH8gUAi589oLWwl21wzeuXV8jQtFczLiCJymAYOrrcdAYxrlLEg6fxur+cKWBc YLwdIU27XyIMf/O9ibXsGYJFySneiUgaruEE2VCxc= X-Received: by 2002:a05:7300:e208:b0:2be:a440:7550 with SMTP id 5a478bee46e88-2bea55edf88mr4372653eec.28.1773546095319; Sat, 14 Mar 2026 20:41:35 -0700 (PDT) From: Lucas Amaral To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, agraf@csgraf.de, Lucas Amaral Subject: [PATCH v3 3/6] target/arm/emulate: add load/store pair Date: Sun, 15 Mar 2026 00:41:20 -0300 Message-ID: <20260315034123.41921-4-lucaaamaral@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260315034123.41921-1-lucaaamaral@gmail.com> References: <20260313021850.42379-1-lucaaamaral@gmail.com> <20260315034123.41921-1-lucaaamaral@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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=2607:f8b0:4864:20::132e; envelope-from=lucaaamaral@gmail.com; helo=mail-dy1-x132e.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, FSL_HELO_BARE_IP_2=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, 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 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-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773546176978158500 Add emulation for load/store pair instructions (DDI 0487 C3.3.14 -- C3.3.16). All addressing modes are covered: non-temporal (STNP/LDNP), post-indexed, signed offset, and pre-indexed. Instruction coverage: - STP/LDP (GPR): 32/64-bit pairs, all addressing modes - STP/LDP (SIMD/FP): 32/64/128-bit pairs, all addressing modes - LDPSW: sign-extending 32-bit pair load - STGP: store allocation tag pair (tag operation is NOP for MMIO) Signed-off-by: Lucas Amaral --- target/arm/emulate/a64-ldst.decode | 68 ++++++++++++++++++ target/arm/emulate/arm_emulate.c | 111 +++++++++++++++++++++++++++++ 2 files changed, 179 insertions(+) diff --git a/target/arm/emulate/a64-ldst.decode b/target/arm/emulate/a64-ld= st.decode index af6babe1..f3de3f86 100644 --- a/target/arm/emulate/a64-ldst.decode +++ b/target/arm/emulate/a64-ldst.decode @@ -10,6 +10,9 @@ # 'u' flag: 0 =3D 9-bit signed immediate (byte offset), 1 =3D 12-bit unsig= ned (needs << sz) &ldst_imm rt rn imm sz sign w p unpriv ext u =20 +# Load/store pair (GPR and SIMD/FP) +&ldstpair rt2 rt rn imm sz sign w p + # Load/store register offset &ldst rm rn rt sign ext sz opt s =20 @@ -24,6 +27,9 @@ # Load/store unsigned offset (12-bit, handler scales by << sz) @ldst_uimm .. ... . .. .. imm:12 rn:5 rt:5 &ldst_imm u=3D1 unp= riv=3D0 p=3D0 w=3D0 =20 +# Load/store pair: imm7 is signed, scaled by element size in handler +@ldstpair .. ... . ... . imm:s7 rt2:5 rn:5 rt:5 &ldstpair + # Load/store register offset @ldst .. ... . .. .. . rm:5 opt:3 s:1 .. rn:5 rt:5 &ldst =20 @@ -128,6 +134,68 @@ STR_v_i 00 111 1 01 10 ............ ..... ....= . @ldst_uimm sign=3D LDR_v_i sz:2 111 1 01 01 ............ ..... ..... @ldst_uimm= sign=3D0 ext=3D0 LDR_v_i 00 111 1 01 11 ............ ..... ..... @ldst_uimm= sign=3D0 ext=3D0 sz=3D4 =20 +### Load/store pair =E2=80=94 non-temporal (STNP/LDNP) + +# STNP/LDNP: offset only, no writeback. Non-temporal hint ignored. +STP 00 101 0 000 0 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D0 w=3D0 +LDP 00 101 0 000 1 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D0 w=3D0 +STP 10 101 0 000 0 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D0 w=3D0 +LDP 10 101 0 000 1 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D0 w=3D0 +STP_v 00 101 1 000 0 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D0 w=3D0 +LDP_v 00 101 1 000 1 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D0 w=3D0 +STP_v 01 101 1 000 0 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D0 w=3D0 +LDP_v 01 101 1 000 1 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D0 w=3D0 +STP_v 10 101 1 000 0 ....... ..... ..... ..... @ldstpair = sz=3D4 sign=3D0 p=3D0 w=3D0 +LDP_v 10 101 1 000 1 ....... ..... ..... ..... @ldstpair = sz=3D4 sign=3D0 p=3D0 w=3D0 + +### Load/store pair =E2=80=94 post-indexed + +STP 00 101 0 001 0 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D1 w=3D1 +LDP 00 101 0 001 1 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D1 w=3D1 +LDP 01 101 0 001 1 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D1 p=3D1 w=3D1 +STP 10 101 0 001 0 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D1 w=3D1 +LDP 10 101 0 001 1 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D1 w=3D1 +STP_v 00 101 1 001 0 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D1 w=3D1 +LDP_v 00 101 1 001 1 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D1 w=3D1 +STP_v 01 101 1 001 0 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D1 w=3D1 +LDP_v 01 101 1 001 1 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D1 w=3D1 +STP_v 10 101 1 001 0 ....... ..... ..... ..... @ldstpair = sz=3D4 sign=3D0 p=3D1 w=3D1 +LDP_v 10 101 1 001 1 ....... ..... ..... ..... @ldstpair = sz=3D4 sign=3D0 p=3D1 w=3D1 + +### Load/store pair =E2=80=94 signed offset + +STP 00 101 0 010 0 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D0 w=3D0 +LDP 00 101 0 010 1 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D0 w=3D0 +LDP 01 101 0 010 1 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D1 p=3D0 w=3D0 +STP 10 101 0 010 0 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D0 w=3D0 +LDP 10 101 0 010 1 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D0 w=3D0 +STP_v 00 101 1 010 0 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D0 w=3D0 +LDP_v 00 101 1 010 1 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D0 w=3D0 +STP_v 01 101 1 010 0 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D0 w=3D0 +LDP_v 01 101 1 010 1 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D0 w=3D0 +STP_v 10 101 1 010 0 ....... ..... ..... ..... @ldstpair = sz=3D4 sign=3D0 p=3D0 w=3D0 +LDP_v 10 101 1 010 1 ....... ..... ..... ..... @ldstpair = sz=3D4 sign=3D0 p=3D0 w=3D0 + +### Load/store pair =E2=80=94 pre-indexed + +STP 00 101 0 011 0 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D0 w=3D1 +LDP 00 101 0 011 1 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D0 w=3D1 +LDP 01 101 0 011 1 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D1 p=3D0 w=3D1 +STP 10 101 0 011 0 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D0 w=3D1 +LDP 10 101 0 011 1 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D0 w=3D1 +STP_v 00 101 1 011 0 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D0 w=3D1 +LDP_v 00 101 1 011 1 ....... ..... ..... ..... @ldstpair = sz=3D2 sign=3D0 p=3D0 w=3D1 +STP_v 01 101 1 011 0 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D0 w=3D1 +LDP_v 01 101 1 011 1 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D0 w=3D1 +STP_v 10 101 1 011 0 ....... ..... ..... ..... @ldstpair = sz=3D4 sign=3D0 p=3D0 w=3D1 +LDP_v 10 101 1 011 1 ....... ..... ..... ..... @ldstpair = sz=3D4 sign=3D0 p=3D0 w=3D1 + +### Load/store pair =E2=80=94 STGP (store allocation tag + pair) + +STGP 01 101 0 001 0 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D1 w=3D1 +STGP 01 101 0 010 0 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D0 w=3D0 +STGP 01 101 0 011 0 ....... ..... ..... ..... @ldstpair = sz=3D3 sign=3D0 p=3D0 w=3D1 + ### Load/store register =E2=80=94 register offset =20 # GPR diff --git a/target/arm/emulate/arm_emulate.c b/target/arm/emulate/arm_emul= ate.c index 0e77cf33..a7c62b44 100644 --- a/target/arm/emulate/arm_emulate.c +++ b/target/arm/emulate/arm_emulate.c @@ -111,6 +111,117 @@ static uint64_t load_extend(uint64_t val, int sz, int= sign, int ext) return val; } =20 +/* + * Load/store pair: STP, LDP, STNP, LDNP, STGP, LDPSW + * (DDI 0487 C3.3.14 -- C3.3.16) + */ + +static bool trans_STP(DisasContext *ctx, arg_ldstpair *a) +{ + int esize =3D 1 << a->sz; /* 4 or 8 bytes */ + int64_t offset =3D (int64_t)a->imm << a->sz; + uint64_t base =3D base_read(ctx, a->rn); + uint64_t va =3D a->p ? base : base + offset; /* post-index: unmodified= base */ + uint8_t buf[16]; /* max 2 x 8 bytes */ + + uint64_t v1 =3D gpr_read(ctx, a->rt); + uint64_t v2 =3D gpr_read(ctx, a->rt2); + memcpy(buf, &v1, esize); + memcpy(buf + esize, &v2, esize); + + if (mem_write(ctx, va, buf, 2 * esize) !=3D 0) { + return true; + } + + if (a->w) { + base_write(ctx, a->rn, base + offset); + } + return true; +} + +static bool trans_LDP(DisasContext *ctx, arg_ldstpair *a) +{ + int esize =3D 1 << a->sz; + int64_t offset =3D (int64_t)a->imm << a->sz; + uint64_t base =3D base_read(ctx, a->rn); + uint64_t va =3D a->p ? base : base + offset; + uint8_t buf[16]; + uint64_t v1 =3D 0, v2 =3D 0; + + if (mem_read(ctx, va, buf, 2 * esize) !=3D 0) { + return true; + } + memcpy(&v1, buf, esize); + memcpy(&v2, buf + esize, esize); + + /* LDPSW: sign-extend 32-bit values to 64-bit (sign=3D1, sz=3D2) */ + if (a->sign) { + v1 =3D sign_extend(v1, 8 * esize); + v2 =3D sign_extend(v2, 8 * esize); + } + + gpr_write(ctx, a->rt, v1); + gpr_write(ctx, a->rt2, v2); + + if (a->w) { + base_write(ctx, a->rn, base + offset); + } + return true; +} + +/* STGP: tag operation is a NOP for emulation; data stored via STP */ +static bool trans_STGP(DisasContext *ctx, arg_ldstpair *a) +{ + return trans_STP(ctx, a); +} + +/* + * SIMD/FP load/store pair: STP_v, LDP_v + * (DDI 0487 C3.3.14 -- C3.3.16) + */ + +static bool trans_STP_v(DisasContext *ctx, arg_ldstpair *a) +{ + int esize =3D 1 << a->sz; /* 4, 8, or 16 bytes */ + int64_t offset =3D (int64_t)a->imm << a->sz; + uint64_t base =3D base_read(ctx, a->rn); + uint64_t va =3D a->p ? base : base + offset; + uint8_t buf[32]; /* max 2 x 16 bytes */ + + fpreg_read(ctx, a->rt, buf, esize); + fpreg_read(ctx, a->rt2, buf + esize, esize); + + if (mem_write(ctx, va, buf, 2 * esize) !=3D 0) { + return true; + } + + if (a->w) { + base_write(ctx, a->rn, base + offset); + } + return true; +} + +static bool trans_LDP_v(DisasContext *ctx, arg_ldstpair *a) +{ + int esize =3D 1 << a->sz; + int64_t offset =3D (int64_t)a->imm << a->sz; + uint64_t base =3D base_read(ctx, a->rn); + uint64_t va =3D a->p ? base : base + offset; + uint8_t buf[32]; + + if (mem_read(ctx, va, buf, 2 * esize) !=3D 0) { + return true; + } + + fpreg_write(ctx, a->rt, buf, esize); + fpreg_write(ctx, a->rt2, buf + esize, esize); + + if (a->w) { + base_write(ctx, a->rn, base + offset); + } + return true; +} + /* Load/store single -- immediate (GPR) (DDI 0487 C3.3.8 -- C3.3.13) */ =20 static bool trans_STR_i(DisasContext *ctx, arg_ldst_imm *a) --=20 2.52.0 From nobody Tue Apr 7 07:34:15 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1773546223; cv=none; d=zohomail.com; s=zohoarc; b=Aw9Hl+PDN1U9Z5pY+6RwF4hIime0336RghvIBRTMMcGYw+SQRXSAxM8JeTcAE6rB4PbsQ6ZxmZpx2tvee7XottAYKAnpoVLktwLCORCahj1DmabSERahe7mIvPTxIfW5zQL+RWq8LIRStPoCNsLAHFAzaivVtiYIF+AgZx9G4es= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773546223; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=M74uQJAA18lrko8VglXDfNSgpec0O8615TxjFkMGV3Q=; b=gxvGZ9WrrFvQwfD/uGifPCi6v75H0cTda4QzmcGWnvOy6QNhECoAGZvjgbm8AM47wSJGkdpNwJ2IXWwb7A7hfxw2YE25ISknPp8k4WEGhYAWHlW+KdFTFSVIYUXHAQYvAs2BpW1fX7WqXVRG0nSBGbFl9I+mfSh5G2v04YjEsaY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773546223424412.55659730735147; Sat, 14 Mar 2026 20:43:43 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w1cMI-0004rA-Sk; Sat, 14 Mar 2026 23:41:42 -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 1w1cMG-0004qL-Rm for qemu-devel@nongnu.org; Sat, 14 Mar 2026 23:41:40 -0400 Received: from mail-dy1-x1333.google.com ([2607:f8b0:4864:20::1333]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w1cMF-0003d5-A8 for qemu-devel@nongnu.org; Sat, 14 Mar 2026 23:41:40 -0400 Received: by mail-dy1-x1333.google.com with SMTP id 5a478bee46e88-2beab594d8eso3929979eec.0 for ; Sat, 14 Mar 2026 20:41:38 -0700 (PDT) Received: from 192.168.7.2 ([189.6.247.75]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2beab3eec8fsm8886424eec.13.2026.03.14.20.41.35 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 14 Mar 2026 20:41:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773546098; x=1774150898; 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=M74uQJAA18lrko8VglXDfNSgpec0O8615TxjFkMGV3Q=; b=alZueplYZnEO8Ohv8sfg33ckx4xyN96NY2etjFuuMSutEOW9GRRSDJj+Yqbrxs15Gn ajbt9WwjKPhI16t9kPAnGNlVUPrpIW9LuZIGPoifNW8wjYU9KAHE/0qCSkGy1XusjDCD Qf8YjsWREIoq5eJP3z13SgZHWSKkqIvrXSsZoDtfsnZxnT7w8clhYSICbjDaiYd2IMwI KutEoyIXMLNR8ph6Ip5d2tlrWxOvzgZcfgpcGkh50QQYppZMXhJedpQ8/DEJYHjOdPt2 gLhxw569vLZ1v5HnfUDOcrvhvrcY0sFBd89xLDJdo22HgmnEs7JIhvLAOv2rS137tOwB DPiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773546098; x=1774150898; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=M74uQJAA18lrko8VglXDfNSgpec0O8615TxjFkMGV3Q=; b=bXB9KeTvhLmhFDfWvX8VSqLsMXdFAKSJGVT3w+TMMuWqKGNEFSchkK1dZQ2ZXgbIXf cB6zknNCdDcWzX989YgtKGgt/Qgx24uMpQU2vVPOfWhS58RxsAscmAOaAlfPb3oNFgUe CSeWNcOnGkEZXRL0j48EQgQmq47V1NoT1EaU4zhgJqsZkepeLD2ijYhURYqDu0uddiep OvFg+wl1yufVFG2qxzCevRSWQpoDYUSw6rZz05A5A1SwFAp+RtusUsoqZUO8Xr2XBJlP LMmD8NwMQp219mcRqD9c9w9D99jPJu0fShmBxVvsplUfx71mu5NxN/dWSn7n5RY72uNs uXtA== X-Gm-Message-State: AOJu0Yzm5E3IzFVpyZWRP86Vgpw9z0zzxMLkLMtKeoCRelUwjBDFvWMt CEef5Hm/zF92Me2otrqkYEqYU/lWHnxWT0xMNPu/aqoXOlJ8MxN8dTADySFOKKcX X-Gm-Gg: ATEYQzz9bgz2Z9QG9X0kroDzRXgcePFGQhhLEP4TDGutZMIcVWAreiNzGShIjnAgih/ Hi9YEXjBrNnwZhK9slt3Hjqj98A68426CfcuYrLdwOngTuoOA/3GhMYN3HyPa19odwc1iI61VpD Iz8Uo432WUCnGEhDDEvaEnB1KQtsEtPXcUV/Xwb1MfXvvWAxRbvquytvKuRZ7PPxDB96Bliphqo wqemsmQn315nIRGctPm4A9hYcC3WFKa4FvLGReOJp8o5fuojWJMabBEFaqhcDebKsg+tO1N4RF1 X5EcVqkrBheZ69wBo9Obsczj83MHkw4VPhynqLeg1llYieDUypuyzmi04dkZTX+QFzuYEUSqs/e 2DGVrWzBDkd8y2+RoC9yjam97f/ELLwF9qNplDM6plhcghTcoT5w95X9Y151Bs1nr8aCpLE2rBu JGJqRHKbbGCoalIybIveALn6ZTtWzGqTbQFSfAbcxXPhW0e3J7Jw== X-Received: by 2002:a05:7301:1688:b0:2ae:5bde:a5c5 with SMTP id 5a478bee46e88-2bea55f06ffmr3753326eec.30.1773546097631; Sat, 14 Mar 2026 20:41:37 -0700 (PDT) From: Lucas Amaral To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, agraf@csgraf.de, Lucas Amaral Subject: [PATCH v3 4/6] target/arm/emulate: add load/store exclusive Date: Sun, 15 Mar 2026 00:41:21 -0300 Message-ID: <20260315034123.41921-5-lucaaamaral@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260315034123.41921-1-lucaaamaral@gmail.com> References: <20260313021850.42379-1-lucaaamaral@gmail.com> <20260315034123.41921-1-lucaaamaral@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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=2607:f8b0:4864:20::1333; envelope-from=lucaaamaral@gmail.com; helo=mail-dy1-x1333.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, FSL_HELO_BARE_IP_2=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, 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 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-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773546225674154100 Add emulation for load/store exclusive instructions (DDI 0487 C3.3.6). Exclusive monitors have no meaning on emulated MMIO accesses, so STXR always reports success (Rs=3D0) and LDXR does not set a monitor. Instruction coverage: - STXR/STLXR: exclusive store, 8/16/32/64-bit - LDXR/LDAXR: exclusive load, 8/16/32/64-bit - STXP/STLXP: exclusive store pair, 32/64-bit - LDXP/LDAXP: exclusive load pair, 32/64-bit STXP/LDXP use two explicit decode patterns (sz=3D2, sz=3D3) for the 32/64-bit size variants. Signed-off-by: Lucas Amaral --- target/arm/emulate/a64-ldst.decode | 22 +++++++++ target/arm/emulate/arm_emulate.c | 74 ++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/target/arm/emulate/a64-ldst.decode b/target/arm/emulate/a64-ld= st.decode index f3de3f86..fadf6fd2 100644 --- a/target/arm/emulate/a64-ldst.decode +++ b/target/arm/emulate/a64-ldst.decode @@ -10,6 +10,9 @@ # 'u' flag: 0 =3D 9-bit signed immediate (byte offset), 1 =3D 12-bit unsig= ned (needs << sz) &ldst_imm rt rn imm sz sign w p unpriv ext u =20 +# Load/store exclusive +&stxr rn rt rt2 rs sz lasr + # Load/store pair (GPR and SIMD/FP) &ldstpair rt2 rt rn imm sz sign w p =20 @@ -18,6 +21,9 @@ =20 ### Format templates =20 +# Exclusives +@stxr sz:2 ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr + # Load/store immediate (9-bit signed) @ldst_imm .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm u=3D0 unp= riv=3D0 p=3D0 w=3D0 @ldst_imm_pre .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm u=3D0 unp= riv=3D0 p=3D0 w=3D1 @@ -134,6 +140,22 @@ STR_v_i 00 111 1 01 10 ............ ..... ....= . @ldst_uimm sign=3D LDR_v_i sz:2 111 1 01 01 ............ ..... ..... @ldst_uimm= sign=3D0 ext=3D0 LDR_v_i 00 111 1 01 11 ............ ..... ..... @ldst_uimm= sign=3D0 ext=3D0 sz=3D4 =20 +### Load/store exclusive + +# STXR / STLXR (sz encodes 8/16/32/64-bit) +STXR .. 001000 000 ..... . ..... ..... ..... @stxr + +# LDXR / LDAXR +LDXR .. 001000 010 ..... . ..... ..... ..... @stxr + +# STXP / STLXP (bit[31]=3D1, bit[30]=3Dsf =E2=86=92 sz=3D2 for 32-bit, sz= =3D3 for 64-bit) +STXP 10 001000 001 rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr sz=3D2 +STXP 11 001000 001 rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr sz=3D3 + +# LDXP / LDAXP +LDXP 10 001000 011 rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr sz=3D2 +LDXP 11 001000 011 rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr sz=3D3 + ### Load/store pair =E2=80=94 non-temporal (STNP/LDNP) =20 # STNP/LDNP: offset only, no writeback. Non-temporal hint ignored. diff --git a/target/arm/emulate/arm_emulate.c b/target/arm/emulate/arm_emul= ate.c index a7c62b44..fd567e65 100644 --- a/target/arm/emulate/arm_emulate.c +++ b/target/arm/emulate/arm_emulate.c @@ -414,6 +414,80 @@ static bool trans_LDR_v(DisasContext *ctx, arg_ldst *a) return true; } =20 +/* + * Load/store exclusive: STXR, LDXR, STXP, LDXP + * (DDI 0487 C3.3.6) + * + * Exclusive monitors have no meaning on MMIO. STXR always reports + * success (Rs=3D0) and LDXR does not set an exclusive monitor. + */ + +static bool trans_STXR(DisasContext *ctx, arg_stxr *a) +{ + int esize =3D 1 << a->sz; + uint64_t va =3D base_read(ctx, a->rn); + uint64_t val =3D gpr_read(ctx, a->rt); + + if (mem_write(ctx, va, &val, esize) !=3D 0) { + return true; + } + + /* Report success -- no exclusive monitor on emulated access */ + gpr_write(ctx, a->rs, 0); + return true; +} + +static bool trans_LDXR(DisasContext *ctx, arg_stxr *a) +{ + int esize =3D 1 << a->sz; + uint64_t va =3D base_read(ctx, a->rn); + uint64_t val =3D 0; + + if (mem_read(ctx, va, &val, esize) !=3D 0) { + return true; + } + + gpr_write(ctx, a->rt, val); + return true; +} + +static bool trans_STXP(DisasContext *ctx, arg_stxr *a) +{ + int esize =3D 1 << a->sz; /* sz=3D2->4, sz=3D3->8 */ + uint64_t va =3D base_read(ctx, a->rn); + uint8_t buf[16]; + + uint64_t v1 =3D gpr_read(ctx, a->rt); + uint64_t v2 =3D gpr_read(ctx, a->rt2); + memcpy(buf, &v1, esize); + memcpy(buf + esize, &v2, esize); + + if (mem_write(ctx, va, buf, 2 * esize) !=3D 0) { + return true; + } + + gpr_write(ctx, a->rs, 0); /* success */ + return true; +} + +static bool trans_LDXP(DisasContext *ctx, arg_stxr *a) +{ + int esize =3D 1 << a->sz; + uint64_t va =3D base_read(ctx, a->rn); + uint8_t buf[16]; + uint64_t v1 =3D 0, v2 =3D 0; + + if (mem_read(ctx, va, buf, 2 * esize) !=3D 0) { + return true; + } + + memcpy(&v1, buf, esize); + memcpy(&v2, buf + esize, esize); + gpr_write(ctx, a->rt, v1); + gpr_write(ctx, a->rt2, v2); + return true; +} + /* PRFM, DC cache maintenance -- treated as NOP */ static bool trans_NOP(DisasContext *ctx, arg_NOP *a) { --=20 2.52.0 From nobody Tue Apr 7 07:34:15 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; 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; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1773546187; cv=none; d=zohomail.com; s=zohoarc; b=lZ+TYfubFKtl5/VF9XIBMm2PUmqSBA9IMiCjbXfhThzd9uWvdsjKlf02qfq+H6wAzV4gEMqe7iaTXPeCQYDz/4V+cieCEZv8/vWE/2Gm/kzqDzrBpR3/hsolpwi7L4vBXFNNdCReLec//U/0eQH1FDAoF3bUZCnGVG2hkVk9oU8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773546187; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=miLoIusXP1Ecer02Tb5Dj+C4XhFfWztzibTZahI8F/0=; b=FSNBy9Dofz70Qisumlw644CQ07xWlh1zv5+7ruifd2juSUE/W3i9yLWjggx1AN+W9eib2UJmCVx2xknSiNApbi2MlyTP4LjQn2N1JMJKNTRejY5FsSVlS/KUQBl3/lfj1M74WILpUYz32pYyqQlidPNcyAoSO3IXn4IJ77rKQNc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; 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; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773546187167124.63395982989175; Sat, 14 Mar 2026 20:43:07 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w1cML-0004s5-VH; Sat, 14 Mar 2026 23:41:46 -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 1w1cMK-0004rN-2U for qemu-devel@nongnu.org; Sat, 14 Mar 2026 23:41:44 -0400 Received: from mail-dy1-x132f.google.com ([2607:f8b0:4864:20::132f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w1cMI-0003dc-2v for qemu-devel@nongnu.org; Sat, 14 Mar 2026 23:41:43 -0400 Received: by mail-dy1-x132f.google.com with SMTP id 5a478bee46e88-2beab594d8eso3930024eec.0 for ; Sat, 14 Mar 2026 20:41:41 -0700 (PDT) Received: from 192.168.7.2 ([189.6.247.75]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2beab3eec8fsm8886424eec.13.2026.03.14.20.41.38 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 14 Mar 2026 20:41:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773546100; x=1774150900; 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=miLoIusXP1Ecer02Tb5Dj+C4XhFfWztzibTZahI8F/0=; b=cJx3aQvXvcK0b4k5f/VfrXkVezGl4BphtCwKH9EYFuMD1T30hJv+4gEuwlgbH2X2A2 x7l+/Xa+xA/2deSNTa9QjO52dDazgr2lUxXuJLjt5M8pe9JQAWdgTpMXA/4gQ7RDHVXv cI08mPGUDU7PtgNFcx+aovlVVSFNuJSCBvePBsSamRHWwQSmnZ9rrfuqjRzQ8nwldA8P o/Drg9I3Nf9/qoc7bJsmNJb5Y17N7nqIPeBIKIdo460l2clUtSVrynEPl48h4BxRqXw1 vQormIws7hG+d0IVFiTi8MTdBCtnENxkKOdaXPUWNF6U9J5Zh3DzPiooGioJmu6YG8wZ kRXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773546100; x=1774150900; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=miLoIusXP1Ecer02Tb5Dj+C4XhFfWztzibTZahI8F/0=; b=WhF7FXkRO6xhQ9VDLBMaLeH/OCvW9CkAJZG3F56R7rugyCQOkpUtZ8iTwsCDTvbUv1 xTQMkpUyf1t+9UjY/HG60W0QGtdVOHkBPSS69W9ioSpef27NzXHruKb7av98sIiPAoK4 ueAJqzWVkjKmYtV/mgOEMLl7qrr0cbnJOg1WUlDRM60L9OUPT+Tvwo2Osz1xw2ajDg9S WRChL4d/4VW/OFkoOZ3YoDf8cpesbBm5mt8tRkBuG/O/uYCGw+XnCeKZwwwJ5IVBA9U7 DuuLpwk/k8nfsm7yCp5aJfXwiE6kz8i2ZkcT5K3RVSPG0RMQxlFe6+Sr09pvQocn/MCk 0BFg== X-Gm-Message-State: AOJu0YzmsmFCXBAOiOUu4PXYhl+lc0qpAFxbJZuRckJqYRfzngtRXbcm oOmQLpuwePFO5c2pBRySVX30nkIWKe71DB28EhU70KGLx+QexRGIy0jS9UNYsEwX X-Gm-Gg: ATEYQzyyRrWNr5djVs4MrxX9Vn2onc9TL69ua6WlI6687sjq77XTiFxCpNSXjYEfNNh iGM3MbwHptnsHHP3tsK7f7wc5HAIzExQ7Nbw0JAWTSP9hOhyIUZpsTYDb43rBTGtNHu6s6jT/mE pb/BbD7eziNCuVZAVsEgxgbDT0nefzpm9Jes/WHDKRiu3/RJ8WE79qhVS1y7Qv7GwiqpJwpdlzw a8PCq3e2HGxKtwMnzI2i1QXjchOnX/dHAGGy9aoyldzW2XQi8yKxygUBf6r1etOFuO7H92/mOnF Pjq1sbftKWtz8mA6dn9tWH7Sn2r1MvJOJ6cGgIgo0dcP1X5Y1ZiMvm1Okc1ZYX6xd9Yv2MUWSka llCRlnQR365KP4lb98hUtLo46yMLwxnxDJOYk+vDJp+tFcCBR4+TGpj26vhECL5FILAE949ziEk XN/hQTwK/cNgpnldbZTQqNXjT03E0OIadlBbcfM8g= X-Received: by 2002:a05:7301:100b:b0:2be:8216:57d3 with SMTP id 5a478bee46e88-2bea55f92bamr3945874eec.31.1773546100209; Sat, 14 Mar 2026 20:41:40 -0700 (PDT) From: Lucas Amaral To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, agraf@csgraf.de, Lucas Amaral Subject: [PATCH v3 5/6] target/arm/emulate: add atomic, compare-and-swap, and PAC load Date: Sun, 15 Mar 2026 00:41:22 -0300 Message-ID: <20260315034123.41921-6-lucaaamaral@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260315034123.41921-1-lucaaamaral@gmail.com> References: <20260313021850.42379-1-lucaaamaral@gmail.com> <20260315034123.41921-1-lucaaamaral@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 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=2607:f8b0:4864:20::132f; envelope-from=lucaaamaral@gmail.com; helo=mail-dy1-x132f.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, FSL_HELO_BARE_IP_2=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, 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 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-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773546188489158500 Add emulation for remaining ISV=3D0 load/store instruction classes. Atomic memory operations (DDI 0487 C3.3.2): - LDADD, LDCLR, LDEOR, LDSET: arithmetic/logic atomics - LDSMAX, LDSMIN, LDUMAX, LDUMIN: signed/unsigned min/max - SWP: atomic swap Non-atomic read-modify-write, sufficient for MMIO where concurrent access is not a concern. Acquire/release semantics are ignored. Compare-and-swap (DDI 0487 C3.3.1): - CAS/CASA/CASAL/CASL: single-register compare-and-swap - CASP/CASPA/CASPAL/CASPL: register-pair compare-and-swap CASP validates even register pairs; odd or r31 returns UNHANDLED. Load with PAC (DDI 0487 C6.2.121): - LDRAA/LDRAB: pointer-authenticated load, offset/pre-indexed Pointer authentication is not emulated (equivalent to auth always succeeding), which is correct for MMIO since PAC is a software security mechanism, not a memory access semantic. CASP uses two explicit decode patterns for the 32/64-bit size variants. LDRA's offset immediate is stored raw in the decode; the handler scales by << 3. Signed-off-by: Lucas Amaral --- target/arm/emulate/a64-ldst.decode | 45 ++++++ target/arm/emulate/arm_emulate.c | 233 +++++++++++++++++++++++++++++ 2 files changed, 278 insertions(+) diff --git a/target/arm/emulate/a64-ldst.decode b/target/arm/emulate/a64-ld= st.decode index fadf6fd2..9292bfdf 100644 --- a/target/arm/emulate/a64-ldst.decode +++ b/target/arm/emulate/a64-ldst.decode @@ -16,6 +16,16 @@ # Load/store pair (GPR and SIMD/FP) &ldstpair rt2 rt rn imm sz sign w p =20 +# Atomic memory operations +&atomic rs rn rt a r sz + +# Compare-and-swap +&cas rs rn rt sz a r + +# Load with PAC (LDRAA/LDRAB, FEAT_PAuth) +%ldra_imm 22:s1 12:9 +&ldra rt rn imm m w + # Load/store register offset &ldst rm rn rt sign ext sz opt s =20 @@ -36,6 +46,15 @@ # Load/store pair: imm7 is signed, scaled by element size in handler @ldstpair .. ... . ... . imm:s7 rt2:5 rn:5 rt:5 &ldstpair =20 +# Atomics +@atomic sz:2 ... . .. a:1 r:1 . rs:5 . ... .. rn:5 rt:5 &atomic + +# Compare-and-swap: sz extracted by pattern (CAS) or set constant (CASP) +@cas .. ...... . a:1 . rs:5 r:1 ..... rn:5 rt:5 &cas + +# Load with PAC +@ldra .. ... . .. m:1 . . ......... w:1 . rn:5 rt:5 &ldra im= m=3D%ldra_imm + # Load/store register offset @ldst .. ... . .. .. . rm:5 opt:3 s:1 .. rn:5 rt:5 &ldst =20 @@ -241,6 +260,32 @@ STR_v 00 111 1 00 10 1 ..... ... . 10 ..... = ..... @ldst sign=3D0 ext=3D LDR_v sz:2 111 1 00 01 1 ..... ... . 10 ..... ..... @ldst sign= =3D0 ext=3D0 LDR_v 00 111 1 00 11 1 ..... ... . 10 ..... ..... @ldst sign= =3D0 ext=3D0 sz=3D4 =20 +### Compare-and-swap + +# CAS / CASA / CASAL / CASL +CAS sz:2 001000 1 . 1 ..... . 11111 ..... ..... @cas + +# CASP / CASPA / CASPAL / CASPL (pair: Rt,Rt+1 and Rs,Rs+1) +CASP 00 001000 0 . 1 ..... . 11111 ..... ..... @cas sz=3D2 +CASP 01 001000 0 . 1 ..... . 11111 ..... ..... @cas sz=3D3 + +### Atomic memory operations + +LDADD .. 111 0 00 . . 1 ..... 0000 00 ..... ..... @atomic +LDCLR .. 111 0 00 . . 1 ..... 0001 00 ..... ..... @atomic +LDEOR .. 111 0 00 . . 1 ..... 0010 00 ..... ..... @atomic +LDSET .. 111 0 00 . . 1 ..... 0011 00 ..... ..... @atomic +LDSMAX .. 111 0 00 . . 1 ..... 0100 00 ..... ..... @atomic +LDSMIN .. 111 0 00 . . 1 ..... 0101 00 ..... ..... @atomic +LDUMAX .. 111 0 00 . . 1 ..... 0110 00 ..... ..... @atomic +LDUMIN .. 111 0 00 . . 1 ..... 0111 00 ..... ..... @atomic +SWP .. 111 0 00 . . 1 ..... 1000 00 ..... ..... @atomic + +### Load with PAC (FEAT_PAuth) + +# LDRAA (M=3D0) / LDRAB (M=3D1), offset (W=3D0) / pre-indexed (W=3D1) +LDRA 11 111 0 00 . . 1 ......... . 1 ..... ..... @ldra + ### System instructions =E2=80=94 DC cache maintenance =20 # SYS with CRn=3DC7 covers all data cache operations (DC CIVAC, CVAC, etc.= ). diff --git a/target/arm/emulate/arm_emulate.c b/target/arm/emulate/arm_emul= ate.c index fd567e65..1b959745 100644 --- a/target/arm/emulate/arm_emulate.c +++ b/target/arm/emulate/arm_emulate.c @@ -488,6 +488,239 @@ static bool trans_LDXP(DisasContext *ctx, arg_stxr *a) return true; } =20 +/* + * Atomic memory operations (DDI 0487 C3.3.2) + * + * Non-atomic read-modify-write; sufficient for MMIO. + * Acquire/release semantics ignored (sequentially consistent by design). + */ + +typedef uint64_t (*atomic_op_fn)(uint64_t old, uint64_t operand, int bits); + +static uint64_t atomic_add(uint64_t old, uint64_t op, int bits) +{ + (void)bits; + return old + op; +} + +static uint64_t atomic_clr(uint64_t old, uint64_t op, int bits) +{ + (void)bits; + return old & ~op; +} + +static uint64_t atomic_eor(uint64_t old, uint64_t op, int bits) +{ + (void)bits; + return old ^ op; +} + +static uint64_t atomic_set(uint64_t old, uint64_t op, int bits) +{ + (void)bits; + return old | op; +} + +static uint64_t atomic_smax(uint64_t old, uint64_t op, int bits) +{ + int64_t a =3D sign_extend(old, bits); + int64_t b =3D sign_extend(op, bits); + return (a >=3D b) ? old : op; +} + +static uint64_t atomic_smin(uint64_t old, uint64_t op, int bits) +{ + int64_t a =3D sign_extend(old, bits); + int64_t b =3D sign_extend(op, bits); + return (a <=3D b) ? old : op; +} + +static uint64_t atomic_umax(uint64_t old, uint64_t op, int bits) +{ + uint64_t mask =3D (bits =3D=3D 64) ? UINT64_MAX : (1ULL << bits) - 1; + return ((old & mask) >=3D (op & mask)) ? old : op; +} + +static uint64_t atomic_umin(uint64_t old, uint64_t op, int bits) +{ + uint64_t mask =3D (bits =3D=3D 64) ? UINT64_MAX : (1ULL << bits) - 1; + return ((old & mask) <=3D (op & mask)) ? old : op; +} + +static bool do_atomic(DisasContext *ctx, arg_atomic *a, atomic_op_fn fn) +{ + int esize =3D 1 << a->sz; + int bits =3D 8 * esize; + uint64_t va =3D base_read(ctx, a->rn); + uint64_t old =3D 0; + + if (mem_read(ctx, va, &old, esize) !=3D 0) { + return true; + } + + uint64_t operand =3D gpr_read(ctx, a->rs); + uint64_t result =3D fn(old, operand, bits); + + if (mem_write(ctx, va, &result, esize) !=3D 0) { + return true; + } + + /* Rt receives the old value (before modification) */ + gpr_write(ctx, a->rt, old); + return true; +} + +static bool trans_LDADD(DisasContext *ctx, arg_atomic *a) +{ + return do_atomic(ctx, a, atomic_add); +} + +static bool trans_LDCLR(DisasContext *ctx, arg_atomic *a) +{ + return do_atomic(ctx, a, atomic_clr); +} + +static bool trans_LDEOR(DisasContext *ctx, arg_atomic *a) +{ + return do_atomic(ctx, a, atomic_eor); +} + +static bool trans_LDSET(DisasContext *ctx, arg_atomic *a) +{ + return do_atomic(ctx, a, atomic_set); +} + +static bool trans_LDSMAX(DisasContext *ctx, arg_atomic *a) +{ + return do_atomic(ctx, a, atomic_smax); +} + +static bool trans_LDSMIN(DisasContext *ctx, arg_atomic *a) +{ + return do_atomic(ctx, a, atomic_smin); +} + +static bool trans_LDUMAX(DisasContext *ctx, arg_atomic *a) +{ + return do_atomic(ctx, a, atomic_umax); +} + +static bool trans_LDUMIN(DisasContext *ctx, arg_atomic *a) +{ + return do_atomic(ctx, a, atomic_umin); +} + +static bool trans_SWP(DisasContext *ctx, arg_atomic *a) +{ + int esize =3D 1 << a->sz; + uint64_t va =3D base_read(ctx, a->rn); + uint64_t old =3D 0; + + if (mem_read(ctx, va, &old, esize) !=3D 0) { + return true; + } + + uint64_t newval =3D gpr_read(ctx, a->rs); + if (mem_write(ctx, va, &newval, esize) !=3D 0) { + return true; + } + + gpr_write(ctx, a->rt, old); + return true; +} + +/* Compare-and-swap: CAS, CASP (DDI 0487 C3.3.1) */ + +static bool trans_CAS(DisasContext *ctx, arg_cas *a) +{ + int esize =3D 1 << a->sz; + uint64_t va =3D base_read(ctx, a->rn); + uint64_t current =3D 0; + + if (mem_read(ctx, va, ¤t, esize) !=3D 0) { + return true; + } + + uint64_t mask =3D (esize =3D=3D 8) ? UINT64_MAX : (1ULL << (8 * esize)= ) - 1; + uint64_t compare =3D gpr_read(ctx, a->rs) & mask; + + if ((current & mask) =3D=3D compare) { + uint64_t newval =3D gpr_read(ctx, a->rt) & mask; + if (mem_write(ctx, va, &newval, esize) !=3D 0) { + return true; + } + } + + /* Rs receives the old memory value (whether or not swap occurred) */ + gpr_write(ctx, a->rs, current); + return true; +} + +/* CASP: compare-and-swap pair (Rs,Rs+1 compared; Rt,Rt+1 stored) */ +static bool trans_CASP(DisasContext *ctx, arg_cas *a) +{ + /* CASP requires even register pairs; odd or r31 is UNPREDICTABLE */ + if ((a->rs & 1) || a->rs >=3D 31 || (a->rt & 1) || a->rt >=3D 31) { + return false; + } + + int esize =3D 1 << a->sz; /* per-register size */ + uint64_t va =3D base_read(ctx, a->rn); + uint8_t buf[16]; + uint64_t cur1 =3D 0, cur2 =3D 0; + + if (mem_read(ctx, va, buf, 2 * esize) !=3D 0) { + return true; + } + memcpy(&cur1, buf, esize); + memcpy(&cur2, buf + esize, esize); + + uint64_t mask =3D (esize =3D=3D 8) ? UINT64_MAX : (1ULL << (8 * esize)= ) - 1; + uint64_t cmp1 =3D gpr_read(ctx, a->rs) & mask; + uint64_t cmp2 =3D gpr_read(ctx, a->rs + 1) & mask; + + if ((cur1 & mask) =3D=3D cmp1 && (cur2 & mask) =3D=3D cmp2) { + uint64_t new1 =3D gpr_read(ctx, a->rt) & mask; + uint64_t new2 =3D gpr_read(ctx, a->rt + 1) & mask; + memcpy(buf, &new1, esize); + memcpy(buf + esize, &new2, esize); + if (mem_write(ctx, va, buf, 2 * esize) !=3D 0) { + return true; + } + } + + gpr_write(ctx, a->rs, cur1); + gpr_write(ctx, a->rs + 1, cur2); + return true; +} + +/* + * Load with PAC: LDRAA / LDRAB (FEAT_PAuth) + * (DDI 0487 C6.2.121) + * + * Pointer authentication is not emulated -- the base register is used + * directly (equivalent to auth always succeeding). + */ + +static bool trans_LDRA(DisasContext *ctx, arg_ldra *a) +{ + int64_t offset =3D (int64_t)a->imm << 3; /* S:imm9, scaled by 8 */ + uint64_t base =3D base_read(ctx, a->rn); + uint64_t va =3D base + offset; /* auth not emulated */ + uint64_t val =3D 0; + + if (mem_read(ctx, va, &val, 8) !=3D 0) { + return true; + } + + gpr_write(ctx, a->rt, val); + + if (a->w) { + base_write(ctx, a->rn, va); + } + return true; +} + /* PRFM, DC cache maintenance -- treated as NOP */ static bool trans_NOP(DisasContext *ctx, arg_NOP *a) { --=20 2.52.0 From nobody Tue Apr 7 07:34:15 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; 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; dmarc=fail(p=none dis=none) header.from=gmail.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1773546223344436.62911346339376; Sat, 14 Mar 2026 20:43:43 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w1cMN-0004sz-CZ; Sat, 14 Mar 2026 23:41:47 -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 1w1cML-0004s1-S2 for qemu-devel@nongnu.org; Sat, 14 Mar 2026 23:41:45 -0400 Received: from mail-dy1-x1330.google.com ([2607:f8b0:4864:20::1330]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w1cMK-0003eP-82 for qemu-devel@nongnu.org; Sat, 14 Mar 2026 23:41:45 -0400 Received: by mail-dy1-x1330.google.com with SMTP id 5a478bee46e88-2c0bcd8f194so169697eec.1 for ; Sat, 14 Mar 2026 20:41:43 -0700 (PDT) Received: from 192.168.7.2 ([189.6.247.75]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2beab3eec8fsm8886424eec.13.2026.03.14.20.41.40 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 14 Mar 2026 20:41:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773546103; x=1774150903; 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=FAox7KuzEjN6uMKR15HpaLwREkZOhi+MKGAAIeeTYzk=; b=CxfzrHsJPlwMjgbdE0AMHaOHdGCxlBg5xwdsoPe5FIK9KqwAiVV0S4pSRXwZ22J/Ka aXWDjdO666n38AswVtxqrcqjPvQm67HaBSU4Ns7VYxrd6/cnJu6VIVxfdmofx9ihaICe bXXMgx5Kto13rSqDPZsyCCqXFgxlqgbgi0S3lfZzCSjVpUT4aKsAx7L3cjYqrYLeTans s/JD7LC6mjck+EXTIP8IicDANORW0P4NytrJ005TznWChF3YUUHADTOeD2/5RTvLg63V RNJGQVDn8eOBs3v0r/MuH9m+aj2umg4u7BvJu/TDJtOPGLSY6E/Xf65OqZNHmN1Ba/kG 98IA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773546103; x=1774150903; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=FAox7KuzEjN6uMKR15HpaLwREkZOhi+MKGAAIeeTYzk=; b=ePcj8hLKumn1SQIii5mg7mh95tf1uyKYbg5FcOKOC6nITxXeM2trp8I1xdh1taSe8l dOS1QB27wAc3X+o5s3l+wO+C2Drn4v5RPqUvYxDcAulXvVyPzlgfqhaUyaTJXm/DHldS JlFCvdo/YNqsW7/5rJ/w3M9v+8AkBVPVrfi741PZrUYUEs3wTTVccLThkR3PoyMWM8x9 DoT/x8L5+lpVW34pIwmy40ov9zY40vFXs0NWr/oi2EEK14cT4/Rt2x/AgOfQlvhiq+e7 mjjnRLfCsJcgjSe/Rul3xhsAGJ8QoUfy6Bu6P7S25zz3qotTC1fCthNZExIP+4gVg+5v tTdQ== X-Gm-Message-State: AOJu0YyhLzJplbnC2eIFgfJL7OmshJ3kwPk4OlNYauSyU26/P/px0XYX 2Kz/y+1XQPEYnEwUf/8VjnSn1GB33kPVP39upyaI88AzYZp3ehyiFmEBX62t4INr X-Gm-Gg: ATEYQzwdqYEKnfWZXLpnstSbpuTJNJUKnmBoQfhUjBPGfdAvUI5evR0HjK7iHo+x2cc OzgtACl3JAqUUJVx+tQUzIgSHPnIuaHXieJ7JPpJx6NkD85GSxDXVkWfsp7ByWw7gPkl4YPMKVc uu1j815Y1bZTjJd6iQ0ev57ptSEx89JhwywOCyKWNfVQv8LPPNJcOstiXbzhYclnvkJyuALGlbP H2X31eWTgSTBol9FJ+5clhrOh/s3jH8sJjWYq9QJmlVvw0RZZSSk1tJuhvVVQhVL6/OvX0VcwDq uQxTg02J2/E8YgByRDc3AOxMOoMg46jLycHgVWUPNVj1OWI4bCTZXXv9lKHA20eI7PeHaPIs8ww CkoGTmkgn2EWjLX7lCTiUoFQA4NTNUsDJDvPKVLzm+7b50WakKCKSZWmBvtFUDcD3KdXhNOK4Du lStBqht808XwpJR6DJpvQbrDQZkvrRF2PtB30mGwc= X-Received: by 2002:a05:7300:190f:b0:2be:7885:31df with SMTP id 5a478bee46e88-2bea54adff6mr4233975eec.17.1773546102517; Sat, 14 Mar 2026 20:41:42 -0700 (PDT) From: Lucas Amaral To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, agraf@csgraf.de, Lucas Amaral Subject: [PATCH v3 6/6] target/arm/hvf, whpx: wire ISV=0 emulation for data aborts Date: Sun, 15 Mar 2026 00:41:23 -0300 Message-ID: <20260315034123.41921-7-lucaaamaral@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260315034123.41921-1-lucaaamaral@gmail.com> References: <20260313021850.42379-1-lucaaamaral@gmail.com> <20260315034123.41921-1-lucaaamaral@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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=2607:f8b0:4864:20::1330; envelope-from=lucaaamaral@gmail.com; helo=mail-dy1-x1330.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, FSL_HELO_BARE_IP_2=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, 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 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-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1773546225690154100 Content-Type: text/plain; charset="utf-8" When a data abort with ISV=3D0 occurs during MMIO emulation, the syndrome register does not carry the access size or target register. Previously this hit an assert(isv) and killed the VM. Replace the assert with instruction fetch + decode + emulate using the shared library in target/arm/emulate/. The faulting instruction is read from guest memory via cpu_memory_rw_debug(), decoded by the decodetree- generated decoder, and emulated against the vCPU register file. Both HVF (macOS) and WHPX (Windows Hyper-V) use the same pattern: 1. cpu_synchronize_state() to flush hypervisor registers 2. Fetch 4-byte instruction at env->pc 3. arm_emul_insn(env, insn) 4. Log errors for unhandled/memory-fault cases, advance PC This makes ISV=3D0 data aborts non-fatal, enabling MMIO access from SIMD/FP loads, load/store pairs, atomics, and other instructions that hardware does not decode into the syndrome. Signed-off-by: Lucas Amaral --- target/arm/hvf/hvf.c | 41 +++++++++++++++++++++++++++++++++++--- target/arm/whpx/whpx-all.c | 39 +++++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 5fc8f6bb..219dbbca 100644 --- a/target/arm/hvf/hvf.c +++ b/target/arm/hvf/hvf.c @@ -32,6 +32,7 @@ #include "arm-powerctl.h" #include "target/arm/cpu.h" #include "target/arm/internals.h" +#include "emulate/arm_emulate.h" #include "target/arm/multiprocessing.h" #include "target/arm/gtimer.h" #include "target/arm/trace.h" @@ -2175,10 +2176,44 @@ static int hvf_handle_exception(CPUState *cpu, hv_v= cpu_exit_exception_t *excp) assert(!s1ptw); =20 /* - * TODO: ISV will be 0 for SIMD or SVE accesses. - * Inject the exception into the guest. + * ISV=3D0: syndrome doesn't carry access size/register info. + * Fetch and emulate via target/arm/emulate/. + * Unhandled instructions log an error and advance PC. */ - assert(isv); + if (!isv) { + ARMCPU *arm_cpu =3D ARM_CPU(cpu); + CPUARMState *env =3D &arm_cpu->env; + uint32_t insn; + ArmEmulResult r; + + cpu_synchronize_state(cpu); + + if (cpu_memory_rw_debug(cpu, env->pc, + (uint8_t *)&insn, 4, false) !=3D 0) { + error_report("HVF: cannot read insn at pc=3D0x%" PRIx64, + (uint64_t)env->pc); + advance_pc =3D true; + break; + } + + r =3D arm_emul_insn(env, insn); + if (r =3D=3D ARM_EMUL_UNHANDLED) { + /* + * TODO: Inject data abort into guest instead of + * advancing PC. Requires setting ESR_EL1/FAR_EL1/ + * ELR_EL1/SPSR_EL1 and redirecting to VBAR_EL1. + */ + error_report("HVF: ISV=3D0 unhandled insn 0x%08x at " + "pc=3D0x%" PRIx64, insn, (uint64_t)env->pc); + } else if (r =3D=3D ARM_EMUL_ERR_MEM) { + error_report("HVF: ISV=3D0 memory error emulating " + "insn 0x%08x at pc=3D0x%" PRIx64, + insn, (uint64_t)env->pc); + } + + advance_pc =3D true; + break; + } =20 /* * Emulate MMIO. diff --git a/target/arm/whpx/whpx-all.c b/target/arm/whpx/whpx-all.c index 513551be..2f8ffc7f 100644 --- a/target/arm/whpx/whpx-all.c +++ b/target/arm/whpx/whpx-all.c @@ -29,6 +29,7 @@ #include "syndrome.h" #include "target/arm/cpregs.h" #include "internals.h" +#include "emulate/arm_emulate.h" =20 #include "system/whpx-internal.h" #include "system/whpx-accel-ops.h" @@ -366,7 +367,43 @@ static int whpx_handle_mmio(CPUState *cpu, WHV_MEMORY_= ACCESS_CONTEXT *ctx) uint64_t val =3D 0; =20 assert(!cm); - assert(isv); + + /* + * ISV=3D0: syndrome doesn't carry access size/register info. + * Fetch and decode the faulting instruction via the emulation library. + */ + if (!isv) { + ARMCPU *arm_cpu =3D ARM_CPU(cpu); + CPUARMState *env =3D &arm_cpu->env; + uint32_t insn; + ArmEmulResult r; + + cpu_synchronize_state(cpu); + + if (cpu_memory_rw_debug(cpu, env->pc, + (uint8_t *)&insn, 4, false) !=3D 0) { + error_report("WHPX: cannot read insn at pc=3D0x%" PRIx64, + (uint64_t)env->pc); + return 0; + } + + r =3D arm_emul_insn(env, insn); + if (r =3D=3D ARM_EMUL_UNHANDLED) { + /* + * TODO: Inject data abort into guest instead of + * advancing PC. Requires setting ESR_EL1/FAR_EL1/ + * ELR_EL1/SPSR_EL1 and redirecting to VBAR_EL1. + */ + error_report("WHPX: ISV=3D0 unhandled insn 0x%08x at " + "pc=3D0x%" PRIx64, insn, (uint64_t)env->pc); + } else if (r =3D=3D ARM_EMUL_ERR_MEM) { + error_report("WHPX: ISV=3D0 memory error emulating " + "insn 0x%08x at pc=3D0x%" PRIx64, + insn, (uint64_t)env->pc); + } + + return 0; + } =20 if (iswrite) { val =3D whpx_get_gp_reg(cpu, srt); --=20 2.52.0