From nobody Tue Apr 7 04:41:54 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=1773629506; cv=none; d=zohomail.com; s=zohoarc; b=FcxMDMc9C+bkWutVeiFzz860VK9c4uS6uZKVQCSfCfr/qK4jDOgo1/ZzeL0hmYBxYoSvV0zq+lFgZ6sEXHAqTuTmvXvdncI06WJeG2jbMkDulHLMhaa3QRoFh3Dq0J91071e8hcqK/nWcPFhGS8+azT1MfdFMu6fqPOCAGC+pUw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773629506; 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=rkntRO9BlfKguUfCc4hgxLdTFp8ZwdG5JLYNcilE8GE=; b=MGBSMOcoTdD22XkaVOvgCkhvHVeOVHk8PcAJ4+3G1fd+NtHOTgayMIcziqzgY6gBvTmtWuuwYkxhIKyDzEmlqo+LQ3VLa+juetXPBUJSh/4vHC9RfpBRzHQ2dlRWEBIOhVjVgIGlow5V1gwFfB+OA1bxsp4/Q+MzBQ5tCcw4/gY= 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 1773629506581332.2332797358106; Sun, 15 Mar 2026 19:51:46 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w1y2c-00026W-Uh; Sun, 15 Mar 2026 22:50:50 -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 1w1y2a-00025j-LK for qemu-devel@nongnu.org; Sun, 15 Mar 2026 22:50:49 -0400 Received: from mail-dl1-x1232.google.com ([2607:f8b0:4864:20::1232]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w1y2X-0000Ux-Bu for qemu-devel@nongnu.org; Sun, 15 Mar 2026 22:50:48 -0400 Received: by mail-dl1-x1232.google.com with SMTP id a92af1059eb24-128ef6c4a41so1493915c88.1 for ; Sun, 15 Mar 2026 19:50:44 -0700 (PDT) Received: from 192.168.7.2 ([189.6.247.75]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2beab3a12e2sm13138973eec.2.2026.03.15.19.50.40 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sun, 15 Mar 2026 19:50:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773629444; x=1774234244; 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=rkntRO9BlfKguUfCc4hgxLdTFp8ZwdG5JLYNcilE8GE=; b=CQncA2xRBDTYLGAVJfm8dL0plxGy4LLkOiFzO0ViIs5O3VRS7fjiPzFsuBVYC2oHnU AI7fK156HR350dRsDnsI3jgIOGyNFVC1xc21z0yN0QC2ygg598432V/nZjdxNlaYyhJC vjOIwxGDbic8wSzCg5vyt1knTHxlFa9rrK0/SCVYIPUx9EaSN/QGbx62ZWBwz94V7sz0 kGhy35rnQJj10vOnx9/oBAFvPyWq3EtCtn4eKRK3M6kOVSaV1oAXl7H5af9rqweou7Xt Co2IOwjP6RTN58hFvDFCTc9a2xbJvltvJCbqG1W+1GyrT+J7SWZN6a1RelEzBZn71ULd 8bPQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773629444; x=1774234244; 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=rkntRO9BlfKguUfCc4hgxLdTFp8ZwdG5JLYNcilE8GE=; b=N1ik1gpmLqezhjxdAbU1AV4gxDNkousiZ5ZNgMM1CLEF02m4VR7uMp+Ak7wKqC55nf rRLn/Gdcm7PBqeb6MIzyIacwfJlgT6EuU8mw+o5QCBJWmdFHOw/r3GE2LtJ3aPDDELGu NO41kFg+dpXWVbWJVlm008D/7GGguIPpUH7EZhXzoU0wkstyyYhYWNZ85y0Rf2uIDTR1 EAQZmZ9UJ9PEZrRvghUO9j10uQeaaxF2wDFu/H+u7pZdz9ZrgTZdhY2CTkfErjRtdxAW 1Lb3lRdY/ugaiAqR1FscKLdbnvb770lxxaLk2ZoAxNQ4gOYnh/3U5PhSeszDl1Zqgw5U 2g4A== X-Gm-Message-State: AOJu0Yxv0ixg4rNdcBJGgdWesTE8JjF8hwEqKAT76mT+ZRu00ee2sqet ZJQzPie2MSLi8o+PRu21yKPYqvTB6VFsZeKJefP2CCIHFcAHQEbVu4tGjnzh700m X-Gm-Gg: ATEYQzyGFZa0TBarGX//cPdke+ExEStmT1E7fVQ8om+Nb/3Mwhmi3Z9UJKSd9UxBV6b 897qX2tCjuss4QFyd5XVFuscztp8o2RrFQNrF9qZ+v0/t2u2ivyWl1M9jnSkw0W75XHdXbQKIhF ec8pAzLninkr3soZyB8YktCpZkQ2n0AoNrqMpfRRTO8w2SIUBARCzM87o082o+UOQB3rvZN4utQ KOon45GRhvULRq0uS0Ro6K5tcZwYQh42/iUv2ZWoeku+K+RUbu4L0fEPZJItQOARSx2jvO2Z+AB yudvSHilv+LIQpC4giCspB7SAL81N3ju+fRQRgCfHLb47hko6xEoTL9RsnpopnvYDcJ5Tw+FjNr 8RLi/diNfm0D6xTONZ0MmlXA9S+vfDwpUGaLdh87LqV1W/ucTlXT8wWhy+bwye2pVgHpyJJAXVr +1KDzIbbkxNCuEYZ0F9ticpUKP+d/HYV1v00GekqI= X-Received: by 2002:a05:7022:f97:b0:128:ce44:be8b with SMTP id a92af1059eb24-128f3dd1398mr4897372c88.25.1773629443439; Sun, 15 Mar 2026 19:50:43 -0700 (PDT) From: Lucas Amaral To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, agraf@csgraf.de, peter.maydell@linaro.org, mohamed@unpredictable.fr, Lucas Amaral Subject: [PATCH v4 1/6] target/arm/emulate: add ISV=0 emulation library with load/store immediate Date: Sun, 15 Mar 2026 23:50:29 -0300 Message-ID: <20260316025034.85611-2-lucaaamaral@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260316025034.85611-1-lucaaamaral@gmail.com> References: <20260315034123.41921-1-lucaaamaral@gmail.com> <20260316025034.85611-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::1232; envelope-from=lucaaamaral@gmail.com; helo=mail-dl1-x1232.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=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773629510247158500 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 | 237 +++++++++++++++++++++++++++++ target/arm/emulate/arm_emulate.h | 30 ++++ target/arm/emulate/meson.build | 6 + target/arm/meson.build | 1 + 5 files changed, 403 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..02fefc30 --- /dev/null +++ b/target/arm/emulate/arm_emulate.c @@ -0,0 +1,237 @@ +/* + * 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" +#include "exec/target_page.h" + +/* TODO: assumes LE guest data layout (sufficient for HVF/WHPX, both LE-on= ly) */ + +/* 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) +{ + if (((va & ~TARGET_PAGE_MASK) + size) > TARGET_PAGE_SIZE) { + ctx->result =3D ARM_EMUL_ERR_MEM; + return -1; + } + 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) +{ + if (((va & ~TARGET_PAGE_MASK) + size) > TARGET_PAGE_SIZE) { + ctx->result =3D ARM_EMUL_ERR_MEM; + return -1; + } + 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 04:41:54 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=1773629549; cv=none; d=zohomail.com; s=zohoarc; b=mtjKQXRhdKuKcojpF2c9iou0NHs/h2xqj0FLfcwFEON4rCqlBKo0IwqjwwN2FHWDW4Zp62GY6LuOkKkh40IT1EN9EsTVmN/wkPbk9JG8gSLKmr4qRTAW1K83G6N8sav9zmWrttbZOajynfqsvyg5K14qwjUXVzFuJnxa6coTVR8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773629549; 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=sMIe4BH1dC23aKjJXdUIHsVXt5i12Nl20FH16xA6kBU=; b=KYKCbnRDHi+5RlPkS511cSgSQF1+07XIe1Zv1Kh/i6sCNuqjK+RiRv9tr8+GSc/CzhE6KaRpF4ZA66h9odVl3dhb15IiP5Yg7yGoKZ8fGdEjRAY+USeXb/NT9R4SEqvru0/F1Jq8nNAl6mjUGMrr4CmxUXwg+vUn0YT8RKdUQYI= 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 1773629549022493.71495123427417; Sun, 15 Mar 2026 19:52:29 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w1y2d-00026t-IR; Sun, 15 Mar 2026 22:50:51 -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 1w1y2c-000265-8E for qemu-devel@nongnu.org; Sun, 15 Mar 2026 22:50:50 -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 1w1y2a-0000VK-ER for qemu-devel@nongnu.org; Sun, 15 Mar 2026 22:50:49 -0400 Received: by mail-dy1-x1330.google.com with SMTP id 5a478bee46e88-2ba9c484e5eso4807428eec.1 for ; Sun, 15 Mar 2026 19:50:48 -0700 (PDT) Received: from 192.168.7.2 ([189.6.247.75]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2beab3a12e2sm13138973eec.2.2026.03.15.19.50.43 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sun, 15 Mar 2026 19:50:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773629447; x=1774234247; 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=sMIe4BH1dC23aKjJXdUIHsVXt5i12Nl20FH16xA6kBU=; b=cSLUTL2Lq+XMApG3xJ9Kd1NNVdyQ2Dd94yl524bJqAw5S9pc4kUa2G3HaHklYwo1bw 7NiX0BBGX5zoZqnA1TcbeyqR2b+AYENzM3NcMf9T16ut5A/wvtkYfjiLtuc300i6ceY6 RTne/yCupjwCC3um8gKroVeiuFXpW4yLFGulFZ4jvl3H01Vj/tEmOwyjGFVWLXYf2d4j XOBsp2pSBBrxmUOT5QsDFeJZzrTuWbADkit3Ed5kgTsKIxG06SJIHHmdBHPfM5TSpFrC 1d0AsvSTzrbLTiWkI8ON23v7Br5XvDgyDuxoD8yesJ6IJZ/X3UkUK6alBpULKQAiKeFh 6K7g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773629447; x=1774234247; 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=sMIe4BH1dC23aKjJXdUIHsVXt5i12Nl20FH16xA6kBU=; b=bZ7zBYnHDOhgYFRIdo8mHLrDln1fTjG+S1fdwd7lEWAPmI6dgxVL2RYypI+jmqgBRO ck+cL1omMWit/wzmt8QESQQD5nHwE8BErpyRpD91dU0W5YdOYb6IZMKOe6WzFVxW3wsn W9dN1XULA5n10IUk/d31sTEV5pVcmyg082/9t3rXVCb15PFlXL29pktO8l4hGWsrON8u D5Pro49ZlNmo3V/waVLYtU6ZdUmIPs3oPLXuzFT8BqPFflAW5Uuvf+aM07k7sqw7f4So J1Ml6OvWcD5VZa5gV97ss76MxDUSkr2DbF9fJfzVhvVNeEi6fVC1HbvwrNXB2R/ZNfNA jWCg== X-Gm-Message-State: AOJu0Yw0xSfsr/zr08mYIZQMQU3SMGg5oHuMVDJ7oaH5GnR7DMPPzUQw rhr0cgO0v+ga6sCWCPb3e3dRHLEQKmKs4c1xm2+gHKR3eR1V6L/xaEGWarMTIQMW X-Gm-Gg: ATEYQzyNTL4Y09GaUWtm7L7ecx0HQJ6bHdgnBog2r6jNkpEAOcAuAT7VCZCXsyRy2LI MpIaLIqvaJOHZupMkYErRbgBEU80/UdxVIAiSTlC+6jIO3rRd/g6zT0dgKgOW3ro4lRDqtHMtdk DcB2kUJFmHmTwRPyQ359fEmzDBAh1gCZm1cQ4yXU+XFwV+Qw5GBQtVU9re2/TPn8+YRUO+v0S5c jXOAiWnjUPdNWSShVltio6uIFOiQTN+o7shmkoJjBVVcJSvTIC+DiTQJK5TkIqq3FJv8FqbY43B Vgv3Ff4J5dPe4P0InXCcO6JZk05eWy+D3L9IKDoVqJ72/SMYLB/i4fxaHmb9Mkb10pDHKuHl5ZL kJHU9jCixkPE8tLO1Vho7jLlJUWiXUch2kYjzBWU5Zfq6o12vNpUDeYA7e0ejpuNqBL2IZqHUsJ 7+RlIGjGID/2OC5IQvAbsHk2B97pVsKnxsvL7JHE8= X-Received: by 2002:a05:7301:d0f:b0:2be:ca4:e10b with SMTP id 5a478bee46e88-2bea55915eemr5065970eec.35.1773629446448; Sun, 15 Mar 2026 19:50:46 -0700 (PDT) From: Lucas Amaral To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, agraf@csgraf.de, peter.maydell@linaro.org, mohamed@unpredictable.fr, Lucas Amaral Subject: [PATCH v4 2/6] target/arm/emulate: add load/store register offset Date: Sun, 15 Mar 2026 23:50:30 -0300 Message-ID: <20260316025034.85611-3-lucaaamaral@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260316025034.85611-1-lucaaamaral@gmail.com> References: <20260315034123.41921-1-lucaaamaral@gmail.com> <20260316025034.85611-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::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: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773629551364154100 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 02fefc30..bf09e2a6 100644 --- a/target/arm/emulate/arm_emulate.c +++ b/target/arm/emulate/arm_emulate.c @@ -211,6 +211,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 04:41:54 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=1773629513; cv=none; d=zohomail.com; s=zohoarc; b=B+M1jxg/NW2FnBJSQl/mkQwJS7v863AXn1AFMhjUWLmx8RrbdmSn4CRPiqadxcqL9uwg2A62dOGhr1PxvjQAiqRfMVQgmiRQ5uBbIQhmOZLXwNS3kbw7FVL0skbBwLRKOKSJtUrlZl6alb8Id0Pdu6t5U2LGXx15Wbg/midQbsw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773629513; 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=GAsSc2doTgfK1k7+3MuUQJhqHA5GPQ1JX8r2cpgADWY=; b=MD72TLV6wPMoEi5ID8w8++xu3rlkZmahB6mknFLVyQV+Xjb4Gk8INFfz8OjB87z8JwVfFUh3p7yAyZOp19oZSb8fY2yadZHoqK+n3m6Y6hA9qeTP/XRCX4Znvs0oFHL1PCzkSvidgZtHk0dzBYzbn4RCS1kJYD1MhqcTrUDXogI= 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 1773629513140971.1852403251859; Sun, 15 Mar 2026 19:51:53 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w1y2h-00028E-Ms; Sun, 15 Mar 2026 22:50:55 -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 1w1y2f-00027f-Ok for qemu-devel@nongnu.org; Sun, 15 Mar 2026 22:50:53 -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 1w1y2d-0000WR-Ab for qemu-devel@nongnu.org; Sun, 15 Mar 2026 22:50:53 -0400 Received: by mail-dy1-x1333.google.com with SMTP id 5a478bee46e88-2c0b7eda342so729303eec.1 for ; Sun, 15 Mar 2026 19:50:50 -0700 (PDT) Received: from 192.168.7.2 ([189.6.247.75]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2beab3a12e2sm13138973eec.2.2026.03.15.19.50.46 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sun, 15 Mar 2026 19:50:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773629449; x=1774234249; 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=GAsSc2doTgfK1k7+3MuUQJhqHA5GPQ1JX8r2cpgADWY=; b=V721awQX/aGgNZQ/eAFqcykcXfAbD+cbSGkvlSNTJf+Z9nTWAGdLuj7IP/ubrI9YmC yDBAhk8miRAx2qvKUCFf0Yr2gZzKi0fyyLaXYlgtV5b86O9EO7RCiU6s3MAfLy7wSOlQ 6biahBeyaIit5Ockw9VgPI02YQ6ED/6yBG94uDKOqZlzbhk88jC+ztM1+QASa4UR2efB u37iXvTKyVqFgzc7DA/rPzkgukMZiirzMG5z3soclsgP/BHa/xa+/Ddq9qZj+KqxO1KG l/29Zo6YLJm+Fhxc8sa9N4NayYp4pOjdPwklyNl8kAc9ACK/NRgB04wveeXProq5pq6s UrsA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773629450; x=1774234250; 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=GAsSc2doTgfK1k7+3MuUQJhqHA5GPQ1JX8r2cpgADWY=; b=Lwyatprh9tdP9OZ5faNfvNuEEsd+H1fnOxGGrkuo7xAZD4Mm4CXLHZbNVNWx4dm8U2 gHrQGjeSQjMmB7dQh/BTVgVBIxSCFRU4AMyBQXYnpZzAnmoE9DhM6FZKs6MbmICDEdzN nUUm0C0uq0TbUrc43rMHYro54DVM1b9e09L9OeFZ7iEnv6HJo6qcqpy1e3CZD9OuI4hM 1cLLOWM2PHtRXyd9Ei3yU2ZzKwAPCu4Z9BuLdXzkH7nxw0UWlyRaxnFBfGiuLhNRzPX1 lZiSZz9m6jyGYbvLEWt0pb/WGQaBSMubAbnAricnnxuRWgQQEdKKJrBGmusM1Swgy7u9 482Q== X-Gm-Message-State: AOJu0Yy1LYFd0Ea19pVz4yK5S4I5gjc3iN9QpgAHo9gvUG460cq7u4sa xPtzYvnpXPtjzPAn9wjxD01XlTyluyWuxklAl/O/5bWqOeROapp9hoh0fmUSZzth X-Gm-Gg: ATEYQzwv+51IsMPvfndoy76GCC/ZRc1uV25M03iLN7rJI+4i0bQ5FtWzOeVipOAduHO CXzVMGScFOvNnxtPvhcVhBoH2KawPpQtX1qMIW21b8HMzcXJlYHV5KBuSpnWiJ08rZ++sL0LPww h1A3h6N1IOGvoGdQzeWB/8zwYPKLOgcnlU8eu97WDnQJcdZB7LDqP3beRGDwJjop70YQm/i7Ewv cjqTrcDO4Pwg3o9xAu4/uxmQSpMaJMeBPqHh0z6BCl16HNNVHl6qMXrgrBGmWbJmEICnddUA0+g IUnyCY21z8YwW2JkIJDwbzFmEwZc8kubLglKewVAKy1rbX3gpnxDb+oOA1EQLBEvcQKDyH2NGlb czHZTbqxgdgFT+8FS9VxjDUSAAEt+kJC4StH81sJwVyipRTYKf+RmPjhEiXEy356VUxXf19dL1C DkmvhQjimMtcyCn/ecS8CJyXCKrP+7525AzDX4fr8= X-Received: by 2002:a05:7300:6c27:b0:2be:aa:9a4a with SMTP id 5a478bee46e88-2bea51e50d3mr4119697eec.0.1773629449458; Sun, 15 Mar 2026 19:50:49 -0700 (PDT) From: Lucas Amaral To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, agraf@csgraf.de, peter.maydell@linaro.org, mohamed@unpredictable.fr, Lucas Amaral Subject: [PATCH v4 3/6] target/arm/emulate: add load/store pair Date: Sun, 15 Mar 2026 23:50:31 -0300 Message-ID: <20260316025034.85611-4-lucaaamaral@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260316025034.85611-1-lucaaamaral@gmail.com> References: <20260315034123.41921-1-lucaaamaral@gmail.com> <20260316025034.85611-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: 1773629515436158500 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 bf09e2a6..6c63a0d0 100644 --- a/target/arm/emulate/arm_emulate.c +++ b/target/arm/emulate/arm_emulate.c @@ -122,6 +122,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 04:41:54 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=1773629559; cv=none; d=zohomail.com; s=zohoarc; b=jJmjIk7ElUegs6WXSNyQxH4dvTwYx0A+fPMv0dB4AymKrKURdvWuFd23mtMbloVanYSkYDwiLApNeL+p/p8LDtKRskbXN8a3JyuSJylvDIenQ6gXdcb6Da5Diw8j7LwPa3earVtvTO982JgX/3s4rQJg8QRvOYm2SIiCwFq2opI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773629559; 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=iqLIpVr4djLYDOqzYTbrP//evleS3LXj53m2D/JbGEc=; b=Y9WURg+aPSRaOM+lOErdmziJD+FIC+OFqT0Bvbv5pd0i6Wzw210v2QeH6lwjx2NLAOT3TJtn6lA0GoDlhkWaRnO4ZaXDIK1X9vH57IbrC+WTVn7m51eyNYRiX0TND71DqJKIa23wRO7txPEY/h0aG5D71C62b7CqhBLJ16XLFhA= 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 1773629559639891.6705848799807; Sun, 15 Mar 2026 19:52:39 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w1y32-0002BJ-2O; Sun, 15 Mar 2026 22:51:16 -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 1w1y2i-00028N-27 for qemu-devel@nongnu.org; Sun, 15 Mar 2026 22:50:56 -0400 Received: from mail-dy1-x132c.google.com ([2607:f8b0:4864:20::132c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w1y2g-0000Wu-9J for qemu-devel@nongnu.org; Sun, 15 Mar 2026 22:50:55 -0400 Received: by mail-dy1-x132c.google.com with SMTP id 5a478bee46e88-2be4781d2baso1710110eec.0 for ; Sun, 15 Mar 2026 19:50:53 -0700 (PDT) Received: from 192.168.7.2 ([189.6.247.75]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2beab3a12e2sm13138973eec.2.2026.03.15.19.50.49 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sun, 15 Mar 2026 19:50:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773629453; x=1774234253; 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=iqLIpVr4djLYDOqzYTbrP//evleS3LXj53m2D/JbGEc=; b=J5MUEOBJpePp1l+DWz22xvTfAG1AvzPeNvEkmb3AlYDu3HFBE1pNBbiCxOOgGMQL9k IWxiIxDld7rsn8GOLidNwRRVHKEMHjzfHM5fQWlsXoX5Y51CEiMJK3zWn5z5ZSEAjqCa u+/St4BAAPxjMN0bd8xbCuNP3Q/MEYAdYTcIhprxKJMrS8+XNydx6PZ5ZyghTk9ySmKt SOcH/+gA7I5KEIDImQ9qceNvwPpWCP/R7VdRcfqQIEishwl811LQvOIi0cw+CLFxJQDF mAE9+O34FeTb4DoPxrDDFXBwp7/lOSDGMlZUvywTARu0PuLQbYMyyaFQ6xZTEPBCelDl lAAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773629453; x=1774234253; 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=iqLIpVr4djLYDOqzYTbrP//evleS3LXj53m2D/JbGEc=; b=F3C9V+mnmS8mQd2iEN/lyES8nsU/xbbvyD+MfZcfDh9RR/3iBvxlNGVgYTmY88Wgpq GO45BeF4r3SJyhBbNDDapksR888e0COfZzJIk3iI+GY+Ng9Aqp3eF8/hflgeZlgMC7Cl WCu50ezZiPCaLFWoZHbE9kBIYISwFU2U7xusm7V49F1kKo9Q9wLXQZuKHoT4JbkGLK9R ogO3lnaX2BEPqsml8zRR4HSTF9A7PcdhkFXex1acIus8VIR1XH/JsiQoOza8Cm7Wrfr/ 5uNod/QD3l9sUlTN/Gwm+xRS6TLUaCTakp3iEJbO9AYrh6yRt888T1ACLp3OOp3ZSPbv 7IkQ== X-Gm-Message-State: AOJu0YxceUqWUSD+XdaCwpDuLmGPq74F/r6uClXQFxUlXru6nDhkERtg CdL9iBWnWtt16Kn71ygtj3EZ2zKTF+WZo4xOAglulDYJWhdbhirqpqcXyQgVsGjD X-Gm-Gg: ATEYQzxu5hBkBauXtDJDV2ADjPpqGho6JNuCYUK1EYM7xnkIBlOMY8k3vpjaA75N5gE V3eGRpQhc6uSV5iEldHpvs5unl5d7gQQa2infEn5vYw660awtYOUEaorDxdXMq0eS5u5ZzYuQbK V08+fVIonDCXs5HSkl4KGBqGn71YKrAE8uq36makhqavR7FBZBkMqUdrh0nLQ8RVISlt/yYrcYb vZTq3TKQNyYFi0oyArmuSaopaffQKN3xIApLsj/2uS416+baA4NNR1KMxVWn7w+3tnKYNPPlibF BXFYSAKcgd09+2SgZ9/0Uz+6YhCazo625/MaDuOXB++5b7vnA9ZU973xq1BrTPIYBjGOW0rJB+e nngSQRkXbaj/crsoqvMcnMA+aEN6xe2QKxHW4wR9/5oA4kstBl9Oxg/ADvAUu/oNUw91jACwd7T L3QsQXgileJt/uUmABv+yg2FVNBPQcay28SAfMofir04kqWJxM5Q== X-Received: by 2002:a05:7300:fd02:b0:2be:8216:57db with SMTP id 5a478bee46e88-2bea5418f42mr5173298eec.3.1773629452552; Sun, 15 Mar 2026 19:50:52 -0700 (PDT) From: Lucas Amaral To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, agraf@csgraf.de, peter.maydell@linaro.org, mohamed@unpredictable.fr, Lucas Amaral Subject: [PATCH v4 4/6] target/arm/emulate: add load/store exclusive Date: Sun, 15 Mar 2026 23:50:32 -0300 Message-ID: <20260316025034.85611-5-lucaaamaral@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260316025034.85611-1-lucaaamaral@gmail.com> References: <20260315034123.41921-1-lucaaamaral@gmail.com> <20260316025034.85611-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::132c; envelope-from=lucaaamaral@gmail.com; helo=mail-dy1-x132c.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: 1773629561771158500 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 6c63a0d0..52e41703 100644 --- a/target/arm/emulate/arm_emulate.c +++ b/target/arm/emulate/arm_emulate.c @@ -425,6 +425,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 04:41:54 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=1773629505; cv=none; d=zohomail.com; s=zohoarc; b=HEUZgrjandFS/lzYfASpHg45yT0rlX5W5WOKa6vo+ZBqcxvr4hwVO6TNNXFUKJPlEe6p56ccfCV2XXx73yFaIIYG811Rv2WILu+AuKlpjPFVMBuYVGPts5CLC12Cl7+5h4jBtOKf1IFYEkgvKh3GOMohcsq0BeZSEZnUKMkhuD8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1773629505; 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=XUL3MdtW+tx35/EnWaKqwdzi9rS198ej4aXzJufMgC4=; b=kbTXNaybNXwBq1KkMUYwbZDuBd9/5+JCEnJs9qraP/XBkk/t8cMLIZnBKUObpb558stjnYWizirYnMpP5BjuqPAa+GkkMk+QJIM91SGCajTaX4fVbTg59vR/VFFuAqF8LsYHgGQN6w3GOWQrqNpYXWx33mu7iP3vd8a4EWyEmMg= 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 1773629505658783.3561467623972; Sun, 15 Mar 2026 19:51:45 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w1y31-0002Ag-Mu; Sun, 15 Mar 2026 22:51:15 -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 1w1y2l-00028k-K3 for qemu-devel@nongnu.org; Sun, 15 Mar 2026 22:51:00 -0400 Received: from mail-dy1-x1335.google.com ([2607:f8b0:4864:20::1335]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w1y2j-0000XZ-MW for qemu-devel@nongnu.org; Sun, 15 Mar 2026 22:50:59 -0400 Received: by mail-dy1-x1335.google.com with SMTP id 5a478bee46e88-2b4520f6b32so5826108eec.0 for ; Sun, 15 Mar 2026 19:50:57 -0700 (PDT) Received: from 192.168.7.2 ([189.6.247.75]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2beab3a12e2sm13138973eec.2.2026.03.15.19.50.53 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sun, 15 Mar 2026 19:50:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773629456; x=1774234256; 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=XUL3MdtW+tx35/EnWaKqwdzi9rS198ej4aXzJufMgC4=; b=dwcj5lurtvg7pZIyRb8yoWGWyVnPlScmVZKu00xIU0R/ODUsQKK4ixlCtulAO5uCWi g1eaYFEWufjLEXxE6fh8cJXzdmEZAc0GJYdHPbpHg+zci7stcbF1qPK/GMpjFUZNCjLP flvA99IkQUmrZG6cCVxufs0lwINvNaxi9yiQsaaaK/JFG7v3/+eOB1BYfs5R0Yk7P2JO lIWFaHR2sEJBRCz/Pq8ShB4lnuRlJ4tPkH35PVCqYEX9roXCPMwWgKM9h9o7L8QTLknp TDqnmjnAhsDm4oUxVv30/Jjf6eXN11X3XXzySOeFMOqs59uP95YVNpUtLQHcAlNywF2L vbNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773629456; x=1774234256; 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=XUL3MdtW+tx35/EnWaKqwdzi9rS198ej4aXzJufMgC4=; b=f8Q0Pl/PJl1EgljoiWvuvHt4LvNw0JCCNrqGDHhKoVwPN0qIZKLTAxuAbAVfkBj1We Nz9Dew0pIoZ0Wo4t7gN6EPY+Cxlcrewespj1XiATmfsyKhpVHab6MMu3spN4gw3nEjzT OMNXokMJ/cgftdA43tbRssau06m+0GBDg/s16ZQ1vZvDh47ueAF7/usnOiBICIwqyKw7 cA8pDA++C1LRfSq8rn1By5mnCsbgtCkSduj972LIasfJgLvzFYMTuIzeUkEJdEEKAURI wgnyGjp8Ny82OUfCugKsrnua1pfIa60pCielLwhA7ZGXoeP4JxQI3NVDQ+s/S1lysB2A 0NTQ== X-Gm-Message-State: AOJu0YzIcSig7zovEwr+83Q8qZt+OGGsYUbF1RlJmbffEuEs2R8xy0Vy EqFT1nUCzsxAGkaFpl9dKtDEjKEgTw+VukDLQeNatCkFzfSGuTsl/zsfrVRFMIM9 X-Gm-Gg: ATEYQzxDvdwimHcuHlTFnWrJh8LyH3ISQoA9HVKb0i3sZqYSktdn0MjItc1upc2GCnY Wqaz/rCFo0V8l3d9z/aJ9N6Dwmuqc4y5JHDKBg1AlVdDZAT+J99pzZCx2bCwmBX0Ta5fljryMGb i+bINLe7TZ20wtewR1cMVgNEFuLoByLxeIjWm+GfM4nMKaeiDBpeGl/DwAOBRjFGu/HJ8qKobh4 xNm6lsg5n0NLoDpNqYq0MZAQUWxmzfMqNn7IGhnujFA2hdMOKI9MjtmYnqtvqTmfBV4HkIMVd3M ejbfGh0cHwXIZQz1+xDkD0TCY+h8uALne7qPtaUmlzSc8VdEEd3TqAn7CO38g0oUgiAAP9O8Vwo GdGSufbtDS0J5mGI6FrDZar8viv0wKDFrIhEkUc0DyjZ73NDH5gIn4ejLCJ0v7cuzASYbWjbLvH gQr3UabKiT1049Cj6TEc4mxU2o3XIheyMGKoTftJ8= X-Received: by 2002:a05:7300:f194:b0:2bd:e892:b075 with SMTP id 5a478bee46e88-2bea547ccd6mr4942131eec.9.1773629455725; Sun, 15 Mar 2026 19:50:55 -0700 (PDT) From: Lucas Amaral To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, agraf@csgraf.de, peter.maydell@linaro.org, mohamed@unpredictable.fr, Lucas Amaral Subject: [PATCH v4 5/6] target/arm/emulate: add atomic, compare-and-swap, and PAC load Date: Sun, 15 Mar 2026 23:50:33 -0300 Message-ID: <20260316025034.85611-6-lucaaamaral@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260316025034.85611-1-lucaaamaral@gmail.com> References: <20260315034123.41921-1-lucaaamaral@gmail.com> <20260316025034.85611-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::1335; envelope-from=lucaaamaral@gmail.com; helo=mail-dy1-x1335.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=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1773629510275154100 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 52e41703..44a559ad 100644 --- a/target/arm/emulate/arm_emulate.c +++ b/target/arm/emulate/arm_emulate.c @@ -499,6 +499,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 04:41:54 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 1773629569508776.4727054501886; Sun, 15 Mar 2026 19:52:49 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1w1y33-0002Ci-PL; Sun, 15 Mar 2026 22:51:17 -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 1w1y2o-00029S-Oo for qemu-devel@nongnu.org; Sun, 15 Mar 2026 22:51:07 -0400 Received: from mail-dy1-x1336.google.com ([2607:f8b0:4864:20::1336]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1w1y2m-0000Xq-W9 for qemu-devel@nongnu.org; Sun, 15 Mar 2026 22:51:02 -0400 Received: by mail-dy1-x1336.google.com with SMTP id 5a478bee46e88-2c0bcd8f194so1134815eec.1 for ; Sun, 15 Mar 2026 19:51:00 -0700 (PDT) Received: from 192.168.7.2 ([189.6.247.75]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2beab3a12e2sm13138973eec.2.2026.03.15.19.50.56 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sun, 15 Mar 2026 19:50:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773629459; x=1774234259; 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=VoJVdciZFaewroq0cySKl+vu/S+aD/kerrA4/hB7jSw=; b=m8zq+Rx1Lv5r07qV6BcwN8l9DHgPlK/CLE8L2eaU1sYF5QCkCyCPfOMF9krQVdO8QH UkyAsOMuwrwV0zGs+VdJUW8Tf+Z/Y6D8Oi2uuOks9god0Prd6GfPpf0W+ZjpspxVJlZM s4WwPIER2Q79B4RYUbDlv4rObq6AWeu9k5YvHS5awEwj/fSBPdKnV9wbx7iwIRDB15W0 YLW3l4uNrEBPauP6S3FCSE4DtHO5HpsZkerB9cN6Pc/A+VG0z2sAtUmESe9DLji05xgQ eaS9eVi1DDENbdcrMiBWDfGnxwbDtijBYhupOuEnIWOHo+ie4VyYcHRJaTsnbla5Ut+h L2lw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773629459; x=1774234259; 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=VoJVdciZFaewroq0cySKl+vu/S+aD/kerrA4/hB7jSw=; b=hw0wIdvA8nMNGBFkwxwjBhuI6SG1ATVMM17W/9T9mDU/ta7rbB2GrQcQDMQRCCdzxo zsPqUYySVjPjkl9JNUctxmN+jvINyFjzvlq5080sxslvU+DT0T0Lt/OeOnruEPqeeRNv dxtMqni4t1a1JlMpbYdFD0/PicFhM2zWT73JAqO1BP8VQIXLBBJ1raqj1I09UQTGWeJc LHWpf1K7J5fXt/IiNW6KlcXYoAM+uaBgP5Gfpxvb3NMzaFQL2eQI8capBTf2tEpVllv3 oMCbPpOM2Z/4/a29ZhFgp8bDhqUX6BpGNnqRWDx11hqBuAnWl8I2tXBw+x2VCFTw20wo uHCQ== X-Gm-Message-State: AOJu0YyzT62uByxnJsSnzrOwZ8yQ9ihhw1oVyqyk7cVJq+Cr7vvuljzx Xw6pBzrgxjwMp6NyIiozq+DwkR0Zb1fdulxNxL4+IveBHqdv0AfqMX/b+xpCHoX3 X-Gm-Gg: ATEYQzwInNR+0odYkSUNc/kRJazWunefejeKTFecWB3e688NMYZZis9YCqy2NOpJGiH wuYH1tJ7DzQvqurr8PFCTvs4CLZz+0foro8CRfHoSu+L17GLnV/XYFXHGwYk97CWk66d5DmeoEk gXP3E2vQHPz4r44tCKYnqTfqucUkA6v0BQAmnZ4SS3e5F3GC9hTm6pt9lhUDp/aPNeYIXJD8tSX GJ7JOPuLvWn4RL0WoYlZQshYw2sPQbw8n4CeINbgdOhyn9tD7PCIYGf+901a2iBU3jS7+afF52z O1HXNBC8Xos+OIdZfxzLlsy9IwAtEq2dJmxp5+Jr1eikx8Swv6SMKd6SXLfgtkR7B22GoL9morv neyue0ZCAQcdCXCHSSl1lNX49lORJlrnibas4mGsC6sZRp3SM0Tg+R02Fey8nKvSJFKdu1rCzCG Q3YvdvShDaC/TsmhnFOjes+HtlZ/G/60vWHpGe5BXpLvrTTWqABg== X-Received: by 2002:a05:693c:3113:b0:2b7:fdb6:ccf6 with SMTP id 5a478bee46e88-2bea547ecd8mr4693975eec.14.1773629458994; Sun, 15 Mar 2026 19:50:58 -0700 (PDT) From: Lucas Amaral To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, agraf@csgraf.de, peter.maydell@linaro.org, mohamed@unpredictable.fr, Lucas Amaral Subject: [PATCH v4 6/6] target/arm/hvf, whpx: wire ISV=0 emulation for data aborts Date: Sun, 15 Mar 2026 23:50:34 -0300 Message-ID: <20260316025034.85611-7-lucaaamaral@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260316025034.85611-1-lucaaamaral@gmail.com> References: <20260315034123.41921-1-lucaaamaral@gmail.com> <20260316025034.85611-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::1336; envelope-from=lucaaamaral@gmail.com; helo=mail-dy1-x1336.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: 1773629571852154100 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. On success, advance PC past the emulated instruction If the instruction is unhandled or a memory error occurs, a synchronous external abort is injected into the guest via syn_data_abort_no_iss() with fnv=3D1 and fsc=3D0x10, matching the syndrome that KVM uses in kvm_inject_arm_sea(). The guest kernel's fault handler then reports the error through its normal data abort path. WHPX adds a whpx_inject_data_abort() helper and adjusts the whpx_handle_mmio() return convention so the caller skips PC advancement when an exception has been injected. Signed-off-by: Lucas Amaral --- target/arm/hvf/hvf.c | 46 ++++++++++++++++++++++++++-- target/arm/whpx/whpx-all.c | 61 +++++++++++++++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 4 deletions(-) diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c index 5fc8f6bb..000e54bd 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,49 @@ 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/. */ - 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) { + bool same_el =3D arm_current_el(env) =3D=3D 1; + uint32_t esr =3D syn_data_abort_no_iss(same_el, + 1, 0, 0, 0, iswrite, 0x10); + + error_report("HVF: cannot read insn at pc=3D0x%" PRIx64, + (uint64_t)env->pc); + env->exception.vaddress =3D excp->virtual_address; + hvf_raise_exception(cpu, EXCP_DATA_ABORT, esr, 1); + break; + } + + r =3D arm_emul_insn(env, insn); + if (r =3D=3D ARM_EMUL_UNHANDLED || r =3D=3D ARM_EMUL_ERR_MEM) { + bool same_el =3D arm_current_el(env) =3D=3D 1; + uint32_t esr =3D syn_data_abort_no_iss(same_el, + 1, 0, 0, 0, iswrite, 0x10); + + error_report("HVF: ISV=3D0 %s insn 0x%08x at " + "pc=3D0x%" PRIx64 ", injecting data abort", + r =3D=3D ARM_EMUL_UNHANDLED ? "unhandled" + : "memory error", + insn, (uint64_t)env->pc); + env->exception.vaddress =3D excp->virtual_address; + hvf_raise_exception(cpu, EXCP_DATA_ABORT, esr, 1); + break; + } + + 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..0c04073e 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" @@ -352,6 +353,27 @@ static void whpx_set_gp_reg(CPUState *cpu, int rt, uin= t64_t val) whpx_set_reg(cpu, reg, reg_val); } =20 +/* + * Inject a synchronous external abort (data abort) into the guest. + * Used when ISV=3D0 instruction emulation fails. Matches the syndrome + * that KVM uses in kvm_inject_arm_sea(). + */ +static void whpx_inject_data_abort(CPUState *cpu, bool iswrite) +{ + ARMCPU *arm_cpu =3D ARM_CPU(cpu); + CPUARMState *env =3D &arm_cpu->env; + bool same_el =3D arm_current_el(env) =3D=3D 1; + uint32_t esr =3D syn_data_abort_no_iss(same_el, 1, 0, 0, 0, iswrite, 0= x10); + + cpu->exception_index =3D EXCP_DATA_ABORT; + env->exception.target_el =3D 1; + env->exception.syndrome =3D esr; + + bql_lock(); + arm_cpu_do_interrupt(cpu); + bql_unlock(); +} + static int whpx_handle_mmio(CPUState *cpu, WHV_MEMORY_ACCESS_CONTEXT *ctx) { uint64_t syndrome =3D ctx->Syndrome; @@ -366,7 +388,40 @@ 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); + whpx_inject_data_abort(cpu, iswrite); + return 1; + } + + r =3D arm_emul_insn(env, insn); + if (r =3D=3D ARM_EMUL_UNHANDLED || r =3D=3D ARM_EMUL_ERR_MEM) { + error_report("WHPX: ISV=3D0 %s insn 0x%08x at " + "pc=3D0x%" PRIx64 ", injecting data abort", + r =3D=3D ARM_EMUL_UNHANDLED ? "unhandled" + : "memory error", + insn, (uint64_t)env->pc); + whpx_inject_data_abort(cpu, iswrite); + return 1; + } + + return 0; + } =20 if (iswrite) { val =3D whpx_get_gp_reg(cpu, srt); @@ -451,6 +506,10 @@ int whpx_vcpu_run(CPUState *cpu) } =20 ret =3D whpx_handle_mmio(cpu, &vcpu->exit_ctx.MemoryAccess); + if (ret > 0) { + advance_pc =3D false; + ret =3D 0; + } break; case WHvRunVpExitReasonCanceled: cpu->exception_index =3D EXCP_INTERRUPT; --=20 2.52.0