From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304836; cv=none; d=zohomail.com; s=zohoarc; b=fLepA+XkXHDocYcKBxGVHNGqhq0ZubwqMZVGJPKm1M4atvsWwxqJ1oDeZJosi9/2Hhd1D4epVfBYLH3rnkC3x2CYfFrEBQ0bVhw2qeZUK9Eh6whuRiAH+FKH9Irwi+dos78KodohV9Jwr4pSLAZ40F5CMvr59+rOE5SlZKtHf/A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304836; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=jtBlDG6AzO3GlcmI9dLf0KajP9v35d6tlu+6KN68VhM=; b=k/2bfzB8itybrBKYMkO2c19cKCAJziFCZh2v10yKlpJh3Lf192zKbA0559wX/LZtFSBGjyidPvX7T1j5lAGUcCQ1/VTfoxdLD3y1e2x9yTQohduP3K+wtc7kef+WhDaAH6tTxOmw+UkO5C41BH+rwnfAwkpXwMttbMyeniZJFKo= 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 1673304836725870.8163847019082; Mon, 9 Jan 2023 14:53:56 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0qr-00040L-KK; Mon, 09 Jan 2023 17:42:46 -0500 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 1pF0qp-0003zU-IO; Mon, 09 Jan 2023 17:42:44 -0500 Received: from smtp-out2.suse.de ([2001:67c:2178:6::1d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0qn-0003xs-SX; Mon, 09 Jan 2023 17:42:43 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 6766F5CDD7; Mon, 9 Jan 2023 22:42:40 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id CAB2213583; Mon, 9 Jan 2023 22:42:37 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id QHORJF2YvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:42:37 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304160; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jtBlDG6AzO3GlcmI9dLf0KajP9v35d6tlu+6KN68VhM=; b=b20Wjfdj49+6UZy4f7UN5spygZQ4CIdDxx5K8K+JtO8hn7F2c9Ao7UBuV41H/fvmN9qqrR caaSUhylWuoLLI/fGKj/GiK0SL2sMiJRgiFBCxegYYL0W6XK+DiEWR8iFxu0DVHZezqV1I 94FdgS5wF9FkZpTqQPh0bdOnnwx+q6c= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304160; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jtBlDG6AzO3GlcmI9dLf0KajP9v35d6tlu+6KN68VhM=; b=pFA+8el8wPtQN2WUN4f9B5X04Wax0w1KpTQR7cRTQB61eCyzRstYpEzIDU2aiaVNJm2Cw+ U+2yLHFOW1OBXDBg== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf Subject: [RFC PATCH v2 01/19] target/arm: rename handle_semihosting to tcg_handle_semihosting Date: Mon, 9 Jan 2023 19:42:14 -0300 Message-Id: <20230109224232.11661-2-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=2001:67c:2178:6::1d; envelope-from=farosas@suse.de; helo=smtp-out2.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304837916100001 From: Claudio Fontana make it clearer from the name that this is a tcg-only function. Signed-off-by: Claudio Fontana Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- target/arm/helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index cee3804354..e02a463d46 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -10765,7 +10765,7 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *= cs) * trapped to the hypervisor in KVM. */ #ifdef CONFIG_TCG -static void handle_semihosting(CPUState *cs) +static void tcg_handle_semihosting(CPUState *cs) { ARMCPU *cpu =3D ARM_CPU(cs); CPUARMState *env =3D &cpu->env; @@ -10827,7 +10827,7 @@ void arm_cpu_do_interrupt(CPUState *cs) */ #ifdef CONFIG_TCG if (cs->exception_index =3D=3D EXCP_SEMIHOST) { - handle_semihosting(cs); + tcg_handle_semihosting(cs); return; } #endif --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304538; cv=none; d=zohomail.com; s=zohoarc; b=nozrTqt50KK5ZIZKtMAMdfZQVXYfVWfoiECH3Ec/m4gbsJtAh+/mz4Uz8lUzoCIeeTmc4uHIG3NIwUIf+K4VI3PMqmaTpmWUHdXQLrn4gFF06pJcmRcMAnQtE3WS//5qDig1gJPVk19nVW85j45j4L0aUJ5duoYlrnek3aqMi6Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304538; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=i9+pzyUsDGtshwlle5j06h5MGSSDuJHxlDLTwBzpln4=; b=B/MS+8WpZNuYiQ1PDE+cmdwIShY2Vx3svl6u2hEouoQ+vc9bU/Uiu+PSyCwM5pHyeVuchnyqBlOZGTTrTd426Ss7tBZmhcWcK+o4Cnt/bFgCh+MyOkELVJeJiKIAE/3DrtBD1kEW6p9sZvlWma3mxAjB4bKNvZsWl7qyozib9gA= 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 1673304538354558.0184626828642; Mon, 9 Jan 2023 14:48:58 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0r1-00042a-UM; Mon, 09 Jan 2023 17:42:55 -0500 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 1pF0qs-00040p-Md; Mon, 09 Jan 2023 17:42:48 -0500 Received: from smtp-out1.suse.de ([2001:67c:2178:6::1c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0qr-0003yU-Bw; Mon, 09 Jan 2023 17:42:46 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 6A5064039E; Mon, 9 Jan 2023 22:42:43 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id CC6F713583; Mon, 9 Jan 2023 22:42:40 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id YOQdJWCYvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:42:40 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304163; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=i9+pzyUsDGtshwlle5j06h5MGSSDuJHxlDLTwBzpln4=; b=z/hj0ZAli6eBXfcbKpkBdfgSIGhdULT5+C6E3eFxGBDFtisKFoiDsyY5k+Uvy2oNeppJ6d CFyptisMTpeQ1iSqHn+wIdHUkJEp9vH+qAkY2ZkWlAJEOVKJjfgWSElxRgxYUQ5WCLOPKj DC2vG7az+bw+VF0sydYjINHMtpfia2I= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304163; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=i9+pzyUsDGtshwlle5j06h5MGSSDuJHxlDLTwBzpln4=; b=Bn+iZOWPWX4Y0OWMV2gBGTQ8LbkJnM3YrWx0W6MZuFZ2vpgeIuBYiRFMk+rUHYahRsyDVI OizAaINv+ngyHhAA== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf Subject: [RFC PATCH v2 02/19] target/arm: wrap psci call with tcg_enabled Date: Mon, 9 Jan 2023 19:42:15 -0300 Message-Id: <20230109224232.11661-3-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=2001:67c:2178:6::1c; envelope-from=farosas@suse.de; helo=smtp-out1.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304539847100003 Content-Type: text/plain; charset="utf-8" From: Claudio Fontana for "all" builds (tcg + kvm), we want to avoid doing the psci check if tcg is built-in, but not enabled. Signed-off-by: Claudio Fontana Reviewed-by: Richard Henderson Signed-off-by: Fabiano Rosas --- target/arm/helper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index e02a463d46..9cc136b508 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -22,6 +22,7 @@ #include "hw/irq.h" #include "sysemu/cpu-timers.h" #include "sysemu/kvm.h" +#include "sysemu/tcg.h" #include "qapi/qapi-commands-machine-target.h" #include "qapi/error.h" #include "qemu/guest-random.h" @@ -10814,7 +10815,7 @@ void arm_cpu_do_interrupt(CPUState *cs) env->exception.syndrome); } =20 - if (arm_is_psci_call(cpu, cs->exception_index)) { + if (tcg_enabled() && arm_is_psci_call(cpu, cs->exception_index)) { arm_handle_psci_call(cpu); qemu_log_mask(CPU_LOG_INT, "...handled as PSCI call\n"); return; --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304207; cv=none; d=zohomail.com; s=zohoarc; b=LHjHzGonBTrXEX4Jkt6ZI+3oRFi8KU52nfqkpRbT8EsJX57b6VYkuER+XJNjJSXDOT2LgQL4zkZhv6wkcc1vdSzF3aD6SrY6HYWybDBRnzY71b6EJdxVFBzqN5FkJTqi2YYLQc52VP1A5sVlLHdjtebXnM+SpcWxXPGrSuzOUG0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304207; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=h3KkNITzSs94Fyk0YxMQd+TgFbMPFMYrLs7cwANF9j0=; b=S9rTT3fUO7e2mSLM82cOD+rtVgM9UsS7F26peYt2srPJqxQMPz1eVLbY3p9tLPr5w0sll/BrRuZm5K6aBYiHEbu09hHLLAqWrFVSkP151zFXIhK1Vzl8Vig19qtQKmsPTmN3PV3EFbwSTJuL+koy+xc+lwON1KMzqfQtFainRIw= 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 1673304207752967.7874240145794; Mon, 9 Jan 2023 14:43:27 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0qz-00041l-Ve; Mon, 09 Jan 2023 17:42:54 -0500 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 1pF0qv-000414-Ii; Mon, 09 Jan 2023 17:42:49 -0500 Received: from smtp-out1.suse.de ([195.135.220.28]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0qu-0003yh-1b; Mon, 09 Jan 2023 17:42:49 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 66CDC4D34C; Mon, 9 Jan 2023 22:42:46 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id CF06E13583; Mon, 9 Jan 2023 22:42:43 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id sE2qJWOYvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:42:43 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304166; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=h3KkNITzSs94Fyk0YxMQd+TgFbMPFMYrLs7cwANF9j0=; b=DMup9pbsXPiB30ZSrF5liE/1wQfoXzrShyxiDqr1YfTKlWpIei+PN0NAZq4ToXztkb4d3E xu9rGedpHS4lOS4VnnZ8fRBpngOILKkIPiw/XPiMftqvvj2UT3EFWc7z5m2Q75+1szicwL Ub1JheJ+bPKEbgarJW5W/1t0YNugS58= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304166; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=h3KkNITzSs94Fyk0YxMQd+TgFbMPFMYrLs7cwANF9j0=; b=iWw3yOgOZn5FwSHPNSI3/8lQH8AVTQRBDwTCti9uJ1qlTsZzikrlfpe24+Ze/4aRk0G4Sp QD3t2ArzAQMnJqCA== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf Subject: [RFC PATCH v2 03/19] target/arm: wrap call to aarch64_sve_change_el in tcg_enabled() Date: Mon, 9 Jan 2023 19:42:16 -0300 Message-Id: <20230109224232.11661-4-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=195.135.220.28; envelope-from=farosas@suse.de; helo=smtp-out1.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304208068100003 Content-Type: text/plain; charset="utf-8" From: Claudio Fontana Signed-off-by: Claudio Fontana Reviewed-by: Richard Henderson Signed-off-by: Fabiano Rosas --- target/arm/helper.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index 9cc136b508..ddb0d76b70 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -10578,11 +10578,13 @@ static void arm_cpu_do_interrupt_aarch64(CPUState= *cs) unsigned int cur_el =3D arm_current_el(env); int rt; =20 - /* - * Note that new_el can never be 0. If cur_el is 0, then - * el0_a64 is is_a64(), else el0_a64 is ignored. - */ - aarch64_sve_change_el(env, cur_el, new_el, is_a64(env)); + if (tcg_enabled()) { + /* + * Note that new_el can never be 0. If cur_el is 0, then + * el0_a64 is is_a64(), else el0_a64 is ignored. + */ + aarch64_sve_change_el(env, cur_el, new_el, is_a64(env)); + } =20 if (cur_el < new_el) { /* --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304301; cv=none; d=zohomail.com; s=zohoarc; b=Sc17IuwsYkOTcpLi3T53JnCQrMamB2o0NY1hgOxMqrOtOIauWq9Iq7lc46MPFIviX1FI+Az7BzZ9p8g3qDgolNkvHKdbM8UCymSlDfK/PmGGjj7860hRENfjJsepYELhGrDUCSM6UiuYtufFn+4e7rKnLUAntMDEGzYPkCWugpY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304301; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=eeJh5uMajepX2o6i3IFybvlJ7FeTuN8w6d/EVXkaFcg=; b=GRz0kk3HM4kf3NT++1EPYpYFQVOIVn2jrOkAcACWwxvYWGRjhMUUuAlhYw9/XaEUPO+69Oi56NIv65NLZ3JdidFsbG2Fy1YUvtfYwno7lf9GTN4mOrLfcqCWirmB3XDyxuUPzf+DaFpiroxupuObT3Yy9rxUeKs7ESb0oMe+GMQ= 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 1673304301930261.7090550266446; Mon, 9 Jan 2023 14:45:01 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0r3-00043d-85; Mon, 09 Jan 2023 17:42:57 -0500 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 1pF0qy-00041n-M4; Mon, 09 Jan 2023 17:42:52 -0500 Received: from smtp-out1.suse.de ([195.135.220.28]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0qx-0003z9-7N; Mon, 09 Jan 2023 17:42:52 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 5FF7D4D35C; Mon, 9 Jan 2023 22:42:49 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id CB19913583; Mon, 9 Jan 2023 22:42:46 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id GI3vJGaYvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:42:46 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304169; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eeJh5uMajepX2o6i3IFybvlJ7FeTuN8w6d/EVXkaFcg=; b=W7w2ZfA+OS3TLuHnzSQQmo/0hO4Bjh7AXLJo32S+dXnb28aS5Djcrl0O5YbhgOYY4MoTBq FIlSRbhXystX61n2VXVBGiZVDK7+G7CtZDlnM2bgjjhwwYplpuwyPheaXUAUByZt/Ex34P 3KNBlo1tXio6Y9C21jSFKIwHEiG9G8w= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304169; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eeJh5uMajepX2o6i3IFybvlJ7FeTuN8w6d/EVXkaFcg=; b=JTBLw/p+onaNR+xQy818F0DlmfB58GdF2iio0dn2dCCAFDqjMqC1ssZsTlpjA+yeARDdvh gan8XgoRPgjj0yCA== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf Subject: [RFC PATCH v2 04/19] target/arm: Move PC alignment check Date: Mon, 9 Jan 2023 19:42:17 -0300 Message-Id: <20230109224232.11661-5-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=195.135.220.28; envelope-from=farosas@suse.de; helo=smtp-out1.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304302475100005 Content-Type: text/plain; charset="utf-8" Move this earlier to make the next patch diff cleaner. While here update the comment slightly to not give the impression that the misalignment affects only TCG. Reviewed-by: Richard Henderson Signed-off-by: Fabiano Rosas --- target/arm/machine.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/target/arm/machine.c b/target/arm/machine.c index 5f26152652..b4c3850570 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -839,6 +839,15 @@ static int cpu_post_load(void *opaque, int version_id) } } =20 + /* + * Misaligned thumb pc is architecturally impossible. Fail the + * incoming migration. For TCG it would trigger the assert in + * thumb_tr_translate_insn(). + */ + if (!is_a64(env) && env->thumb && (env->regs[15] & 1)) { + return -1; + } + hw_breakpoint_update_all(cpu); hw_watchpoint_update_all(cpu); =20 @@ -856,15 +865,6 @@ static int cpu_post_load(void *opaque, int version_id) } } =20 - /* - * Misaligned thumb pc is architecturally impossible. - * We have an assert in thumb_tr_translate_insn to verify this. - * Fail an incoming migrate to avoid this assert. - */ - if (!is_a64(env) && env->thumb && (env->regs[15] & 1)) { - return -1; - } - if (!kvm_enabled()) { pmu_op_finish(&cpu->env); } --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304302; cv=none; d=zohomail.com; s=zohoarc; b=UAD7XYIJWsPBm1yBsKXsBfqYDYobZad6P8R1G/Y9fQNBiF6IEbKOn0ly6yOAkq1/5v71XW/bLsxhVzrJTkBOX8DH+VGAq8g6KcCjBQNo3rGfHm7vohbWbvlZpceX6YnMnuJ1IPfwcc1cKXM63IFzcytoSnYKjNmuBio9CWwtNeA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304302; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=MJwG2qJhZLBd6/SRDBYGioYmK7lhgk4d0aK1OOo/P7c=; b=bzrj9eBpShgRv9wagtKAvjxTzfb8vpNKRCb8lfzvQVzo0hMNoxx06MQG2zouhaz3ZtwmkaBKY8nn53M6XH9ZyJgx+ABjNtbGsVmBYTfhTUtWCNpAK435dsdg+HBFw2NKMhfANseiOn8VEffqvMPvkLZLq8Y7CMH+eEqSf5HvlL8= 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 1673304302055819.155748205401; Mon, 9 Jan 2023 14:45:02 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0rB-00048C-Fo; Mon, 09 Jan 2023 17:43:05 -0500 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 1pF0r8-00046f-OL; Mon, 09 Jan 2023 17:43:02 -0500 Received: from smtp-out1.suse.de ([2001:67c:2178:6::1c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0r2-0003zW-5r; Mon, 09 Jan 2023 17:43:02 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 886534039E; Mon, 9 Jan 2023 22:42:53 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id CB92813583; Mon, 9 Jan 2023 22:42:49 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id oBfxJGmYvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:42:49 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304173; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MJwG2qJhZLBd6/SRDBYGioYmK7lhgk4d0aK1OOo/P7c=; b=F6HeCpbybvzdYB4xxxe+u/6xLkyNlF9tqDi5NKeuX4utEdmD/+q9qT5vnY7YNOhv9o/z+Q BAeSdplUm6zTtoT49XHVd5yPyfolXuRldIGLOHj/hYCgUVQQ6zI9B2RvS1Z9Gdvoccnkex jvN2Coc+5oLo87LRgDYow4zxkroQPcA= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304173; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MJwG2qJhZLBd6/SRDBYGioYmK7lhgk4d0aK1OOo/P7c=; b=53a3//TdPPqMuAGXgXa3p0TtLcNb7Phnwg02SQqEKWx3dylgPMmPBV1a1REeFK7FHjsxcp ZLbA7NhSobL/huDQ== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf Subject: [RFC PATCH v2 05/19] target/arm: Move cpregs code into cpregs.c Date: Mon, 9 Jan 2023 19:42:18 -0300 Message-Id: <20230109224232.11661-6-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=2001:67c:2178:6::1c; envelope-from=farosas@suse.de; helo=smtp-out1.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304303125100007 Content-Type: text/plain; charset="utf-8" Code moved verbatim. Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson --- target/arm/cpregs.c | 9089 ++++++++++++++++++++++++++++++++++++ target/arm/cpu.c | 1 + target/arm/helper.c | 9067 ----------------------------------- target/arm/machine.c | 1 + target/arm/meson.build | 1 + target/arm/op_helper.c | 1 + target/arm/trace-events | 2 +- target/arm/translate-a64.c | 1 + target/arm/translate.c | 1 + 9 files changed, 9096 insertions(+), 9068 deletions(-) create mode 100644 target/arm/cpregs.c diff --git a/target/arm/cpregs.c b/target/arm/cpregs.c new file mode 100644 index 0000000000..9f15337b68 --- /dev/null +++ b/target/arm/cpregs.c @@ -0,0 +1,9089 @@ +/* + * ARM CP registers + * + * This code is licensed under the GNU GPL v2 or later. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "trace.h" +#include "cpu.h" +#include "internals.h" +#include "exec/helper-proto.h" +#include "qemu/main-loop.h" +#include "exec/exec-all.h" +#include "hw/irq.h" +#include "sysemu/cpu-timers.h" +#include "qapi/error.h" +#include "qemu/guest-random.h" +#include "cpregs.h" + +#define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */ + +static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + assert(ri->fieldoffset); + if (cpreg_field_is_64bit(ri)) { + return CPREG_FIELD64(env, ri); + } else { + return CPREG_FIELD32(env, ri); + } +} + +void raw_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) +{ + assert(ri->fieldoffset); + if (cpreg_field_is_64bit(ri)) { + CPREG_FIELD64(env, ri) =3D value; + } else { + CPREG_FIELD32(env, ri) =3D value; + } +} + +static void *raw_ptr(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return (char *)env + ri->fieldoffset; +} + +uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri) +{ + /* Raw read of a coprocessor register (as needed for migration, etc). = */ + if (ri->type & ARM_CP_CONST) { + return ri->resetvalue; + } else if (ri->raw_readfn) { + return ri->raw_readfn(env, ri); + } else if (ri->readfn) { + return ri->readfn(env, ri); + } else { + return raw_read(env, ri); + } +} + +static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t v) +{ + /* + * Raw write of a coprocessor register (as needed for migration, etc). + * Note that constant registers are treated as write-ignored; the + * caller should check for success by whether a readback gives the + * value written. + */ + if (ri->type & ARM_CP_CONST) { + return; + } else if (ri->raw_writefn) { + ri->raw_writefn(env, ri, v); + } else if (ri->writefn) { + ri->writefn(env, ri, v); + } else { + raw_write(env, ri, v); + } +} + +static bool raw_accessors_invalid(const ARMCPRegInfo *ri) +{ + /* + * Return true if the regdef would cause an assertion if you called + * read_raw_cp_reg() or write_raw_cp_reg() on it (ie if it is a + * program bug for it not to have the NO_RAW flag). + * NB that returning false here doesn't necessarily mean that calling + * read/write_raw_cp_reg() is safe, because we can't distinguish "has + * read/write access functions which are safe for raw use" from "has + * read/write access functions which have side effects but has forgotten + * to provide raw access functions". + * The tests here line up with the conditions in read/write_raw_cp_reg() + * and assertions in raw_read()/raw_write(). + */ + if ((ri->type & ARM_CP_CONST) || + ri->fieldoffset || + ((ri->raw_writefn || ri->writefn) && (ri->raw_readfn || ri->readfn= ))) { + return false; + } + return true; +} + +bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) +{ + /* Write the coprocessor state from cpu->env to the (index,value) list= . */ + int i; + bool ok =3D true; + + for (i =3D 0; i < cpu->cpreg_array_len; i++) { + uint32_t regidx =3D kvm_to_cpreg_id(cpu->cpreg_indexes[i]); + const ARMCPRegInfo *ri; + uint64_t newval; + + ri =3D get_arm_cp_reginfo(cpu->cp_regs, regidx); + if (!ri) { + ok =3D false; + continue; + } + if (ri->type & ARM_CP_NO_RAW) { + continue; + } + + newval =3D read_raw_cp_reg(&cpu->env, ri); + if (kvm_sync) { + /* + * Only sync if the previous list->cpustate sync succeeded. + * Rather than tracking the success/failure state for every + * item in the list, we just recheck "does the raw write we mu= st + * have made in write_list_to_cpustate() read back OK" here. + */ + uint64_t oldval =3D cpu->cpreg_values[i]; + + if (oldval =3D=3D newval) { + continue; + } + + write_raw_cp_reg(&cpu->env, ri, oldval); + if (read_raw_cp_reg(&cpu->env, ri) !=3D oldval) { + continue; + } + + write_raw_cp_reg(&cpu->env, ri, newval); + } + cpu->cpreg_values[i] =3D newval; + } + return ok; +} + +bool write_list_to_cpustate(ARMCPU *cpu) +{ + int i; + bool ok =3D true; + + for (i =3D 0; i < cpu->cpreg_array_len; i++) { + uint32_t regidx =3D kvm_to_cpreg_id(cpu->cpreg_indexes[i]); + uint64_t v =3D cpu->cpreg_values[i]; + const ARMCPRegInfo *ri; + + ri =3D get_arm_cp_reginfo(cpu->cp_regs, regidx); + if (!ri) { + ok =3D false; + continue; + } + if (ri->type & ARM_CP_NO_RAW) { + continue; + } + /* + * Write value and confirm it reads back as written + * (to catch read-only registers and partially read-only + * registers where the incoming migration value doesn't match) + */ + write_raw_cp_reg(&cpu->env, ri, v); + if (read_raw_cp_reg(&cpu->env, ri) !=3D v) { + ok =3D false; + } + } + return ok; +} + +static void add_cpreg_to_list(gpointer key, gpointer opaque) +{ + ARMCPU *cpu =3D opaque; + uint32_t regidx =3D (uintptr_t)key; + const ARMCPRegInfo *ri =3D get_arm_cp_reginfo(cpu->cp_regs, regidx); + + if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_ALIAS))) { + cpu->cpreg_indexes[cpu->cpreg_array_len] =3D cpreg_to_kvm_id(regid= x); + /* The value array need not be initialized at this point */ + cpu->cpreg_array_len++; + } +} + +static void count_cpreg(gpointer key, gpointer opaque) +{ + ARMCPU *cpu =3D opaque; + const ARMCPRegInfo *ri; + + ri =3D g_hash_table_lookup(cpu->cp_regs, key); + + if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_ALIAS))) { + cpu->cpreg_array_len++; + } +} + +static gint cpreg_key_compare(gconstpointer a, gconstpointer b) +{ + uint64_t aidx =3D cpreg_to_kvm_id((uintptr_t)a); + uint64_t bidx =3D cpreg_to_kvm_id((uintptr_t)b); + + if (aidx > bidx) { + return 1; + } + if (aidx < bidx) { + return -1; + } + return 0; +} + +void init_cpreg_list(ARMCPU *cpu) +{ + /* + * Initialise the cpreg_tuples[] array based on the cp_regs hash. + * Note that we require cpreg_tuples[] to be sorted by key ID. + */ + GList *keys; + int arraylen; + + keys =3D g_hash_table_get_keys(cpu->cp_regs); + keys =3D g_list_sort(keys, cpreg_key_compare); + + cpu->cpreg_array_len =3D 0; + + g_list_foreach(keys, count_cpreg, cpu); + + arraylen =3D cpu->cpreg_array_len; + cpu->cpreg_indexes =3D g_new(uint64_t, arraylen); + cpu->cpreg_values =3D g_new(uint64_t, arraylen); + cpu->cpreg_vmstate_indexes =3D g_new(uint64_t, arraylen); + cpu->cpreg_vmstate_values =3D g_new(uint64_t, arraylen); + cpu->cpreg_vmstate_array_len =3D cpu->cpreg_array_len; + cpu->cpreg_array_len =3D 0; + + g_list_foreach(keys, add_cpreg_to_list, cpu); + + assert(cpu->cpreg_array_len =3D=3D arraylen); + + g_list_free(keys); +} + +/* + * Some registers are not accessible from AArch32 EL3 if SCR.NS =3D=3D 0. + */ +static CPAccessResult access_el3_aa32ns(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + if (!is_a64(env) && arm_current_el(env) =3D=3D 3 && + arm_is_secure_below_el3(env)) { + return CP_ACCESS_TRAP_UNCATEGORIZED; + } + return CP_ACCESS_OK; +} + +/* + * Some secure-only AArch32 registers trap to EL3 if used from + * Secure EL1 (but are just ordinary UNDEF in other non-EL3 contexts). + * Note that an access from Secure EL1 can only happen if EL3 is AArch64. + * We assume that the .access field is set to PL1_RW. + */ +static CPAccessResult access_trap_aa32s_el1(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + if (arm_current_el(env) =3D=3D 3) { + return CP_ACCESS_OK; + } + if (arm_is_secure_below_el3(env)) { + if (env->cp15.scr_el3 & SCR_EEL2) { + return CP_ACCESS_TRAP_EL2; + } + return CP_ACCESS_TRAP_EL3; + } + /* This will be EL1 NS and EL2 NS, which just UNDEF */ + return CP_ACCESS_TRAP_UNCATEGORIZED; +} + +/* + * Check for traps to performance monitor registers, which are controlled + * by MDCR_EL2.TPM for EL2 and MDCR_EL3.TPM for EL3. + */ +static CPAccessResult access_tpm(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + int el =3D arm_current_el(env); + uint64_t mdcr_el2 =3D arm_mdcr_el2_eff(env); + + if (el < 2 && (mdcr_el2 & MDCR_TPM)) { + return CP_ACCESS_TRAP_EL2; + } + if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + +/* Check for traps from EL1 due to HCR_EL2.TVM and HCR_EL2.TRVM. */ +static CPAccessResult access_tvm_trvm(CPUARMState *env, const ARMCPRegInfo= *ri, + bool isread) +{ + if (arm_current_el(env) =3D=3D 1) { + uint64_t trap =3D isread ? HCR_TRVM : HCR_TVM; + if (arm_hcr_el2_eff(env) & trap) { + return CP_ACCESS_TRAP_EL2; + } + } + return CP_ACCESS_OK; +} + +/* Check for traps from EL1 due to HCR_EL2.TSW. */ +static CPAccessResult access_tsw(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + if (arm_current_el(env) =3D=3D 1 && (arm_hcr_el2_eff(env) & HCR_TSW)) { + return CP_ACCESS_TRAP_EL2; + } + return CP_ACCESS_OK; +} + +/* Check for traps from EL1 due to HCR_EL2.TACR. */ +static CPAccessResult access_tacr(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + if (arm_current_el(env) =3D=3D 1 && (arm_hcr_el2_eff(env) & HCR_TACR))= { + return CP_ACCESS_TRAP_EL2; + } + return CP_ACCESS_OK; +} + +/* Check for traps from EL1 due to HCR_EL2.TTLB. */ +static CPAccessResult access_ttlb(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + if (arm_current_el(env) =3D=3D 1 && (arm_hcr_el2_eff(env) & HCR_TTLB))= { + return CP_ACCESS_TRAP_EL2; + } + return CP_ACCESS_OK; +} + +/* Check for traps from EL1 due to HCR_EL2.TTLB or TTLBIS. */ +static CPAccessResult access_ttlbis(CPUARMState *env, const ARMCPRegInfo *= ri, + bool isread) +{ + if (arm_current_el(env) =3D=3D 1 && + (arm_hcr_el2_eff(env) & (HCR_TTLB | HCR_TTLBIS))) { + return CP_ACCESS_TRAP_EL2; + } + return CP_ACCESS_OK; +} + +#ifdef TARGET_AARCH64 +/* Check for traps from EL1 due to HCR_EL2.TTLB or TTLBOS. */ +static CPAccessResult access_ttlbos(CPUARMState *env, const ARMCPRegInfo *= ri, + bool isread) +{ + if (arm_current_el(env) =3D=3D 1 && + (arm_hcr_el2_eff(env) & (HCR_TTLB | HCR_TTLBOS))) { + return CP_ACCESS_TRAP_EL2; + } + return CP_ACCESS_OK; +} +#endif + +static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t = value) +{ + ARMCPU *cpu =3D env_archcpu(env); + + raw_write(env, ri, value); + tlb_flush(CPU(cpu)); /* Flush TLB as domain not tracked in TLB */ +} + +static void fcse_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t = value) +{ + ARMCPU *cpu =3D env_archcpu(env); + + if (raw_read(env, ri) !=3D value) { + /* + * Unlike real hardware the qemu TLB uses virtual addresses, + * not modified virtual addresses, so this causes a TLB flush. + */ + tlb_flush(CPU(cpu)); + raw_write(env, ri, value); + } +} + +static void contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + + if (raw_read(env, ri) !=3D value && !arm_feature(env, ARM_FEATURE_PMSA) + && !extended_addresses_enabled(env)) { + /* + * For VMSA (when not using the LPAE long descriptor page table + * format) this register includes the ASID, so do a TLB flush. + * For PMSA it is purely a process ID and no action is needed. + */ + tlb_flush(CPU(cpu)); + } + raw_write(env, ri, value); +} + +static int alle1_tlbmask(CPUARMState *env) +{ + /* + * Note that the 'ALL' scope must invalidate both stage 1 and + * stage 2 translations, whereas most other scopes only invalidate + * stage 1 translations. + */ + return (ARMMMUIdxBit_E10_1 | + ARMMMUIdxBit_E10_1_PAN | + ARMMMUIdxBit_E10_0 | + ARMMMUIdxBit_Stage2 | + ARMMMUIdxBit_Stage2_S); +} + + +/* IS variants of TLB operations must affect all cores */ +static void tlbiall_is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + + tlb_flush_all_cpus_synced(cs); +} + +static void tlbiasid_is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + + tlb_flush_all_cpus_synced(cs); +} + +static void tlbimva_is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + + tlb_flush_page_all_cpus_synced(cs, value & TARGET_PAGE_MASK); +} + +static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + + tlb_flush_page_all_cpus_synced(cs, value & TARGET_PAGE_MASK); +} + +/* + * Non-IS variants of TLB operations are upgraded to + * IS versions if we are at EL1 and HCR_EL2.FB is effectively set to + * force broadcast of these operations. + */ +static bool tlb_force_broadcast(CPUARMState *env) +{ + return arm_current_el(env) =3D=3D 1 && (arm_hcr_el2_eff(env) & HCR_FB); +} + +static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Invalidate all (TLBIALL) */ + CPUState *cs =3D env_cpu(env); + + if (tlb_force_broadcast(env)) { + tlb_flush_all_cpus_synced(cs); + } else { + tlb_flush(cs); + } +} + +static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Invalidate single TLB entry by MVA and ASID (TLBIMVA) */ + CPUState *cs =3D env_cpu(env); + + value &=3D TARGET_PAGE_MASK; + if (tlb_force_broadcast(env)) { + tlb_flush_page_all_cpus_synced(cs, value); + } else { + tlb_flush_page(cs, value); + } +} + +static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Invalidate by ASID (TLBIASID) */ + CPUState *cs =3D env_cpu(env); + + if (tlb_force_broadcast(env)) { + tlb_flush_all_cpus_synced(cs); + } else { + tlb_flush(cs); + } +} + +static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Invalidate single entry by MVA, all ASIDs (TLBIMVAA) */ + CPUState *cs =3D env_cpu(env); + + value &=3D TARGET_PAGE_MASK; + if (tlb_force_broadcast(env)) { + tlb_flush_page_all_cpus_synced(cs, value); + } else { + tlb_flush_page(cs, value); + } +} + +static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + + tlb_flush_by_mmuidx(cs, alle1_tlbmask(env)); +} + +static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + + tlb_flush_by_mmuidx_all_cpus_synced(cs, alle1_tlbmask(env)); +} + + +static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + + tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2); +} + +static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + + tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2); +} + +static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + uint64_t pageaddr =3D value & ~MAKE_64BIT_MASK(0, 12); + + tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E2); +} + +static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + uint64_t pageaddr =3D value & ~MAKE_64BIT_MASK(0, 12); + + tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, + ARMMMUIdxBit_E2); +} + +static void tlbiipas2_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + uint64_t pageaddr =3D (value & MAKE_64BIT_MASK(0, 28)) << 12; + + tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2); +} + +static void tlbiipas2is_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + uint64_t pageaddr =3D (value & MAKE_64BIT_MASK(0, 28)) << 12; + + tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_St= age2); +} + +static const ARMCPRegInfo cp_reginfo[] =3D { + /* + * Define the secure and non-secure FCSE identifier CP registers + * separately because there is no secure bank in V8 (no _EL3). This a= llows + * the secure register to be properly reset and migrated. There is als= o no + * v8 EL1 version of the register so the non-secure instance stands al= one. + */ + { .name =3D "FCSEIDR", + .cp =3D 15, .opc1 =3D 0, .crn =3D 13, .crm =3D 0, .opc2 =3D 0, + .access =3D PL1_RW, .secure =3D ARM_CP_SECSTATE_NS, + .fieldoffset =3D offsetof(CPUARMState, cp15.fcseidr_ns), + .resetvalue =3D 0, .writefn =3D fcse_write, .raw_writefn =3D raw_wri= te, }, + { .name =3D "FCSEIDR_S", + .cp =3D 15, .opc1 =3D 0, .crn =3D 13, .crm =3D 0, .opc2 =3D 0, + .access =3D PL1_RW, .secure =3D ARM_CP_SECSTATE_S, + .fieldoffset =3D offsetof(CPUARMState, cp15.fcseidr_s), + .resetvalue =3D 0, .writefn =3D fcse_write, .raw_writefn =3D raw_wri= te, }, + /* + * Define the secure and non-secure context identifier CP registers + * separately because there is no secure bank in V8 (no _EL3). This a= llows + * the secure register to be properly reset and migrated. In the + * non-secure case, the 32-bit register will have reset and migration + * disabled during registration as it is handled by the 64-bit instanc= e. + */ + { .name =3D "CONTEXTIDR_EL1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 13, .crm =3D 0, .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .secure =3D ARM_CP_SECSTATE_NS, + .fieldoffset =3D offsetof(CPUARMState, cp15.contextidr_el[1]), + .resetvalue =3D 0, .writefn =3D contextidr_write, .raw_writefn =3D r= aw_write, }, + { .name =3D "CONTEXTIDR_S", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 0, .crn =3D 13, .crm =3D 0, .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .secure =3D ARM_CP_SECSTATE_S, + .fieldoffset =3D offsetof(CPUARMState, cp15.contextidr_s), + .resetvalue =3D 0, .writefn =3D contextidr_write, .raw_writefn =3D r= aw_write, }, +}; + +static const ARMCPRegInfo not_v8_cp_reginfo[] =3D { + /* + * NB: Some of these registers exist in v8 but with more precise + * definitions that don't use CP_ANY wildcards (mostly in v8_cp_reginf= o[]). + */ + /* MMU Domain access control / MPU write buffer control */ + { .name =3D "DACR", + .cp =3D 15, .opc1 =3D CP_ANY, .crn =3D 3, .crm =3D CP_ANY, .opc2 =3D= CP_ANY, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, .resetvalue =3D 0, + .writefn =3D dacr_write, .raw_writefn =3D raw_write, + .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.dacr_s), + offsetoflow32(CPUARMState, cp15.dacr_ns) } }, + /* + * ARMv7 allocates a range of implementation defined TLB LOCKDOWN regs. + * For v6 and v5, these mappings are overly broad. + */ + { .name =3D "TLB_LOCKDOWN", .cp =3D 15, .crn =3D 10, .crm =3D 0, + .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, .access =3D PL1_RW, .type =3D AR= M_CP_NOP }, + { .name =3D "TLB_LOCKDOWN", .cp =3D 15, .crn =3D 10, .crm =3D 1, + .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, .access =3D PL1_RW, .type =3D AR= M_CP_NOP }, + { .name =3D "TLB_LOCKDOWN", .cp =3D 15, .crn =3D 10, .crm =3D 4, + .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, .access =3D PL1_RW, .type =3D AR= M_CP_NOP }, + { .name =3D "TLB_LOCKDOWN", .cp =3D 15, .crn =3D 10, .crm =3D 8, + .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, .access =3D PL1_RW, .type =3D AR= M_CP_NOP }, + /* Cache maintenance ops; some of this space may be overridden later. = */ + { .name =3D "CACHEMAINT", .cp =3D 15, .crn =3D 7, .crm =3D CP_ANY, + .opc1 =3D 0, .opc2 =3D CP_ANY, .access =3D PL1_W, + .type =3D ARM_CP_NOP | ARM_CP_OVERRIDE }, +}; + +static const ARMCPRegInfo not_v6_cp_reginfo[] =3D { + /* + * Not all pre-v6 cores implemented this WFI, so this is slightly + * over-broad. + */ + { .name =3D "WFI_v5", .cp =3D 15, .crn =3D 7, .crm =3D 8, .opc1 =3D 0,= .opc2 =3D 2, + .access =3D PL1_W, .type =3D ARM_CP_WFI }, +}; + +static const ARMCPRegInfo not_v7_cp_reginfo[] =3D { + /* + * Standard v6 WFI (also used in some pre-v6 cores); not in v7 (which + * is UNPREDICTABLE; we choose to NOP as most implementations do). + */ + { .name =3D "WFI_v6", .cp =3D 15, .crn =3D 7, .crm =3D 0, .opc1 =3D 0,= .opc2 =3D 4, + .access =3D PL1_W, .type =3D ARM_CP_WFI }, + /* + * L1 cache lockdown. Not architectural in v6 and earlier but in pract= ice + * implemented in 926, 946, 1026, 1136, 1176 and 11MPCore. StrongARM a= nd + * OMAPCP will override this space. + */ + { .name =3D "DLOCKDOWN", .cp =3D 15, .crn =3D 9, .crm =3D 0, .opc1 =3D= 0, .opc2 =3D 0, + .access =3D PL1_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.c9_d= ata), + .resetvalue =3D 0 }, + { .name =3D "ILOCKDOWN", .cp =3D 15, .crn =3D 9, .crm =3D 0, .opc1 =3D= 0, .opc2 =3D 1, + .access =3D PL1_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.c9_i= nsn), + .resetvalue =3D 0 }, + /* v6 doesn't have the cache ID registers but Linux reads them anyway = */ + { .name =3D "DUMMY", .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 1, = .opc2 =3D CP_ANY, + .access =3D PL1_R, .type =3D ARM_CP_CONST | ARM_CP_NO_RAW, + .resetvalue =3D 0 }, + /* + * We don't implement pre-v7 debug but most CPUs had at least a DBGDID= R; + * implementing it as RAZ means the "debug architecture version" bits + * will read as a reserved value, which should cause Linux to not try + * to use the debug hardware. + */ + { .name =3D "DBGDIDR", .cp =3D 14, .crn =3D 0, .crm =3D 0, .opc1 =3D 0= , .opc2 =3D 0, + .access =3D PL0_R, .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + /* + * MMU TLB control. Note that the wildcarding means we cover not just + * the unified TLB ops but also the dside/iside/inner-shareable varian= ts. + */ + { .name =3D "TLBIALL", .cp =3D 15, .crn =3D 8, .crm =3D CP_ANY, + .opc1 =3D CP_ANY, .opc2 =3D 0, .access =3D PL1_W, .writefn =3D tlbia= ll_write, + .type =3D ARM_CP_NO_RAW }, + { .name =3D "TLBIMVA", .cp =3D 15, .crn =3D 8, .crm =3D CP_ANY, + .opc1 =3D CP_ANY, .opc2 =3D 1, .access =3D PL1_W, .writefn =3D tlbim= va_write, + .type =3D ARM_CP_NO_RAW }, + { .name =3D "TLBIASID", .cp =3D 15, .crn =3D 8, .crm =3D CP_ANY, + .opc1 =3D CP_ANY, .opc2 =3D 2, .access =3D PL1_W, .writefn =3D tlbia= sid_write, + .type =3D ARM_CP_NO_RAW }, + { .name =3D "TLBIMVAA", .cp =3D 15, .crn =3D 8, .crm =3D CP_ANY, + .opc1 =3D CP_ANY, .opc2 =3D 3, .access =3D PL1_W, .writefn =3D tlbim= vaa_write, + .type =3D ARM_CP_NO_RAW }, + { .name =3D "PRRR", .cp =3D 15, .crn =3D 10, .crm =3D 2, + .opc1 =3D 0, .opc2 =3D 0, .access =3D PL1_RW, .type =3D ARM_CP_NOP }, + { .name =3D "NMRR", .cp =3D 15, .crn =3D 10, .crm =3D 2, + .opc1 =3D 0, .opc2 =3D 1, .access =3D PL1_RW, .type =3D ARM_CP_NOP }, +}; + +static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + uint32_t mask =3D 0; + + /* In ARMv8 most bits of CPACR_EL1 are RES0. */ + if (!arm_feature(env, ARM_FEATURE_V8)) { + /* + * ARMv7 defines bits for unimplemented coprocessors as RAZ/WI. + * ASEDIS [31] and D32DIS [30] are both UNK/SBZP without VFP. + * TRCDIS [28] is RAZ/WI since we do not implement a trace macroce= ll. + */ + if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) { + /* VFP coprocessor: cp10 & cp11 [23:20] */ + mask |=3D R_CPACR_ASEDIS_MASK | + R_CPACR_D32DIS_MASK | + R_CPACR_CP11_MASK | + R_CPACR_CP10_MASK; + + if (!arm_feature(env, ARM_FEATURE_NEON)) { + /* ASEDIS [31] bit is RAO/WI */ + value |=3D R_CPACR_ASEDIS_MASK; + } + + /* + * VFPv3 and upwards with NEON implement 32 double precision + * registers (D0-D31). + */ + if (!cpu_isar_feature(aa32_simd_r32, env_archcpu(env))) { + /* D32DIS [30] is RAO/WI if D16-31 are not implemented. */ + value |=3D R_CPACR_D32DIS_MASK; + } + } + value &=3D mask; + } + + /* + * For A-profile AArch32 EL3 (but not M-profile secure mode), if NSACR= .CP10 + * is 0 then CPACR.{CP11,CP10} ignore writes and read as 0b00. + */ + if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) && + !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) { + mask =3D R_CPACR_CP11_MASK | R_CPACR_CP10_MASK; + value =3D (value & ~mask) | (env->cp15.cpacr_el1 & mask); + } + + env->cp15.cpacr_el1 =3D value; +} + +static uint64_t cpacr_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + /* + * For A-profile AArch32 EL3 (but not M-profile secure mode), if NSACR= .CP10 + * is 0 then CPACR.{CP11,CP10} ignore writes and read as 0b00. + */ + uint64_t value =3D env->cp15.cpacr_el1; + + if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) && + !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) { + value =3D ~(R_CPACR_CP11_MASK | R_CPACR_CP10_MASK); + } + return value; +} + + +static void cpacr_reset(CPUARMState *env, const ARMCPRegInfo *ri) +{ + /* + * Call cpacr_write() so that we reset with the correct RAO bits set + * for our CPU features. + */ + cpacr_write(env, ri, 0); +} + +static CPAccessResult cpacr_access(CPUARMState *env, const ARMCPRegInfo *r= i, + bool isread) +{ + if (arm_feature(env, ARM_FEATURE_V8)) { + /* Check if CPACR accesses are to be trapped to EL2 */ + if (arm_current_el(env) =3D=3D 1 && arm_is_el2_enabled(env) && + FIELD_EX64(env->cp15.cptr_el[2], CPTR_EL2, TCPAC)) { + return CP_ACCESS_TRAP_EL2; + /* Check if CPACR accesses are to be trapped to EL3 */ + } else if (arm_current_el(env) < 3 && + FIELD_EX64(env->cp15.cptr_el[3], CPTR_EL3, TCPAC)) { + return CP_ACCESS_TRAP_EL3; + } + } + + return CP_ACCESS_OK; +} + +static CPAccessResult cptr_access(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + /* Check if CPTR accesses are set to trap to EL3 */ + if (arm_current_el(env) =3D=3D 2 && + FIELD_EX64(env->cp15.cptr_el[3], CPTR_EL3, TCPAC)) { + return CP_ACCESS_TRAP_EL3; + } + + return CP_ACCESS_OK; +} + +static const ARMCPRegInfo v6_cp_reginfo[] =3D { + /* prefetch by MVA in v6, NOP in v7 */ + { .name =3D "MVA_prefetch", + .cp =3D 15, .crn =3D 7, .crm =3D 13, .opc1 =3D 0, .opc2 =3D 1, + .access =3D PL1_W, .type =3D ARM_CP_NOP }, + /* + * We need to break the TB after ISB to execute self-modifying code + * correctly and also to take any pending interrupts immediately. + * So use arm_cp_write_ignore() function instead of ARM_CP_NOP flag. + */ + { .name =3D "ISB", .cp =3D 15, .crn =3D 7, .crm =3D 5, .opc1 =3D 0, .o= pc2 =3D 4, + .access =3D PL0_W, .type =3D ARM_CP_NO_RAW, .writefn =3D arm_cp_writ= e_ignore }, + { .name =3D "DSB", .cp =3D 15, .crn =3D 7, .crm =3D 10, .opc1 =3D 0, .= opc2 =3D 4, + .access =3D PL0_W, .type =3D ARM_CP_NOP }, + { .name =3D "DMB", .cp =3D 15, .crn =3D 7, .crm =3D 10, .opc1 =3D 0, .= opc2 =3D 5, + .access =3D PL0_W, .type =3D ARM_CP_NOP }, + { .name =3D "IFAR", .cp =3D 15, .crn =3D 6, .crm =3D 0, .opc1 =3D 0, .= opc2 =3D 2, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.ifar_s), + offsetof(CPUARMState, cp15.ifar_ns) }, + .resetvalue =3D 0, }, + /* + * Watchpoint Fault Address Register : should actually only be present + * for 1136, 1176, 11MPCore. + */ + { .name =3D "WFAR", .cp =3D 15, .crn =3D 6, .crm =3D 0, .opc1 =3D 0, .= opc2 =3D 1, + .access =3D PL1_RW, .type =3D ARM_CP_CONST, .resetvalue =3D 0, }, + { .name =3D "CPACR", .state =3D ARM_CP_STATE_BOTH, .opc0 =3D 3, + .crn =3D 1, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 2, .accessfn =3D cpac= r_access, + .access =3D PL1_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.cpac= r_el1), + .resetfn =3D cpacr_reset, .writefn =3D cpacr_write, .readfn =3D cpac= r_read }, +}; + +typedef struct pm_event { + uint16_t number; /* PMEVTYPER.evtCount is 16 bits wide */ + /* If the event is supported on this CPU (used to generate PMCEID[01])= */ + bool (*supported)(CPUARMState *); + /* + * Retrieve the current count of the underlying event. The programmed + * counters hold a difference from the return value from this function + */ + uint64_t (*get_count)(CPUARMState *); + /* + * Return how many nanoseconds it will take (at a minimum) for count e= vents + * to occur. A negative value indicates the counter will never overflo= w, or + * that the counter has otherwise arranged for the overflow bit to be = set + * and the PMU interrupt to be raised on overflow. + */ + int64_t (*ns_per_count)(uint64_t); +} pm_event; + +static bool event_always_supported(CPUARMState *env) +{ + return true; +} + +static uint64_t swinc_get_count(CPUARMState *env) +{ + /* + * SW_INCR events are written directly to the pmevcntr's by writes to + * PMSWINC, so there is no underlying count maintained by the PMU itse= lf + */ + return 0; +} + +static int64_t swinc_ns_per(uint64_t ignored) +{ + return -1; +} + +/* + * Return the underlying cycle count for the PMU cycle counters. If we're = in + * usermode, simply return 0. + */ +static uint64_t cycles_get_count(CPUARMState *env) +{ +#ifndef CONFIG_USER_ONLY + return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), + ARM_CPU_FREQ, NANOSECONDS_PER_SECOND); +#else + return cpu_get_host_ticks(); +#endif +} + +#ifndef CONFIG_USER_ONLY +static int64_t cycles_ns_per(uint64_t cycles) +{ + return (ARM_CPU_FREQ / NANOSECONDS_PER_SECOND) * cycles; +} + +static bool instructions_supported(CPUARMState *env) +{ + return icount_enabled() =3D=3D 1; /* Precise instruction counting */ +} + +static uint64_t instructions_get_count(CPUARMState *env) +{ + return (uint64_t)icount_get_raw(); +} + +static int64_t instructions_ns_per(uint64_t icount) +{ + return icount_to_ns((int64_t)icount); +} +#endif + +static bool pmuv3p1_events_supported(CPUARMState *env) +{ + /* For events which are supported in any v8.1 PMU */ + return cpu_isar_feature(any_pmuv3p1, env_archcpu(env)); +} + +static bool pmuv3p4_events_supported(CPUARMState *env) +{ + /* For events which are supported in any v8.1 PMU */ + return cpu_isar_feature(any_pmuv3p4, env_archcpu(env)); +} + +static uint64_t zero_event_get_count(CPUARMState *env) +{ + /* For events which on QEMU never fire, so their count is always zero = */ + return 0; +} + +static int64_t zero_event_ns_per(uint64_t cycles) +{ + /* An event which never fires can never overflow */ + return -1; +} + +static const pm_event pm_events[] =3D { + { .number =3D 0x000, /* SW_INCR */ + .supported =3D event_always_supported, + .get_count =3D swinc_get_count, + .ns_per_count =3D swinc_ns_per, + }, +#ifndef CONFIG_USER_ONLY + { .number =3D 0x008, /* INST_RETIRED, Instruction architecturally exec= uted */ + .supported =3D instructions_supported, + .get_count =3D instructions_get_count, + .ns_per_count =3D instructions_ns_per, + }, + { .number =3D 0x011, /* CPU_CYCLES, Cycle */ + .supported =3D event_always_supported, + .get_count =3D cycles_get_count, + .ns_per_count =3D cycles_ns_per, + }, +#endif + { .number =3D 0x023, /* STALL_FRONTEND */ + .supported =3D pmuv3p1_events_supported, + .get_count =3D zero_event_get_count, + .ns_per_count =3D zero_event_ns_per, + }, + { .number =3D 0x024, /* STALL_BACKEND */ + .supported =3D pmuv3p1_events_supported, + .get_count =3D zero_event_get_count, + .ns_per_count =3D zero_event_ns_per, + }, + { .number =3D 0x03c, /* STALL */ + .supported =3D pmuv3p4_events_supported, + .get_count =3D zero_event_get_count, + .ns_per_count =3D zero_event_ns_per, + }, +}; + +/* + * Note: Before increasing MAX_EVENT_ID beyond 0x3f into the 0x40xx range = of + * events (i.e. the statistical profiling extension), this implementation + * should first be updated to something sparse instead of the current + * supported_event_map[] array. + */ +#define MAX_EVENT_ID 0x3c +#define UNSUPPORTED_EVENT UINT16_MAX +static uint16_t supported_event_map[MAX_EVENT_ID + 1]; + +/* + * Called upon CPU initialization to initialize PMCEID[01]_EL0 and build a= map + * of ARM event numbers to indices in our pm_events array. + * + * Note: Events in the 0x40XX range are not currently supported. + */ +void pmu_init(ARMCPU *cpu) +{ + unsigned int i; + + /* + * Empty supported_event_map and cpu->pmceid[01] before adding support= ed + * events to them + */ + for (i =3D 0; i < ARRAY_SIZE(supported_event_map); i++) { + supported_event_map[i] =3D UNSUPPORTED_EVENT; + } + cpu->pmceid0 =3D 0; + cpu->pmceid1 =3D 0; + + for (i =3D 0; i < ARRAY_SIZE(pm_events); i++) { + const pm_event *cnt =3D &pm_events[i]; + assert(cnt->number <=3D MAX_EVENT_ID); + /* We do not currently support events in the 0x40xx range */ + assert(cnt->number <=3D 0x3f); + + if (cnt->supported(&cpu->env)) { + supported_event_map[cnt->number] =3D i; + uint64_t event_mask =3D 1ULL << (cnt->number & 0x1f); + if (cnt->number & 0x20) { + cpu->pmceid1 |=3D event_mask; + } else { + cpu->pmceid0 |=3D event_mask; + } + } + } +} + +/* + * Check at runtime whether a PMU event is supported for the current machi= ne + */ +static bool event_supported(uint16_t number) +{ + if (number > MAX_EVENT_ID) { + return false; + } + return supported_event_map[number] !=3D UNSUPPORTED_EVENT; +} + +static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *r= i, + bool isread) +{ + /* + * Performance monitor registers user accessibility is controlled + * by PMUSERENR. MDCR_EL2.TPM and MDCR_EL3.TPM allow configurable + * trapping to EL2 or EL3 for other accesses. + */ + int el =3D arm_current_el(env); + uint64_t mdcr_el2 =3D arm_mdcr_el2_eff(env); + + if (el =3D=3D 0 && !(env->cp15.c9_pmuserenr & 1)) { + return CP_ACCESS_TRAP; + } + if (el < 2 && (mdcr_el2 & MDCR_TPM)) { + return CP_ACCESS_TRAP_EL2; + } + if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) { + return CP_ACCESS_TRAP_EL3; + } + + return CP_ACCESS_OK; +} + +static CPAccessResult pmreg_access_xevcntr(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + /* ER: event counter read trap control */ + if (arm_feature(env, ARM_FEATURE_V8) + && arm_current_el(env) =3D=3D 0 + && (env->cp15.c9_pmuserenr & (1 << 3)) !=3D 0 + && isread) { + return CP_ACCESS_OK; + } + + return pmreg_access(env, ri, isread); +} + +static CPAccessResult pmreg_access_swinc(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + /* SW: software increment write trap control */ + if (arm_feature(env, ARM_FEATURE_V8) + && arm_current_el(env) =3D=3D 0 + && (env->cp15.c9_pmuserenr & (1 << 1)) !=3D 0 + && !isread) { + return CP_ACCESS_OK; + } + + return pmreg_access(env, ri, isread); +} + +static CPAccessResult pmreg_access_selr(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + /* ER: event counter read trap control */ + if (arm_feature(env, ARM_FEATURE_V8) + && arm_current_el(env) =3D=3D 0 + && (env->cp15.c9_pmuserenr & (1 << 3)) !=3D 0) { + return CP_ACCESS_OK; + } + + return pmreg_access(env, ri, isread); +} + +static CPAccessResult pmreg_access_ccntr(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + /* CR: cycle counter read trap control */ + if (arm_feature(env, ARM_FEATURE_V8) + && arm_current_el(env) =3D=3D 0 + && (env->cp15.c9_pmuserenr & (1 << 2)) !=3D 0 + && isread) { + return CP_ACCESS_OK; + } + + return pmreg_access(env, ri, isread); +} + +/* + * Bits in MDCR_EL2 and MDCR_EL3 which pmu_counter_enabled() looks at. + * We use these to decide whether we need to wrap a write to MDCR_EL2 + * or MDCR_EL3 in pmu_op_start()/pmu_op_finish() calls. + */ +#define MDCR_EL2_PMU_ENABLE_BITS \ + (MDCR_HPME | MDCR_HPMD | MDCR_HPMN | MDCR_HCCD | MDCR_HLP) +#define MDCR_EL3_PMU_ENABLE_BITS (MDCR_SPME | MDCR_SCCD) + +/* + * Returns true if the counter (pass 31 for PMCCNTR) should count events u= sing + * the current EL, security state, and register configuration. + */ +static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter) +{ + uint64_t filter; + bool e, p, u, nsk, nsu, nsh, m; + bool enabled, prohibited =3D false, filtered; + bool secure =3D arm_is_secure(env); + int el =3D arm_current_el(env); + uint64_t mdcr_el2 =3D arm_mdcr_el2_eff(env); + uint8_t hpmn =3D mdcr_el2 & MDCR_HPMN; + + if (!arm_feature(env, ARM_FEATURE_PMU)) { + return false; + } + + if (!arm_feature(env, ARM_FEATURE_EL2) || + (counter < hpmn || counter =3D=3D 31)) { + e =3D env->cp15.c9_pmcr & PMCRE; + } else { + e =3D mdcr_el2 & MDCR_HPME; + } + enabled =3D e && (env->cp15.c9_pmcnten & (1 << counter)); + + /* Is event counting prohibited? */ + if (el =3D=3D 2 && (counter < hpmn || counter =3D=3D 31)) { + prohibited =3D mdcr_el2 & MDCR_HPMD; + } + if (secure) { + prohibited =3D prohibited || !(env->cp15.mdcr_el3 & MDCR_SPME); + } + + if (counter =3D=3D 31) { + /* + * The cycle counter defaults to running. PMCR.DP says "disable + * the cycle counter when event counting is prohibited". + * Some MDCR bits disable the cycle counter specifically. + */ + prohibited =3D prohibited && env->cp15.c9_pmcr & PMCRDP; + if (cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) { + if (secure) { + prohibited =3D prohibited || (env->cp15.mdcr_el3 & MDCR_SC= CD); + } + if (el =3D=3D 2) { + prohibited =3D prohibited || (mdcr_el2 & MDCR_HCCD); + } + } + } + + if (counter =3D=3D 31) { + filter =3D env->cp15.pmccfiltr_el0; + } else { + filter =3D env->cp15.c14_pmevtyper[counter]; + } + + p =3D filter & PMXEVTYPER_P; + u =3D filter & PMXEVTYPER_U; + nsk =3D arm_feature(env, ARM_FEATURE_EL3) && (filter & PMXEVTYPER_NSK); + nsu =3D arm_feature(env, ARM_FEATURE_EL3) && (filter & PMXEVTYPER_NSU); + nsh =3D arm_feature(env, ARM_FEATURE_EL2) && (filter & PMXEVTYPER_NSH); + m =3D arm_el_is_aa64(env, 1) && + arm_feature(env, ARM_FEATURE_EL3) && (filter & PMXEVTYPER_M); + + if (el =3D=3D 0) { + filtered =3D secure ? u : u !=3D nsu; + } else if (el =3D=3D 1) { + filtered =3D secure ? p : p !=3D nsk; + } else if (el =3D=3D 2) { + filtered =3D !nsh; + } else { /* EL3 */ + filtered =3D m !=3D p; + } + + if (counter !=3D 31) { + /* + * If not checking PMCCNTR, ensure the counter is setup to an even= t we + * support + */ + uint16_t event =3D filter & PMXEVTYPER_EVTCOUNT; + if (!event_supported(event)) { + return false; + } + } + + return enabled && !prohibited && !filtered; +} + +static void pmu_update_irq(CPUARMState *env) +{ + ARMCPU *cpu =3D env_archcpu(env); + qemu_set_irq(cpu->pmu_interrupt, (env->cp15.c9_pmcr & PMCRE) && + (env->cp15.c9_pminten & env->cp15.c9_pmovsr)); +} + +static bool pmccntr_clockdiv_enabled(CPUARMState *env) +{ + /* + * Return true if the clock divider is enabled and the cycle counter + * is supposed to tick only once every 64 clock cycles. This is + * controlled by PMCR.D, but if PMCR.LC is set to enable the long + * (64-bit) cycle counter PMCR.D has no effect. + */ + return (env->cp15.c9_pmcr & (PMCRD | PMCRLC)) =3D=3D PMCRD; +} + +static bool pmevcntr_is_64_bit(CPUARMState *env, int counter) +{ + /* Return true if the specified event counter is configured to be 64 b= it */ + + /* This isn't intended to be used with the cycle counter */ + assert(counter < 31); + + if (!cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) { + return false; + } + + if (arm_feature(env, ARM_FEATURE_EL2)) { + /* + * MDCR_EL2.HLP still applies even when EL2 is disabled in the + * current security state, so we don't use arm_mdcr_el2_eff() here. + */ + bool hlp =3D env->cp15.mdcr_el2 & MDCR_HLP; + int hpmn =3D env->cp15.mdcr_el2 & MDCR_HPMN; + + if (hpmn !=3D 0 && counter >=3D hpmn) { + return hlp; + } + } + return env->cp15.c9_pmcr & PMCRLP; +} + +/* + * Ensure c15_ccnt is the guest-visible count so that operations such as + * enabling/disabling the counter or filtering, modifying the count itself, + * etc. can be done logically. This is essentially a no-op if the counter = is + * not enabled at the time of the call. + */ +static void pmccntr_op_start(CPUARMState *env) +{ + uint64_t cycles =3D cycles_get_count(env); + + if (pmu_counter_enabled(env, 31)) { + uint64_t eff_cycles =3D cycles; + if (pmccntr_clockdiv_enabled(env)) { + eff_cycles /=3D 64; + } + + uint64_t new_pmccntr =3D eff_cycles - env->cp15.c15_ccnt_delta; + + uint64_t overflow_mask =3D env->cp15.c9_pmcr & PMCRLC ? \ + 1ull << 63 : 1ull << 31; + if (env->cp15.c15_ccnt & ~new_pmccntr & overflow_mask) { + env->cp15.c9_pmovsr |=3D (1ULL << 31); + pmu_update_irq(env); + } + + env->cp15.c15_ccnt =3D new_pmccntr; + } + env->cp15.c15_ccnt_delta =3D cycles; +} + +/* + * If PMCCNTR is enabled, recalculate the delta between the clock and the + * guest-visible count. A call to pmccntr_op_finish should follow every ca= ll to + * pmccntr_op_start. + */ +static void pmccntr_op_finish(CPUARMState *env) +{ + if (pmu_counter_enabled(env, 31)) { +#ifndef CONFIG_USER_ONLY + /* Calculate when the counter will next overflow */ + uint64_t remaining_cycles =3D -env->cp15.c15_ccnt; + if (!(env->cp15.c9_pmcr & PMCRLC)) { + remaining_cycles =3D (uint32_t)remaining_cycles; + } + int64_t overflow_in =3D cycles_ns_per(remaining_cycles); + + if (overflow_in > 0) { + int64_t overflow_at; + + if (!sadd64_overflow(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), + overflow_in, &overflow_at)) { + ARMCPU *cpu =3D env_archcpu(env); + timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at); + } + } +#endif + + uint64_t prev_cycles =3D env->cp15.c15_ccnt_delta; + if (pmccntr_clockdiv_enabled(env)) { + prev_cycles /=3D 64; + } + env->cp15.c15_ccnt_delta =3D prev_cycles - env->cp15.c15_ccnt; + } +} + +static void pmevcntr_op_start(CPUARMState *env, uint8_t counter) +{ + + uint16_t event =3D env->cp15.c14_pmevtyper[counter] & PMXEVTYPER_EVTCO= UNT; + uint64_t count =3D 0; + if (event_supported(event)) { + uint16_t event_idx =3D supported_event_map[event]; + count =3D pm_events[event_idx].get_count(env); + } + + if (pmu_counter_enabled(env, counter)) { + uint64_t new_pmevcntr =3D count - env->cp15.c14_pmevcntr_delta[cou= nter]; + uint64_t overflow_mask =3D pmevcntr_is_64_bit(env, counter) ? + 1ULL << 63 : 1ULL << 31; + + if (env->cp15.c14_pmevcntr[counter] & ~new_pmevcntr & overflow_mas= k) { + env->cp15.c9_pmovsr |=3D (1 << counter); + pmu_update_irq(env); + } + env->cp15.c14_pmevcntr[counter] =3D new_pmevcntr; + } + env->cp15.c14_pmevcntr_delta[counter] =3D count; +} + +static void pmevcntr_op_finish(CPUARMState *env, uint8_t counter) +{ + if (pmu_counter_enabled(env, counter)) { +#ifndef CONFIG_USER_ONLY + uint16_t event =3D env->cp15.c14_pmevtyper[counter] & PMXEVTYPER_E= VTCOUNT; + uint16_t event_idx =3D supported_event_map[event]; + uint64_t delta =3D -(env->cp15.c14_pmevcntr[counter] + 1); + int64_t overflow_in; + + if (!pmevcntr_is_64_bit(env, counter)) { + delta =3D (uint32_t)delta; + } + overflow_in =3D pm_events[event_idx].ns_per_count(delta); + + if (overflow_in > 0) { + int64_t overflow_at; + + if (!sadd64_overflow(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), + overflow_in, &overflow_at)) { + ARMCPU *cpu =3D env_archcpu(env); + timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at); + } + } +#endif + + env->cp15.c14_pmevcntr_delta[counter] -=3D + env->cp15.c14_pmevcntr[counter]; + } +} + +void pmu_op_start(CPUARMState *env) +{ + unsigned int i; + pmccntr_op_start(env); + for (i =3D 0; i < pmu_num_counters(env); i++) { + pmevcntr_op_start(env, i); + } +} + +void pmu_op_finish(CPUARMState *env) +{ + unsigned int i; + pmccntr_op_finish(env); + for (i =3D 0; i < pmu_num_counters(env); i++) { + pmevcntr_op_finish(env, i); + } +} + +void pmu_pre_el_change(ARMCPU *cpu, void *ignored) +{ + pmu_op_start(&cpu->env); +} + +void pmu_post_el_change(ARMCPU *cpu, void *ignored) +{ + pmu_op_finish(&cpu->env); +} + +void arm_pmu_timer_cb(void *opaque) +{ + ARMCPU *cpu =3D opaque; + + /* + * Update all the counter values based on the current underlying count= s, + * triggering interrupts to be raised, if necessary. pmu_op_finish() a= lso + * has the effect of setting the cpu->pmu_timer to the next earliest t= ime a + * counter may expire. + */ + pmu_op_start(&cpu->env); + pmu_op_finish(&cpu->env); +} + +static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + pmu_op_start(env); + + if (value & PMCRC) { + /* The counter has been reset */ + env->cp15.c15_ccnt =3D 0; + } + + if (value & PMCRP) { + unsigned int i; + for (i =3D 0; i < pmu_num_counters(env); i++) { + env->cp15.c14_pmevcntr[i] =3D 0; + } + } + + env->cp15.c9_pmcr &=3D ~PMCR_WRITABLE_MASK; + env->cp15.c9_pmcr |=3D (value & PMCR_WRITABLE_MASK); + + pmu_op_finish(env); +} + +static void pmswinc_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + unsigned int i; + uint64_t overflow_mask, new_pmswinc; + + for (i =3D 0; i < pmu_num_counters(env); i++) { + /* Increment a counter's count iff: */ + if ((value & (1 << i)) && /* counter's bit is set */ + /* counter is enabled and not filtered */ + pmu_counter_enabled(env, i) && + /* counter is SW_INCR */ + (env->cp15.c14_pmevtyper[i] & PMXEVTYPER_EVTCOUNT) =3D=3D = 0x0) { + pmevcntr_op_start(env, i); + + /* + * Detect if this write causes an overflow since we can't pred= ict + * PMSWINC overflows like we can for other events + */ + new_pmswinc =3D env->cp15.c14_pmevcntr[i] + 1; + + overflow_mask =3D pmevcntr_is_64_bit(env, i) ? + 1ULL << 63 : 1ULL << 31; + + if (env->cp15.c14_pmevcntr[i] & ~new_pmswinc & overflow_mask) { + env->cp15.c9_pmovsr |=3D (1 << i); + pmu_update_irq(env); + } + + env->cp15.c14_pmevcntr[i] =3D new_pmswinc; + + pmevcntr_op_finish(env, i); + } + } +} + +static uint64_t pmccntr_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + uint64_t ret; + pmccntr_op_start(env); + ret =3D env->cp15.c15_ccnt; + pmccntr_op_finish(env); + return ret; +} + +static void pmselr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * The value of PMSELR.SEL affects the behavior of PMXEVTYPER and + * PMXEVCNTR. We allow [0..31] to be written to PMSELR here; in the + * meanwhile, we check PMSELR.SEL when PMXEVTYPER and PMXEVCNTR are + * accessed. + */ + env->cp15.c9_pmselr =3D value & 0x1f; +} + +static void pmccntr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + pmccntr_op_start(env); + env->cp15.c15_ccnt =3D value; + pmccntr_op_finish(env); +} + +static void pmccntr_write32(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + uint64_t cur_val =3D pmccntr_read(env, NULL); + + pmccntr_write(env, ri, deposit64(cur_val, 0, 32, value)); +} + +static void pmccfiltr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + pmccntr_op_start(env); + env->cp15.pmccfiltr_el0 =3D value & PMCCFILTR_EL0; + pmccntr_op_finish(env); +} + +static void pmccfiltr_write_a32(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + pmccntr_op_start(env); + /* M is not accessible from AArch32 */ + env->cp15.pmccfiltr_el0 =3D (env->cp15.pmccfiltr_el0 & PMCCFILTR_M) | + (value & PMCCFILTR); + pmccntr_op_finish(env); +} + +static uint64_t pmccfiltr_read_a32(CPUARMState *env, const ARMCPRegInfo *r= i) +{ + /* M is not visible in AArch32 */ + return env->cp15.pmccfiltr_el0 & PMCCFILTR; +} + +static void pmcntenset_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + pmu_op_start(env); + value &=3D pmu_counter_mask(env); + env->cp15.c9_pmcnten |=3D value; + pmu_op_finish(env); +} + +static void pmcntenclr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + pmu_op_start(env); + value &=3D pmu_counter_mask(env); + env->cp15.c9_pmcnten &=3D ~value; + pmu_op_finish(env); +} + +static void pmovsr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + value &=3D pmu_counter_mask(env); + env->cp15.c9_pmovsr &=3D ~value; + pmu_update_irq(env); +} + +static void pmovsset_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + value &=3D pmu_counter_mask(env); + env->cp15.c9_pmovsr |=3D value; + pmu_update_irq(env); +} + +static void pmevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value, const uint8_t counter) +{ + if (counter =3D=3D 31) { + pmccfiltr_write(env, ri, value); + } else if (counter < pmu_num_counters(env)) { + pmevcntr_op_start(env, counter); + + /* + * If this counter's event type is changing, store the current + * underlying count for the new type in c14_pmevcntr_delta[counter= ] so + * pmevcntr_op_finish has the correct baseline when it converts ba= ck to + * a delta. + */ + uint16_t old_event =3D env->cp15.c14_pmevtyper[counter] & + PMXEVTYPER_EVTCOUNT; + uint16_t new_event =3D value & PMXEVTYPER_EVTCOUNT; + if (old_event !=3D new_event) { + uint64_t count =3D 0; + if (event_supported(new_event)) { + uint16_t event_idx =3D supported_event_map[new_event]; + count =3D pm_events[event_idx].get_count(env); + } + env->cp15.c14_pmevcntr_delta[counter] =3D count; + } + + env->cp15.c14_pmevtyper[counter] =3D value & PMXEVTYPER_MASK; + pmevcntr_op_finish(env, counter); + } + /* + * Attempts to access PMXEVTYPER are CONSTRAINED UNPREDICTABLE when + * PMSELR value is equal to or greater than the number of implemented + * counters, but not equal to 0x1f. We opt to behave as a RAZ/WI. + */ +} + +static uint64_t pmevtyper_read(CPUARMState *env, const ARMCPRegInfo *ri, + const uint8_t counter) +{ + if (counter =3D=3D 31) { + return env->cp15.pmccfiltr_el0; + } else if (counter < pmu_num_counters(env)) { + return env->cp15.c14_pmevtyper[counter]; + } else { + /* + * We opt to behave as a RAZ/WI when attempts to access PMXEVTYPER + * are CONSTRAINED UNPREDICTABLE. See comments in pmevtyper_write(). + */ + return 0; + } +} + +static void pmevtyper_writefn(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + uint8_t counter =3D ((ri->crm & 3) << 3) | (ri->opc2 & 7); + pmevtyper_write(env, ri, value, counter); +} + +static void pmevtyper_rawwrite(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + uint8_t counter =3D ((ri->crm & 3) << 3) | (ri->opc2 & 7); + env->cp15.c14_pmevtyper[counter] =3D value; + + /* + * pmevtyper_rawwrite is called between a pair of pmu_op_start and + * pmu_op_finish calls when loading saved state for a migration. Becau= se + * we're potentially updating the type of event here, the value writte= n to + * c14_pmevcntr_delta by the preceeding pmu_op_start call may be for a + * different counter type. Therefore, we need to set this value to the + * current count for the counter type we're writing so that pmu_op_fin= ish + * has the correct count for its calculation. + */ + uint16_t event =3D value & PMXEVTYPER_EVTCOUNT; + if (event_supported(event)) { + uint16_t event_idx =3D supported_event_map[event]; + env->cp15.c14_pmevcntr_delta[counter] =3D + pm_events[event_idx].get_count(env); + } +} + +static uint64_t pmevtyper_readfn(CPUARMState *env, const ARMCPRegInfo *ri) +{ + uint8_t counter =3D ((ri->crm & 3) << 3) | (ri->opc2 & 7); + return pmevtyper_read(env, ri, counter); +} + +static void pmxevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + pmevtyper_write(env, ri, value, env->cp15.c9_pmselr & 31); +} + +static uint64_t pmxevtyper_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return pmevtyper_read(env, ri, env->cp15.c9_pmselr & 31); +} + +static void pmevcntr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value, uint8_t counter) +{ + if (!cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) { + /* Before FEAT_PMUv3p5, top 32 bits of event counters are RES0 */ + value &=3D MAKE_64BIT_MASK(0, 32); + } + if (counter < pmu_num_counters(env)) { + pmevcntr_op_start(env, counter); + env->cp15.c14_pmevcntr[counter] =3D value; + pmevcntr_op_finish(env, counter); + } + /* + * We opt to behave as a RAZ/WI when attempts to access PM[X]EVCNTR + * are CONSTRAINED UNPREDICTABLE. + */ +} + +static uint64_t pmevcntr_read(CPUARMState *env, const ARMCPRegInfo *ri, + uint8_t counter) +{ + if (counter < pmu_num_counters(env)) { + uint64_t ret; + pmevcntr_op_start(env, counter); + ret =3D env->cp15.c14_pmevcntr[counter]; + pmevcntr_op_finish(env, counter); + if (!cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) { + /* Before FEAT_PMUv3p5, top 32 bits of event counters are RES0= */ + ret &=3D MAKE_64BIT_MASK(0, 32); + } + return ret; + } else { + /* + * We opt to behave as a RAZ/WI when attempts to access PM[X]EVCNTR + * are CONSTRAINED UNPREDICTABLE. + */ + return 0; + } +} + +static void pmevcntr_writefn(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + uint8_t counter =3D ((ri->crm & 3) << 3) | (ri->opc2 & 7); + pmevcntr_write(env, ri, value, counter); +} + +static uint64_t pmevcntr_readfn(CPUARMState *env, const ARMCPRegInfo *ri) +{ + uint8_t counter =3D ((ri->crm & 3) << 3) | (ri->opc2 & 7); + return pmevcntr_read(env, ri, counter); +} + +static void pmevcntr_rawwrite(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + uint8_t counter =3D ((ri->crm & 3) << 3) | (ri->opc2 & 7); + assert(counter < pmu_num_counters(env)); + env->cp15.c14_pmevcntr[counter] =3D value; + pmevcntr_write(env, ri, value, counter); +} + +static uint64_t pmevcntr_rawread(CPUARMState *env, const ARMCPRegInfo *ri) +{ + uint8_t counter =3D ((ri->crm & 3) << 3) | (ri->opc2 & 7); + assert(counter < pmu_num_counters(env)); + return env->cp15.c14_pmevcntr[counter]; +} + +static void pmxevcntr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + pmevcntr_write(env, ri, value, env->cp15.c9_pmselr & 31); +} + +static uint64_t pmxevcntr_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return pmevcntr_read(env, ri, env->cp15.c9_pmselr & 31); +} + +static void pmuserenr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + if (arm_feature(env, ARM_FEATURE_V8)) { + env->cp15.c9_pmuserenr =3D value & 0xf; + } else { + env->cp15.c9_pmuserenr =3D value & 1; + } +} + +static void pmintenset_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* We have no event counters so only the C bit can be changed */ + value &=3D pmu_counter_mask(env); + env->cp15.c9_pminten |=3D value; + pmu_update_irq(env); +} + +static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + value &=3D pmu_counter_mask(env); + env->cp15.c9_pminten &=3D ~value; + pmu_update_irq(env); +} + +static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * Note that even though the AArch64 view of this register has bits + * [10:0] all RES0 we can only mask the bottom 5, to comply with the + * architectural requirements for bits which are RES0 only in some + * contexts. (ARMv8 would permit us to do no masking at all, but ARMv7 + * requires the bottom five bits to be RAZ/WI because they're UNK/SBZP= .) + */ + raw_write(env, ri, value & ~0x1FULL); +} + +static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t v= alue) +{ + /* Begin with base v8.0 state. */ + uint64_t valid_mask =3D 0x3fff; + ARMCPU *cpu =3D env_archcpu(env); + uint64_t changed; + + /* + * Because SCR_EL3 is the "real" cpreg and SCR is the alias, reset alw= ays + * passes the reginfo for SCR_EL3, which has type ARM_CP_STATE_AA64. + * Instead, choose the format based on the mode of EL3. + */ + if (arm_el_is_aa64(env, 3)) { + value |=3D SCR_FW | SCR_AW; /* RES1 */ + valid_mask &=3D ~SCR_NET; /* RES0 */ + + if (!cpu_isar_feature(aa64_aa32_el1, cpu) && + !cpu_isar_feature(aa64_aa32_el2, cpu)) { + value |=3D SCR_RW; /* RAO/WI */ + } + if (cpu_isar_feature(aa64_ras, cpu)) { + valid_mask |=3D SCR_TERR; + } + if (cpu_isar_feature(aa64_lor, cpu)) { + valid_mask |=3D SCR_TLOR; + } + if (cpu_isar_feature(aa64_pauth, cpu)) { + valid_mask |=3D SCR_API | SCR_APK; + } + if (cpu_isar_feature(aa64_sel2, cpu)) { + valid_mask |=3D SCR_EEL2; + } + if (cpu_isar_feature(aa64_mte, cpu)) { + valid_mask |=3D SCR_ATA; + } + if (cpu_isar_feature(aa64_scxtnum, cpu)) { + valid_mask |=3D SCR_ENSCXT; + } + if (cpu_isar_feature(aa64_doublefault, cpu)) { + valid_mask |=3D SCR_EASE | SCR_NMEA; + } + if (cpu_isar_feature(aa64_sme, cpu)) { + valid_mask |=3D SCR_ENTP2; + } + } else { + valid_mask &=3D ~(SCR_RW | SCR_ST); + if (cpu_isar_feature(aa32_ras, cpu)) { + valid_mask |=3D SCR_TERR; + } + } + + if (!arm_feature(env, ARM_FEATURE_EL2)) { + valid_mask &=3D ~SCR_HCE; + + /* + * On ARMv7, SMD (or SCD as it is called in v7) is only + * supported if EL2 exists. The bit is UNK/SBZP when + * EL2 is unavailable. In QEMU ARMv7, we force it to always zero + * when EL2 is unavailable. + * On ARMv8, this bit is always available. + */ + if (arm_feature(env, ARM_FEATURE_V7) && + !arm_feature(env, ARM_FEATURE_V8)) { + valid_mask &=3D ~SCR_SMD; + } + } + + /* Clear all-context RES0 bits. */ + value &=3D valid_mask; + changed =3D env->cp15.scr_el3 ^ value; + env->cp15.scr_el3 =3D value; + + /* + * If SCR_EL3.NS changes, i.e. arm_is_secure_below_el3, then + * we must invalidate all TLBs below EL3. + */ + if (changed & SCR_NS) { + tlb_flush_by_mmuidx(env_cpu(env), (ARMMMUIdxBit_E10_0 | + ARMMMUIdxBit_E20_0 | + ARMMMUIdxBit_E10_1 | + ARMMMUIdxBit_E20_2 | + ARMMMUIdxBit_E10_1_PAN | + ARMMMUIdxBit_E20_2_PAN | + ARMMMUIdxBit_E2)); + } +} + +static void scr_reset(CPUARMState *env, const ARMCPRegInfo *ri) +{ + /* + * scr_write will set the RES1 bits on an AArch64-only CPU. + * The reset value will be 0x30 on an AArch64-only CPU and 0 otherwise. + */ + scr_write(env, ri, 0); +} + +static CPAccessResult access_tid4(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + if (arm_current_el(env) =3D=3D 1 && + (arm_hcr_el2_eff(env) & (HCR_TID2 | HCR_TID4))) { + return CP_ACCESS_TRAP_EL2; + } + + return CP_ACCESS_OK; +} + +static uint64_t ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + ARMCPU *cpu =3D env_archcpu(env); + + /* + * Acquire the CSSELR index from the bank corresponding to the CCSIDR + * bank + */ + uint32_t index =3D A32_BANKED_REG_GET(env, csselr, + ri->secure & ARM_CP_SECSTATE_S); + + return cpu->ccsidr[index]; +} + +static void csselr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + raw_write(env, ri, value & 0xf); +} + +static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + CPUState *cs =3D env_cpu(env); + bool el1 =3D arm_current_el(env) =3D=3D 1; + uint64_t hcr_el2 =3D el1 ? arm_hcr_el2_eff(env) : 0; + uint64_t ret =3D 0; + + if (hcr_el2 & HCR_IMO) { + if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) { + ret |=3D CPSR_I; + } + } else { + if (cs->interrupt_request & CPU_INTERRUPT_HARD) { + ret |=3D CPSR_I; + } + } + + if (hcr_el2 & HCR_FMO) { + if (cs->interrupt_request & CPU_INTERRUPT_VFIQ) { + ret |=3D CPSR_F; + } + } else { + if (cs->interrupt_request & CPU_INTERRUPT_FIQ) { + ret |=3D CPSR_F; + } + } + + if (hcr_el2 & HCR_AMO) { + if (cs->interrupt_request & CPU_INTERRUPT_VSERR) { + ret |=3D CPSR_A; + } + } + + return ret; +} + +static CPAccessResult access_aa64_tid1(CPUARMState *env, const ARMCPRegInf= o *ri, + bool isread) +{ + if (arm_current_el(env) =3D=3D 1 && (arm_hcr_el2_eff(env) & HCR_TID1))= { + return CP_ACCESS_TRAP_EL2; + } + + return CP_ACCESS_OK; +} + +static CPAccessResult access_aa32_tid1(CPUARMState *env, const ARMCPRegInf= o *ri, + bool isread) +{ + if (arm_feature(env, ARM_FEATURE_V8)) { + return access_aa64_tid1(env, ri, isread); + } + + return CP_ACCESS_OK; +} + +static const ARMCPRegInfo v7_cp_reginfo[] =3D { + /* the old v6 WFI, UNPREDICTABLE in v7 but we choose to NOP */ + { .name =3D "NOP", .cp =3D 15, .crn =3D 7, .crm =3D 0, .opc1 =3D 0, .o= pc2 =3D 4, + .access =3D PL1_W, .type =3D ARM_CP_NOP }, + /* + * Performance monitors are implementation defined in v7, + * but with an ARM recommended set of registers, which we + * follow. + * + * Performance registers fall into three categories: + * (a) always UNDEF in PL0, RW in PL1 (PMINTENSET, PMINTENCLR) + * (b) RO in PL0 (ie UNDEF on write), RW in PL1 (PMUSERENR) + * (c) UNDEF in PL0 if PMUSERENR.EN=3D=3D0, otherwise accessible (all= others) + * For the cases controlled by PMUSERENR we must set .access to PL0_RW + * or PL0_RO as appropriate and then check PMUSERENR in the helper fn. + */ + { .name =3D "PMCNTENSET", .cp =3D 15, .crn =3D 9, .crm =3D 12, .opc1 = =3D 0, .opc2 =3D 1, + .access =3D PL0_RW, .type =3D ARM_CP_ALIAS | ARM_CP_IO, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pmcnten), + .writefn =3D pmcntenset_write, + .accessfn =3D pmreg_access, + .raw_writefn =3D raw_write }, + { .name =3D "PMCNTENSET_EL0", .state =3D ARM_CP_STATE_AA64, .type =3D = ARM_CP_IO, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D 1, + .access =3D PL0_RW, .accessfn =3D pmreg_access, + .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pmcnten), .resetvalue= =3D 0, + .writefn =3D pmcntenset_write, .raw_writefn =3D raw_write }, + { .name =3D "PMCNTENCLR", .cp =3D 15, .crn =3D 9, .crm =3D 12, .opc1 = =3D 0, .opc2 =3D 2, + .access =3D PL0_RW, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pmcnten), + .accessfn =3D pmreg_access, + .writefn =3D pmcntenclr_write, + .type =3D ARM_CP_ALIAS | ARM_CP_IO }, + { .name =3D "PMCNTENCLR_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D 2, + .access =3D PL0_RW, .accessfn =3D pmreg_access, + .type =3D ARM_CP_ALIAS | ARM_CP_IO, + .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pmcnten), + .writefn =3D pmcntenclr_write }, + { .name =3D "PMOVSR", .cp =3D 15, .crn =3D 9, .crm =3D 12, .opc1 =3D 0= , .opc2 =3D 3, + .access =3D PL0_RW, .type =3D ARM_CP_IO, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pmovsr), + .accessfn =3D pmreg_access, + .writefn =3D pmovsr_write, + .raw_writefn =3D raw_write }, + { .name =3D "PMOVSCLR_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D 3, + .access =3D PL0_RW, .accessfn =3D pmreg_access, + .type =3D ARM_CP_ALIAS | ARM_CP_IO, + .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pmovsr), + .writefn =3D pmovsr_write, + .raw_writefn =3D raw_write }, + { .name =3D "PMSWINC", .cp =3D 15, .crn =3D 9, .crm =3D 12, .opc1 =3D = 0, .opc2 =3D 4, + .access =3D PL0_W, .accessfn =3D pmreg_access_swinc, + .type =3D ARM_CP_NO_RAW | ARM_CP_IO, + .writefn =3D pmswinc_write }, + { .name =3D "PMSWINC_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D 4, + .access =3D PL0_W, .accessfn =3D pmreg_access_swinc, + .type =3D ARM_CP_NO_RAW | ARM_CP_IO, + .writefn =3D pmswinc_write }, + { .name =3D "PMSELR", .cp =3D 15, .crn =3D 9, .crm =3D 12, .opc1 =3D 0= , .opc2 =3D 5, + .access =3D PL0_RW, .type =3D ARM_CP_ALIAS, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pmselr), + .accessfn =3D pmreg_access_selr, .writefn =3D pmselr_write, + .raw_writefn =3D raw_write}, + { .name =3D "PMSELR_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D 5, + .access =3D PL0_RW, .accessfn =3D pmreg_access_selr, + .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pmselr), + .writefn =3D pmselr_write, .raw_writefn =3D raw_write, }, + { .name =3D "PMCCNTR", .cp =3D 15, .crn =3D 9, .crm =3D 13, .opc1 =3D = 0, .opc2 =3D 0, + .access =3D PL0_RW, .resetvalue =3D 0, .type =3D ARM_CP_ALIAS | ARM_= CP_IO, + .readfn =3D pmccntr_read, .writefn =3D pmccntr_write32, + .accessfn =3D pmreg_access_ccntr }, + { .name =3D "PMCCNTR_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 13, .opc2 =3D 0, + .access =3D PL0_RW, .accessfn =3D pmreg_access_ccntr, + .type =3D ARM_CP_IO, + .fieldoffset =3D offsetof(CPUARMState, cp15.c15_ccnt), + .readfn =3D pmccntr_read, .writefn =3D pmccntr_write, + .raw_readfn =3D raw_read, .raw_writefn =3D raw_write, }, + { .name =3D "PMCCFILTR", .cp =3D 15, .opc1 =3D 0, .crn =3D 14, .crm = =3D 15, .opc2 =3D 7, + .writefn =3D pmccfiltr_write_a32, .readfn =3D pmccfiltr_read_a32, + .access =3D PL0_RW, .accessfn =3D pmreg_access, + .type =3D ARM_CP_ALIAS | ARM_CP_IO, + .resetvalue =3D 0, }, + { .name =3D "PMCCFILTR_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 15, .opc2 =3D 7, + .writefn =3D pmccfiltr_write, .raw_writefn =3D raw_write, + .access =3D PL0_RW, .accessfn =3D pmreg_access, + .type =3D ARM_CP_IO, + .fieldoffset =3D offsetof(CPUARMState, cp15.pmccfiltr_el0), + .resetvalue =3D 0, }, + { .name =3D "PMXEVTYPER", .cp =3D 15, .crn =3D 9, .crm =3D 13, .opc1 = =3D 0, .opc2 =3D 1, + .access =3D PL0_RW, .type =3D ARM_CP_NO_RAW | ARM_CP_IO, + .accessfn =3D pmreg_access, + .writefn =3D pmxevtyper_write, .readfn =3D pmxevtyper_read }, + { .name =3D "PMXEVTYPER_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 13, .opc2 =3D 1, + .access =3D PL0_RW, .type =3D ARM_CP_NO_RAW | ARM_CP_IO, + .accessfn =3D pmreg_access, + .writefn =3D pmxevtyper_write, .readfn =3D pmxevtyper_read }, + { .name =3D "PMXEVCNTR", .cp =3D 15, .crn =3D 9, .crm =3D 13, .opc1 = =3D 0, .opc2 =3D 2, + .access =3D PL0_RW, .type =3D ARM_CP_NO_RAW | ARM_CP_IO, + .accessfn =3D pmreg_access_xevcntr, + .writefn =3D pmxevcntr_write, .readfn =3D pmxevcntr_read }, + { .name =3D "PMXEVCNTR_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 13, .opc2 =3D 2, + .access =3D PL0_RW, .type =3D ARM_CP_NO_RAW | ARM_CP_IO, + .accessfn =3D pmreg_access_xevcntr, + .writefn =3D pmxevcntr_write, .readfn =3D pmxevcntr_read }, + { .name =3D "PMUSERENR", .cp =3D 15, .crn =3D 9, .crm =3D 14, .opc1 = =3D 0, .opc2 =3D 0, + .access =3D PL0_R | PL1_RW, .accessfn =3D access_tpm, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pmuserenr), + .resetvalue =3D 0, + .writefn =3D pmuserenr_write, .raw_writefn =3D raw_write }, + { .name =3D "PMUSERENR_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 14, .opc2 =3D 0, + .access =3D PL0_R | PL1_RW, .accessfn =3D access_tpm, .type =3D ARM_= CP_ALIAS, + .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pmuserenr), + .resetvalue =3D 0, + .writefn =3D pmuserenr_write, .raw_writefn =3D raw_write }, + { .name =3D "PMINTENSET", .cp =3D 15, .crn =3D 9, .crm =3D 14, .opc1 = =3D 0, .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_tpm, + .type =3D ARM_CP_ALIAS | ARM_CP_IO, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pminten), + .resetvalue =3D 0, + .writefn =3D pmintenset_write, .raw_writefn =3D raw_write }, + { .name =3D "PMINTENSET_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 9, .crm =3D 14, .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_tpm, + .type =3D ARM_CP_IO, + .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pminten), + .writefn =3D pmintenset_write, .raw_writefn =3D raw_write, + .resetvalue =3D 0x0 }, + { .name =3D "PMINTENCLR", .cp =3D 15, .crn =3D 9, .crm =3D 14, .opc1 = =3D 0, .opc2 =3D 2, + .access =3D PL1_RW, .accessfn =3D access_tpm, + .type =3D ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW, + .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pminten), + .writefn =3D pmintenclr_write, }, + { .name =3D "PMINTENCLR_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 9, .crm =3D 14, .opc2 =3D 2, + .access =3D PL1_RW, .accessfn =3D access_tpm, + .type =3D ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW, + .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pminten), + .writefn =3D pmintenclr_write }, + { .name =3D "CCSIDR", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .crn =3D 0, .crm =3D 0, .opc1 =3D 1, .opc2 =3D 0, + .access =3D PL1_R, + .accessfn =3D access_tid4, + .readfn =3D ccsidr_read, .type =3D ARM_CP_NO_RAW }, + { .name =3D "CSSELR", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .crn =3D 0, .crm =3D 0, .opc1 =3D 2, .opc2 =3D 0, + .access =3D PL1_RW, + .accessfn =3D access_tid4, + .writefn =3D csselr_write, .resetvalue =3D 0, + .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.csselr_s), + offsetof(CPUARMState, cp15.csselr_ns) } }, + /* + * Auxiliary ID register: this actually has an IMPDEF value but for now + * just RAZ for all cores: + */ + { .name =3D "AIDR", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 1, .crn =3D 0, .crm =3D 0, .opc2 =3D 7, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid1, + .resetvalue =3D 0 }, + /* + * Auxiliary fault status registers: these also are IMPDEF, and we + * choose to RAZ/WI for all cores. + */ + { .name =3D "AFSR0_EL1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 5, .crm =3D 1, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + { .name =3D "AFSR1_EL1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 5, .crm =3D 1, .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + /* + * MAIR can just read-as-written because we don't implement caches + * and so don't need to care about memory attributes. + */ + { .name =3D "MAIR_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 10, .crm =3D 2, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .fieldoffset =3D offsetof(CPUARMState, cp15.mair_el[1]), + .resetvalue =3D 0 }, + { .name =3D "MAIR_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 10, .crm =3D 2, .opc2 =3D 0, + .access =3D PL3_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.mair= _el[3]), + .resetvalue =3D 0 }, + /* + * For non-long-descriptor page tables these are PRRR and NMRR; + * regardless they still act as reads-as-written for QEMU. + */ + /* + * MAIR0/1 are defined separately from their 64-bit counterpart which + * allows them to assign the correct fieldoffset based on the endiann= ess + * handled in the field definitions. + */ + { .name =3D "MAIR0", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 0, .crn =3D 10, .crm =3D 2, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.mair0_s), + offsetof(CPUARMState, cp15.mair0_ns) }, + .resetfn =3D arm_cp_reset_ignore }, + { .name =3D "MAIR1", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 0, .crn =3D 10, .crm =3D 2, .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.mair1_s), + offsetof(CPUARMState, cp15.mair1_ns) }, + .resetfn =3D arm_cp_reset_ignore }, + { .name =3D "ISR_EL1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 12, .crm =3D 1, .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_R, .readfn =3D isr_read }, + /* 32 bit ITLB invalidates */ + { .name =3D "ITLBIALL", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D = 5, .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, + .writefn =3D tlbiall_write }, + { .name =3D "ITLBIMVA", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D = 5, .opc2 =3D 1, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, + .writefn =3D tlbimva_write }, + { .name =3D "ITLBIASID", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D= 5, .opc2 =3D 2, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, + .writefn =3D tlbiasid_write }, + /* 32 bit DTLB invalidates */ + { .name =3D "DTLBIALL", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D = 6, .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, + .writefn =3D tlbiall_write }, + { .name =3D "DTLBIMVA", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D = 6, .opc2 =3D 1, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, + .writefn =3D tlbimva_write }, + { .name =3D "DTLBIASID", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D= 6, .opc2 =3D 2, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, + .writefn =3D tlbiasid_write }, + /* 32 bit TLB invalidates */ + { .name =3D "TLBIALL", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D 7= , .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, + .writefn =3D tlbiall_write }, + { .name =3D "TLBIMVA", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D 7= , .opc2 =3D 1, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, + .writefn =3D tlbimva_write }, + { .name =3D "TLBIASID", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D = 7, .opc2 =3D 2, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, + .writefn =3D tlbiasid_write }, + { .name =3D "TLBIMVAA", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D = 7, .opc2 =3D 3, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, + .writefn =3D tlbimvaa_write }, +}; + +static const ARMCPRegInfo v7mp_cp_reginfo[] =3D { + /* 32 bit TLB invalidates, Inner Shareable */ + { .name =3D "TLBIALLIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D= 3, .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= bis, + .writefn =3D tlbiall_is_write }, + { .name =3D "TLBIMVAIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D= 3, .opc2 =3D 1, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= bis, + .writefn =3D tlbimva_is_write }, + { .name =3D "TLBIASIDIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm = =3D 3, .opc2 =3D 2, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= bis, + .writefn =3D tlbiasid_is_write }, + { .name =3D "TLBIMVAAIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm = =3D 3, .opc2 =3D 3, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= bis, + .writefn =3D tlbimvaa_is_write }, +}; + +static const ARMCPRegInfo pmovsset_cp_reginfo[] =3D { + /* PMOVSSET is not implemented in v7 before v7ve */ + { .name =3D "PMOVSSET", .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D = 14, .opc2 =3D 3, + .access =3D PL0_RW, .accessfn =3D pmreg_access, + .type =3D ARM_CP_ALIAS | ARM_CP_IO, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pmovsr), + .writefn =3D pmovsset_write, + .raw_writefn =3D raw_write }, + { .name =3D "PMOVSSET_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 14, .opc2 =3D 3, + .access =3D PL0_RW, .accessfn =3D pmreg_access, + .type =3D ARM_CP_ALIAS | ARM_CP_IO, + .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pmovsr), + .writefn =3D pmovsset_write, + .raw_writefn =3D raw_write }, +}; + +static void teecr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + value &=3D 1; + env->teecr =3D value; +} + +static CPAccessResult teecr_access(CPUARMState *env, const ARMCPRegInfo *r= i, + bool isread) +{ + /* + * HSTR.TTEE only exists in v7A, not v8A, but v8A doesn't have T2EE + * at all, so we don't need to check whether we're v8A. + */ + if (arm_current_el(env) < 2 && !arm_is_secure_below_el3(env) && + (env->cp15.hstr_el2 & HSTR_TTEE)) { + return CP_ACCESS_TRAP_EL2; + } + return CP_ACCESS_OK; +} + +static CPAccessResult teehbr_access(CPUARMState *env, const ARMCPRegInfo *= ri, + bool isread) +{ + if (arm_current_el(env) =3D=3D 0 && (env->teecr & 1)) { + return CP_ACCESS_TRAP; + } + return teecr_access(env, ri, isread); +} + +static const ARMCPRegInfo t2ee_cp_reginfo[] =3D { + { .name =3D "TEECR", .cp =3D 14, .crn =3D 0, .crm =3D 0, .opc1 =3D 6, = .opc2 =3D 0, + .access =3D PL1_RW, .fieldoffset =3D offsetof(CPUARMState, teecr), + .resetvalue =3D 0, + .writefn =3D teecr_write, .accessfn =3D teecr_access }, + { .name =3D "TEEHBR", .cp =3D 14, .crn =3D 1, .crm =3D 0, .opc1 =3D 6,= .opc2 =3D 0, + .access =3D PL0_RW, .fieldoffset =3D offsetof(CPUARMState, teehbr), + .accessfn =3D teehbr_access, .resetvalue =3D 0 }, +}; + +static const ARMCPRegInfo v6k_cp_reginfo[] =3D { + { .name =3D "TPIDR_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 2, .crn =3D 13, .crm =3D 0, + .access =3D PL0_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.tpidr_el[0]), .resetvalu= e =3D 0 }, + { .name =3D "TPIDRURW", .cp =3D 15, .crn =3D 13, .crm =3D 0, .opc1 =3D= 0, .opc2 =3D 2, + .access =3D PL0_RW, + .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.tpidrurw_s), + offsetoflow32(CPUARMState, cp15.tpidrurw_ns) = }, + .resetfn =3D arm_cp_reset_ignore }, + { .name =3D "TPIDRRO_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 3, .crn =3D 13, .crm =3D 0, + .access =3D PL0_R | PL1_W, + .fieldoffset =3D offsetof(CPUARMState, cp15.tpidrro_el[0]), + .resetvalue =3D 0}, + { .name =3D "TPIDRURO", .cp =3D 15, .crn =3D 13, .crm =3D 0, .opc1 =3D= 0, .opc2 =3D 3, + .access =3D PL0_R | PL1_W, + .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.tpidruro_s), + offsetoflow32(CPUARMState, cp15.tpidruro_ns) = }, + .resetfn =3D arm_cp_reset_ignore }, + { .name =3D "TPIDR_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .opc2 =3D 4, .crn =3D 13, .crm =3D 0, + .access =3D PL1_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.tpidr_el[1]), .resetvalu= e =3D 0 }, + { .name =3D "TPIDRPRW", .opc1 =3D 0, .cp =3D 15, .crn =3D 13, .crm =3D= 0, .opc2 =3D 4, + .access =3D PL1_RW, + .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.tpidrprw_s), + offsetoflow32(CPUARMState, cp15.tpidrprw_ns) = }, + .resetvalue =3D 0 }, +}; + +#ifndef CONFIG_USER_ONLY + +static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInf= o *ri, + bool isread) +{ + /* + * CNTFRQ: not visible from PL0 if both PL0PCTEN and PL0VCTEN are zero. + * Writable only at the highest implemented exception level. + */ + int el =3D arm_current_el(env); + uint64_t hcr; + uint32_t cntkctl; + + switch (el) { + case 0: + hcr =3D arm_hcr_el2_eff(env); + if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { + cntkctl =3D env->cp15.cnthctl_el2; + } else { + cntkctl =3D env->cp15.c14_cntkctl; + } + if (!extract32(cntkctl, 0, 2)) { + return CP_ACCESS_TRAP; + } + break; + case 1: + if (!isread && ri->state =3D=3D ARM_CP_STATE_AA32 && + arm_is_secure_below_el3(env)) { + /* Accesses from 32-bit Secure EL1 UNDEF (*not* trap to EL3!) = */ + return CP_ACCESS_TRAP_UNCATEGORIZED; + } + break; + case 2: + case 3: + break; + } + + if (!isread && el < arm_highest_el(env)) { + return CP_ACCESS_TRAP_UNCATEGORIZED; + } + + return CP_ACCESS_OK; +} + +static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx, + bool isread) +{ + unsigned int cur_el =3D arm_current_el(env); + bool has_el2 =3D arm_is_el2_enabled(env); + uint64_t hcr =3D arm_hcr_el2_eff(env); + + switch (cur_el) { + case 0: + /* If HCR_EL2. =3D=3D '11': check CNTHCTL_EL2.EL0[PV]CTEN= . */ + if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { + return (extract32(env->cp15.cnthctl_el2, timeridx, 1) + ? CP_ACCESS_OK : CP_ACCESS_TRAP_EL2); + } + + /* CNT[PV]CT: not visible from PL0 if EL0[PV]CTEN is zero */ + if (!extract32(env->cp15.c14_cntkctl, timeridx, 1)) { + return CP_ACCESS_TRAP; + } + + /* If HCR_EL2. =3D=3D '10': check CNTHCTL_EL2.EL1PCTEN. */ + if (hcr & HCR_E2H) { + if (timeridx =3D=3D GTIMER_PHYS && + !extract32(env->cp15.cnthctl_el2, 10, 1)) { + return CP_ACCESS_TRAP_EL2; + } + } else { + /* If HCR_EL2. =3D=3D 0: check CNTHCTL_EL2.EL1PCEN. */ + if (has_el2 && timeridx =3D=3D GTIMER_PHYS && + !extract32(env->cp15.cnthctl_el2, 1, 1)) { + return CP_ACCESS_TRAP_EL2; + } + } + break; + + case 1: + /* Check CNTHCTL_EL2.EL1PCTEN, which changes location based on E2H= . */ + if (has_el2 && timeridx =3D=3D GTIMER_PHYS && + (hcr & HCR_E2H + ? !extract32(env->cp15.cnthctl_el2, 10, 1) + : !extract32(env->cp15.cnthctl_el2, 0, 1))) { + return CP_ACCESS_TRAP_EL2; + } + break; + } + return CP_ACCESS_OK; +} + +static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx, + bool isread) +{ + unsigned int cur_el =3D arm_current_el(env); + bool has_el2 =3D arm_is_el2_enabled(env); + uint64_t hcr =3D arm_hcr_el2_eff(env); + + switch (cur_el) { + case 0: + if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { + /* If HCR_EL2. =3D=3D '11': check CNTHCTL_EL2.EL0[PV]= TEN. */ + return (extract32(env->cp15.cnthctl_el2, 9 - timeridx, 1) + ? CP_ACCESS_OK : CP_ACCESS_TRAP_EL2); + } + + /* + * CNT[PV]_CVAL, CNT[PV]_CTL, CNT[PV]_TVAL: not visible from + * EL0 if EL0[PV]TEN is zero. + */ + if (!extract32(env->cp15.c14_cntkctl, 9 - timeridx, 1)) { + return CP_ACCESS_TRAP; + } + /* fall through */ + + case 1: + if (has_el2 && timeridx =3D=3D GTIMER_PHYS) { + if (hcr & HCR_E2H) { + /* If HCR_EL2. =3D=3D '10': check CNTHCTL_EL2.EL1= PTEN. */ + if (!extract32(env->cp15.cnthctl_el2, 11, 1)) { + return CP_ACCESS_TRAP_EL2; + } + } else { + /* If HCR_EL2. =3D=3D 0: check CNTHCTL_EL2.EL1PCEN. */ + if (!extract32(env->cp15.cnthctl_el2, 1, 1)) { + return CP_ACCESS_TRAP_EL2; + } + } + } + break; + } + return CP_ACCESS_OK; +} + +static CPAccessResult gt_pct_access(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + return gt_counter_access(env, GTIMER_PHYS, isread); +} + +static CPAccessResult gt_vct_access(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + return gt_counter_access(env, GTIMER_VIRT, isread); +} + +static CPAccessResult gt_ptimer_access(CPUARMState *env, const ARMCPRegInf= o *ri, + bool isread) +{ + return gt_timer_access(env, GTIMER_PHYS, isread); +} + +static CPAccessResult gt_vtimer_access(CPUARMState *env, const ARMCPRegInf= o *ri, + bool isread) +{ + return gt_timer_access(env, GTIMER_VIRT, isread); +} + +static CPAccessResult gt_stimer_access(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + /* + * The AArch64 register view of the secure physical timer is + * always accessible from EL3, and configurably accessible from + * Secure EL1. + */ + switch (arm_current_el(env)) { + case 1: + if (!arm_is_secure(env)) { + return CP_ACCESS_TRAP; + } + if (!(env->cp15.scr_el3 & SCR_ST)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; + case 0: + case 2: + return CP_ACCESS_TRAP; + case 3: + return CP_ACCESS_OK; + default: + g_assert_not_reached(); + } +} + +static uint64_t gt_get_countervalue(CPUARMState *env) +{ + ARMCPU *cpu =3D env_archcpu(env); + + return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / gt_cntfrq_period_ns(cpu= ); +} + +static void gt_recalc_timer(ARMCPU *cpu, int timeridx) +{ + ARMGenericTimer *gt =3D &cpu->env.cp15.c14_timer[timeridx]; + + if (gt->ctl & 1) { + /* + * Timer enabled: calculate and set current ISTATUS, irq, and + * reset timer to when ISTATUS next has to change + */ + uint64_t offset =3D timeridx =3D=3D GTIMER_VIRT ? + cpu->env.cp15.cntvoff_el2 : 0; + uint64_t count =3D gt_get_countervalue(&cpu->env); + /* Note that this must be unsigned 64 bit arithmetic: */ + int istatus =3D count - offset >=3D gt->cval; + uint64_t nexttick; + int irqstate; + + gt->ctl =3D deposit32(gt->ctl, 2, 1, istatus); + + irqstate =3D (istatus && !(gt->ctl & 2)); + qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate); + + if (istatus) { + /* Next transition is when count rolls back over to zero */ + nexttick =3D UINT64_MAX; + } else { + /* Next transition is when we hit cval */ + nexttick =3D gt->cval + offset; + } + /* + * Note that the desired next expiry time might be beyond the + * signed-64-bit range of a QEMUTimer -- in this case we just + * set the timer for as far in the future as possible. When the + * timer expires we will reset the timer for any remaining period. + */ + if (nexttick > INT64_MAX / gt_cntfrq_period_ns(cpu)) { + timer_mod_ns(cpu->gt_timer[timeridx], INT64_MAX); + } else { + timer_mod(cpu->gt_timer[timeridx], nexttick); + } + trace_arm_gt_recalc(timeridx, irqstate, nexttick); + } else { + /* Timer disabled: ISTATUS and timer output always clear */ + gt->ctl &=3D ~4; + qemu_set_irq(cpu->gt_timer_outputs[timeridx], 0); + timer_del(cpu->gt_timer[timeridx]); + trace_arm_gt_recalc_disabled(timeridx); + } +} + +static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri, + int timeridx) +{ + ARMCPU *cpu =3D env_archcpu(env); + + timer_del(cpu->gt_timer[timeridx]); +} + +static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return gt_get_countervalue(env); +} + +static uint64_t gt_virt_cnt_offset(CPUARMState *env) +{ + uint64_t hcr; + + switch (arm_current_el(env)) { + case 2: + hcr =3D arm_hcr_el2_eff(env); + if (hcr & HCR_E2H) { + return 0; + } + break; + case 0: + hcr =3D arm_hcr_el2_eff(env); + if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { + return 0; + } + break; + } + + return env->cp15.cntvoff_el2; +} + +static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return gt_get_countervalue(env) - gt_virt_cnt_offset(env); +} + +static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri, + int timeridx, + uint64_t value) +{ + trace_arm_gt_cval_write(timeridx, value); + env->cp15.c14_timer[timeridx].cval =3D value; + gt_recalc_timer(env_archcpu(env), timeridx); +} + +static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri, + int timeridx) +{ + uint64_t offset =3D 0; + + switch (timeridx) { + case GTIMER_VIRT: + case GTIMER_HYPVIRT: + offset =3D gt_virt_cnt_offset(env); + break; + } + + return (uint32_t)(env->cp15.c14_timer[timeridx].cval - + (gt_get_countervalue(env) - offset)); +} + +static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri, + int timeridx, + uint64_t value) +{ + uint64_t offset =3D 0; + + switch (timeridx) { + case GTIMER_VIRT: + case GTIMER_HYPVIRT: + offset =3D gt_virt_cnt_offset(env); + break; + } + + trace_arm_gt_tval_write(timeridx, value); + env->cp15.c14_timer[timeridx].cval =3D gt_get_countervalue(env) - offs= et + + sextract64(value, 0, 32); + gt_recalc_timer(env_archcpu(env), timeridx); +} + +static void gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri, + int timeridx, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + uint32_t oldval =3D env->cp15.c14_timer[timeridx].ctl; + + trace_arm_gt_ctl_write(timeridx, value); + env->cp15.c14_timer[timeridx].ctl =3D deposit64(oldval, 0, 2, value); + if ((oldval ^ value) & 1) { + /* Enable toggled */ + gt_recalc_timer(cpu, timeridx); + } else if ((oldval ^ value) & 2) { + /* + * IMASK toggled: don't need to recalculate, + * just set the interrupt line based on ISTATUS + */ + int irqstate =3D (oldval & 4) && !(value & 2); + + trace_arm_gt_imask_toggle(timeridx, irqstate); + qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate); + } +} + +static void gt_phys_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri) +{ + gt_timer_reset(env, ri, GTIMER_PHYS); +} + +static void gt_phys_cval_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + gt_cval_write(env, ri, GTIMER_PHYS, value); +} + +static uint64_t gt_phys_tval_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return gt_tval_read(env, ri, GTIMER_PHYS); +} + +static void gt_phys_tval_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + gt_tval_write(env, ri, GTIMER_PHYS, value); +} + +static void gt_phys_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + gt_ctl_write(env, ri, GTIMER_PHYS, value); +} + +static int gt_phys_redir_timeridx(CPUARMState *env) +{ + switch (arm_mmu_idx(env)) { + case ARMMMUIdx_E20_0: + case ARMMMUIdx_E20_2: + case ARMMMUIdx_E20_2_PAN: + return GTIMER_HYP; + default: + return GTIMER_PHYS; + } +} + +static int gt_virt_redir_timeridx(CPUARMState *env) +{ + switch (arm_mmu_idx(env)) { + case ARMMMUIdx_E20_0: + case ARMMMUIdx_E20_2: + case ARMMMUIdx_E20_2_PAN: + return GTIMER_HYPVIRT; + default: + return GTIMER_VIRT; + } +} + +static uint64_t gt_phys_redir_cval_read(CPUARMState *env, + const ARMCPRegInfo *ri) +{ + int timeridx =3D gt_phys_redir_timeridx(env); + return env->cp15.c14_timer[timeridx].cval; +} + +static void gt_phys_redir_cval_write(CPUARMState *env, const ARMCPRegInfo = *ri, + uint64_t value) +{ + int timeridx =3D gt_phys_redir_timeridx(env); + gt_cval_write(env, ri, timeridx, value); +} + +static uint64_t gt_phys_redir_tval_read(CPUARMState *env, + const ARMCPRegInfo *ri) +{ + int timeridx =3D gt_phys_redir_timeridx(env); + return gt_tval_read(env, ri, timeridx); +} + +static void gt_phys_redir_tval_write(CPUARMState *env, const ARMCPRegInfo = *ri, + uint64_t value) +{ + int timeridx =3D gt_phys_redir_timeridx(env); + gt_tval_write(env, ri, timeridx, value); +} + +static uint64_t gt_phys_redir_ctl_read(CPUARMState *env, + const ARMCPRegInfo *ri) +{ + int timeridx =3D gt_phys_redir_timeridx(env); + return env->cp15.c14_timer[timeridx].ctl; +} + +static void gt_phys_redir_ctl_write(CPUARMState *env, const ARMCPRegInfo *= ri, + uint64_t value) +{ + int timeridx =3D gt_phys_redir_timeridx(env); + gt_ctl_write(env, ri, timeridx, value); +} + +static void gt_virt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri) +{ + gt_timer_reset(env, ri, GTIMER_VIRT); +} + +static void gt_virt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + gt_cval_write(env, ri, GTIMER_VIRT, value); +} + +static uint64_t gt_virt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return gt_tval_read(env, ri, GTIMER_VIRT); +} + +static void gt_virt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + gt_tval_write(env, ri, GTIMER_VIRT, value); +} + +static void gt_virt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + gt_ctl_write(env, ri, GTIMER_VIRT, value); +} + +static void gt_cntvoff_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + + trace_arm_gt_cntvoff_write(value); + raw_write(env, ri, value); + gt_recalc_timer(cpu, GTIMER_VIRT); +} + +static uint64_t gt_virt_redir_cval_read(CPUARMState *env, + const ARMCPRegInfo *ri) +{ + int timeridx =3D gt_virt_redir_timeridx(env); + return env->cp15.c14_timer[timeridx].cval; +} + +static void gt_virt_redir_cval_write(CPUARMState *env, const ARMCPRegInfo = *ri, + uint64_t value) +{ + int timeridx =3D gt_virt_redir_timeridx(env); + gt_cval_write(env, ri, timeridx, value); +} + +static uint64_t gt_virt_redir_tval_read(CPUARMState *env, + const ARMCPRegInfo *ri) +{ + int timeridx =3D gt_virt_redir_timeridx(env); + return gt_tval_read(env, ri, timeridx); +} + +static void gt_virt_redir_tval_write(CPUARMState *env, const ARMCPRegInfo = *ri, + uint64_t value) +{ + int timeridx =3D gt_virt_redir_timeridx(env); + gt_tval_write(env, ri, timeridx, value); +} + +static uint64_t gt_virt_redir_ctl_read(CPUARMState *env, + const ARMCPRegInfo *ri) +{ + int timeridx =3D gt_virt_redir_timeridx(env); + return env->cp15.c14_timer[timeridx].ctl; +} + +static void gt_virt_redir_ctl_write(CPUARMState *env, const ARMCPRegInfo *= ri, + uint64_t value) +{ + int timeridx =3D gt_virt_redir_timeridx(env); + gt_ctl_write(env, ri, timeridx, value); +} + +static void gt_hyp_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri) +{ + gt_timer_reset(env, ri, GTIMER_HYP); +} + +static void gt_hyp_cval_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + gt_cval_write(env, ri, GTIMER_HYP, value); +} + +static uint64_t gt_hyp_tval_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return gt_tval_read(env, ri, GTIMER_HYP); +} + +static void gt_hyp_tval_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + gt_tval_write(env, ri, GTIMER_HYP, value); +} + +static void gt_hyp_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + gt_ctl_write(env, ri, GTIMER_HYP, value); +} + +static void gt_sec_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri) +{ + gt_timer_reset(env, ri, GTIMER_SEC); +} + +static void gt_sec_cval_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + gt_cval_write(env, ri, GTIMER_SEC, value); +} + +static uint64_t gt_sec_tval_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return gt_tval_read(env, ri, GTIMER_SEC); +} + +static void gt_sec_tval_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + gt_tval_write(env, ri, GTIMER_SEC, value); +} + +static void gt_sec_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + gt_ctl_write(env, ri, GTIMER_SEC, value); +} + +static void gt_hv_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri) +{ + gt_timer_reset(env, ri, GTIMER_HYPVIRT); +} + +static void gt_hv_cval_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + gt_cval_write(env, ri, GTIMER_HYPVIRT, value); +} + +static uint64_t gt_hv_tval_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return gt_tval_read(env, ri, GTIMER_HYPVIRT); +} + +static void gt_hv_tval_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + gt_tval_write(env, ri, GTIMER_HYPVIRT, value); +} + +static void gt_hv_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + gt_ctl_write(env, ri, GTIMER_HYPVIRT, value); +} + +void arm_gt_ptimer_cb(void *opaque) +{ + ARMCPU *cpu =3D opaque; + + gt_recalc_timer(cpu, GTIMER_PHYS); +} + +void arm_gt_vtimer_cb(void *opaque) +{ + ARMCPU *cpu =3D opaque; + + gt_recalc_timer(cpu, GTIMER_VIRT); +} + +void arm_gt_htimer_cb(void *opaque) +{ + ARMCPU *cpu =3D opaque; + + gt_recalc_timer(cpu, GTIMER_HYP); +} + +void arm_gt_stimer_cb(void *opaque) +{ + ARMCPU *cpu =3D opaque; + + gt_recalc_timer(cpu, GTIMER_SEC); +} + +void arm_gt_hvtimer_cb(void *opaque) +{ + ARMCPU *cpu =3D opaque; + + gt_recalc_timer(cpu, GTIMER_HYPVIRT); +} + +static void arm_gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *opaq= ue) +{ + ARMCPU *cpu =3D env_archcpu(env); + + cpu->env.cp15.c14_cntfrq =3D cpu->gt_cntfrq_hz; +} + +static const ARMCPRegInfo generic_timer_cp_reginfo[] =3D { + /* + * Note that CNTFRQ is purely reads-as-written for the benefit + * of software; writing it doesn't actually change the timer frequency. + * Our reset value matches the fixed frequency we implement the timer = at. + */ + { .name =3D "CNTFRQ", .cp =3D 15, .crn =3D 14, .crm =3D 0, .opc1 =3D 0= , .opc2 =3D 0, + .type =3D ARM_CP_ALIAS, + .access =3D PL1_RW | PL0_R, .accessfn =3D gt_cntfrq_access, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c14_cntfrq), + }, + { .name =3D "CNTFRQ_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 0, .opc2 =3D 0, + .access =3D PL1_RW | PL0_R, .accessfn =3D gt_cntfrq_access, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_cntfrq), + .resetfn =3D arm_gt_cntfrq_reset, + }, + /* overall control: mostly access permissions */ + { .name =3D "CNTKCTL", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 14, .crm =3D 1, .opc2 =3D 0, + .access =3D PL1_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_cntkctl), + .resetvalue =3D 0, + }, + /* per-timer control */ + { .name =3D "CNTP_CTL", .cp =3D 15, .crn =3D 14, .crm =3D 2, .opc1 =3D= 0, .opc2 =3D 1, + .secure =3D ARM_CP_SECSTATE_NS, + .type =3D ARM_CP_IO | ARM_CP_ALIAS, .access =3D PL0_RW, + .accessfn =3D gt_ptimer_access, + .fieldoffset =3D offsetoflow32(CPUARMState, + cp15.c14_timer[GTIMER_PHYS].ctl), + .readfn =3D gt_phys_redir_ctl_read, .raw_readfn =3D raw_read, + .writefn =3D gt_phys_redir_ctl_write, .raw_writefn =3D raw_write, + }, + { .name =3D "CNTP_CTL_S", + .cp =3D 15, .crn =3D 14, .crm =3D 2, .opc1 =3D 0, .opc2 =3D 1, + .secure =3D ARM_CP_SECSTATE_S, + .type =3D ARM_CP_IO | ARM_CP_ALIAS, .access =3D PL0_RW, + .accessfn =3D gt_ptimer_access, + .fieldoffset =3D offsetoflow32(CPUARMState, + cp15.c14_timer[GTIMER_SEC].ctl), + .writefn =3D gt_sec_ctl_write, .raw_writefn =3D raw_write, + }, + { .name =3D "CNTP_CTL_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 2, .opc2 =3D 1, + .type =3D ARM_CP_IO, .access =3D PL0_RW, + .accessfn =3D gt_ptimer_access, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].c= tl), + .resetvalue =3D 0, + .readfn =3D gt_phys_redir_ctl_read, .raw_readfn =3D raw_read, + .writefn =3D gt_phys_redir_ctl_write, .raw_writefn =3D raw_write, + }, + { .name =3D "CNTV_CTL", .cp =3D 15, .crn =3D 14, .crm =3D 3, .opc1 =3D= 0, .opc2 =3D 1, + .type =3D ARM_CP_IO | ARM_CP_ALIAS, .access =3D PL0_RW, + .accessfn =3D gt_vtimer_access, + .fieldoffset =3D offsetoflow32(CPUARMState, + cp15.c14_timer[GTIMER_VIRT].ctl), + .readfn =3D gt_virt_redir_ctl_read, .raw_readfn =3D raw_read, + .writefn =3D gt_virt_redir_ctl_write, .raw_writefn =3D raw_write, + }, + { .name =3D "CNTV_CTL_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 3, .opc2 =3D 1, + .type =3D ARM_CP_IO, .access =3D PL0_RW, + .accessfn =3D gt_vtimer_access, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].c= tl), + .resetvalue =3D 0, + .readfn =3D gt_virt_redir_ctl_read, .raw_readfn =3D raw_read, + .writefn =3D gt_virt_redir_ctl_write, .raw_writefn =3D raw_write, + }, + /* TimerValue views: a 32 bit downcounting view of the underlying stat= e */ + { .name =3D "CNTP_TVAL", .cp =3D 15, .crn =3D 14, .crm =3D 2, .opc1 = =3D 0, .opc2 =3D 0, + .secure =3D ARM_CP_SECSTATE_NS, + .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL0_RW, + .accessfn =3D gt_ptimer_access, + .readfn =3D gt_phys_redir_tval_read, .writefn =3D gt_phys_redir_tval= _write, + }, + { .name =3D "CNTP_TVAL_S", + .cp =3D 15, .crn =3D 14, .crm =3D 2, .opc1 =3D 0, .opc2 =3D 0, + .secure =3D ARM_CP_SECSTATE_S, + .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL0_RW, + .accessfn =3D gt_ptimer_access, + .readfn =3D gt_sec_tval_read, .writefn =3D gt_sec_tval_write, + }, + { .name =3D "CNTP_TVAL_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 2, .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL0_RW, + .accessfn =3D gt_ptimer_access, .resetfn =3D gt_phys_timer_reset, + .readfn =3D gt_phys_redir_tval_read, .writefn =3D gt_phys_redir_tval= _write, + }, + { .name =3D "CNTV_TVAL", .cp =3D 15, .crn =3D 14, .crm =3D 3, .opc1 = =3D 0, .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL0_RW, + .accessfn =3D gt_vtimer_access, + .readfn =3D gt_virt_redir_tval_read, .writefn =3D gt_virt_redir_tval= _write, + }, + { .name =3D "CNTV_TVAL_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 3, .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL0_RW, + .accessfn =3D gt_vtimer_access, .resetfn =3D gt_virt_timer_reset, + .readfn =3D gt_virt_redir_tval_read, .writefn =3D gt_virt_redir_tval= _write, + }, + /* The counter itself */ + { .name =3D "CNTPCT", .cp =3D 15, .crm =3D 14, .opc1 =3D 0, + .access =3D PL0_R, .type =3D ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_I= O, + .accessfn =3D gt_pct_access, + .readfn =3D gt_cnt_read, .resetfn =3D arm_cp_reset_ignore, + }, + { .name =3D "CNTPCT_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 0, .opc2 =3D 1, + .access =3D PL0_R, .type =3D ARM_CP_NO_RAW | ARM_CP_IO, + .accessfn =3D gt_pct_access, .readfn =3D gt_cnt_read, + }, + { .name =3D "CNTVCT", .cp =3D 15, .crm =3D 14, .opc1 =3D 1, + .access =3D PL0_R, .type =3D ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_I= O, + .accessfn =3D gt_vct_access, + .readfn =3D gt_virt_cnt_read, .resetfn =3D arm_cp_reset_ignore, + }, + { .name =3D "CNTVCT_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 0, .opc2 =3D 2, + .access =3D PL0_R, .type =3D ARM_CP_NO_RAW | ARM_CP_IO, + .accessfn =3D gt_vct_access, .readfn =3D gt_virt_cnt_read, + }, + /* Comparison value, indicating when the timer goes off */ + { .name =3D "CNTP_CVAL", .cp =3D 15, .crm =3D 14, .opc1 =3D 2, + .secure =3D ARM_CP_SECSTATE_NS, + .access =3D PL0_RW, + .type =3D ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].c= val), + .accessfn =3D gt_ptimer_access, + .readfn =3D gt_phys_redir_cval_read, .raw_readfn =3D raw_read, + .writefn =3D gt_phys_redir_cval_write, .raw_writefn =3D raw_write, + }, + { .name =3D "CNTP_CVAL_S", .cp =3D 15, .crm =3D 14, .opc1 =3D 2, + .secure =3D ARM_CP_SECSTATE_S, + .access =3D PL0_RW, + .type =3D ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].cv= al), + .accessfn =3D gt_ptimer_access, + .writefn =3D gt_sec_cval_write, .raw_writefn =3D raw_write, + }, + { .name =3D "CNTP_CVAL_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 2, .opc2 =3D 2, + .access =3D PL0_RW, + .type =3D ARM_CP_IO, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].c= val), + .resetvalue =3D 0, .accessfn =3D gt_ptimer_access, + .readfn =3D gt_phys_redir_cval_read, .raw_readfn =3D raw_read, + .writefn =3D gt_phys_redir_cval_write, .raw_writefn =3D raw_write, + }, + { .name =3D "CNTV_CVAL", .cp =3D 15, .crm =3D 14, .opc1 =3D 3, + .access =3D PL0_RW, + .type =3D ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].c= val), + .accessfn =3D gt_vtimer_access, + .readfn =3D gt_virt_redir_cval_read, .raw_readfn =3D raw_read, + .writefn =3D gt_virt_redir_cval_write, .raw_writefn =3D raw_write, + }, + { .name =3D "CNTV_CVAL_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 3, .opc2 =3D 2, + .access =3D PL0_RW, + .type =3D ARM_CP_IO, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].c= val), + .resetvalue =3D 0, .accessfn =3D gt_vtimer_access, + .readfn =3D gt_virt_redir_cval_read, .raw_readfn =3D raw_read, + .writefn =3D gt_virt_redir_cval_write, .raw_writefn =3D raw_write, + }, + /* + * Secure timer -- this is actually restricted to only EL3 + * and configurably Secure-EL1 via the accessfn. + */ + { .name =3D "CNTPS_TVAL_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 7, .crn =3D 14, .crm =3D 2, .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL1_RW, + .accessfn =3D gt_stimer_access, + .readfn =3D gt_sec_tval_read, + .writefn =3D gt_sec_tval_write, + .resetfn =3D gt_sec_timer_reset, + }, + { .name =3D "CNTPS_CTL_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 7, .crn =3D 14, .crm =3D 2, .opc2 =3D 1, + .type =3D ARM_CP_IO, .access =3D PL1_RW, + .accessfn =3D gt_stimer_access, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].ct= l), + .resetvalue =3D 0, + .writefn =3D gt_sec_ctl_write, .raw_writefn =3D raw_write, + }, + { .name =3D "CNTPS_CVAL_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 7, .crn =3D 14, .crm =3D 2, .opc2 =3D 2, + .type =3D ARM_CP_IO, .access =3D PL1_RW, + .accessfn =3D gt_stimer_access, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].cv= al), + .writefn =3D gt_sec_cval_write, .raw_writefn =3D raw_write, + }, +}; + +static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + if (!(arm_hcr_el2_eff(env) & HCR_E2H)) { + return CP_ACCESS_TRAP; + } + return CP_ACCESS_OK; +} + +#else + +/* + * In user-mode most of the generic timer registers are inaccessible + * however modern kernels (4.12+) allow access to cntvct_el0 + */ + +static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + ARMCPU *cpu =3D env_archcpu(env); + + /* + * Currently we have no support for QEMUTimer in linux-user so we + * can't call gt_get_countervalue(env), instead we directly + * call the lower level functions. + */ + return cpu_get_clock() / gt_cntfrq_period_ns(cpu); +} + +static const ARMCPRegInfo generic_timer_cp_reginfo[] =3D { + { .name =3D "CNTFRQ_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 0, .opc2 =3D 0, + .type =3D ARM_CP_CONST, .access =3D PL0_R /* no PL1_RW in linux-user= */, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_cntfrq), + .resetvalue =3D NANOSECONDS_PER_SECOND / GTIMER_SCALE, + }, + { .name =3D "CNTVCT_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 0, .opc2 =3D 2, + .access =3D PL0_R, .type =3D ARM_CP_NO_RAW | ARM_CP_IO, + .readfn =3D gt_virt_cnt_read, + }, +}; + +#endif + +static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t v= alue) +{ + if (arm_feature(env, ARM_FEATURE_LPAE)) { + raw_write(env, ri, value); + } else if (arm_feature(env, ARM_FEATURE_V7)) { + raw_write(env, ri, value & 0xfffff6ff); + } else { + raw_write(env, ri, value & 0xfffff1ff); + } +} + +#ifndef CONFIG_USER_ONLY +/* get_phys_addr() isn't present for user-mode-only targets */ + +static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + if (ri->opc2 & 4) { + /* + * The ATS12NSO* operations must trap to EL3 or EL2 if executed in + * Secure EL1 (which can only happen if EL3 is AArch64). + * They are simply UNDEF if executed from NS EL1. + * They function normally from EL2 or EL3. + */ + if (arm_current_el(env) =3D=3D 1) { + if (arm_is_secure_below_el3(env)) { + if (env->cp15.scr_el3 & SCR_EEL2) { + return CP_ACCESS_TRAP_UNCATEGORIZED_EL2; + } + return CP_ACCESS_TRAP_UNCATEGORIZED_EL3; + } + return CP_ACCESS_TRAP_UNCATEGORIZED; + } + } + return CP_ACCESS_OK; +} + +#ifdef CONFIG_TCG +static uint64_t do_ats_write(CPUARMState *env, uint64_t value, + MMUAccessType access_type, ARMMMUIdx mmu_idx, + bool is_secure) +{ + bool ret; + uint64_t par64; + bool format64 =3D false; + ARMMMUFaultInfo fi =3D {}; + GetPhysAddrResult res =3D {}; + + ret =3D get_phys_addr_with_secure(env, value, access_type, mmu_idx, + is_secure, &res, &fi); + + /* + * ATS operations only do S1 or S1+S2 translations, so we never + * have to deal with the ARMCacheAttrs format for S2 only. + */ + assert(!res.cacheattrs.is_s2_format); + + if (ret) { + /* + * Some kinds of translation fault must cause exceptions rather + * than being reported in the PAR. + */ + int current_el =3D arm_current_el(env); + int target_el; + uint32_t syn, fsr, fsc; + bool take_exc =3D false; + + if (fi.s1ptw && current_el =3D=3D 1 + && arm_mmu_idx_is_stage1_of_2(mmu_idx)) { + /* + * Synchronous stage 2 fault on an access made as part of the + * translation table walk for AT S1E0* or AT S1E1* insn + * executed from NS EL1. If this is a synchronous external abo= rt + * and SCR_EL3.EA =3D=3D 1, then we take a synchronous externa= l abort + * to EL3. Otherwise the fault is taken as an exception to EL2, + * and HPFAR_EL2 holds the faulting IPA. + */ + if (fi.type =3D=3D ARMFault_SyncExternalOnWalk && + (env->cp15.scr_el3 & SCR_EA)) { + target_el =3D 3; + } else { + env->cp15.hpfar_el2 =3D extract64(fi.s2addr, 12, 47) << 4; + if (arm_is_secure_below_el3(env) && fi.s1ns) { + env->cp15.hpfar_el2 |=3D HPFAR_NS; + } + target_el =3D 2; + } + take_exc =3D true; + } else if (fi.type =3D=3D ARMFault_SyncExternalOnWalk) { + /* + * Synchronous external aborts during a translation table walk + * are taken as Data Abort exceptions. + */ + if (fi.stage2) { + if (current_el =3D=3D 3) { + target_el =3D 3; + } else { + target_el =3D 2; + } + } else { + target_el =3D exception_target_el(env); + } + take_exc =3D true; + } + + if (take_exc) { + /* Construct FSR and FSC using same logic as arm_deliver_fault= () */ + if (target_el =3D=3D 2 || arm_el_is_aa64(env, target_el) || + arm_s1_regime_using_lpae_format(env, mmu_idx)) { + fsr =3D arm_fi_to_lfsc(&fi); + fsc =3D extract32(fsr, 0, 6); + } else { + fsr =3D arm_fi_to_sfsc(&fi); + fsc =3D 0x3f; + } + /* + * Report exception with ESR indicating a fault due to a + * translation table walk for a cache maintenance instruction. + */ + syn =3D syn_data_abort_no_iss(current_el =3D=3D target_el, 0, + fi.ea, 1, fi.s1ptw, 1, fsc); + env->exception.vaddress =3D value; + env->exception.fsr =3D fsr; + raise_exception(env, EXCP_DATA_ABORT, syn, target_el); + } + } + + if (is_a64(env)) { + format64 =3D true; + } else if (arm_feature(env, ARM_FEATURE_LPAE)) { + /* + * ATS1Cxx: + * * TTBCR.EAE determines whether the result is returned using the + * 32-bit or the 64-bit PAR format + * * Instructions executed in Hyp mode always use the 64bit format + * + * ATS1S2NSOxx uses the 64bit format if any of the following is tr= ue: + * * The Non-secure TTBCR.EAE bit is set to 1 + * * The implementation includes EL2, and the value of HCR.VM is 1 + * + * (Note that HCR.DC makes HCR.VM behave as if it is 1.) + * + * ATS1Hx always uses the 64bit format. + */ + format64 =3D arm_s1_regime_using_lpae_format(env, mmu_idx); + + if (arm_feature(env, ARM_FEATURE_EL2)) { + if (mmu_idx =3D=3D ARMMMUIdx_E10_0 || + mmu_idx =3D=3D ARMMMUIdx_E10_1 || + mmu_idx =3D=3D ARMMMUIdx_E10_1_PAN) { + format64 |=3D env->cp15.hcr_el2 & (HCR_VM | HCR_DC); + } else { + format64 |=3D arm_current_el(env) =3D=3D 2; + } + } + } + + if (format64) { + /* Create a 64-bit PAR */ + par64 =3D (1 << 11); /* LPAE bit always set */ + if (!ret) { + par64 |=3D res.f.phys_addr & ~0xfffULL; + if (!res.f.attrs.secure) { + par64 |=3D (1 << 9); /* NS */ + } + par64 |=3D (uint64_t)res.cacheattrs.attrs << 56; /* ATTR */ + par64 |=3D res.cacheattrs.shareability << 7; /* SH */ + } else { + uint32_t fsr =3D arm_fi_to_lfsc(&fi); + + par64 |=3D 1; /* F */ + par64 |=3D (fsr & 0x3f) << 1; /* FS */ + if (fi.stage2) { + par64 |=3D (1 << 9); /* S */ + } + if (fi.s1ptw) { + par64 |=3D (1 << 8); /* PTW */ + } + } + } else { + /* + * fsr is a DFSR/IFSR value for the short descriptor + * translation table format (with WnR always clear). + * Convert it to a 32-bit PAR. + */ + if (!ret) { + /* We do not set any attribute bits in the PAR */ + if (res.f.lg_page_size =3D=3D 24 + && arm_feature(env, ARM_FEATURE_V7)) { + par64 =3D (res.f.phys_addr & 0xff000000) | (1 << 1); + } else { + par64 =3D res.f.phys_addr & 0xfffff000; + } + if (!res.f.attrs.secure) { + par64 |=3D (1 << 9); /* NS */ + } + } else { + uint32_t fsr =3D arm_fi_to_sfsc(&fi); + + par64 =3D ((fsr & (1 << 10)) >> 5) | ((fsr & (1 << 12)) >> 6) | + ((fsr & 0xf) << 1) | 1; + } + } + return par64; +} +#endif /* CONFIG_TCG */ + +static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t v= alue) +{ +#ifdef CONFIG_TCG + MMUAccessType access_type =3D ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA= _LOAD; + uint64_t par64; + ARMMMUIdx mmu_idx; + int el =3D arm_current_el(env); + bool secure =3D arm_is_secure_below_el3(env); + + switch (ri->opc2 & 6) { + case 0: + /* stage 1 current state PL1: ATS1CPR, ATS1CPW, ATS1CPRP, ATS1CPWP= */ + switch (el) { + case 3: + mmu_idx =3D ARMMMUIdx_E3; + secure =3D true; + break; + case 2: + g_assert(!secure); /* ARMv8.4-SecEL2 is 64-bit only */ + /* fall through */ + case 1: + if (ri->crm =3D=3D 9 && (env->uncached_cpsr & CPSR_PAN)) { + mmu_idx =3D ARMMMUIdx_Stage1_E1_PAN; + } else { + mmu_idx =3D ARMMMUIdx_Stage1_E1; + } + break; + default: + g_assert_not_reached(); + } + break; + case 2: + /* stage 1 current state PL0: ATS1CUR, ATS1CUW */ + switch (el) { + case 3: + mmu_idx =3D ARMMMUIdx_E10_0; + secure =3D true; + break; + case 2: + g_assert(!secure); /* ARMv8.4-SecEL2 is 64-bit only */ + mmu_idx =3D ARMMMUIdx_Stage1_E0; + break; + case 1: + mmu_idx =3D ARMMMUIdx_Stage1_E0; + break; + default: + g_assert_not_reached(); + } + break; + case 4: + /* stage 1+2 NonSecure PL1: ATS12NSOPR, ATS12NSOPW */ + mmu_idx =3D ARMMMUIdx_E10_1; + secure =3D false; + break; + case 6: + /* stage 1+2 NonSecure PL0: ATS12NSOUR, ATS12NSOUW */ + mmu_idx =3D ARMMMUIdx_E10_0; + secure =3D false; + break; + default: + g_assert_not_reached(); + } + + par64 =3D do_ats_write(env, value, access_type, mmu_idx, secure); + + A32_BANKED_CURRENT_REG_SET(env, par, par64); +#else + /* Handled by hardware accelerator. */ + g_assert_not_reached(); +#endif /* CONFIG_TCG */ +} + +static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ +#ifdef CONFIG_TCG + MMUAccessType access_type =3D ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA= _LOAD; + uint64_t par64; + + /* There is no SecureEL2 for AArch32. */ + par64 =3D do_ats_write(env, value, access_type, ARMMMUIdx_E2, false); + + A32_BANKED_CURRENT_REG_SET(env, par, par64); +#else + /* Handled by hardware accelerator. */ + g_assert_not_reached(); +#endif /* CONFIG_TCG */ +} + +static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo = *ri, + bool isread) +{ + if (arm_current_el(env) =3D=3D 3 && + !(env->cp15.scr_el3 & (SCR_NS | SCR_EEL2))) { + return CP_ACCESS_TRAP; + } + return CP_ACCESS_OK; +} + +static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ +#ifdef CONFIG_TCG + MMUAccessType access_type =3D ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA= _LOAD; + ARMMMUIdx mmu_idx; + int secure =3D arm_is_secure_below_el3(env); + uint64_t hcr_el2 =3D arm_hcr_el2_eff(env); + bool regime_e20 =3D (hcr_el2 & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | = HCR_TGE); + + switch (ri->opc2 & 6) { + case 0: + switch (ri->opc1) { + case 0: /* AT S1E1R, AT S1E1W, AT S1E1RP, AT S1E1WP */ + if (ri->crm =3D=3D 9 && (env->pstate & PSTATE_PAN)) { + mmu_idx =3D regime_e20 ? + ARMMMUIdx_E20_2_PAN : ARMMMUIdx_Stage1_E1_PAN; + } else { + mmu_idx =3D regime_e20 ? ARMMMUIdx_E20_2 : ARMMMUIdx_Stage= 1_E1; + } + break; + case 4: /* AT S1E2R, AT S1E2W */ + mmu_idx =3D hcr_el2 & HCR_E2H ? ARMMMUIdx_E20_2 : ARMMMUIdx_E2; + break; + case 6: /* AT S1E3R, AT S1E3W */ + mmu_idx =3D ARMMMUIdx_E3; + secure =3D true; + break; + default: + g_assert_not_reached(); + } + break; + case 2: /* AT S1E0R, AT S1E0W */ + mmu_idx =3D regime_e20 ? ARMMMUIdx_E20_0 : ARMMMUIdx_Stage1_E0; + break; + case 4: /* AT S12E1R, AT S12E1W */ + mmu_idx =3D regime_e20 ? ARMMMUIdx_E20_2 : ARMMMUIdx_E10_1; + break; + case 6: /* AT S12E0R, AT S12E0W */ + mmu_idx =3D regime_e20 ? ARMMMUIdx_E20_0 : ARMMMUIdx_E10_0; + break; + default: + g_assert_not_reached(); + } + + env->cp15.par_el[1] =3D do_ats_write(env, value, access_type, + mmu_idx, secure); +#else + /* Handled by hardware accelerator. */ + g_assert_not_reached(); +#endif /* CONFIG_TCG */ +} +#endif + +static const ARMCPRegInfo vapa_cp_reginfo[] =3D { + { .name =3D "PAR", .cp =3D 15, .crn =3D 7, .crm =3D 4, .opc1 =3D 0, .o= pc2 =3D 0, + .access =3D PL1_RW, .resetvalue =3D 0, + .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.par_s), + offsetoflow32(CPUARMState, cp15.par_ns) }, + .writefn =3D par_write }, +#ifndef CONFIG_USER_ONLY + /* This underdecoding is safe because the reginfo is NO_RAW. */ + { .name =3D "ATS", .cp =3D 15, .crn =3D 7, .crm =3D 8, .opc1 =3D 0, .o= pc2 =3D CP_ANY, + .access =3D PL1_W, .accessfn =3D ats_access, + .writefn =3D ats_write, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC = }, +#endif +}; + +/* Return basic MPU access permission bits. */ +static uint32_t simple_mpu_ap_bits(uint32_t val) +{ + uint32_t ret; + uint32_t mask; + int i; + ret =3D 0; + mask =3D 3; + for (i =3D 0; i < 16; i +=3D 2) { + ret |=3D (val >> i) & mask; + mask <<=3D 2; + } + return ret; +} + +/* Pad basic MPU access permission bits to extended format. */ +static uint32_t extended_mpu_ap_bits(uint32_t val) +{ + uint32_t ret; + uint32_t mask; + int i; + ret =3D 0; + mask =3D 3; + for (i =3D 0; i < 16; i +=3D 2) { + ret |=3D (val & mask) << i; + mask <<=3D 2; + } + return ret; +} + +static void pmsav5_data_ap_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + env->cp15.pmsav5_data_ap =3D extended_mpu_ap_bits(value); +} + +static uint64_t pmsav5_data_ap_read(CPUARMState *env, const ARMCPRegInfo *= ri) +{ + return simple_mpu_ap_bits(env->cp15.pmsav5_data_ap); +} + +static void pmsav5_insn_ap_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + env->cp15.pmsav5_insn_ap =3D extended_mpu_ap_bits(value); +} + +static uint64_t pmsav5_insn_ap_read(CPUARMState *env, const ARMCPRegInfo *= ri) +{ + return simple_mpu_ap_bits(env->cp15.pmsav5_insn_ap); +} + +static uint64_t pmsav7_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + uint32_t *u32p =3D *(uint32_t **)raw_ptr(env, ri); + + if (!u32p) { + return 0; + } + + u32p +=3D env->pmsav7.rnr[M_REG_NS]; + return *u32p; +} + +static void pmsav7_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + uint32_t *u32p =3D *(uint32_t **)raw_ptr(env, ri); + + if (!u32p) { + return; + } + + u32p +=3D env->pmsav7.rnr[M_REG_NS]; + tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */ + *u32p =3D value; +} + +static void pmsav7_rgnr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + uint32_t nrgs =3D cpu->pmsav7_dregion; + + if (value >=3D nrgs) { + qemu_log_mask(LOG_GUEST_ERROR, + "PMSAv7 RGNR write >=3D # supported regions, %" PRIu= 32 + " > %" PRIu32 "\n", (uint32_t)value, nrgs); + return; + } + + raw_write(env, ri, value); +} + +static void prbar_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + + tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */ + env->pmsav8.rbar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]] =3D value; +} + +static uint64_t prbar_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return env->pmsav8.rbar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]]; +} + +static void prlar_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + + tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */ + env->pmsav8.rlar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]] =3D value; +} + +static uint64_t prlar_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return env->pmsav8.rlar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]]; +} + +static void prselr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + + /* + * Ignore writes that would select not implemented region. + * This is architecturally UNPREDICTABLE. + */ + if (value >=3D cpu->pmsav7_dregion) { + return; + } + + env->pmsav7.rnr[M_REG_NS] =3D value; +} + +static void hprbar_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + + tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */ + env->pmsav8.hprbar[env->pmsav8.hprselr] =3D value; +} + +static uint64_t hprbar_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return env->pmsav8.hprbar[env->pmsav8.hprselr]; +} + +static void hprlar_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + + tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */ + env->pmsav8.hprlar[env->pmsav8.hprselr] =3D value; +} + +static uint64_t hprlar_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return env->pmsav8.hprlar[env->pmsav8.hprselr]; +} + +static void hprenr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + uint32_t n; + uint32_t bit; + ARMCPU *cpu =3D env_archcpu(env); + + /* Ignore writes to unimplemented regions */ + int rmax =3D MIN(cpu->pmsav8r_hdregion, 32); + value &=3D MAKE_64BIT_MASK(0, rmax); + + tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */ + + /* Register alias is only valid for first 32 indexes */ + for (n =3D 0; n < rmax; ++n) { + bit =3D extract32(value, n, 1); + env->pmsav8.hprlar[n] =3D deposit32( + env->pmsav8.hprlar[n], 0, 1, bit); + } +} + +static uint64_t hprenr_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + uint32_t n; + uint32_t result =3D 0x0; + ARMCPU *cpu =3D env_archcpu(env); + + /* Register alias is only valid for first 32 indexes */ + for (n =3D 0; n < MIN(cpu->pmsav8r_hdregion, 32); ++n) { + if (env->pmsav8.hprlar[n] & 0x1) { + result |=3D (0x1 << n); + } + } + return result; +} + +static void hprselr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + + /* + * Ignore writes that would select not implemented region. + * This is architecturally UNPREDICTABLE. + */ + if (value >=3D cpu->pmsav8r_hdregion) { + return; + } + + env->pmsav8.hprselr =3D value; +} + +static void pmsav8r_regn_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + uint8_t index =3D (extract32(ri->opc0, 0, 1) << 4) | + (extract32(ri->crm, 0, 3) << 1) | extract32(ri->opc2, = 2, 1); + + tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */ + + if (ri->opc1 & 4) { + if (index >=3D cpu->pmsav8r_hdregion) { + return; + } + if (ri->opc2 & 0x1) { + env->pmsav8.hprlar[index] =3D value; + } else { + env->pmsav8.hprbar[index] =3D value; + } + } else { + if (index >=3D cpu->pmsav7_dregion) { + return; + } + if (ri->opc2 & 0x1) { + env->pmsav8.rlar[M_REG_NS][index] =3D value; + } else { + env->pmsav8.rbar[M_REG_NS][index] =3D value; + } + } +} + +static uint64_t pmsav8r_regn_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + ARMCPU *cpu =3D env_archcpu(env); + uint8_t index =3D (extract32(ri->opc0, 0, 1) << 4) | + (extract32(ri->crm, 0, 3) << 1) | extract32(ri->opc2, = 2, 1); + + if (ri->opc1 & 4) { + if (index >=3D cpu->pmsav8r_hdregion) { + return 0x0; + } + if (ri->opc2 & 0x1) { + return env->pmsav8.hprlar[index]; + } else { + return env->pmsav8.hprbar[index]; + } + } else { + if (index >=3D cpu->pmsav7_dregion) { + return 0x0; + } + if (ri->opc2 & 0x1) { + return env->pmsav8.rlar[M_REG_NS][index]; + } else { + return env->pmsav8.rbar[M_REG_NS][index]; + } + } +} + +static const ARMCPRegInfo pmsav8r_cp_reginfo[] =3D { + { .name =3D "PRBAR", + .cp =3D 15, .opc1 =3D 0, .crn =3D 6, .crm =3D 3, .opc2 =3D 0, + .access =3D PL1_RW, .type =3D ARM_CP_NO_RAW, + .accessfn =3D access_tvm_trvm, + .readfn =3D prbar_read, .writefn =3D prbar_write }, + { .name =3D "PRLAR", + .cp =3D 15, .opc1 =3D 0, .crn =3D 6, .crm =3D 3, .opc2 =3D 1, + .access =3D PL1_RW, .type =3D ARM_CP_NO_RAW, + .accessfn =3D access_tvm_trvm, + .readfn =3D prlar_read, .writefn =3D prlar_write }, + { .name =3D "PRSELR", .resetvalue =3D 0, + .cp =3D 15, .opc1 =3D 0, .crn =3D 6, .crm =3D 2, .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .writefn =3D prselr_write, + .fieldoffset =3D offsetof(CPUARMState, pmsav7.rnr[M_REG_NS]) }, + { .name =3D "HPRBAR", .resetvalue =3D 0, + .cp =3D 15, .opc1 =3D 4, .crn =3D 6, .crm =3D 3, .opc2 =3D 0, + .access =3D PL2_RW, .type =3D ARM_CP_NO_RAW, + .readfn =3D hprbar_read, .writefn =3D hprbar_write }, + { .name =3D "HPRLAR", + .cp =3D 15, .opc1 =3D 4, .crn =3D 6, .crm =3D 3, .opc2 =3D 1, + .access =3D PL2_RW, .type =3D ARM_CP_NO_RAW, + .readfn =3D hprlar_read, .writefn =3D hprlar_write }, + { .name =3D "HPRSELR", .resetvalue =3D 0, + .cp =3D 15, .opc1 =3D 4, .crn =3D 6, .crm =3D 2, .opc2 =3D 1, + .access =3D PL2_RW, + .writefn =3D hprselr_write, + .fieldoffset =3D offsetof(CPUARMState, pmsav8.hprselr) }, + { .name =3D "HPRENR", + .cp =3D 15, .opc1 =3D 4, .crn =3D 6, .crm =3D 1, .opc2 =3D 1, + .access =3D PL2_RW, .type =3D ARM_CP_NO_RAW, + .readfn =3D hprenr_read, .writefn =3D hprenr_write }, +}; + +static const ARMCPRegInfo pmsav7_cp_reginfo[] =3D { + /* + * Reset for all these registers is handled in arm_cpu_reset(), + * because the PMSAv7 is also used by M-profile CPUs, which do + * not register cpregs but still need the state to be reset. + */ + { .name =3D "DRBAR", .cp =3D 15, .crn =3D 6, .opc1 =3D 0, .crm =3D 1, = .opc2 =3D 0, + .access =3D PL1_RW, .type =3D ARM_CP_NO_RAW, + .fieldoffset =3D offsetof(CPUARMState, pmsav7.drbar), + .readfn =3D pmsav7_read, .writefn =3D pmsav7_write, + .resetfn =3D arm_cp_reset_ignore }, + { .name =3D "DRSR", .cp =3D 15, .crn =3D 6, .opc1 =3D 0, .crm =3D 1, .= opc2 =3D 2, + .access =3D PL1_RW, .type =3D ARM_CP_NO_RAW, + .fieldoffset =3D offsetof(CPUARMState, pmsav7.drsr), + .readfn =3D pmsav7_read, .writefn =3D pmsav7_write, + .resetfn =3D arm_cp_reset_ignore }, + { .name =3D "DRACR", .cp =3D 15, .crn =3D 6, .opc1 =3D 0, .crm =3D 1, = .opc2 =3D 4, + .access =3D PL1_RW, .type =3D ARM_CP_NO_RAW, + .fieldoffset =3D offsetof(CPUARMState, pmsav7.dracr), + .readfn =3D pmsav7_read, .writefn =3D pmsav7_write, + .resetfn =3D arm_cp_reset_ignore }, + { .name =3D "RGNR", .cp =3D 15, .crn =3D 6, .opc1 =3D 0, .crm =3D 2, .= opc2 =3D 0, + .access =3D PL1_RW, + .fieldoffset =3D offsetof(CPUARMState, pmsav7.rnr[M_REG_NS]), + .writefn =3D pmsav7_rgnr_write, + .resetfn =3D arm_cp_reset_ignore }, +}; + +static const ARMCPRegInfo pmsav5_cp_reginfo[] =3D { + { .name =3D "DATA_AP", .cp =3D 15, .crn =3D 5, .crm =3D 0, .opc1 =3D 0= , .opc2 =3D 0, + .access =3D PL1_RW, .type =3D ARM_CP_ALIAS, + .fieldoffset =3D offsetof(CPUARMState, cp15.pmsav5_data_ap), + .readfn =3D pmsav5_data_ap_read, .writefn =3D pmsav5_data_ap_write, = }, + { .name =3D "INSN_AP", .cp =3D 15, .crn =3D 5, .crm =3D 0, .opc1 =3D 0= , .opc2 =3D 1, + .access =3D PL1_RW, .type =3D ARM_CP_ALIAS, + .fieldoffset =3D offsetof(CPUARMState, cp15.pmsav5_insn_ap), + .readfn =3D pmsav5_insn_ap_read, .writefn =3D pmsav5_insn_ap_write, = }, + { .name =3D "DATA_EXT_AP", .cp =3D 15, .crn =3D 5, .crm =3D 0, .opc1 = =3D 0, .opc2 =3D 2, + .access =3D PL1_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.pmsav5_data_ap), + .resetvalue =3D 0, }, + { .name =3D "INSN_EXT_AP", .cp =3D 15, .crn =3D 5, .crm =3D 0, .opc1 = =3D 0, .opc2 =3D 3, + .access =3D PL1_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.pmsav5_insn_ap), + .resetvalue =3D 0, }, + { .name =3D "DCACHE_CFG", .cp =3D 15, .crn =3D 2, .crm =3D 0, .opc1 = =3D 0, .opc2 =3D 0, + .access =3D PL1_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.c2_data), .resetvalue = =3D 0, }, + { .name =3D "ICACHE_CFG", .cp =3D 15, .crn =3D 2, .crm =3D 0, .opc1 = =3D 0, .opc2 =3D 1, + .access =3D PL1_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.c2_insn), .resetvalue = =3D 0, }, + /* Protection region base and size registers */ + { .name =3D "946_PRBS0", .cp =3D 15, .crn =3D 6, .crm =3D 0, .opc1 =3D= 0, + .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[0]) }, + { .name =3D "946_PRBS1", .cp =3D 15, .crn =3D 6, .crm =3D 1, .opc1 =3D= 0, + .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[1]) }, + { .name =3D "946_PRBS2", .cp =3D 15, .crn =3D 6, .crm =3D 2, .opc1 =3D= 0, + .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[2]) }, + { .name =3D "946_PRBS3", .cp =3D 15, .crn =3D 6, .crm =3D 3, .opc1 =3D= 0, + .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[3]) }, + { .name =3D "946_PRBS4", .cp =3D 15, .crn =3D 6, .crm =3D 4, .opc1 =3D= 0, + .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[4]) }, + { .name =3D "946_PRBS5", .cp =3D 15, .crn =3D 6, .crm =3D 5, .opc1 =3D= 0, + .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[5]) }, + { .name =3D "946_PRBS6", .cp =3D 15, .crn =3D 6, .crm =3D 6, .opc1 =3D= 0, + .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[6]) }, + { .name =3D "946_PRBS7", .cp =3D 15, .crn =3D 6, .crm =3D 7, .opc1 =3D= 0, + .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[7]) }, +}; + +static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + + if (!arm_feature(env, ARM_FEATURE_V8)) { + if (arm_feature(env, ARM_FEATURE_LPAE) && (value & TTBCR_EAE)) { + /* + * Pre ARMv8 bits [21:19], [15:14] and [6:3] are UNK/SBZP when + * using Long-descriptor translation table format + */ + value &=3D ~((7 << 19) | (3 << 14) | (0xf << 3)); + } else if (arm_feature(env, ARM_FEATURE_EL3)) { + /* + * In an implementation that includes the Security Extensions + * TTBCR has additional fields PD0 [4] and PD1 [5] for + * Short-descriptor translation table format. + */ + value &=3D TTBCR_PD1 | TTBCR_PD0 | TTBCR_N; + } else { + value &=3D TTBCR_N; + } + } + + if (arm_feature(env, ARM_FEATURE_LPAE)) { + /* + * With LPAE the TTBCR could result in a change of ASID + * via the TTBCR.A1 bit, so do a TLB flush. + */ + tlb_flush(CPU(cpu)); + } + raw_write(env, ri, value); +} + +static void vmsa_tcr_el12_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + + /* For AArch64 the A1 bit could result in a change of ASID, so TLB flu= sh. */ + tlb_flush(CPU(cpu)); + raw_write(env, ri, value); +} + +static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* If the ASID changes (with a 64-bit write), we must flush the TLB. = */ + if (cpreg_field_is_64bit(ri) && + extract64(raw_read(env, ri) ^ value, 48, 16) !=3D 0) { + ARMCPU *cpu =3D env_archcpu(env); + tlb_flush(CPU(cpu)); + } + raw_write(env, ri, value); +} + +static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *= ri, + uint64_t value) +{ + /* + * If we are running with E2&0 regime, then an ASID is active. + * Flush if that might be changing. Note we're not checking + * TCR_EL2.A1 to know if this is really the TTBRx_EL2 that + * holds the active ASID, only checking the field that might. + */ + if (extract64(raw_read(env, ri) ^ value, 48, 16) && + (arm_hcr_el2_eff(env) & HCR_E2H)) { + uint16_t mask =3D ARMMMUIdxBit_E20_2 | + ARMMMUIdxBit_E20_2_PAN | + ARMMMUIdxBit_E20_0; + tlb_flush_by_mmuidx(env_cpu(env), mask); + } + raw_write(env, ri, value); +} + +static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + CPUState *cs =3D CPU(cpu); + + /* + * A change in VMID to the stage2 page table (Stage2) invalidates + * the stage2 and combined stage 1&2 tlbs (EL10_1 and EL10_0). + */ + if (extract64(raw_read(env, ri) ^ value, 48, 16) !=3D 0) { + tlb_flush_by_mmuidx(cs, alle1_tlbmask(env)); + } + raw_write(env, ri, value); +} + +static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] =3D { + { .name =3D "DFSR", .cp =3D 15, .crn =3D 5, .crm =3D 0, .opc1 =3D 0, .= opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, .type =3D ARM_CP_= ALIAS, + .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.dfsr_s), + offsetoflow32(CPUARMState, cp15.dfsr_ns) }, }, + { .name =3D "IFSR", .cp =3D 15, .crn =3D 5, .crm =3D 0, .opc1 =3D 0, .= opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, .resetvalue =3D 0, + .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.ifsr_s), + offsetoflow32(CPUARMState, cp15.ifsr_ns) } }, + { .name =3D "DFAR", .cp =3D 15, .opc1 =3D 0, .crn =3D 6, .crm =3D 0, .= opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, .resetvalue =3D 0, + .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.dfar_s), + offsetof(CPUARMState, cp15.dfar_ns) } }, + { .name =3D "FAR_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .crn =3D 6, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .fieldoffset =3D offsetof(CPUARMState, cp15.far_el[1]), + .resetvalue =3D 0, }, +}; + +static const ARMCPRegInfo vmsa_cp_reginfo[] =3D { + { .name =3D "ESR_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .crn =3D 5, .crm =3D 2, .opc1 =3D 0, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .fieldoffset =3D offsetof(CPUARMState, cp15.esr_el[1]), .resetvalue = =3D 0, }, + { .name =3D "TTBR0_EL1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 0, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .writefn =3D vmsa_ttbr_write, .resetvalue =3D 0, + .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.ttbr0_s), + offsetof(CPUARMState, cp15.ttbr0_ns) } }, + { .name =3D "TTBR1_EL1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 0, .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .writefn =3D vmsa_ttbr_write, .resetvalue =3D 0, + .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.ttbr1_s), + offsetof(CPUARMState, cp15.ttbr1_ns) } }, + { .name =3D "TCR_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .crn =3D 2, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 2, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .writefn =3D vmsa_tcr_el12_write, + .raw_writefn =3D raw_write, + .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.tcr_el[1]) }, + { .name =3D "TTBCR", .cp =3D 15, .crn =3D 2, .crm =3D 0, .opc1 =3D 0, = .opc2 =3D 2, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .type =3D ARM_CP_ALIAS, .writefn =3D vmsa_ttbcr_write, + .raw_writefn =3D raw_write, + .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.tcr_el[3]), + offsetoflow32(CPUARMState, cp15.tcr_el[1])} }, +}; + +/* + * Note that unlike TTBCR, writing to TTBCR2 does not require flushing + * qemu tlbs nor adjusting cached masks. + */ +static const ARMCPRegInfo ttbcr2_reginfo =3D { + .name =3D "TTBCR2", .cp =3D 15, .opc1 =3D 0, .crn =3D 2, .crm =3D 0, .= opc2 =3D 3, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .type =3D ARM_CP_ALIAS, + .bank_fieldoffsets =3D { + offsetofhigh32(CPUARMState, cp15.tcr_el[3]), + offsetofhigh32(CPUARMState, cp15.tcr_el[1]), + }, +}; + +static void omap_ticonfig_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + env->cp15.c15_ticonfig =3D value & 0xe7; + /* The OS_TYPE bit in this register changes the reported CPUID! */ + env->cp15.c0_cpuid =3D (value & (1 << 5)) ? + ARM_CPUID_TI915T : ARM_CPUID_TI925T; +} + +static void omap_threadid_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + env->cp15.c15_threadid =3D value & 0xffff; +} + +static void omap_wfi_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Wait-for-interrupt (deprecated) */ + cpu_interrupt(env_cpu(env), CPU_INTERRUPT_HALT); +} + +static void omap_cachemaint_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * On OMAP there are registers indicating the max/min index of dcache = lines + * containing a dirty line; cache flush operations have to reset these. + */ + env->cp15.c15_i_max =3D 0x000; + env->cp15.c15_i_min =3D 0xff0; +} + +static const ARMCPRegInfo omap_cp_reginfo[] =3D { + { .name =3D "DFSR", .cp =3D 15, .crn =3D 5, .crm =3D CP_ANY, + .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, .access =3D PL1_RW, .type =3D AR= M_CP_OVERRIDE, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.esr_el[1]), + .resetvalue =3D 0, }, + { .name =3D "", .cp =3D 15, .crn =3D 15, .crm =3D 0, .opc1 =3D 0, .opc= 2 =3D 0, + .access =3D PL1_RW, .type =3D ARM_CP_NOP }, + { .name =3D "TICONFIG", .cp =3D 15, .crn =3D 15, .crm =3D 1, .opc1 =3D= 0, .opc2 =3D 0, + .access =3D PL1_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.c15_ticonfig), .resetval= ue =3D 0, + .writefn =3D omap_ticonfig_write }, + { .name =3D "IMAX", .cp =3D 15, .crn =3D 15, .crm =3D 2, .opc1 =3D 0, = .opc2 =3D 0, + .access =3D PL1_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.c15_i_max), .resetvalue = =3D 0, }, + { .name =3D "IMIN", .cp =3D 15, .crn =3D 15, .crm =3D 3, .opc1 =3D 0, = .opc2 =3D 0, + .access =3D PL1_RW, .resetvalue =3D 0xff0, + .fieldoffset =3D offsetof(CPUARMState, cp15.c15_i_min) }, + { .name =3D "THREADID", .cp =3D 15, .crn =3D 15, .crm =3D 4, .opc1 =3D= 0, .opc2 =3D 0, + .access =3D PL1_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.c15_threadid), .resetval= ue =3D 0, + .writefn =3D omap_threadid_write }, + { .name =3D "TI925T_STATUS", .cp =3D 15, .crn =3D 15, + .crm =3D 8, .opc1 =3D 0, .opc2 =3D 0, .access =3D PL1_RW, + .type =3D ARM_CP_NO_RAW, + .readfn =3D arm_cp_read_zero, .writefn =3D omap_wfi_write, }, + /* + * TODO: Peripheral port remap register: + * On OMAP2 mcr p15, 0, rn, c15, c2, 4 sets up the interrupt controller + * base address at $rn & ~0xfff and map size of 0x200 << ($rn & 0xfff), + * when MMU is off. + */ + { .name =3D "OMAP_CACHEMAINT", .cp =3D 15, .crn =3D 7, .crm =3D CP_ANY, + .opc1 =3D 0, .opc2 =3D CP_ANY, .access =3D PL1_W, + .type =3D ARM_CP_OVERRIDE | ARM_CP_NO_RAW, + .writefn =3D omap_cachemaint_write }, + { .name =3D "C9", .cp =3D 15, .crn =3D 9, + .crm =3D CP_ANY, .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, .access =3D PL1= _RW, + .type =3D ARM_CP_CONST | ARM_CP_OVERRIDE, .resetvalue =3D 0 }, +}; + +static void xscale_cpar_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + env->cp15.c15_cpar =3D value & 0x3fff; +} + +static const ARMCPRegInfo xscale_cp_reginfo[] =3D { + { .name =3D "XSCALE_CPAR", + .cp =3D 15, .crn =3D 15, .crm =3D 1, .opc1 =3D 0, .opc2 =3D 0, .acce= ss =3D PL1_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.c15_cpar), .resetvalue = =3D 0, + .writefn =3D xscale_cpar_write, }, + { .name =3D "XSCALE_AUXCR", + .cp =3D 15, .crn =3D 1, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 1, .acces= s =3D PL1_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.c1_xscaleauxcr), + .resetvalue =3D 0, }, + /* + * XScale specific cache-lockdown: since we have no cache we NOP these + * and hope the guest does not really rely on cache behaviour. + */ + { .name =3D "XSCALE_LOCK_ICACHE_LINE", + .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 1, .opc2 =3D 0, + .access =3D PL1_W, .type =3D ARM_CP_NOP }, + { .name =3D "XSCALE_UNLOCK_ICACHE", + .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 1, .opc2 =3D 1, + .access =3D PL1_W, .type =3D ARM_CP_NOP }, + { .name =3D "XSCALE_DCACHE_LOCK", + .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 2, .opc2 =3D 0, + .access =3D PL1_RW, .type =3D ARM_CP_NOP }, + { .name =3D "XSCALE_UNLOCK_DCACHE", + .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 2, .opc2 =3D 1, + .access =3D PL1_W, .type =3D ARM_CP_NOP }, +}; + +static const ARMCPRegInfo dummy_c15_cp_reginfo[] =3D { + /* + * RAZ/WI the whole crn=3D15 space, when we don't have a more specific + * implementation of this implementation-defined space. + * Ideally this should eventually disappear in favour of actually + * implementing the correct behaviour for all cores. + */ + { .name =3D "C15_IMPDEF", .cp =3D 15, .crn =3D 15, + .crm =3D CP_ANY, .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, + .access =3D PL1_RW, + .type =3D ARM_CP_CONST | ARM_CP_NO_RAW | ARM_CP_OVERRIDE, + .resetvalue =3D 0 }, +}; + +static const ARMCPRegInfo cache_dirty_status_cp_reginfo[] =3D { + /* Cache status: RAZ because we have no cache so it's always clean */ + { .name =3D "CDSR", .cp =3D 15, .crn =3D 7, .crm =3D 10, .opc1 =3D 0, = .opc2 =3D 6, + .access =3D PL1_R, .type =3D ARM_CP_CONST | ARM_CP_NO_RAW, + .resetvalue =3D 0 }, +}; + +static const ARMCPRegInfo cache_block_ops_cp_reginfo[] =3D { + /* We never have a block transfer operation in progress */ + { .name =3D "BXSR", .cp =3D 15, .crn =3D 7, .crm =3D 12, .opc1 =3D 0, = .opc2 =3D 4, + .access =3D PL0_R, .type =3D ARM_CP_CONST | ARM_CP_NO_RAW, + .resetvalue =3D 0 }, + /* The cache ops themselves: these all NOP for QEMU */ + { .name =3D "IICR", .cp =3D 15, .crm =3D 5, .opc1 =3D 0, + .access =3D PL1_W, .type =3D ARM_CP_NOP | ARM_CP_64BIT }, + { .name =3D "IDCR", .cp =3D 15, .crm =3D 6, .opc1 =3D 0, + .access =3D PL1_W, .type =3D ARM_CP_NOP | ARM_CP_64BIT }, + { .name =3D "CDCR", .cp =3D 15, .crm =3D 12, .opc1 =3D 0, + .access =3D PL0_W, .type =3D ARM_CP_NOP | ARM_CP_64BIT }, + { .name =3D "PIR", .cp =3D 15, .crm =3D 12, .opc1 =3D 1, + .access =3D PL0_W, .type =3D ARM_CP_NOP | ARM_CP_64BIT }, + { .name =3D "PDR", .cp =3D 15, .crm =3D 12, .opc1 =3D 2, + .access =3D PL0_W, .type =3D ARM_CP_NOP | ARM_CP_64BIT }, + { .name =3D "CIDCR", .cp =3D 15, .crm =3D 14, .opc1 =3D 0, + .access =3D PL1_W, .type =3D ARM_CP_NOP | ARM_CP_64BIT }, +}; + +static const ARMCPRegInfo cache_test_clean_cp_reginfo[] =3D { + /* + * The cache test-and-clean instructions always return (1 << 30) + * to indicate that there are no dirty cache lines. + */ + { .name =3D "TC_DCACHE", .cp =3D 15, .crn =3D 7, .crm =3D 10, .opc1 = =3D 0, .opc2 =3D 3, + .access =3D PL0_R, .type =3D ARM_CP_CONST | ARM_CP_NO_RAW, + .resetvalue =3D (1 << 30) }, + { .name =3D "TCI_DCACHE", .cp =3D 15, .crn =3D 7, .crm =3D 14, .opc1 = =3D 0, .opc2 =3D 3, + .access =3D PL0_R, .type =3D ARM_CP_CONST | ARM_CP_NO_RAW, + .resetvalue =3D (1 << 30) }, +}; + +static const ARMCPRegInfo strongarm_cp_reginfo[] =3D { + /* Ignore ReadBuffer accesses */ + { .name =3D "C9_READBUFFER", .cp =3D 15, .crn =3D 9, + .crm =3D CP_ANY, .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, + .access =3D PL1_RW, .resetvalue =3D 0, + .type =3D ARM_CP_CONST | ARM_CP_OVERRIDE | ARM_CP_NO_RAW }, +}; + +static uint64_t midr_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + unsigned int cur_el =3D arm_current_el(env); + + if (arm_is_el2_enabled(env) && cur_el =3D=3D 1) { + return env->cp15.vpidr_el2; + } + return raw_read(env, ri); +} + +static uint64_t mpidr_read_val(CPUARMState *env) +{ + ARMCPU *cpu =3D env_archcpu(env); + uint64_t mpidr =3D cpu->mp_affinity; + + if (arm_feature(env, ARM_FEATURE_V7MP)) { + mpidr |=3D (1U << 31); + /* + * Cores which are uniprocessor (non-coherent) + * but still implement the MP extensions set + * bit 30. (For instance, Cortex-R5). + */ + if (cpu->mp_is_up) { + mpidr |=3D (1u << 30); + } + } + return mpidr; +} + +static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + unsigned int cur_el =3D arm_current_el(env); + + if (arm_is_el2_enabled(env) && cur_el =3D=3D 1) { + return env->cp15.vmpidr_el2; + } + return mpidr_read_val(env); +} + +static const ARMCPRegInfo lpae_cp_reginfo[] =3D { + /* NOP AMAIR0/1 */ + { .name =3D "AMAIR0", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .crn =3D 10, .crm =3D 3, .opc1 =3D 0, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + /* AMAIR1 is mapped to AMAIR_EL1[63:32] */ + { .name =3D "AMAIR1", .cp =3D 15, .crn =3D 10, .crm =3D 3, .opc1 =3D 0= , .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + { .name =3D "PAR", .cp =3D 15, .crm =3D 7, .opc1 =3D 0, + .access =3D PL1_RW, .type =3D ARM_CP_64BIT, .resetvalue =3D 0, + .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.par_s), + offsetof(CPUARMState, cp15.par_ns)} }, + { .name =3D "TTBR0", .cp =3D 15, .crm =3D 2, .opc1 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .type =3D ARM_CP_64BIT | ARM_CP_ALIAS, + .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.ttbr0_s), + offsetof(CPUARMState, cp15.ttbr0_ns) }, + .writefn =3D vmsa_ttbr_write, }, + { .name =3D "TTBR1", .cp =3D 15, .crm =3D 2, .opc1 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .type =3D ARM_CP_64BIT | ARM_CP_ALIAS, + .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.ttbr1_s), + offsetof(CPUARMState, cp15.ttbr1_ns) }, + .writefn =3D vmsa_ttbr_write, }, +}; + +static uint64_t aa64_fpcr_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return vfp_get_fpcr(env); +} + +static void aa64_fpcr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + vfp_set_fpcr(env, value); +} + +static uint64_t aa64_fpsr_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return vfp_get_fpsr(env); +} + +static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + vfp_set_fpsr(env, value); +} + +static CPAccessResult aa64_daif_access(CPUARMState *env, const ARMCPRegInf= o *ri, + bool isread) +{ + if (arm_current_el(env) =3D=3D 0 && !(arm_sctlr(env, 0) & SCTLR_UMA)) { + return CP_ACCESS_TRAP; + } + return CP_ACCESS_OK; +} + +static void aa64_daif_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + env->daif =3D value & PSTATE_DAIF; +} + +static uint64_t aa64_pan_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return env->pstate & PSTATE_PAN; +} + +static void aa64_pan_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + env->pstate =3D (env->pstate & ~PSTATE_PAN) | (value & PSTATE_PAN); +} + +static const ARMCPRegInfo pan_reginfo =3D { + .name =3D "PAN", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 4, .crm =3D 2, .opc2 =3D 3, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_RW, + .readfn =3D aa64_pan_read, .writefn =3D aa64_pan_write +}; + +static uint64_t aa64_uao_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return env->pstate & PSTATE_UAO; +} + +static void aa64_uao_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + env->pstate =3D (env->pstate & ~PSTATE_UAO) | (value & PSTATE_UAO); +} + +static const ARMCPRegInfo uao_reginfo =3D { + .name =3D "UAO", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 4, .crm =3D 2, .opc2 =3D 4, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_RW, + .readfn =3D aa64_uao_read, .writefn =3D aa64_uao_write +}; + +static uint64_t aa64_dit_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return env->pstate & PSTATE_DIT; +} + +static void aa64_dit_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + env->pstate =3D (env->pstate & ~PSTATE_DIT) | (value & PSTATE_DIT); +} + +static const ARMCPRegInfo dit_reginfo =3D { + .name =3D "DIT", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 4, .crm =3D 2, .opc2 =3D 5, + .type =3D ARM_CP_NO_RAW, .access =3D PL0_RW, + .readfn =3D aa64_dit_read, .writefn =3D aa64_dit_write +}; + +static uint64_t aa64_ssbs_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return env->pstate & PSTATE_SSBS; +} + +static void aa64_ssbs_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + env->pstate =3D (env->pstate & ~PSTATE_SSBS) | (value & PSTATE_SSBS); +} + +static const ARMCPRegInfo ssbs_reginfo =3D { + .name =3D "SSBS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 4, .crm =3D 2, .opc2 =3D 6, + .type =3D ARM_CP_NO_RAW, .access =3D PL0_RW, + .readfn =3D aa64_ssbs_read, .writefn =3D aa64_ssbs_write +}; + +static CPAccessResult aa64_cacheop_poc_access(CPUARMState *env, + const ARMCPRegInfo *ri, + bool isread) +{ + /* Cache invalidate/clean to Point of Coherency or Persistence... */ + switch (arm_current_el(env)) { + case 0: + /* ... EL0 must UNDEF unless SCTLR_EL1.UCI is set. */ + if (!(arm_sctlr(env, 0) & SCTLR_UCI)) { + return CP_ACCESS_TRAP; + } + /* fall through */ + case 1: + /* ... EL1 must trap to EL2 if HCR_EL2.TPCP is set. */ + if (arm_hcr_el2_eff(env) & HCR_TPCP) { + return CP_ACCESS_TRAP_EL2; + } + break; + } + return CP_ACCESS_OK; +} + +static CPAccessResult do_cacheop_pou_access(CPUARMState *env, uint64_t hcr= flags) +{ + /* Cache invalidate/clean to Point of Unification... */ + switch (arm_current_el(env)) { + case 0: + /* ... EL0 must UNDEF unless SCTLR_EL1.UCI is set. */ + if (!(arm_sctlr(env, 0) & SCTLR_UCI)) { + return CP_ACCESS_TRAP; + } + /* fall through */ + case 1: + /* ... EL1 must trap to EL2 if relevant HCR_EL2 flags are set. */ + if (arm_hcr_el2_eff(env) & hcrflags) { + return CP_ACCESS_TRAP_EL2; + } + break; + } + return CP_ACCESS_OK; +} + +static CPAccessResult access_ticab(CPUARMState *env, const ARMCPRegInfo *r= i, + bool isread) +{ + return do_cacheop_pou_access(env, HCR_TICAB | HCR_TPU); +} + +static CPAccessResult access_tocu(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + return do_cacheop_pou_access(env, HCR_TOCU | HCR_TPU); +} + +/* + * See: D4.7.2 TLB maintenance requirements and the TLB maintenance instru= ctions + * Page D4-1736 (DDI0487A.b) + */ + +static int vae1_tlbmask(CPUARMState *env) +{ + uint64_t hcr =3D arm_hcr_el2_eff(env); + uint16_t mask; + + if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { + mask =3D ARMMMUIdxBit_E20_2 | + ARMMMUIdxBit_E20_2_PAN | + ARMMMUIdxBit_E20_0; + } else { + mask =3D ARMMMUIdxBit_E10_1 | + ARMMMUIdxBit_E10_1_PAN | + ARMMMUIdxBit_E10_0; + } + return mask; +} + +/* Return 56 if TBI is enabled, 64 otherwise. */ +static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx, + uint64_t addr) +{ + uint64_t tcr =3D regime_tcr(env, mmu_idx); + int tbi =3D aa64_va_parameter_tbi(tcr, mmu_idx); + int select =3D extract64(addr, 55, 1); + + return (tbi >> select) & 1 ? 56 : 64; +} + +static int vae1_tlbbits(CPUARMState *env, uint64_t addr) +{ + uint64_t hcr =3D arm_hcr_el2_eff(env); + ARMMMUIdx mmu_idx; + + /* Only the regime of the mmu_idx below is significant. */ + if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { + mmu_idx =3D ARMMMUIdx_E20_0; + } else { + mmu_idx =3D ARMMMUIdx_E10_0; + } + + return tlbbits_for_regime(env, mmu_idx, addr); +} + +static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo= *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + int mask =3D vae1_tlbmask(env); + + tlb_flush_by_mmuidx_all_cpus_synced(cs, mask); +} + +static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *= ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + int mask =3D vae1_tlbmask(env); + + if (tlb_force_broadcast(env)) { + tlb_flush_by_mmuidx_all_cpus_synced(cs, mask); + } else { + tlb_flush_by_mmuidx(cs, mask); + } +} + +static int e2_tlbmask(CPUARMState *env) +{ + return (ARMMMUIdxBit_E20_0 | + ARMMMUIdxBit_E20_2 | + ARMMMUIdxBit_E20_2_PAN | + ARMMMUIdxBit_E2); +} + +static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + int mask =3D alle1_tlbmask(env); + + tlb_flush_by_mmuidx(cs, mask); +} + +static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + int mask =3D e2_tlbmask(env); + + tlb_flush_by_mmuidx(cs, mask); +} + +static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + CPUState *cs =3D CPU(cpu); + + tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E3); +} + +static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *= ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + int mask =3D alle1_tlbmask(env); + + tlb_flush_by_mmuidx_all_cpus_synced(cs, mask); +} + +static void tlbi_aa64_alle2is_write(CPUARMState *env, const ARMCPRegInfo *= ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + int mask =3D e2_tlbmask(env); + + tlb_flush_by_mmuidx_all_cpus_synced(cs, mask); +} + +static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *= ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + + tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E3); +} + +static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * Invalidate by VA, EL2 + * Currently handles both VAE2 and VALE2, since we don't support + * flush-last-level-only. + */ + CPUState *cs =3D env_cpu(env); + int mask =3D e2_tlbmask(env); + uint64_t pageaddr =3D sextract64(value << 12, 0, 56); + + tlb_flush_page_by_mmuidx(cs, pageaddr, mask); +} + +static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * Invalidate by VA, EL3 + * Currently handles both VAE3 and VALE3, since we don't support + * flush-last-level-only. + */ + ARMCPU *cpu =3D env_archcpu(env); + CPUState *cs =3D CPU(cpu); + uint64_t pageaddr =3D sextract64(value << 12, 0, 56); + + tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E3); +} + +static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *r= i, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + int mask =3D vae1_tlbmask(env); + uint64_t pageaddr =3D sextract64(value << 12, 0, 56); + int bits =3D vae1_tlbbits(env, pageaddr); + + tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits= ); +} + +static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * Invalidate by VA, EL1&0 (AArch64 version). + * Currently handles all of VAE1, VAAE1, VAALE1 and VALE1, + * since we don't support flush-for-specific-ASID-only or + * flush-last-level-only. + */ + CPUState *cs =3D env_cpu(env); + int mask =3D vae1_tlbmask(env); + uint64_t pageaddr =3D sextract64(value << 12, 0, 56); + int bits =3D vae1_tlbbits(env, pageaddr); + + if (tlb_force_broadcast(env)) { + tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, = bits); + } else { + tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits); + } +} + +static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *r= i, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + uint64_t pageaddr =3D sextract64(value << 12, 0, 56); + int bits =3D tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr); + + tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, + ARMMMUIdxBit_E2, bits); +} + +static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *r= i, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + uint64_t pageaddr =3D sextract64(value << 12, 0, 56); + int bits =3D tlbbits_for_regime(env, ARMMMUIdx_E3, pageaddr); + + tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, + ARMMMUIdxBit_E3, bits); +} + +static int ipas2e1_tlbmask(CPUARMState *env, int64_t value) +{ + /* + * The MSB of value is the NS field, which only applies if SEL2 + * is implemented and SCR_EL3.NS is not set (i.e. in secure mode). + */ + return (value >=3D 0 + && cpu_isar_feature(aa64_sel2, env_archcpu(env)) + && arm_is_secure_below_el3(env) + ? ARMMMUIdxBit_Stage2_S + : ARMMMUIdxBit_Stage2); +} + +static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *= ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + int mask =3D ipas2e1_tlbmask(env, value); + uint64_t pageaddr =3D sextract64(value << 12, 0, 56); + + if (tlb_force_broadcast(env)) { + tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask); + } else { + tlb_flush_page_by_mmuidx(cs, pageaddr, mask); + } +} + +static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo= *ri, + uint64_t value) +{ + CPUState *cs =3D env_cpu(env); + int mask =3D ipas2e1_tlbmask(env, value); + uint64_t pageaddr =3D sextract64(value << 12, 0, 56); + + tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask); +} + +#ifdef TARGET_AARCH64 +typedef struct { + uint64_t base; + uint64_t length; +} TLBIRange; + +static ARMGranuleSize tlbi_range_tg_to_gran_size(int tg) +{ + /* + * Note that the TLBI range TG field encoding differs from both + * TG0 and TG1 encodings. + */ + switch (tg) { + case 1: + return Gran4K; + case 2: + return Gran16K; + case 3: + return Gran64K; + default: + return GranInvalid; + } +} + +static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx, + uint64_t value) +{ + unsigned int page_size_granule, page_shift, num, scale, exponent; + /* Extract one bit to represent the va selector in use. */ + uint64_t select =3D sextract64(value, 36, 1); + ARMVAParameters param =3D aa64_va_parameters(env, select, mmuidx, true= ); + TLBIRange ret =3D { }; + ARMGranuleSize gran; + + page_size_granule =3D extract64(value, 46, 2); + gran =3D tlbi_range_tg_to_gran_size(page_size_granule); + + /* The granule encoded in value must match the granule in use. */ + if (gran !=3D param.gran) { + qemu_log_mask(LOG_GUEST_ERROR, "Invalid tlbi page size granule %d\= n", + page_size_granule); + return ret; + } + + page_shift =3D arm_granule_bits(gran); + num =3D extract64(value, 39, 5); + scale =3D extract64(value, 44, 2); + exponent =3D (5 * scale) + 1; + + ret.length =3D (num + 1) << (exponent + page_shift); + + if (param.select) { + ret.base =3D sextract64(value, 0, 37); + } else { + ret.base =3D extract64(value, 0, 37); + } + if (param.ds) { + /* + * With DS=3D1, BaseADDR is always shifted 16 so that it is able + * to address all 52 va bits. The input address is perforce + * aligned on a 64k boundary regardless of translation granule. + */ + page_shift =3D 16; + } + ret.base <<=3D page_shift; + + return ret; +} + +static void do_rvae_write(CPUARMState *env, uint64_t value, + int idxmap, bool synced) +{ + ARMMMUIdx one_idx =3D ARM_MMU_IDX_A | ctz32(idxmap); + TLBIRange range; + int bits; + + range =3D tlbi_aa64_get_range(env, one_idx, value); + bits =3D tlbbits_for_regime(env, one_idx, range.base); + + if (synced) { + tlb_flush_range_by_mmuidx_all_cpus_synced(env_cpu(env), + range.base, + range.length, + idxmap, + bits); + } else { + tlb_flush_range_by_mmuidx(env_cpu(env), range.base, + range.length, idxmap, bits); + } +} + +static void tlbi_aa64_rvae1_write(CPUARMState *env, + const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * Invalidate by VA range, EL1&0. + * Currently handles all of RVAE1, RVAAE1, RVAALE1 and RVALE1, + * since we don't support flush-for-specific-ASID-only or + * flush-last-level-only. + */ + + do_rvae_write(env, value, vae1_tlbmask(env), + tlb_force_broadcast(env)); +} + +static void tlbi_aa64_rvae1is_write(CPUARMState *env, + const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * Invalidate by VA range, Inner/Outer Shareable EL1&0. + * Currently handles all of RVAE1IS, RVAE1OS, RVAAE1IS, RVAAE1OS, + * RVAALE1IS, RVAALE1OS, RVALE1IS and RVALE1OS, since we don't support + * flush-for-specific-ASID-only, flush-last-level-only or inner/outer + * shareable specific flushes. + */ + + do_rvae_write(env, value, vae1_tlbmask(env), true); +} + +static int vae2_tlbmask(CPUARMState *env) +{ + return ARMMMUIdxBit_E2; +} + +static void tlbi_aa64_rvae2_write(CPUARMState *env, + const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * Invalidate by VA range, EL2. + * Currently handles all of RVAE2 and RVALE2, + * since we don't support flush-for-specific-ASID-only or + * flush-last-level-only. + */ + + do_rvae_write(env, value, vae2_tlbmask(env), + tlb_force_broadcast(env)); + + +} + +static void tlbi_aa64_rvae2is_write(CPUARMState *env, + const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * Invalidate by VA range, Inner/Outer Shareable, EL2. + * Currently handles all of RVAE2IS, RVAE2OS, RVALE2IS and RVALE2OS, + * since we don't support flush-for-specific-ASID-only, + * flush-last-level-only or inner/outer shareable specific flushes. + */ + + do_rvae_write(env, value, vae2_tlbmask(env), true); + +} + +static void tlbi_aa64_rvae3_write(CPUARMState *env, + const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * Invalidate by VA range, EL3. + * Currently handles all of RVAE3 and RVALE3, + * since we don't support flush-for-specific-ASID-only or + * flush-last-level-only. + */ + + do_rvae_write(env, value, ARMMMUIdxBit_E3, tlb_force_broadcast(env)); +} + +static void tlbi_aa64_rvae3is_write(CPUARMState *env, + const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * Invalidate by VA range, EL3, Inner/Outer Shareable. + * Currently handles all of RVAE3IS, RVAE3OS, RVALE3IS and RVALE3OS, + * since we don't support flush-for-specific-ASID-only, + * flush-last-level-only or inner/outer specific flushes. + */ + + do_rvae_write(env, value, ARMMMUIdxBit_E3, true); +} + +static void tlbi_aa64_ripas2e1_write(CPUARMState *env, const ARMCPRegInfo = *ri, + uint64_t value) +{ + do_rvae_write(env, value, ipas2e1_tlbmask(env, value), + tlb_force_broadcast(env)); +} + +static void tlbi_aa64_ripas2e1is_write(CPUARMState *env, + const ARMCPRegInfo *ri, + uint64_t value) +{ + do_rvae_write(env, value, ipas2e1_tlbmask(env, value), true); +} +#endif + +static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo= *ri, + bool isread) +{ + int cur_el =3D arm_current_el(env); + + if (cur_el < 2) { + uint64_t hcr =3D arm_hcr_el2_eff(env); + + if (cur_el =3D=3D 0) { + if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { + if (!(env->cp15.sctlr_el[2] & SCTLR_DZE)) { + return CP_ACCESS_TRAP_EL2; + } + } else { + if (!(env->cp15.sctlr_el[1] & SCTLR_DZE)) { + return CP_ACCESS_TRAP; + } + if (hcr & HCR_TDZ) { + return CP_ACCESS_TRAP_EL2; + } + } + } else if (hcr & HCR_TDZ) { + return CP_ACCESS_TRAP_EL2; + } + } + return CP_ACCESS_OK; +} + +static uint64_t aa64_dczid_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + ARMCPU *cpu =3D env_archcpu(env); + int dzp_bit =3D 1 << 4; + + /* DZP indicates whether DC ZVA access is allowed */ + if (aa64_zva_access(env, NULL, false) =3D=3D CP_ACCESS_OK) { + dzp_bit =3D 0; + } + return cpu->dcz_blocksize | dzp_bit; +} + +static CPAccessResult sp_el0_access(CPUARMState *env, const ARMCPRegInfo *= ri, + bool isread) +{ + if (!(env->pstate & PSTATE_SP)) { + /* + * Access to SP_EL0 is undefined if it's being used as + * the stack pointer. + */ + return CP_ACCESS_TRAP_UNCATEGORIZED; + } + return CP_ACCESS_OK; +} + +static uint64_t spsel_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return env->pstate & PSTATE_SP; +} + +static void spsel_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t= val) +{ + update_spsel(env, val); +} + +static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + + if (arm_feature(env, ARM_FEATURE_PMSA) && !cpu->has_mpu) { + /* M bit is RAZ/WI for PMSA with no MPU implemented */ + value &=3D ~SCTLR_M; + } + + /* ??? Lots of these bits are not implemented. */ + + if (ri->state =3D=3D ARM_CP_STATE_AA64 && !cpu_isar_feature(aa64_mte, = cpu)) { + if (ri->opc1 =3D=3D 6) { /* SCTLR_EL3 */ + value &=3D ~(SCTLR_ITFSB | SCTLR_TCF | SCTLR_ATA); + } else { + value &=3D ~(SCTLR_ITFSB | SCTLR_TCF0 | SCTLR_TCF | + SCTLR_ATA0 | SCTLR_ATA); + } + } + + if (raw_read(env, ri) =3D=3D value) { + /* + * Skip the TLB flush if nothing actually changed; Linux likes + * to do a lot of pointless SCTLR writes. + */ + return; + } + + raw_write(env, ri, value); + + /* This may enable/disable the MMU, so do a TLB flush. */ + tlb_flush(CPU(cpu)); + + if (ri->type & ARM_CP_SUPPRESS_TB_END) { + /* + * Normally we would always end the TB on an SCTLR write; see the + * comment in ARMCPRegInfo sctlr initialization below for why Xsca= le + * is special. Setting ARM_CP_SUPPRESS_TB_END also stops the rebu= ild + * of hflags from the translator, so do it here. + */ + arm_rebuild_hflags(env); + } +} + +static void mdcr_el3_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * Some MDCR_EL3 bits affect whether PMU counters are running: + * if we are trying to change any of those then we must + * bracket this update with PMU start/finish calls. + */ + bool pmu_op =3D (env->cp15.mdcr_el3 ^ value) & MDCR_EL3_PMU_ENABLE_BIT= S; + + if (pmu_op) { + pmu_op_start(env); + } + env->cp15.mdcr_el3 =3D value; + if (pmu_op) { + pmu_op_finish(env); + } +} + +static void sdcr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Not all bits defined for MDCR_EL3 exist in the AArch32 SDCR */ + mdcr_el3_write(env, ri, value & SDCR_VALID_MASK); +} + +static void mdcr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * Some MDCR_EL2 bits affect whether PMU counters are running: + * if we are trying to change any of those then we must + * bracket this update with PMU start/finish calls. + */ + bool pmu_op =3D (env->cp15.mdcr_el2 ^ value) & MDCR_EL2_PMU_ENABLE_BIT= S; + + if (pmu_op) { + pmu_op_start(env); + } + env->cp15.mdcr_el2 =3D value; + if (pmu_op) { + pmu_op_finish(env); + } +} + +static const ARMCPRegInfo v8_cp_reginfo[] =3D { + /* + * Minimal set of EL0-visible registers. This will need to be expanded + * significantly for system emulation of AArch64 CPUs. + */ + { .name =3D "NZCV", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 0, .crn =3D 4, .crm =3D 2, + .access =3D PL0_RW, .type =3D ARM_CP_NZCV }, + { .name =3D "DAIF", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 1, .crn =3D 4, .crm =3D 2, + .type =3D ARM_CP_NO_RAW, + .access =3D PL0_RW, .accessfn =3D aa64_daif_access, + .fieldoffset =3D offsetof(CPUARMState, daif), + .writefn =3D aa64_daif_write, .resetfn =3D arm_cp_reset_ignore }, + { .name =3D "FPCR", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 0, .crn =3D 4, .crm =3D 4, + .access =3D PL0_RW, .type =3D ARM_CP_FPU | ARM_CP_SUPPRESS_TB_END, + .readfn =3D aa64_fpcr_read, .writefn =3D aa64_fpcr_write }, + { .name =3D "FPSR", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 1, .crn =3D 4, .crm =3D 4, + .access =3D PL0_RW, .type =3D ARM_CP_FPU | ARM_CP_SUPPRESS_TB_END, + .readfn =3D aa64_fpsr_read, .writefn =3D aa64_fpsr_write }, + { .name =3D "DCZID_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 7, .crn =3D 0, .crm =3D 0, + .access =3D PL0_R, .type =3D ARM_CP_NO_RAW, + .readfn =3D aa64_dczid_read }, + { .name =3D "DC_ZVA", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 4, .opc2 =3D 1, + .access =3D PL0_W, .type =3D ARM_CP_DC_ZVA, +#ifndef CONFIG_USER_ONLY + /* Avoid overhead of an access check that always passes in user-mode= */ + .accessfn =3D aa64_zva_access, +#endif + }, + { .name =3D "CURRENTEL", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .opc2 =3D 2, .crn =3D 4, .crm =3D 2, + .access =3D PL1_R, .type =3D ARM_CP_CURRENTEL }, + /* Cache ops: all NOPs since we don't emulate caches */ + { .name =3D "IC_IALLUIS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 1, .opc2 =3D 0, + .access =3D PL1_W, .type =3D ARM_CP_NOP, + .accessfn =3D access_ticab }, + { .name =3D "IC_IALLU", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 5, .opc2 =3D 0, + .access =3D PL1_W, .type =3D ARM_CP_NOP, + .accessfn =3D access_tocu }, + { .name =3D "IC_IVAU", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 5, .opc2 =3D 1, + .access =3D PL0_W, .type =3D ARM_CP_NOP, + .accessfn =3D access_tocu }, + { .name =3D "DC_IVAC", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 6, .opc2 =3D 1, + .access =3D PL1_W, .accessfn =3D aa64_cacheop_poc_access, + .type =3D ARM_CP_NOP }, + { .name =3D "DC_ISW", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 6, .opc2 =3D 2, + .access =3D PL1_W, .accessfn =3D access_tsw, .type =3D ARM_CP_NOP }, + { .name =3D "DC_CVAC", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 10, .opc2 =3D 1, + .access =3D PL0_W, .type =3D ARM_CP_NOP, + .accessfn =3D aa64_cacheop_poc_access }, + { .name =3D "DC_CSW", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 10, .opc2 =3D 2, + .access =3D PL1_W, .accessfn =3D access_tsw, .type =3D ARM_CP_NOP }, + { .name =3D "DC_CVAU", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 11, .opc2 =3D 1, + .access =3D PL0_W, .type =3D ARM_CP_NOP, + .accessfn =3D access_tocu }, + { .name =3D "DC_CIVAC", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 14, .opc2 =3D 1, + .access =3D PL0_W, .type =3D ARM_CP_NOP, + .accessfn =3D aa64_cacheop_poc_access }, + { .name =3D "DC_CISW", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 14, .opc2 =3D 2, + .access =3D PL1_W, .accessfn =3D access_tsw, .type =3D ARM_CP_NOP }, + /* TLBI operations */ + { .name =3D "TLBI_VMALLE1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 3, .opc2 =3D 0, + .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_vmalle1is_write }, + { .name =3D "TLBI_VAE1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 3, .opc2 =3D 1, + .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_vae1is_write }, + { .name =3D "TLBI_ASIDE1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 3, .opc2 =3D 2, + .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_vmalle1is_write }, + { .name =3D "TLBI_VAAE1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 3, .opc2 =3D 3, + .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_vae1is_write }, + { .name =3D "TLBI_VALE1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 3, .opc2 =3D 5, + .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_vae1is_write }, + { .name =3D "TLBI_VAALE1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 3, .opc2 =3D 7, + .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_vae1is_write }, + { .name =3D "TLBI_VMALLE1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 7, .opc2 =3D 0, + .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, + .writefn =3D tlbi_aa64_vmalle1_write }, + { .name =3D "TLBI_VAE1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 7, .opc2 =3D 1, + .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, + .writefn =3D tlbi_aa64_vae1_write }, + { .name =3D "TLBI_ASIDE1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 7, .opc2 =3D 2, + .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, + .writefn =3D tlbi_aa64_vmalle1_write }, + { .name =3D "TLBI_VAAE1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 7, .opc2 =3D 3, + .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, + .writefn =3D tlbi_aa64_vae1_write }, + { .name =3D "TLBI_VALE1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 7, .opc2 =3D 5, + .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, + .writefn =3D tlbi_aa64_vae1_write }, + { .name =3D "TLBI_VAALE1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 7, .opc2 =3D 7, + .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, + .writefn =3D tlbi_aa64_vae1_write }, + { .name =3D "TLBI_IPAS2E1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 0, .opc2 =3D 1, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_ipas2e1is_write }, + { .name =3D "TLBI_IPAS2LE1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 0, .opc2 =3D 5, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_ipas2e1is_write }, + { .name =3D "TLBI_ALLE1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 3, .opc2 =3D 4, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_alle1is_write }, + { .name =3D "TLBI_VMALLS12E1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 3, .opc2 =3D 6, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_alle1is_write }, + { .name =3D "TLBI_IPAS2E1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 1, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_ipas2e1_write }, + { .name =3D "TLBI_IPAS2LE1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 5, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_ipas2e1_write }, + { .name =3D "TLBI_ALLE1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 7, .opc2 =3D 4, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_alle1_write }, + { .name =3D "TLBI_VMALLS12E1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 7, .opc2 =3D 6, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_alle1is_write }, +#ifndef CONFIG_USER_ONLY + /* 64 bit address translation operations */ + { .name =3D "AT_S1E1R", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 8, .opc2 =3D 0, + .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, + .writefn =3D ats_write64 }, + { .name =3D "AT_S1E1W", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 8, .opc2 =3D 1, + .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, + .writefn =3D ats_write64 }, + { .name =3D "AT_S1E0R", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 8, .opc2 =3D 2, + .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, + .writefn =3D ats_write64 }, + { .name =3D "AT_S1E0W", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 8, .opc2 =3D 3, + .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, + .writefn =3D ats_write64 }, + { .name =3D "AT_S12E1R", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 7, .crm =3D 8, .opc2 =3D 4, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, + .writefn =3D ats_write64 }, + { .name =3D "AT_S12E1W", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 7, .crm =3D 8, .opc2 =3D 5, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, + .writefn =3D ats_write64 }, + { .name =3D "AT_S12E0R", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 7, .crm =3D 8, .opc2 =3D 6, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, + .writefn =3D ats_write64 }, + { .name =3D "AT_S12E0W", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 7, .crm =3D 8, .opc2 =3D 7, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, + .writefn =3D ats_write64 }, + /* AT S1E2* are elsewhere as they UNDEF from EL3 if EL2 is not present= */ + { .name =3D "AT_S1E3R", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 7, .crm =3D 8, .opc2 =3D 0, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, + .writefn =3D ats_write64 }, + { .name =3D "AT_S1E3W", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 7, .crm =3D 8, .opc2 =3D 1, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, + .writefn =3D ats_write64 }, + { .name =3D "PAR_EL1", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_ALIAS, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 7, .crm =3D 4, .opc2 =3D 0, + .access =3D PL1_RW, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.par_el[1]), + .writefn =3D par_write }, +#endif + /* TLB invalidate last level of translation table walk */ + { .name =3D "TLBIMVALIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm = =3D 3, .opc2 =3D 5, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= bis, + .writefn =3D tlbimva_is_write }, + { .name =3D "TLBIMVAALIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm = =3D 3, .opc2 =3D 7, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= bis, + .writefn =3D tlbimvaa_is_write }, + { .name =3D "TLBIMVAL", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D = 7, .opc2 =3D 5, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, + .writefn =3D tlbimva_write }, + { .name =3D "TLBIMVAAL", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D= 7, .opc2 =3D 7, + .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, + .writefn =3D tlbimvaa_write }, + { .name =3D "TLBIMVALH", .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D= 7, .opc2 =3D 5, + .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, + .writefn =3D tlbimva_hyp_write }, + { .name =3D "TLBIMVALHIS", + .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D 3, .opc2 =3D 5, + .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, + .writefn =3D tlbimva_hyp_is_write }, + { .name =3D "TLBIIPAS2", + .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 1, + .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, + .writefn =3D tlbiipas2_hyp_write }, + { .name =3D "TLBIIPAS2IS", + .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D 0, .opc2 =3D 1, + .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, + .writefn =3D tlbiipas2is_hyp_write }, + { .name =3D "TLBIIPAS2L", + .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 5, + .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, + .writefn =3D tlbiipas2_hyp_write }, + { .name =3D "TLBIIPAS2LIS", + .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D 0, .opc2 =3D 5, + .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, + .writefn =3D tlbiipas2is_hyp_write }, + /* 32 bit cache operations */ + { .name =3D "ICIALLUIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D= 1, .opc2 =3D 0, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_ticab = }, + { .name =3D "BPIALLUIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D= 1, .opc2 =3D 6, + .type =3D ARM_CP_NOP, .access =3D PL1_W }, + { .name =3D "ICIALLU", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 5= , .opc2 =3D 0, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tocu }, + { .name =3D "ICIMVAU", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 5= , .opc2 =3D 1, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tocu }, + { .name =3D "BPIALL", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 5,= .opc2 =3D 6, + .type =3D ARM_CP_NOP, .access =3D PL1_W }, + { .name =3D "BPIMVA", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 5,= .opc2 =3D 7, + .type =3D ARM_CP_NOP, .access =3D PL1_W }, + { .name =3D "DCIMVAC", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 6= , .opc2 =3D 1, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D aa64_cacheop_= poc_access }, + { .name =3D "DCISW", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 6, = .opc2 =3D 2, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, + { .name =3D "DCCMVAC", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 1= 0, .opc2 =3D 1, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D aa64_cacheop_= poc_access }, + { .name =3D "DCCSW", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 10,= .opc2 =3D 2, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, + { .name =3D "DCCMVAU", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 1= 1, .opc2 =3D 1, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tocu }, + { .name =3D "DCCIMVAC", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D = 14, .opc2 =3D 1, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D aa64_cacheop_= poc_access }, + { .name =3D "DCCISW", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 14= , .opc2 =3D 2, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, + /* MMU Domain access control / MPU write buffer control */ + { .name =3D "DACR", .cp =3D 15, .opc1 =3D 0, .crn =3D 3, .crm =3D 0, .= opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, .resetvalue =3D 0, + .writefn =3D dacr_write, .raw_writefn =3D raw_write, + .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.dacr_s), + offsetoflow32(CPUARMState, cp15.dacr_ns) } }, + { .name =3D "ELR_EL1", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_ALIAS, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 4, .crm =3D 0, .opc2 =3D 1, + .access =3D PL1_RW, + .fieldoffset =3D offsetof(CPUARMState, elr_el[1]) }, + { .name =3D "SPSR_EL1", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_ALIAS, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 4, .crm =3D 0, .opc2 =3D 0, + .access =3D PL1_RW, + .fieldoffset =3D offsetof(CPUARMState, banked_spsr[BANK_SVC]) }, + /* + * We rely on the access checks not allowing the guest to write to the + * state field when SPSel indicates that it's being used as the stack + * pointer. + */ + { .name =3D "SP_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 4, .crm =3D 1, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D sp_el0_access, + .type =3D ARM_CP_ALIAS, + .fieldoffset =3D offsetof(CPUARMState, sp_el[0]) }, + { .name =3D "SP_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 4, .crm =3D 1, .opc2 =3D 0, + .access =3D PL2_RW, .type =3D ARM_CP_ALIAS | ARM_CP_EL3_NO_EL2_KEEP, + .fieldoffset =3D offsetof(CPUARMState, sp_el[1]) }, + { .name =3D "SPSel", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 4, .crm =3D 2, .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW, + .access =3D PL1_RW, .readfn =3D spsel_read, .writefn =3D spsel_write= }, + { .name =3D "FPEXC32_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 5, .crm =3D 3, .opc2 =3D 0, + .access =3D PL2_RW, + .type =3D ARM_CP_ALIAS | ARM_CP_FPU | ARM_CP_EL3_NO_EL2_KEEP, + .fieldoffset =3D offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPEXC]) }, + { .name =3D "DACR32_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 3, .crm =3D 0, .opc2 =3D 0, + .access =3D PL2_RW, .resetvalue =3D 0, .type =3D ARM_CP_EL3_NO_EL2_K= EEP, + .writefn =3D dacr_write, .raw_writefn =3D raw_write, + .fieldoffset =3D offsetof(CPUARMState, cp15.dacr32_el2) }, + { .name =3D "IFSR32_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 5, .crm =3D 0, .opc2 =3D 1, + .access =3D PL2_RW, .resetvalue =3D 0, .type =3D ARM_CP_EL3_NO_EL2_K= EEP, + .fieldoffset =3D offsetof(CPUARMState, cp15.ifsr32_el2) }, + { .name =3D "SPSR_IRQ", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_ALIAS, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 4, .crm =3D 3, .opc2 =3D 0, + .access =3D PL2_RW, + .fieldoffset =3D offsetof(CPUARMState, banked_spsr[BANK_IRQ]) }, + { .name =3D "SPSR_ABT", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_ALIAS, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 4, .crm =3D 3, .opc2 =3D 1, + .access =3D PL2_RW, + .fieldoffset =3D offsetof(CPUARMState, banked_spsr[BANK_ABT]) }, + { .name =3D "SPSR_UND", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_ALIAS, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 4, .crm =3D 3, .opc2 =3D 2, + .access =3D PL2_RW, + .fieldoffset =3D offsetof(CPUARMState, banked_spsr[BANK_UND]) }, + { .name =3D "SPSR_FIQ", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_ALIAS, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 4, .crm =3D 3, .opc2 =3D 3, + .access =3D PL2_RW, + .fieldoffset =3D offsetof(CPUARMState, banked_spsr[BANK_FIQ]) }, + { .name =3D "MDCR_EL3", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_IO, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 3, .opc2 =3D 1, + .resetvalue =3D 0, + .access =3D PL3_RW, + .writefn =3D mdcr_el3_write, + .fieldoffset =3D offsetof(CPUARMState, cp15.mdcr_el3) }, + { .name =3D "SDCR", .type =3D ARM_CP_ALIAS | ARM_CP_IO, + .cp =3D 15, .opc1 =3D 0, .crn =3D 1, .crm =3D 3, .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_trap_aa32s_el1, + .writefn =3D sdcr_write, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.mdcr_el3) }, +}; + +static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_= mask) +{ + ARMCPU *cpu =3D env_archcpu(env); + + if (arm_feature(env, ARM_FEATURE_V8)) { + valid_mask |=3D MAKE_64BIT_MASK(0, 34); /* ARMv8.0 */ + } else { + valid_mask |=3D MAKE_64BIT_MASK(0, 28); /* ARMv7VE */ + } + + if (arm_feature(env, ARM_FEATURE_EL3)) { + valid_mask &=3D ~HCR_HCD; + } else if (cpu->psci_conduit !=3D QEMU_PSCI_CONDUIT_SMC) { + /* + * Architecturally HCR.TSC is RES0 if EL3 is not implemented. + * However, if we're using the SMC PSCI conduit then QEMU is + * effectively acting like EL3 firmware and so the guest at + * EL2 should retain the ability to prevent EL1 from being + * able to make SMC calls into the ersatz firmware, so in + * that case HCR.TSC should be read/write. + */ + valid_mask &=3D ~HCR_TSC; + } + + if (arm_feature(env, ARM_FEATURE_AARCH64)) { + if (cpu_isar_feature(aa64_vh, cpu)) { + valid_mask |=3D HCR_E2H; + } + if (cpu_isar_feature(aa64_ras, cpu)) { + valid_mask |=3D HCR_TERR | HCR_TEA; + } + if (cpu_isar_feature(aa64_lor, cpu)) { + valid_mask |=3D HCR_TLOR; + } + if (cpu_isar_feature(aa64_pauth, cpu)) { + valid_mask |=3D HCR_API | HCR_APK; + } + if (cpu_isar_feature(aa64_mte, cpu)) { + valid_mask |=3D HCR_ATA | HCR_DCT | HCR_TID5; + } + if (cpu_isar_feature(aa64_scxtnum, cpu)) { + valid_mask |=3D HCR_ENSCXT; + } + if (cpu_isar_feature(aa64_fwb, cpu)) { + valid_mask |=3D HCR_FWB; + } + } + + if (cpu_isar_feature(any_evt, cpu)) { + valid_mask |=3D HCR_TTLBIS | HCR_TTLBOS | HCR_TICAB | HCR_TOCU | H= CR_TID4; + } else if (cpu_isar_feature(any_half_evt, cpu)) { + valid_mask |=3D HCR_TICAB | HCR_TOCU | HCR_TID4; + } + + /* Clear RES0 bits. */ + value &=3D valid_mask; + + /* + * These bits change the MMU setup: + * HCR_VM enables stage 2 translation + * HCR_PTW forbids certain page-table setups + * HCR_DC disables stage1 and enables stage2 translation + * HCR_DCT enables tagging on (disabled) stage1 translation + * HCR_FWB changes the interpretation of stage2 descriptor bits + */ + if ((env->cp15.hcr_el2 ^ value) & + (HCR_VM | HCR_PTW | HCR_DC | HCR_DCT | HCR_FWB)) { + tlb_flush(CPU(cpu)); + } + env->cp15.hcr_el2 =3D value; + + /* + * Updates to VI and VF require us to update the status of + * virtual interrupts, which are the logical OR of these bits + * and the state of the input lines from the GIC. (This requires + * that we have the iothread lock, which is done by marking the + * reginfo structs as ARM_CP_IO.) + * Note that if a write to HCR pends a VIRQ or VFIQ it is never + * possible for it to be taken immediately, because VIRQ and + * VFIQ are masked unless running at EL0 or EL1, and HCR + * can only be written at EL2. + */ + g_assert(qemu_mutex_iothread_locked()); + arm_cpu_update_virq(cpu); + arm_cpu_update_vfiq(cpu); + arm_cpu_update_vserr(cpu); +} + +static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t v= alue) +{ + do_hcr_write(env, value, 0); +} + +static void hcr_writehigh(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Handle HCR2 write, i.e. write to high half of HCR_EL2 */ + value =3D deposit64(env->cp15.hcr_el2, 32, 32, value); + do_hcr_write(env, value, MAKE_64BIT_MASK(0, 32)); +} + +static void hcr_writelow(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Handle HCR write, i.e. write to low half of HCR_EL2 */ + value =3D deposit64(env->cp15.hcr_el2, 0, 32, value); + do_hcr_write(env, value, MAKE_64BIT_MASK(32, 32)); +} + +static void hcrx_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + uint64_t valid_mask =3D 0; + + /* No features adding bits to HCRX are implemented. */ + + /* Clear RES0 bits. */ + env->cp15.hcrx_el2 =3D value & valid_mask; +} + +static CPAccessResult access_hxen(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + if (arm_current_el(env) < 3 + && arm_feature(env, ARM_FEATURE_EL3) + && !(env->cp15.scr_el3 & SCR_HXEN)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + +static const ARMCPRegInfo hcrx_el2_reginfo =3D { + .name =3D "HCRX_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 2, .opc2 =3D 2, + .access =3D PL2_RW, .writefn =3D hcrx_write, .accessfn =3D access_hxen, + .fieldoffset =3D offsetof(CPUARMState, cp15.hcrx_el2), +}; + +/* Return the effective value of HCRX_EL2. */ +uint64_t arm_hcrx_el2_eff(CPUARMState *env) +{ + /* + * The bits in this register behave as 0 for all purposes other than + * direct reads of the register if: + * - EL2 is not enabled in the current security state, + * - SCR_EL3.HXEn is 0. + */ + if (!arm_is_el2_enabled(env) + || (arm_feature(env, ARM_FEATURE_EL3) + && !(env->cp15.scr_el3 & SCR_HXEN))) { + return 0; + } + return env->cp15.hcrx_el2; +} + +static void cptr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * For A-profile AArch32 EL3, if NSACR.CP10 + * is 0 then HCPTR.{TCP11,TCP10} ignore writes and read as 1. + */ + if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) && + !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) { + uint64_t mask =3D R_HCPTR_TCP11_MASK | R_HCPTR_TCP10_MASK; + value =3D (value & ~mask) | (env->cp15.cptr_el[2] & mask); + } + env->cp15.cptr_el[2] =3D value; +} + +static uint64_t cptr_el2_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + /* + * For A-profile AArch32 EL3, if NSACR.CP10 + * is 0 then HCPTR.{TCP11,TCP10} ignore writes and read as 1. + */ + uint64_t value =3D env->cp15.cptr_el[2]; + + if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) && + !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) { + value |=3D R_HCPTR_TCP11_MASK | R_HCPTR_TCP10_MASK; + } + return value; +} + +static const ARMCPRegInfo el2_cp_reginfo[] =3D { + { .name =3D "HCR_EL2", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_IO, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 1, .opc2 =3D 0, + .access =3D PL2_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.hcr_= el2), + .writefn =3D hcr_write }, + { .name =3D "HCR", .state =3D ARM_CP_STATE_AA32, + .type =3D ARM_CP_ALIAS | ARM_CP_IO, + .cp =3D 15, .opc1 =3D 4, .crn =3D 1, .crm =3D 1, .opc2 =3D 0, + .access =3D PL2_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.hcr_= el2), + .writefn =3D hcr_writelow }, + { .name =3D "HACR_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 1, .opc2 =3D 7, + .access =3D PL2_RW, .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + { .name =3D "ELR_EL2", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_ALIAS, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 4, .crm =3D 0, .opc2 =3D 1, + .access =3D PL2_RW, + .fieldoffset =3D offsetof(CPUARMState, elr_el[2]) }, + { .name =3D "ESR_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 5, .crm =3D 2, .opc2 =3D 0, + .access =3D PL2_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.esr_= el[2]) }, + { .name =3D "FAR_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 6, .crm =3D 0, .opc2 =3D 0, + .access =3D PL2_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.far_= el[2]) }, + { .name =3D "HIFAR", .state =3D ARM_CP_STATE_AA32, + .type =3D ARM_CP_ALIAS, + .cp =3D 15, .opc1 =3D 4, .crn =3D 6, .crm =3D 0, .opc2 =3D 2, + .access =3D PL2_RW, + .fieldoffset =3D offsetofhigh32(CPUARMState, cp15.far_el[2]) }, + { .name =3D "SPSR_EL2", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_ALIAS, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 4, .crm =3D 0, .opc2 =3D 0, + .access =3D PL2_RW, + .fieldoffset =3D offsetof(CPUARMState, banked_spsr[BANK_HYP]) }, + { .name =3D "VBAR_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 12, .crm =3D 0, .opc2 =3D 0, + .access =3D PL2_RW, .writefn =3D vbar_write, + .fieldoffset =3D offsetof(CPUARMState, cp15.vbar_el[2]), + .resetvalue =3D 0 }, + { .name =3D "SP_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 4, .crm =3D 1, .opc2 =3D 0, + .access =3D PL3_RW, .type =3D ARM_CP_ALIAS, + .fieldoffset =3D offsetof(CPUARMState, sp_el[2]) }, + { .name =3D "CPTR_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 1, .opc2 =3D 2, + .access =3D PL2_RW, .accessfn =3D cptr_access, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.cptr_el[2]), + .readfn =3D cptr_el2_read, .writefn =3D cptr_el2_write }, + { .name =3D "MAIR_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 10, .crm =3D 2, .opc2 =3D 0, + .access =3D PL2_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.mair= _el[2]), + .resetvalue =3D 0 }, + { .name =3D "HMAIR1", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 4, .crn =3D 10, .crm =3D 2, .opc2 =3D 1, + .access =3D PL2_RW, .type =3D ARM_CP_ALIAS, + .fieldoffset =3D offsetofhigh32(CPUARMState, cp15.mair_el[2]) }, + { .name =3D "AMAIR_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 10, .crm =3D 3, .opc2 =3D 0, + .access =3D PL2_RW, .type =3D ARM_CP_CONST, + .resetvalue =3D 0 }, + /* HAMAIR1 is mapped to AMAIR_EL2[63:32] */ + { .name =3D "HAMAIR1", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 4, .crn =3D 10, .crm =3D 3, .opc2 =3D 1, + .access =3D PL2_RW, .type =3D ARM_CP_CONST, + .resetvalue =3D 0 }, + { .name =3D "AFSR0_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 5, .crm =3D 1, .opc2 =3D 0, + .access =3D PL2_RW, .type =3D ARM_CP_CONST, + .resetvalue =3D 0 }, + { .name =3D "AFSR1_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 5, .crm =3D 1, .opc2 =3D 1, + .access =3D PL2_RW, .type =3D ARM_CP_CONST, + .resetvalue =3D 0 }, + { .name =3D "TCR_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 2, .crm =3D 0, .opc2 =3D 2, + .access =3D PL2_RW, .writefn =3D vmsa_tcr_el12_write, + .fieldoffset =3D offsetof(CPUARMState, cp15.tcr_el[2]) }, + { .name =3D "VTCR", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 4, .crn =3D 2, .crm =3D 1, .opc2 =3D 2, + .type =3D ARM_CP_ALIAS, + .access =3D PL2_RW, .accessfn =3D access_el3_aa32ns, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.vtcr_el2) }, + { .name =3D "VTCR_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 2, .crm =3D 1, .opc2 =3D 2, + .access =3D PL2_RW, + /* no .writefn needed as this can't cause an ASID change */ + .fieldoffset =3D offsetof(CPUARMState, cp15.vtcr_el2) }, + { .name =3D "VTTBR", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 6, .crm =3D 2, + .type =3D ARM_CP_64BIT | ARM_CP_ALIAS, + .access =3D PL2_RW, .accessfn =3D access_el3_aa32ns, + .fieldoffset =3D offsetof(CPUARMState, cp15.vttbr_el2), + .writefn =3D vttbr_write }, + { .name =3D "VTTBR_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 2, .crm =3D 1, .opc2 =3D 0, + .access =3D PL2_RW, .writefn =3D vttbr_write, + .fieldoffset =3D offsetof(CPUARMState, cp15.vttbr_el2) }, + { .name =3D "SCTLR_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 0, .opc2 =3D 0, + .access =3D PL2_RW, .raw_writefn =3D raw_write, .writefn =3D sctlr_w= rite, + .fieldoffset =3D offsetof(CPUARMState, cp15.sctlr_el[2]) }, + { .name =3D "TPIDR_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 13, .crm =3D 0, .opc2 =3D 2, + .access =3D PL2_RW, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.tpidr_el[2]) }, + { .name =3D "TTBR0_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 2, .crm =3D 0, .opc2 =3D 0, + .access =3D PL2_RW, .resetvalue =3D 0, .writefn =3D vmsa_tcr_ttbr_el= 2_write, + .fieldoffset =3D offsetof(CPUARMState, cp15.ttbr0_el[2]) }, + { .name =3D "HTTBR", .cp =3D 15, .opc1 =3D 4, .crm =3D 2, + .access =3D PL2_RW, .type =3D ARM_CP_64BIT | ARM_CP_ALIAS, + .fieldoffset =3D offsetof(CPUARMState, cp15.ttbr0_el[2]) }, + { .name =3D "TLBIALLNSNH", + .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D 7, .opc2 =3D 4, + .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, + .writefn =3D tlbiall_nsnh_write }, + { .name =3D "TLBIALLNSNHIS", + .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D 3, .opc2 =3D 4, + .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, + .writefn =3D tlbiall_nsnh_is_write }, + { .name =3D "TLBIALLH", .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D = 7, .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, + .writefn =3D tlbiall_hyp_write }, + { .name =3D "TLBIALLHIS", .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm = =3D 3, .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, + .writefn =3D tlbiall_hyp_is_write }, + { .name =3D "TLBIMVAH", .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D = 7, .opc2 =3D 1, + .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, + .writefn =3D tlbimva_hyp_write }, + { .name =3D "TLBIMVAHIS", .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm = =3D 3, .opc2 =3D 1, + .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, + .writefn =3D tlbimva_hyp_is_write }, + { .name =3D "TLBI_ALLE2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 7, .opc2 =3D 0, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, + .writefn =3D tlbi_aa64_alle2_write }, + { .name =3D "TLBI_VAE2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 7, .opc2 =3D 1, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, + .writefn =3D tlbi_aa64_vae2_write }, + { .name =3D "TLBI_VALE2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 7, .opc2 =3D 5, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, + .writefn =3D tlbi_aa64_vae2_write }, + { .name =3D "TLBI_ALLE2IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 3, .opc2 =3D 0, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, + .writefn =3D tlbi_aa64_alle2is_write }, + { .name =3D "TLBI_VAE2IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 3, .opc2 =3D 1, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, + .writefn =3D tlbi_aa64_vae2is_write }, + { .name =3D "TLBI_VALE2IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 3, .opc2 =3D 5, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, + .writefn =3D tlbi_aa64_vae2is_write }, +#ifndef CONFIG_USER_ONLY + /* + * Unlike the other EL2-related AT operations, these must + * UNDEF from EL3 if EL2 is not implemented, which is why we + * define them here rather than with the rest of the AT ops. + */ + { .name =3D "AT_S1E2R", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 7, .crm =3D 8, .opc2 =3D 0, + .access =3D PL2_W, .accessfn =3D at_s1e2_access, + .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC | ARM_CP_EL3_NO_EL2_UNDE= F, + .writefn =3D ats_write64 }, + { .name =3D "AT_S1E2W", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 7, .crm =3D 8, .opc2 =3D 1, + .access =3D PL2_W, .accessfn =3D at_s1e2_access, + .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC | ARM_CP_EL3_NO_EL2_UNDE= F, + .writefn =3D ats_write64 }, + /* + * The AArch32 ATS1H* operations are CONSTRAINED UNPREDICTABLE + * if EL2 is not implemented; we choose to UNDEF. Behaviour at EL3 + * with SCR.NS =3D=3D 0 outside Monitor mode is UNPREDICTABLE; we choo= se + * to behave as if SCR.NS was 1. + */ + { .name =3D "ATS1HR", .cp =3D 15, .opc1 =3D 4, .crn =3D 7, .crm =3D 8,= .opc2 =3D 0, + .access =3D PL2_W, + .writefn =3D ats1h_write, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EX= C }, + { .name =3D "ATS1HW", .cp =3D 15, .opc1 =3D 4, .crn =3D 7, .crm =3D 8,= .opc2 =3D 1, + .access =3D PL2_W, + .writefn =3D ats1h_write, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EX= C }, + { .name =3D "CNTHCTL_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 1, .opc2 =3D 0, + /* + * ARMv7 requires bit 0 and 1 to reset to 1. ARMv8 defines the + * reset values as IMPDEF. We choose to reset to 3 to comply with + * both ARMv7 and ARMv8. + */ + .access =3D PL2_RW, .resetvalue =3D 3, + .fieldoffset =3D offsetof(CPUARMState, cp15.cnthctl_el2) }, + { .name =3D "CNTVOFF_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 0, .opc2 =3D 3, + .access =3D PL2_RW, .type =3D ARM_CP_IO, .resetvalue =3D 0, + .writefn =3D gt_cntvoff_write, + .fieldoffset =3D offsetof(CPUARMState, cp15.cntvoff_el2) }, + { .name =3D "CNTVOFF", .cp =3D 15, .opc1 =3D 4, .crm =3D 14, + .access =3D PL2_RW, .type =3D ARM_CP_64BIT | ARM_CP_ALIAS | ARM_CP_I= O, + .writefn =3D gt_cntvoff_write, + .fieldoffset =3D offsetof(CPUARMState, cp15.cntvoff_el2) }, + { .name =3D "CNTHP_CVAL_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 2, .opc2 =3D 2, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYP].cv= al), + .type =3D ARM_CP_IO, .access =3D PL2_RW, + .writefn =3D gt_hyp_cval_write, .raw_writefn =3D raw_write }, + { .name =3D "CNTHP_CVAL", .cp =3D 15, .opc1 =3D 6, .crm =3D 14, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYP].cv= al), + .access =3D PL2_RW, .type =3D ARM_CP_64BIT | ARM_CP_IO, + .writefn =3D gt_hyp_cval_write, .raw_writefn =3D raw_write }, + { .name =3D "CNTHP_TVAL_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 2, .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL2_RW, + .resetfn =3D gt_hyp_timer_reset, + .readfn =3D gt_hyp_tval_read, .writefn =3D gt_hyp_tval_write }, + { .name =3D "CNTHP_CTL_EL2", .state =3D ARM_CP_STATE_BOTH, + .type =3D ARM_CP_IO, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 2, .opc2 =3D 1, + .access =3D PL2_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYP].ct= l), + .resetvalue =3D 0, + .writefn =3D gt_hyp_ctl_write, .raw_writefn =3D raw_write }, +#endif + { .name =3D "HPFAR", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 4, .crn =3D 6, .crm =3D 0, .opc2 =3D 4, + .access =3D PL2_RW, .accessfn =3D access_el3_aa32ns, + .fieldoffset =3D offsetof(CPUARMState, cp15.hpfar_el2) }, + { .name =3D "HPFAR_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 6, .crm =3D 0, .opc2 =3D 4, + .access =3D PL2_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.hpfar_el2) }, + { .name =3D "HSTR_EL2", .state =3D ARM_CP_STATE_BOTH, + .cp =3D 15, .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 1, .opc2 = =3D 3, + .access =3D PL2_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.hstr_el2) }, +}; + +static const ARMCPRegInfo el2_v8_cp_reginfo[] =3D { + { .name =3D "HCR2", .state =3D ARM_CP_STATE_AA32, + .type =3D ARM_CP_ALIAS | ARM_CP_IO, + .cp =3D 15, .opc1 =3D 4, .crn =3D 1, .crm =3D 1, .opc2 =3D 4, + .access =3D PL2_RW, + .fieldoffset =3D offsetofhigh32(CPUARMState, cp15.hcr_el2), + .writefn =3D hcr_writehigh }, +}; + +static CPAccessResult sel2_access(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + if (arm_current_el(env) =3D=3D 3 || arm_is_secure_below_el3(env)) { + return CP_ACCESS_OK; + } + return CP_ACCESS_TRAP_UNCATEGORIZED; +} + +static const ARMCPRegInfo el2_sec_cp_reginfo[] =3D { + { .name =3D "VSTTBR_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 2, .crm =3D 6, .opc2 =3D 0, + .access =3D PL2_RW, .accessfn =3D sel2_access, + .fieldoffset =3D offsetof(CPUARMState, cp15.vsttbr_el2) }, + { .name =3D "VSTCR_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 2, .crm =3D 6, .opc2 =3D 2, + .access =3D PL2_RW, .accessfn =3D sel2_access, + .fieldoffset =3D offsetof(CPUARMState, cp15.vstcr_el2) }, +}; + +static CPAccessResult nsacr_access(CPUARMState *env, const ARMCPRegInfo *r= i, + bool isread) +{ + /* + * The NSACR is RW at EL3, and RO for NS EL1 and NS EL2. + * At Secure EL1 it traps to EL3 or EL2. + */ + if (arm_current_el(env) =3D=3D 3) { + return CP_ACCESS_OK; + } + if (arm_is_secure_below_el3(env)) { + if (env->cp15.scr_el3 & SCR_EEL2) { + return CP_ACCESS_TRAP_EL2; + } + return CP_ACCESS_TRAP_EL3; + } + /* Accesses from EL1 NS and EL2 NS are UNDEF for write but allow reads= . */ + if (isread) { + return CP_ACCESS_OK; + } + return CP_ACCESS_TRAP_UNCATEGORIZED; +} + +static const ARMCPRegInfo el3_cp_reginfo[] =3D { + { .name =3D "SCR_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 1, .opc2 =3D 0, + .access =3D PL3_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.scr_= el3), + .resetfn =3D scr_reset, .writefn =3D scr_write }, + { .name =3D "SCR", .type =3D ARM_CP_ALIAS | ARM_CP_NEWEL, + .cp =3D 15, .opc1 =3D 0, .crn =3D 1, .crm =3D 1, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_trap_aa32s_el1, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.scr_el3), + .writefn =3D scr_write }, + { .name =3D "SDER32_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 1, .opc2 =3D 1, + .access =3D PL3_RW, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.sder) }, + { .name =3D "SDER", + .cp =3D 15, .opc1 =3D 0, .crn =3D 1, .crm =3D 1, .opc2 =3D 1, + .access =3D PL3_RW, .resetvalue =3D 0, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.sder) }, + { .name =3D "MVBAR", .cp =3D 15, .opc1 =3D 0, .crn =3D 12, .crm =3D 0,= .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_trap_aa32s_el1, + .writefn =3D vbar_write, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.mvbar) }, + { .name =3D "TTBR0_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 2, .crm =3D 0, .opc2 =3D 0, + .access =3D PL3_RW, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.ttbr0_el[3]) }, + { .name =3D "TCR_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 2, .crm =3D 0, .opc2 =3D 2, + .access =3D PL3_RW, + /* no .writefn needed as this can't cause an ASID change */ + .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.tcr_el[3]) }, + { .name =3D "ELR_EL3", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_ALIAS, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 4, .crm =3D 0, .opc2 =3D 1, + .access =3D PL3_RW, + .fieldoffset =3D offsetof(CPUARMState, elr_el[3]) }, + { .name =3D "ESR_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 5, .crm =3D 2, .opc2 =3D 0, + .access =3D PL3_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.esr_= el[3]) }, + { .name =3D "FAR_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 6, .crm =3D 0, .opc2 =3D 0, + .access =3D PL3_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.far_= el[3]) }, + { .name =3D "SPSR_EL3", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_ALIAS, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 4, .crm =3D 0, .opc2 =3D 0, + .access =3D PL3_RW, + .fieldoffset =3D offsetof(CPUARMState, banked_spsr[BANK_MON]) }, + { .name =3D "VBAR_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 12, .crm =3D 0, .opc2 =3D 0, + .access =3D PL3_RW, .writefn =3D vbar_write, + .fieldoffset =3D offsetof(CPUARMState, cp15.vbar_el[3]), + .resetvalue =3D 0 }, + { .name =3D "CPTR_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 1, .opc2 =3D 2, + .access =3D PL3_RW, .accessfn =3D cptr_access, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.cptr_el[3]) }, + { .name =3D "TPIDR_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 13, .crm =3D 0, .opc2 =3D 2, + .access =3D PL3_RW, .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.tpidr_el[3]) }, + { .name =3D "AMAIR_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 10, .crm =3D 3, .opc2 =3D 0, + .access =3D PL3_RW, .type =3D ARM_CP_CONST, + .resetvalue =3D 0 }, + { .name =3D "AFSR0_EL3", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 5, .crm =3D 1, .opc2 =3D 0, + .access =3D PL3_RW, .type =3D ARM_CP_CONST, + .resetvalue =3D 0 }, + { .name =3D "AFSR1_EL3", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 5, .crm =3D 1, .opc2 =3D 1, + .access =3D PL3_RW, .type =3D ARM_CP_CONST, + .resetvalue =3D 0 }, + { .name =3D "TLBI_ALLE3IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 3, .opc2 =3D 0, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_alle3is_write }, + { .name =3D "TLBI_VAE3IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 3, .opc2 =3D 1, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_vae3is_write }, + { .name =3D "TLBI_VALE3IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 3, .opc2 =3D 5, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_vae3is_write }, + { .name =3D "TLBI_ALLE3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 7, .opc2 =3D 0, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_alle3_write }, + { .name =3D "TLBI_VAE3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 7, .opc2 =3D 1, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_vae3_write }, + { .name =3D "TLBI_VALE3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 7, .opc2 =3D 5, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_vae3_write }, +}; + +#ifndef CONFIG_USER_ONLY +/* Test if system register redirection is to occur in the current state. = */ +static bool redirect_for_e2h(CPUARMState *env) +{ + return arm_current_el(env) =3D=3D 2 && (arm_hcr_el2_eff(env) & HCR_E2H= ); +} + +static uint64_t el2_e2h_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + CPReadFn *readfn; + + if (redirect_for_e2h(env)) { + /* Switch to the saved EL2 version of the register. */ + ri =3D ri->opaque; + readfn =3D ri->readfn; + } else { + readfn =3D ri->orig_readfn; + } + if (readfn =3D=3D NULL) { + readfn =3D raw_read; + } + return readfn(env, ri); +} + +static void el2_e2h_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + CPWriteFn *writefn; + + if (redirect_for_e2h(env)) { + /* Switch to the saved EL2 version of the register. */ + ri =3D ri->opaque; + writefn =3D ri->writefn; + } else { + writefn =3D ri->orig_writefn; + } + if (writefn =3D=3D NULL) { + writefn =3D raw_write; + } + writefn(env, ri, value); +} + +static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu) +{ + struct E2HAlias { + uint32_t src_key, dst_key, new_key; + const char *src_name, *dst_name, *new_name; + bool (*feature)(const ARMISARegisters *id); + }; + +#define K(op0, op1, crn, crm, op2) \ + ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP, crn, crm, op0, op1, op2) + + static const struct E2HAlias aliases[] =3D { + { K(3, 0, 1, 0, 0), K(3, 4, 1, 0, 0), K(3, 5, 1, 0, 0), + "SCTLR", "SCTLR_EL2", "SCTLR_EL12" }, + { K(3, 0, 1, 0, 2), K(3, 4, 1, 1, 2), K(3, 5, 1, 0, 2), + "CPACR", "CPTR_EL2", "CPACR_EL12" }, + { K(3, 0, 2, 0, 0), K(3, 4, 2, 0, 0), K(3, 5, 2, 0, 0), + "TTBR0_EL1", "TTBR0_EL2", "TTBR0_EL12" }, + { K(3, 0, 2, 0, 1), K(3, 4, 2, 0, 1), K(3, 5, 2, 0, 1), + "TTBR1_EL1", "TTBR1_EL2", "TTBR1_EL12" }, + { K(3, 0, 2, 0, 2), K(3, 4, 2, 0, 2), K(3, 5, 2, 0, 2), + "TCR_EL1", "TCR_EL2", "TCR_EL12" }, + { K(3, 0, 4, 0, 0), K(3, 4, 4, 0, 0), K(3, 5, 4, 0, 0), + "SPSR_EL1", "SPSR_EL2", "SPSR_EL12" }, + { K(3, 0, 4, 0, 1), K(3, 4, 4, 0, 1), K(3, 5, 4, 0, 1), + "ELR_EL1", "ELR_EL2", "ELR_EL12" }, + { K(3, 0, 5, 1, 0), K(3, 4, 5, 1, 0), K(3, 5, 5, 1, 0), + "AFSR0_EL1", "AFSR0_EL2", "AFSR0_EL12" }, + { K(3, 0, 5, 1, 1), K(3, 4, 5, 1, 1), K(3, 5, 5, 1, 1), + "AFSR1_EL1", "AFSR1_EL2", "AFSR1_EL12" }, + { K(3, 0, 5, 2, 0), K(3, 4, 5, 2, 0), K(3, 5, 5, 2, 0), + "ESR_EL1", "ESR_EL2", "ESR_EL12" }, + { K(3, 0, 6, 0, 0), K(3, 4, 6, 0, 0), K(3, 5, 6, 0, 0), + "FAR_EL1", "FAR_EL2", "FAR_EL12" }, + { K(3, 0, 10, 2, 0), K(3, 4, 10, 2, 0), K(3, 5, 10, 2, 0), + "MAIR_EL1", "MAIR_EL2", "MAIR_EL12" }, + { K(3, 0, 10, 3, 0), K(3, 4, 10, 3, 0), K(3, 5, 10, 3, 0), + "AMAIR0", "AMAIR_EL2", "AMAIR_EL12" }, + { K(3, 0, 12, 0, 0), K(3, 4, 12, 0, 0), K(3, 5, 12, 0, 0), + "VBAR", "VBAR_EL2", "VBAR_EL12" }, + { K(3, 0, 13, 0, 1), K(3, 4, 13, 0, 1), K(3, 5, 13, 0, 1), + "CONTEXTIDR_EL1", "CONTEXTIDR_EL2", "CONTEXTIDR_EL12" }, + { K(3, 0, 14, 1, 0), K(3, 4, 14, 1, 0), K(3, 5, 14, 1, 0), + "CNTKCTL", "CNTHCTL_EL2", "CNTKCTL_EL12" }, + + /* + * Note that redirection of ZCR is mentioned in the description + * of ZCR_EL2, and aliasing in the description of ZCR_EL1, but + * not in the summary table. + */ + { K(3, 0, 1, 2, 0), K(3, 4, 1, 2, 0), K(3, 5, 1, 2, 0), + "ZCR_EL1", "ZCR_EL2", "ZCR_EL12", isar_feature_aa64_sve }, + { K(3, 0, 1, 2, 6), K(3, 4, 1, 2, 6), K(3, 5, 1, 2, 6), + "SMCR_EL1", "SMCR_EL2", "SMCR_EL12", isar_feature_aa64_sme }, + + { K(3, 0, 5, 6, 0), K(3, 4, 5, 6, 0), K(3, 5, 5, 6, 0), + "TFSR_EL1", "TFSR_EL2", "TFSR_EL12", isar_feature_aa64_mte }, + + { K(3, 0, 13, 0, 7), K(3, 4, 13, 0, 7), K(3, 5, 13, 0, 7), + "SCXTNUM_EL1", "SCXTNUM_EL2", "SCXTNUM_EL12", + isar_feature_aa64_scxtnum }, + + /* TODO: ARMv8.2-SPE -- PMSCR_EL2 */ + /* TODO: ARMv8.4-Trace -- TRFCR_EL2 */ + }; +#undef K + + size_t i; + + for (i =3D 0; i < ARRAY_SIZE(aliases); i++) { + const struct E2HAlias *a =3D &aliases[i]; + ARMCPRegInfo *src_reg, *dst_reg, *new_reg; + bool ok; + + if (a->feature && !a->feature(&cpu->isar)) { + continue; + } + + src_reg =3D g_hash_table_lookup(cpu->cp_regs, + (gpointer)(uintptr_t)a->src_key); + dst_reg =3D g_hash_table_lookup(cpu->cp_regs, + (gpointer)(uintptr_t)a->dst_key); + g_assert(src_reg !=3D NULL); + g_assert(dst_reg !=3D NULL); + + /* Cross-compare names to detect typos in the keys. */ + g_assert(strcmp(src_reg->name, a->src_name) =3D=3D 0); + g_assert(strcmp(dst_reg->name, a->dst_name) =3D=3D 0); + + /* None of the core system registers use opaque; we will. */ + g_assert(src_reg->opaque =3D=3D NULL); + + /* Create alias before redirection so we dup the right data. */ + new_reg =3D g_memdup(src_reg, sizeof(ARMCPRegInfo)); + + new_reg->name =3D a->new_name; + new_reg->type |=3D ARM_CP_ALIAS; + /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */ + new_reg->access &=3D PL2_RW | PL3_RW; + + ok =3D g_hash_table_insert(cpu->cp_regs, + (gpointer)(uintptr_t)a->new_key, new_reg); + g_assert(ok); + + src_reg->opaque =3D dst_reg; + src_reg->orig_readfn =3D src_reg->readfn ?: raw_read; + src_reg->orig_writefn =3D src_reg->writefn ?: raw_write; + if (!src_reg->raw_readfn) { + src_reg->raw_readfn =3D raw_read; + } + if (!src_reg->raw_writefn) { + src_reg->raw_writefn =3D raw_write; + } + src_reg->readfn =3D el2_e2h_read; + src_reg->writefn =3D el2_e2h_write; + } +} +#endif + +static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo = *ri, + bool isread) +{ + int cur_el =3D arm_current_el(env); + + if (cur_el < 2) { + uint64_t hcr =3D arm_hcr_el2_eff(env); + + if (cur_el =3D=3D 0) { + if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { + if (!(env->cp15.sctlr_el[2] & SCTLR_UCT)) { + return CP_ACCESS_TRAP_EL2; + } + } else { + if (!(env->cp15.sctlr_el[1] & SCTLR_UCT)) { + return CP_ACCESS_TRAP; + } + if (hcr & HCR_TID2) { + return CP_ACCESS_TRAP_EL2; + } + } + } else if (hcr & HCR_TID2) { + return CP_ACCESS_TRAP_EL2; + } + } + + if (arm_current_el(env) < 2 && arm_hcr_el2_eff(env) & HCR_TID2) { + return CP_ACCESS_TRAP_EL2; + } + + return CP_ACCESS_OK; +} + +/* + * Check for traps to RAS registers, which are controlled + * by HCR_EL2.TERR and SCR_EL3.TERR. + */ +static CPAccessResult access_terr(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + int el =3D arm_current_el(env); + + if (el < 2 && (arm_hcr_el2_eff(env) & HCR_TERR)) { + return CP_ACCESS_TRAP_EL2; + } + if (el < 3 && (env->cp15.scr_el3 & SCR_TERR)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + +static uint64_t disr_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + int el =3D arm_current_el(env); + + if (el < 2 && (arm_hcr_el2_eff(env) & HCR_AMO)) { + return env->cp15.vdisr_el2; + } + if (el < 3 && (env->cp15.scr_el3 & SCR_EA)) { + return 0; /* RAZ/WI */ + } + return env->cp15.disr_el1; +} + +static void disr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t = val) +{ + int el =3D arm_current_el(env); + + if (el < 2 && (arm_hcr_el2_eff(env) & HCR_AMO)) { + env->cp15.vdisr_el2 =3D val; + return; + } + if (el < 3 && (env->cp15.scr_el3 & SCR_EA)) { + return; /* RAZ/WI */ + } + env->cp15.disr_el1 =3D val; +} + +/* + * Minimal RAS implementation with no Error Records. + * Which means that all of the Error Record registers: + * ERXADDR_EL1 + * ERXCTLR_EL1 + * ERXFR_EL1 + * ERXMISC0_EL1 + * ERXMISC1_EL1 + * ERXMISC2_EL1 + * ERXMISC3_EL1 + * ERXPFGCDN_EL1 (RASv1p1) + * ERXPFGCTL_EL1 (RASv1p1) + * ERXPFGF_EL1 (RASv1p1) + * ERXSTATUS_EL1 + * and + * ERRSELR_EL1 + * may generate UNDEFINED, which is the effect we get by not + * listing them at all. + */ +static const ARMCPRegInfo minimal_ras_reginfo[] =3D { + { .name =3D "DISR_EL1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 12, .crm =3D 1, .opc2 =3D 1, + .access =3D PL1_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.disr= _el1), + .readfn =3D disr_read, .writefn =3D disr_write, .raw_writefn =3D raw= _write }, + { .name =3D "ERRIDR_EL1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 5, .crm =3D 3, .opc2 =3D 0, + .access =3D PL1_R, .accessfn =3D access_terr, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + { .name =3D "VDISR_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 12, .crm =3D 1, .opc2 =3D 1, + .access =3D PL2_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.vdis= r_el2) }, + { .name =3D "VSESR_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 5, .crm =3D 2, .opc2 =3D 3, + .access =3D PL2_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.vses= r_el2) }, +}; + +static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + int cur_el =3D arm_current_el(env); + int old_len =3D sve_vqm1_for_el(env, cur_el); + int new_len; + + /* Bits other than [3:0] are RAZ/WI. */ + QEMU_BUILD_BUG_ON(ARM_MAX_VQ > 16); + raw_write(env, ri, value & 0xf); + + /* + * Because we arrived here, we know both FP and SVE are enabled; + * otherwise we would have trapped access to the ZCR_ELn register. + */ + new_len =3D sve_vqm1_for_el(env, cur_el); + if (new_len < old_len) { + aarch64_sve_narrow_vq(env, new_len + 1); + } +} + +static const ARMCPRegInfo zcr_reginfo[] =3D { + { .name =3D "ZCR_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 1, .crm =3D 2, .opc2 =3D 0, + .access =3D PL1_RW, .type =3D ARM_CP_SVE, + .fieldoffset =3D offsetof(CPUARMState, vfp.zcr_el[1]), + .writefn =3D zcr_write, .raw_writefn =3D raw_write }, + { .name =3D "ZCR_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 2, .opc2 =3D 0, + .access =3D PL2_RW, .type =3D ARM_CP_SVE, + .fieldoffset =3D offsetof(CPUARMState, vfp.zcr_el[2]), + .writefn =3D zcr_write, .raw_writefn =3D raw_write }, + { .name =3D "ZCR_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 2, .opc2 =3D 0, + .access =3D PL3_RW, .type =3D ARM_CP_SVE, + .fieldoffset =3D offsetof(CPUARMState, vfp.zcr_el[3]), + .writefn =3D zcr_write, .raw_writefn =3D raw_write }, +}; + +#ifdef TARGET_AARCH64 +static CPAccessResult access_tpidr2(CPUARMState *env, const ARMCPRegInfo *= ri, + bool isread) +{ + int el =3D arm_current_el(env); + + if (el =3D=3D 0) { + uint64_t sctlr =3D arm_sctlr(env, el); + if (!(sctlr & SCTLR_EnTP2)) { + return CP_ACCESS_TRAP; + } + } + /* TODO: FEAT_FGT */ + if (el < 3 + && arm_feature(env, ARM_FEATURE_EL3) + && !(env->cp15.scr_el3 & SCR_ENTP2)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + +static CPAccessResult access_esm(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + /* TODO: FEAT_FGT for SMPRI_EL1 but not SMPRIMAP_EL2 */ + if (arm_current_el(env) < 3 + && arm_feature(env, ARM_FEATURE_EL3) + && !FIELD_EX64(env->cp15.cptr_el[3], CPTR_EL3, ESM)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + +static void svcr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + helper_set_pstate_sm(env, FIELD_EX64(value, SVCR, SM)); + helper_set_pstate_za(env, FIELD_EX64(value, SVCR, ZA)); + arm_rebuild_hflags(env); +} + +static void smcr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + int cur_el =3D arm_current_el(env); + int old_len =3D sve_vqm1_for_el(env, cur_el); + int new_len; + + QEMU_BUILD_BUG_ON(ARM_MAX_VQ > R_SMCR_LEN_MASK + 1); + value &=3D R_SMCR_LEN_MASK | R_SMCR_FA64_MASK; + raw_write(env, ri, value); + + /* + * Note that it is CONSTRAINED UNPREDICTABLE what happens to ZA storage + * when SVL is widened (old values kept, or zeros). Choose to keep the + * current values for simplicity. But for QEMU internals, we must sti= ll + * apply the narrower SVL to the Zregs and Pregs -- see the comment + * above aarch64_sve_narrow_vq. + */ + new_len =3D sve_vqm1_for_el(env, cur_el); + if (new_len < old_len) { + aarch64_sve_narrow_vq(env, new_len + 1); + } +} + +static const ARMCPRegInfo sme_reginfo[] =3D { + { .name =3D "TPIDR2_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 13, .crm =3D 0, .opc2 =3D 5, + .access =3D PL0_RW, .accessfn =3D access_tpidr2, + .fieldoffset =3D offsetof(CPUARMState, cp15.tpidr2_el0) }, + { .name =3D "SVCR", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 4, .crm =3D 2, .opc2 =3D 2, + .access =3D PL0_RW, .type =3D ARM_CP_SME, + .fieldoffset =3D offsetof(CPUARMState, svcr), + .writefn =3D svcr_write, .raw_writefn =3D raw_write }, + { .name =3D "SMCR_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 1, .crm =3D 2, .opc2 =3D 6, + .access =3D PL1_RW, .type =3D ARM_CP_SME, + .fieldoffset =3D offsetof(CPUARMState, vfp.smcr_el[1]), + .writefn =3D smcr_write, .raw_writefn =3D raw_write }, + { .name =3D "SMCR_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 2, .opc2 =3D 6, + .access =3D PL2_RW, .type =3D ARM_CP_SME, + .fieldoffset =3D offsetof(CPUARMState, vfp.smcr_el[2]), + .writefn =3D smcr_write, .raw_writefn =3D raw_write }, + { .name =3D "SMCR_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 2, .opc2 =3D 6, + .access =3D PL3_RW, .type =3D ARM_CP_SME, + .fieldoffset =3D offsetof(CPUARMState, vfp.smcr_el[3]), + .writefn =3D smcr_write, .raw_writefn =3D raw_write }, + { .name =3D "SMIDR_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 1, .crn =3D 0, .crm =3D 0, .opc2 =3D 6, + .access =3D PL1_R, .accessfn =3D access_aa64_tid1, + /* + * IMPLEMENTOR =3D 0 (software) + * REVISION =3D 0 (implementation defined) + * SMPS =3D 0 (no streaming execution priority in QEMU) + * AFFINITY =3D 0 (streaming sve mode not shared with other PEs) + */ + .type =3D ARM_CP_CONST, .resetvalue =3D 0, }, + /* + * Because SMIDR_EL1.SMPS is 0, SMPRI_EL1 and SMPRIMAP_EL2 are RES 0. + */ + { .name =3D "SMPRI_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 1, .crm =3D 2, .opc2 =3D 4, + .access =3D PL1_RW, .accessfn =3D access_esm, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + { .name =3D "SMPRIMAP_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 2, .opc2 =3D 5, + .access =3D PL2_RW, .accessfn =3D access_esm, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, +}; +#endif /* TARGET_AARCH64 */ + +static void define_pmu_regs(ARMCPU *cpu) +{ + /* + * v7 performance monitor control register: same implementor + * field as main ID register, and we implement four counters in + * addition to the cycle count register. + */ + unsigned int i, pmcrn =3D pmu_num_counters(&cpu->env); + ARMCPRegInfo pmcr =3D { + .name =3D "PMCR", .cp =3D 15, .crn =3D 9, .crm =3D 12, .opc1 =3D 0= , .opc2 =3D 0, + .access =3D PL0_RW, + .type =3D ARM_CP_IO | ARM_CP_ALIAS, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pmcr), + .accessfn =3D pmreg_access, .writefn =3D pmcr_write, + .raw_writefn =3D raw_write, + }; + ARMCPRegInfo pmcr64 =3D { + .name =3D "PMCR_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D 0, + .access =3D PL0_RW, .accessfn =3D pmreg_access, + .type =3D ARM_CP_IO, + .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pmcr), + .resetvalue =3D cpu->isar.reset_pmcr_el0, + .writefn =3D pmcr_write, .raw_writefn =3D raw_write, + }; + + define_one_arm_cp_reg(cpu, &pmcr); + define_one_arm_cp_reg(cpu, &pmcr64); + for (i =3D 0; i < pmcrn; i++) { + char *pmevcntr_name =3D g_strdup_printf("PMEVCNTR%d", i); + char *pmevcntr_el0_name =3D g_strdup_printf("PMEVCNTR%d_EL0", i); + char *pmevtyper_name =3D g_strdup_printf("PMEVTYPER%d", i); + char *pmevtyper_el0_name =3D g_strdup_printf("PMEVTYPER%d_EL0", i); + ARMCPRegInfo pmev_regs[] =3D { + { .name =3D pmevcntr_name, .cp =3D 15, .crn =3D 14, + .crm =3D 8 | (3 & (i >> 3)), .opc1 =3D 0, .opc2 =3D i & 7, + .access =3D PL0_RW, .type =3D ARM_CP_IO | ARM_CP_ALIAS, + .readfn =3D pmevcntr_readfn, .writefn =3D pmevcntr_writefn, + .accessfn =3D pmreg_access_xevcntr }, + { .name =3D pmevcntr_el0_name, .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 8 | (3 & (i = >> 3)), + .opc2 =3D i & 7, .access =3D PL0_RW, .accessfn =3D pmreg_acc= ess_xevcntr, + .type =3D ARM_CP_IO, + .readfn =3D pmevcntr_readfn, .writefn =3D pmevcntr_writefn, + .raw_readfn =3D pmevcntr_rawread, + .raw_writefn =3D pmevcntr_rawwrite }, + { .name =3D pmevtyper_name, .cp =3D 15, .crn =3D 14, + .crm =3D 12 | (3 & (i >> 3)), .opc1 =3D 0, .opc2 =3D i & 7, + .access =3D PL0_RW, .type =3D ARM_CP_IO | ARM_CP_ALIAS, + .readfn =3D pmevtyper_readfn, .writefn =3D pmevtyper_writefn, + .accessfn =3D pmreg_access }, + { .name =3D pmevtyper_el0_name, .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 12 | (3 & (i= >> 3)), + .opc2 =3D i & 7, .access =3D PL0_RW, .accessfn =3D pmreg_acc= ess, + .type =3D ARM_CP_IO, + .readfn =3D pmevtyper_readfn, .writefn =3D pmevtyper_writefn, + .raw_writefn =3D pmevtyper_rawwrite }, + }; + define_arm_cp_regs(cpu, pmev_regs); + g_free(pmevcntr_name); + g_free(pmevcntr_el0_name); + g_free(pmevtyper_name); + g_free(pmevtyper_el0_name); + } + if (cpu_isar_feature(aa32_pmuv3p1, cpu)) { + ARMCPRegInfo v81_pmu_regs[] =3D { + { .name =3D "PMCEID2", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 14, .opc2 =3D = 4, + .access =3D PL0_R, .accessfn =3D pmreg_access, .type =3D ARM= _CP_CONST, + .resetvalue =3D extract64(cpu->pmceid0, 32, 32) }, + { .name =3D "PMCEID3", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 14, .opc2 =3D = 5, + .access =3D PL0_R, .accessfn =3D pmreg_access, .type =3D ARM= _CP_CONST, + .resetvalue =3D extract64(cpu->pmceid1, 32, 32) }, + }; + define_arm_cp_regs(cpu, v81_pmu_regs); + } + if (cpu_isar_feature(any_pmuv3p4, cpu)) { + static const ARMCPRegInfo v84_pmmir =3D { + .name =3D "PMMIR_EL1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 9, .crm =3D 14, .opc2 =3D 6, + .access =3D PL1_R, .accessfn =3D pmreg_access, .type =3D ARM_C= P_CONST, + .resetvalue =3D 0 + }; + define_one_arm_cp_reg(cpu, &v84_pmmir); + } +} + +/* + * We don't know until after realize whether there's a GICv3 + * attached, and that is what registers the gicv3 sysregs. + * So we have to fill in the GIC fields in ID_PFR/ID_PFR1_EL1/ID_AA64PFR0_= EL1 + * at runtime. + */ +static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + ARMCPU *cpu =3D env_archcpu(env); + uint64_t pfr1 =3D cpu->isar.id_pfr1; + + if (env->gicv3state) { + pfr1 |=3D 1 << 28; + } + return pfr1; +} + +#ifndef CONFIG_USER_ONLY +static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + ARMCPU *cpu =3D env_archcpu(env); + uint64_t pfr0 =3D cpu->isar.id_aa64pfr0; + + if (env->gicv3state) { + pfr0 |=3D 1 << 24; + } + return pfr0; +} +#endif + +/* + * Shared logic between LORID and the rest of the LOR* registers. + * Secure state exclusion has already been dealt with. + */ +static CPAccessResult access_lor_ns(CPUARMState *env, + const ARMCPRegInfo *ri, bool isread) +{ + int el =3D arm_current_el(env); + + if (el < 2 && (arm_hcr_el2_eff(env) & HCR_TLOR)) { + return CP_ACCESS_TRAP_EL2; + } + if (el < 3 && (env->cp15.scr_el3 & SCR_TLOR)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + +static CPAccessResult access_lor_other(CPUARMState *env, + const ARMCPRegInfo *ri, bool isread) +{ + if (arm_is_secure_below_el3(env)) { + /* Access denied in secure mode. */ + return CP_ACCESS_TRAP; + } + return access_lor_ns(env, ri, isread); +} + +/* + * A trivial implementation of ARMv8.1-LOR leaves all of these + * registers fixed at 0, which indicates that there are zero + * supported Limited Ordering regions. + */ +static const ARMCPRegInfo lor_reginfo[] =3D { + { .name =3D "LORSA_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 10, .crm =3D 4, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_lor_other, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + { .name =3D "LOREA_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 10, .crm =3D 4, .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_lor_other, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + { .name =3D "LORN_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 10, .crm =3D 4, .opc2 =3D 2, + .access =3D PL1_RW, .accessfn =3D access_lor_other, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + { .name =3D "LORC_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 10, .crm =3D 4, .opc2 =3D 3, + .access =3D PL1_RW, .accessfn =3D access_lor_other, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + { .name =3D "LORID_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 10, .crm =3D 4, .opc2 =3D 7, + .access =3D PL1_R, .accessfn =3D access_lor_ns, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, +}; + +#ifdef TARGET_AARCH64 +static CPAccessResult access_pauth(CPUARMState *env, const ARMCPRegInfo *r= i, + bool isread) +{ + int el =3D arm_current_el(env); + + if (el < 2 && + arm_is_el2_enabled(env) && + !(arm_hcr_el2_eff(env) & HCR_APK)) { + return CP_ACCESS_TRAP_EL2; + } + if (el < 3 && + arm_feature(env, ARM_FEATURE_EL3) && + !(env->cp15.scr_el3 & SCR_APK)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + +static const ARMCPRegInfo pauth_reginfo[] =3D { + { .name =3D "APDAKEYLO_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 2, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_pauth, + .fieldoffset =3D offsetof(CPUARMState, keys.apda.lo) }, + { .name =3D "APDAKEYHI_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 2, .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_pauth, + .fieldoffset =3D offsetof(CPUARMState, keys.apda.hi) }, + { .name =3D "APDBKEYLO_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 2, .opc2 =3D 2, + .access =3D PL1_RW, .accessfn =3D access_pauth, + .fieldoffset =3D offsetof(CPUARMState, keys.apdb.lo) }, + { .name =3D "APDBKEYHI_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 2, .opc2 =3D 3, + .access =3D PL1_RW, .accessfn =3D access_pauth, + .fieldoffset =3D offsetof(CPUARMState, keys.apdb.hi) }, + { .name =3D "APGAKEYLO_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 3, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_pauth, + .fieldoffset =3D offsetof(CPUARMState, keys.apga.lo) }, + { .name =3D "APGAKEYHI_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 3, .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_pauth, + .fieldoffset =3D offsetof(CPUARMState, keys.apga.hi) }, + { .name =3D "APIAKEYLO_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 1, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_pauth, + .fieldoffset =3D offsetof(CPUARMState, keys.apia.lo) }, + { .name =3D "APIAKEYHI_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 1, .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_pauth, + .fieldoffset =3D offsetof(CPUARMState, keys.apia.hi) }, + { .name =3D "APIBKEYLO_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 1, .opc2 =3D 2, + .access =3D PL1_RW, .accessfn =3D access_pauth, + .fieldoffset =3D offsetof(CPUARMState, keys.apib.lo) }, + { .name =3D "APIBKEYHI_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 1, .opc2 =3D 3, + .access =3D PL1_RW, .accessfn =3D access_pauth, + .fieldoffset =3D offsetof(CPUARMState, keys.apib.hi) }, +}; + +static const ARMCPRegInfo tlbirange_reginfo[] =3D { + { .name =3D "TLBI_RVAE1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 2, .opc2 =3D 1, + .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_rvae1is_write }, + { .name =3D "TLBI_RVAAE1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 2, .opc2 =3D 3, + .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_rvae1is_write }, + { .name =3D "TLBI_RVALE1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 2, .opc2 =3D 5, + .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_rvae1is_write }, + { .name =3D "TLBI_RVAALE1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 2, .opc2 =3D 7, + .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_rvae1is_write }, + { .name =3D "TLBI_RVAE1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 5, .opc2 =3D 1, + .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_rvae1is_write }, + { .name =3D "TLBI_RVAAE1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 5, .opc2 =3D 3, + .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_rvae1is_write }, + { .name =3D "TLBI_RVALE1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 5, .opc2 =3D 5, + .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_rvae1is_write }, + { .name =3D "TLBI_RVAALE1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 5, .opc2 =3D 7, + .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_rvae1is_write }, + { .name =3D "TLBI_RVAE1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 6, .opc2 =3D 1, + .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, + .writefn =3D tlbi_aa64_rvae1_write }, + { .name =3D "TLBI_RVAAE1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 6, .opc2 =3D 3, + .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, + .writefn =3D tlbi_aa64_rvae1_write }, + { .name =3D "TLBI_RVALE1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 6, .opc2 =3D 5, + .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, + .writefn =3D tlbi_aa64_rvae1_write }, + { .name =3D "TLBI_RVAALE1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 6, .opc2 =3D 7, + .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, + .writefn =3D tlbi_aa64_rvae1_write }, + { .name =3D "TLBI_RIPAS2E1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 0, .opc2 =3D 2, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_ripas2e1is_write }, + { .name =3D "TLBI_RIPAS2LE1IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 0, .opc2 =3D 6, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_ripas2e1is_write }, + { .name =3D "TLBI_RVAE2IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 2, .opc2 =3D 1, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, + .writefn =3D tlbi_aa64_rvae2is_write }, + { .name =3D "TLBI_RVALE2IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 2, .opc2 =3D 5, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, + .writefn =3D tlbi_aa64_rvae2is_write }, + { .name =3D "TLBI_RIPAS2E1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 2, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_ripas2e1_write }, + { .name =3D "TLBI_RIPAS2LE1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 6, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_ripas2e1_write }, + { .name =3D "TLBI_RVAE2OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 5, .opc2 =3D 1, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, + .writefn =3D tlbi_aa64_rvae2is_write }, + { .name =3D "TLBI_RVALE2OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 5, .opc2 =3D 5, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, + .writefn =3D tlbi_aa64_rvae2is_write }, + { .name =3D "TLBI_RVAE2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 6, .opc2 =3D 1, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, + .writefn =3D tlbi_aa64_rvae2_write }, + { .name =3D "TLBI_RVALE2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 6, .opc2 =3D 5, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, + .writefn =3D tlbi_aa64_rvae2_write }, + { .name =3D "TLBI_RVAE3IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 2, .opc2 =3D 1, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_rvae3is_write }, + { .name =3D "TLBI_RVALE3IS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 2, .opc2 =3D 5, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_rvae3is_write }, + { .name =3D "TLBI_RVAE3OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 5, .opc2 =3D 1, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_rvae3is_write }, + { .name =3D "TLBI_RVALE3OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 5, .opc2 =3D 5, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_rvae3is_write }, + { .name =3D "TLBI_RVAE3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 6, .opc2 =3D 1, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_rvae3_write }, + { .name =3D "TLBI_RVALE3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 6, .opc2 =3D 5, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_rvae3_write }, +}; + +static const ARMCPRegInfo tlbios_reginfo[] =3D { + { .name =3D "TLBI_VMALLE1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 1, .opc2 =3D 0, + .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_vmalle1is_write }, + { .name =3D "TLBI_VAE1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 1, .opc2 =3D 1, + .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_vae1is_write }, + { .name =3D "TLBI_ASIDE1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 1, .opc2 =3D 2, + .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_vmalle1is_write }, + { .name =3D "TLBI_VAAE1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 1, .opc2 =3D 3, + .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_vae1is_write }, + { .name =3D "TLBI_VALE1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 1, .opc2 =3D 5, + .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_vae1is_write }, + { .name =3D "TLBI_VAALE1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 1, .opc2 =3D 7, + .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, + .writefn =3D tlbi_aa64_vae1is_write }, + { .name =3D "TLBI_ALLE2OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 1, .opc2 =3D 0, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, + .writefn =3D tlbi_aa64_alle2is_write }, + { .name =3D "TLBI_VAE2OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 1, .opc2 =3D 1, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, + .writefn =3D tlbi_aa64_vae2is_write }, + { .name =3D "TLBI_ALLE1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 1, .opc2 =3D 4, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_alle1is_write }, + { .name =3D "TLBI_VALE2OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 1, .opc2 =3D 5, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, + .writefn =3D tlbi_aa64_vae2is_write }, + { .name =3D "TLBI_VMALLS12E1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 1, .opc2 =3D 6, + .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_alle1is_write }, + { .name =3D "TLBI_IPAS2E1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 0, + .access =3D PL2_W, .type =3D ARM_CP_NOP }, + { .name =3D "TLBI_RIPAS2E1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 3, + .access =3D PL2_W, .type =3D ARM_CP_NOP }, + { .name =3D "TLBI_IPAS2LE1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 4, + .access =3D PL2_W, .type =3D ARM_CP_NOP }, + { .name =3D "TLBI_RIPAS2LE1OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 7, + .access =3D PL2_W, .type =3D ARM_CP_NOP }, + { .name =3D "TLBI_ALLE3OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 1, .opc2 =3D 0, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_alle3is_write }, + { .name =3D "TLBI_VAE3OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 1, .opc2 =3D 1, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_vae3is_write }, + { .name =3D "TLBI_VALE3OS", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 1, .opc2 =3D 5, + .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, + .writefn =3D tlbi_aa64_vae3is_write }, +}; + +static uint64_t rndr_readfn(CPUARMState *env, const ARMCPRegInfo *ri) +{ + Error *err =3D NULL; + uint64_t ret; + + /* Success sets NZCV =3D 0000. */ + env->NF =3D env->CF =3D env->VF =3D 0, env->ZF =3D 1; + + if (qemu_guest_getrandom(&ret, sizeof(ret), &err) < 0) { + /* + * ??? Failed, for unknown reasons in the crypto subsystem. + * The best we can do is log the reason and return the + * timed-out indication to the guest. There is no reason + * we know to expect this failure to be transitory, so the + * guest may well hang retrying the operation. + */ + qemu_log_mask(LOG_UNIMP, "%s: Crypto failure: %s", + ri->name, error_get_pretty(err)); + error_free(err); + + env->ZF =3D 0; /* NZCF =3D 0100 */ + return 0; + } + return ret; +} + +/* We do not support re-seeding, so the two registers operate the same. */ +static const ARMCPRegInfo rndr_reginfo[] =3D { + { .name =3D "RNDR", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END | ARM_CP_IO, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 2, .crm =3D 4, .opc2 =3D 0, + .access =3D PL0_R, .readfn =3D rndr_readfn }, + { .name =3D "RNDRRS", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END | ARM_CP_IO, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 2, .crm =3D 4, .opc2 =3D 1, + .access =3D PL0_R, .readfn =3D rndr_readfn }, +}; + +#ifndef CONFIG_USER_ONLY +static void dccvap_writefn(CPUARMState *env, const ARMCPRegInfo *opaque, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + /* CTR_EL0 System register -> DminLine, bits [19:16] */ + uint64_t dline_size =3D 4 << ((cpu->ctr >> 16) & 0xF); + uint64_t vaddr_in =3D (uint64_t) value; + uint64_t vaddr =3D vaddr_in & ~(dline_size - 1); + void *haddr; + int mem_idx =3D cpu_mmu_index(env, false); + + /* This won't be crossing page boundaries */ + haddr =3D probe_read(env, vaddr, dline_size, mem_idx, GETPC()); + if (haddr) { + + ram_addr_t offset; + MemoryRegion *mr; + + /* RCU lock is already being held */ + mr =3D memory_region_from_host(haddr, &offset); + + if (mr) { + memory_region_writeback(mr, offset, dline_size); + } + } +} + +static const ARMCPRegInfo dcpop_reg[] =3D { + { .name =3D "DC_CVAP", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 12, .opc2 =3D 1, + .access =3D PL0_W, .type =3D ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END, + .accessfn =3D aa64_cacheop_poc_access, .writefn =3D dccvap_writefn }, +}; + +static const ARMCPRegInfo dcpodp_reg[] =3D { + { .name =3D "DC_CVADP", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 13, .opc2 =3D 1, + .access =3D PL0_W, .type =3D ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END, + .accessfn =3D aa64_cacheop_poc_access, .writefn =3D dccvap_writefn }, +}; +#endif /*CONFIG_USER_ONLY*/ + +static CPAccessResult access_aa64_tid5(CPUARMState *env, const ARMCPRegInf= o *ri, + bool isread) +{ + if ((arm_current_el(env) < 2) && (arm_hcr_el2_eff(env) & HCR_TID5)) { + return CP_ACCESS_TRAP_EL2; + } + + return CP_ACCESS_OK; +} + +static CPAccessResult access_mte(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + int el =3D arm_current_el(env); + + if (el < 2 && arm_is_el2_enabled(env)) { + uint64_t hcr =3D arm_hcr_el2_eff(env); + if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) { + return CP_ACCESS_TRAP_EL2; + } + } + if (el < 3 && + arm_feature(env, ARM_FEATURE_EL3) && + !(env->cp15.scr_el3 & SCR_ATA)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + +static uint64_t tco_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + return env->pstate & PSTATE_TCO; +} + +static void tco_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t v= al) +{ + env->pstate =3D (env->pstate & ~PSTATE_TCO) | (val & PSTATE_TCO); +} + +static const ARMCPRegInfo mte_reginfo[] =3D { + { .name =3D "TFSRE0_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 5, .crm =3D 6, .opc2 =3D 1, + .access =3D PL1_RW, .accessfn =3D access_mte, + .fieldoffset =3D offsetof(CPUARMState, cp15.tfsr_el[0]) }, + { .name =3D "TFSR_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 5, .crm =3D 6, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_mte, + .fieldoffset =3D offsetof(CPUARMState, cp15.tfsr_el[1]) }, + { .name =3D "TFSR_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 5, .crm =3D 6, .opc2 =3D 0, + .access =3D PL2_RW, .accessfn =3D access_mte, + .fieldoffset =3D offsetof(CPUARMState, cp15.tfsr_el[2]) }, + { .name =3D "TFSR_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 5, .crm =3D 6, .opc2 =3D 0, + .access =3D PL3_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.tfsr_el[3]) }, + { .name =3D "RGSR_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 1, .crm =3D 0, .opc2 =3D 5, + .access =3D PL1_RW, .accessfn =3D access_mte, + .fieldoffset =3D offsetof(CPUARMState, cp15.rgsr_el1) }, + { .name =3D "GCR_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 1, .crm =3D 0, .opc2 =3D 6, + .access =3D PL1_RW, .accessfn =3D access_mte, + .fieldoffset =3D offsetof(CPUARMState, cp15.gcr_el1) }, + { .name =3D "GMID_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 1, .crn =3D 0, .crm =3D 0, .opc2 =3D 4, + .access =3D PL1_R, .accessfn =3D access_aa64_tid5, + .type =3D ARM_CP_CONST, .resetvalue =3D GMID_EL1_BS }, + { .name =3D "TCO", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 4, .crm =3D 2, .opc2 =3D 7, + .type =3D ARM_CP_NO_RAW, + .access =3D PL0_RW, .readfn =3D tco_read, .writefn =3D tco_write }, + { .name =3D "DC_IGVAC", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 6, .opc2 =3D 3, + .type =3D ARM_CP_NOP, .access =3D PL1_W, + .accessfn =3D aa64_cacheop_poc_access }, + { .name =3D "DC_IGSW", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 6, .opc2 =3D 4, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, + { .name =3D "DC_IGDVAC", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 6, .opc2 =3D 5, + .type =3D ARM_CP_NOP, .access =3D PL1_W, + .accessfn =3D aa64_cacheop_poc_access }, + { .name =3D "DC_IGDSW", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 6, .opc2 =3D 6, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, + { .name =3D "DC_CGSW", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 10, .opc2 =3D 4, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, + { .name =3D "DC_CGDSW", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 10, .opc2 =3D 6, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, + { .name =3D "DC_CIGSW", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 14, .opc2 =3D 4, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, + { .name =3D "DC_CIGDSW", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 14, .opc2 =3D 6, + .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, +}; + +static const ARMCPRegInfo mte_tco_ro_reginfo[] =3D { + { .name =3D "TCO", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 4, .crm =3D 2, .opc2 =3D 7, + .type =3D ARM_CP_CONST, .access =3D PL0_RW, }, +}; + +static const ARMCPRegInfo mte_el0_cacheop_reginfo[] =3D { + { .name =3D "DC_CGVAC", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 10, .opc2 =3D 3, + .type =3D ARM_CP_NOP, .access =3D PL0_W, + .accessfn =3D aa64_cacheop_poc_access }, + { .name =3D "DC_CGDVAC", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 10, .opc2 =3D 5, + .type =3D ARM_CP_NOP, .access =3D PL0_W, + .accessfn =3D aa64_cacheop_poc_access }, + { .name =3D "DC_CGVAP", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 12, .opc2 =3D 3, + .type =3D ARM_CP_NOP, .access =3D PL0_W, + .accessfn =3D aa64_cacheop_poc_access }, + { .name =3D "DC_CGDVAP", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 12, .opc2 =3D 5, + .type =3D ARM_CP_NOP, .access =3D PL0_W, + .accessfn =3D aa64_cacheop_poc_access }, + { .name =3D "DC_CGVADP", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 13, .opc2 =3D 3, + .type =3D ARM_CP_NOP, .access =3D PL0_W, + .accessfn =3D aa64_cacheop_poc_access }, + { .name =3D "DC_CGDVADP", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 13, .opc2 =3D 5, + .type =3D ARM_CP_NOP, .access =3D PL0_W, + .accessfn =3D aa64_cacheop_poc_access }, + { .name =3D "DC_CIGVAC", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 14, .opc2 =3D 3, + .type =3D ARM_CP_NOP, .access =3D PL0_W, + .accessfn =3D aa64_cacheop_poc_access }, + { .name =3D "DC_CIGDVAC", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 14, .opc2 =3D 5, + .type =3D ARM_CP_NOP, .access =3D PL0_W, + .accessfn =3D aa64_cacheop_poc_access }, + { .name =3D "DC_GVA", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 4, .opc2 =3D 3, + .access =3D PL0_W, .type =3D ARM_CP_DC_GVA, +#ifndef CONFIG_USER_ONLY + /* Avoid overhead of an access check that always passes in user-mode= */ + .accessfn =3D aa64_zva_access, +#endif + }, + { .name =3D "DC_GZVA", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 4, .opc2 =3D 4, + .access =3D PL0_W, .type =3D ARM_CP_DC_GZVA, +#ifndef CONFIG_USER_ONLY + /* Avoid overhead of an access check that always passes in user-mode= */ + .accessfn =3D aa64_zva_access, +#endif + }, +}; + +static CPAccessResult access_scxtnum(CPUARMState *env, const ARMCPRegInfo = *ri, + bool isread) +{ + uint64_t hcr =3D arm_hcr_el2_eff(env); + int el =3D arm_current_el(env); + + if (el =3D=3D 0 && !((hcr & HCR_E2H) && (hcr & HCR_TGE))) { + if (env->cp15.sctlr_el[1] & SCTLR_TSCXT) { + if (hcr & HCR_TGE) { + return CP_ACCESS_TRAP_EL2; + } + return CP_ACCESS_TRAP; + } + } else if (el < 2 && (env->cp15.sctlr_el[2] & SCTLR_TSCXT)) { + return CP_ACCESS_TRAP_EL2; + } + if (el < 2 && arm_is_el2_enabled(env) && !(hcr & HCR_ENSCXT)) { + return CP_ACCESS_TRAP_EL2; + } + if (el < 3 + && arm_feature(env, ARM_FEATURE_EL3) + && !(env->cp15.scr_el3 & SCR_ENSCXT)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + +static const ARMCPRegInfo scxtnum_reginfo[] =3D { + { .name =3D "SCXTNUM_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 13, .crm =3D 0, .opc2 =3D 7, + .access =3D PL0_RW, .accessfn =3D access_scxtnum, + .fieldoffset =3D offsetof(CPUARMState, scxtnum_el[0]) }, + { .name =3D "SCXTNUM_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 13, .crm =3D 0, .opc2 =3D 7, + .access =3D PL1_RW, .accessfn =3D access_scxtnum, + .fieldoffset =3D offsetof(CPUARMState, scxtnum_el[1]) }, + { .name =3D "SCXTNUM_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 13, .crm =3D 0, .opc2 =3D 7, + .access =3D PL2_RW, .accessfn =3D access_scxtnum, + .fieldoffset =3D offsetof(CPUARMState, scxtnum_el[2]) }, + { .name =3D "SCXTNUM_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 13, .crm =3D 0, .opc2 =3D 7, + .access =3D PL3_RW, + .fieldoffset =3D offsetof(CPUARMState, scxtnum_el[3]) }, +}; +#endif /* TARGET_AARCH64 */ + +static CPAccessResult access_predinv(CPUARMState *env, const ARMCPRegInfo = *ri, + bool isread) +{ + int el =3D arm_current_el(env); + + if (el =3D=3D 0) { + uint64_t sctlr =3D arm_sctlr(env, el); + if (!(sctlr & SCTLR_EnRCTX)) { + return CP_ACCESS_TRAP; + } + } else if (el =3D=3D 1) { + uint64_t hcr =3D arm_hcr_el2_eff(env); + if (hcr & HCR_NV) { + return CP_ACCESS_TRAP_EL2; + } + } + return CP_ACCESS_OK; +} + +static const ARMCPRegInfo predinv_reginfo[] =3D { + { .name =3D "CFP_RCTX", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 3, .opc2 =3D 4, + .type =3D ARM_CP_NOP, .access =3D PL0_W, .accessfn =3D access_predin= v }, + { .name =3D "DVP_RCTX", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 3, .opc2 =3D 5, + .type =3D ARM_CP_NOP, .access =3D PL0_W, .accessfn =3D access_predin= v }, + { .name =3D "CPP_RCTX", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 3, .opc2 =3D 7, + .type =3D ARM_CP_NOP, .access =3D PL0_W, .accessfn =3D access_predin= v }, + /* + * Note the AArch32 opcodes have a different OPC1. + */ + { .name =3D "CFPRCTX", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 3, .opc2 =3D 4, + .type =3D ARM_CP_NOP, .access =3D PL0_W, .accessfn =3D access_predin= v }, + { .name =3D "DVPRCTX", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 3, .opc2 =3D 5, + .type =3D ARM_CP_NOP, .access =3D PL0_W, .accessfn =3D access_predin= v }, + { .name =3D "CPPRCTX", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 3, .opc2 =3D 7, + .type =3D ARM_CP_NOP, .access =3D PL0_W, .accessfn =3D access_predin= v }, +}; + +static uint64_t ccsidr2_read(CPUARMState *env, const ARMCPRegInfo *ri) +{ + /* Read the high 32 bits of the current CCSIDR */ + return extract64(ccsidr_read(env, ri), 32, 32); +} + +static const ARMCPRegInfo ccsidr2_reginfo[] =3D { + { .name =3D "CCSIDR2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 1, .crn =3D 0, .crm =3D 0, .opc2 =3D 2, + .access =3D PL1_R, + .accessfn =3D access_tid4, + .readfn =3D ccsidr2_read, .type =3D ARM_CP_NO_RAW }, +}; + +static CPAccessResult access_aa64_tid3(CPUARMState *env, const ARMCPRegInf= o *ri, + bool isread) +{ + if ((arm_current_el(env) < 2) && (arm_hcr_el2_eff(env) & HCR_TID3)) { + return CP_ACCESS_TRAP_EL2; + } + + return CP_ACCESS_OK; +} + +static CPAccessResult access_aa32_tid3(CPUARMState *env, const ARMCPRegInf= o *ri, + bool isread) +{ + if (arm_feature(env, ARM_FEATURE_V8)) { + return access_aa64_tid3(env, ri, isread); + } + + return CP_ACCESS_OK; +} + +static CPAccessResult access_jazelle(CPUARMState *env, const ARMCPRegInfo = *ri, + bool isread) +{ + if (arm_current_el(env) =3D=3D 1 && (arm_hcr_el2_eff(env) & HCR_TID0))= { + return CP_ACCESS_TRAP_EL2; + } + + return CP_ACCESS_OK; +} + +static CPAccessResult access_joscr_jmcr(CPUARMState *env, + const ARMCPRegInfo *ri, bool isrea= d) +{ + /* + * HSTR.TJDBX traps JOSCR and JMCR accesses, but it exists only + * in v7A, not in v8A. + */ + if (!arm_feature(env, ARM_FEATURE_V8) && + arm_current_el(env) < 2 && !arm_is_secure_below_el3(env) && + (env->cp15.hstr_el2 & HSTR_TJDBX)) { + return CP_ACCESS_TRAP_EL2; + } + return CP_ACCESS_OK; +} + +static const ARMCPRegInfo jazelle_regs[] =3D { + { .name =3D "JIDR", + .cp =3D 14, .crn =3D 0, .crm =3D 0, .opc1 =3D 7, .opc2 =3D 0, + .access =3D PL1_R, .accessfn =3D access_jazelle, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + { .name =3D "JOSCR", + .cp =3D 14, .crn =3D 1, .crm =3D 0, .opc1 =3D 7, .opc2 =3D 0, + .accessfn =3D access_joscr_jmcr, + .access =3D PL1_RW, .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + { .name =3D "JMCR", + .cp =3D 14, .crn =3D 2, .crm =3D 0, .opc1 =3D 7, .opc2 =3D 0, + .accessfn =3D access_joscr_jmcr, + .access =3D PL1_RW, .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, +}; + +static const ARMCPRegInfo contextidr_el2 =3D { + .name =3D "CONTEXTIDR_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 13, .crm =3D 0, .opc2 =3D 1, + .access =3D PL2_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.contextidr_el[2]) +}; + +static const ARMCPRegInfo vhe_reginfo[] =3D { + { .name =3D "TTBR1_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 2, .crm =3D 0, .opc2 =3D 1, + .access =3D PL2_RW, .writefn =3D vmsa_tcr_ttbr_el2_write, + .fieldoffset =3D offsetof(CPUARMState, cp15.ttbr1_el[2]) }, +#ifndef CONFIG_USER_ONLY + { .name =3D "CNTHV_CVAL_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 3, .opc2 =3D 2, + .fieldoffset =3D + offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYPVIRT].cval), + .type =3D ARM_CP_IO, .access =3D PL2_RW, + .writefn =3D gt_hv_cval_write, .raw_writefn =3D raw_write }, + { .name =3D "CNTHV_TVAL_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 3, .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL2_RW, + .resetfn =3D gt_hv_timer_reset, + .readfn =3D gt_hv_tval_read, .writefn =3D gt_hv_tval_write }, + { .name =3D "CNTHV_CTL_EL2", .state =3D ARM_CP_STATE_BOTH, + .type =3D ARM_CP_IO, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 3, .opc2 =3D 1, + .access =3D PL2_RW, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYPVIRT= ].ctl), + .writefn =3D gt_hv_ctl_write, .raw_writefn =3D raw_write }, + { .name =3D "CNTP_CTL_EL02", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 5, .crn =3D 14, .crm =3D 2, .opc2 =3D 1, + .type =3D ARM_CP_IO | ARM_CP_ALIAS, + .access =3D PL2_RW, .accessfn =3D e2h_access, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].c= tl), + .writefn =3D gt_phys_ctl_write, .raw_writefn =3D raw_write }, + { .name =3D "CNTV_CTL_EL02", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 5, .crn =3D 14, .crm =3D 3, .opc2 =3D 1, + .type =3D ARM_CP_IO | ARM_CP_ALIAS, + .access =3D PL2_RW, .accessfn =3D e2h_access, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].c= tl), + .writefn =3D gt_virt_ctl_write, .raw_writefn =3D raw_write }, + { .name =3D "CNTP_TVAL_EL02", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 5, .crn =3D 14, .crm =3D 2, .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW | ARM_CP_IO | ARM_CP_ALIAS, + .access =3D PL2_RW, .accessfn =3D e2h_access, + .readfn =3D gt_phys_tval_read, .writefn =3D gt_phys_tval_write }, + { .name =3D "CNTV_TVAL_EL02", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 5, .crn =3D 14, .crm =3D 3, .opc2 =3D 0, + .type =3D ARM_CP_NO_RAW | ARM_CP_IO | ARM_CP_ALIAS, + .access =3D PL2_RW, .accessfn =3D e2h_access, + .readfn =3D gt_virt_tval_read, .writefn =3D gt_virt_tval_write }, + { .name =3D "CNTP_CVAL_EL02", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 5, .crn =3D 14, .crm =3D 2, .opc2 =3D 2, + .type =3D ARM_CP_IO | ARM_CP_ALIAS, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].c= val), + .access =3D PL2_RW, .accessfn =3D e2h_access, + .writefn =3D gt_phys_cval_write, .raw_writefn =3D raw_write }, + { .name =3D "CNTV_CVAL_EL02", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 5, .crn =3D 14, .crm =3D 3, .opc2 =3D 2, + .type =3D ARM_CP_IO | ARM_CP_ALIAS, + .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].c= val), + .access =3D PL2_RW, .accessfn =3D e2h_access, + .writefn =3D gt_virt_cval_write, .raw_writefn =3D raw_write }, +#endif +}; + +#ifndef CONFIG_USER_ONLY +static const ARMCPRegInfo ats1e1_reginfo[] =3D { + { .name =3D "AT_S1E1R", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 9, .opc2 =3D 0, + .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, + .writefn =3D ats_write64 }, + { .name =3D "AT_S1E1W", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 9, .opc2 =3D 1, + .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, + .writefn =3D ats_write64 }, +}; + +static const ARMCPRegInfo ats1cp_reginfo[] =3D { + { .name =3D "ATS1CPRP", + .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 9, .opc2 =3D 0, + .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, + .writefn =3D ats_write }, + { .name =3D "ATS1CPWP", + .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 9, .opc2 =3D 1, + .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, + .writefn =3D ats_write }, +}; +#endif + +/* + * ACTLR2 and HACTLR2 map to ACTLR_EL1[63:32] and + * ACTLR_EL2[63:32]. They exist only if the ID_MMFR4.AC2 field + * is non-zero, which is never for ARMv7, optionally in ARMv8 + * and mandatorily for ARMv8.2 and up. + * ACTLR2 is banked for S and NS if EL3 is AArch32. Since QEMU's + * implementation is RAZ/WI we can ignore this detail, as we + * do for ACTLR. + */ +static const ARMCPRegInfo actlr2_hactlr2_reginfo[] =3D { + { .name =3D "ACTLR2", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 0, .crn =3D 1, .crm =3D 0, .opc2 =3D 3, + .access =3D PL1_RW, .accessfn =3D access_tacr, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + { .name =3D "HACTLR2", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 4, .crn =3D 1, .crm =3D 0, .opc2 =3D 3, + .access =3D PL2_RW, .type =3D ARM_CP_CONST, + .resetvalue =3D 0 }, +}; + +void register_cp_regs_for_features(ARMCPU *cpu) +{ + /* Register all the coprocessor registers based on feature bits */ + CPUARMState *env =3D &cpu->env; + if (arm_feature(env, ARM_FEATURE_M)) { + /* M profile has no coprocessor registers */ + return; + } + + define_arm_cp_regs(cpu, cp_reginfo); + if (!arm_feature(env, ARM_FEATURE_V8)) { + /* + * Must go early as it is full of wildcards that may be + * overridden by later definitions. + */ + define_arm_cp_regs(cpu, not_v8_cp_reginfo); + } + + if (arm_feature(env, ARM_FEATURE_V6)) { + /* The ID registers all have impdef reset values */ + ARMCPRegInfo v6_idregs[] =3D { + { .name =3D "ID_PFR0", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 0, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa32_tid3, + .resetvalue =3D cpu->isar.id_pfr0 }, + /* + * ID_PFR1 is not a plain ARM_CP_CONST because we don't know + * the value of the GIC field until after we define these regs. + */ + { .name =3D "ID_PFR1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 1, + .access =3D PL1_R, .type =3D ARM_CP_NO_RAW, + .accessfn =3D access_aa32_tid3, + .readfn =3D id_pfr1_read, + .writefn =3D arm_cp_write_ignore }, + { .name =3D "ID_DFR0", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 2, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa32_tid3, + .resetvalue =3D cpu->isar.id_dfr0 }, + { .name =3D "ID_AFR0", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 3, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa32_tid3, + .resetvalue =3D cpu->id_afr0 }, + { .name =3D "ID_MMFR0", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 4, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa32_tid3, + .resetvalue =3D cpu->isar.id_mmfr0 }, + { .name =3D "ID_MMFR1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 5, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa32_tid3, + .resetvalue =3D cpu->isar.id_mmfr1 }, + { .name =3D "ID_MMFR2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 6, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa32_tid3, + .resetvalue =3D cpu->isar.id_mmfr2 }, + { .name =3D "ID_MMFR3", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 7, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa32_tid3, + .resetvalue =3D cpu->isar.id_mmfr3 }, + { .name =3D "ID_ISAR0", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 0, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa32_tid3, + .resetvalue =3D cpu->isar.id_isar0 }, + { .name =3D "ID_ISAR1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 1, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa32_tid3, + .resetvalue =3D cpu->isar.id_isar1 }, + { .name =3D "ID_ISAR2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 2, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa32_tid3, + .resetvalue =3D cpu->isar.id_isar2 }, + { .name =3D "ID_ISAR3", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 3, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa32_tid3, + .resetvalue =3D cpu->isar.id_isar3 }, + { .name =3D "ID_ISAR4", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 4, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa32_tid3, + .resetvalue =3D cpu->isar.id_isar4 }, + { .name =3D "ID_ISAR5", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 5, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa32_tid3, + .resetvalue =3D cpu->isar.id_isar5 }, + { .name =3D "ID_MMFR4", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 6, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa32_tid3, + .resetvalue =3D cpu->isar.id_mmfr4 }, + { .name =3D "ID_ISAR6", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 7, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa32_tid3, + .resetvalue =3D cpu->isar.id_isar6 }, + }; + define_arm_cp_regs(cpu, v6_idregs); + define_arm_cp_regs(cpu, v6_cp_reginfo); + } else { + define_arm_cp_regs(cpu, not_v6_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_V6K)) { + define_arm_cp_regs(cpu, v6k_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_V7MP) && + !arm_feature(env, ARM_FEATURE_PMSA)) { + define_arm_cp_regs(cpu, v7mp_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_V7VE)) { + define_arm_cp_regs(cpu, pmovsset_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_V7)) { + ARMCPRegInfo clidr =3D { + .name =3D "CLIDR", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .crn =3D 0, .crm =3D 0, .opc1 =3D 1, .opc2 =3D 1, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_tid4, + .resetvalue =3D cpu->clidr + }; + define_one_arm_cp_reg(cpu, &clidr); + define_arm_cp_regs(cpu, v7_cp_reginfo); + define_debug_regs(cpu); + define_pmu_regs(cpu); + } else { + define_arm_cp_regs(cpu, not_v7_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_V8)) { + /* + * v8 ID registers, which all have impdef reset values. + * Note that within the ID register ranges the unused slots + * must all RAZ, not UNDEF; future architecture versions may + * define new registers here. + * ID registers which are AArch64 views of the AArch32 ID registers + * which already existed in v6 and v7 are handled elsewhere, + * in v6_idregs[]. + */ + int i; + ARMCPRegInfo v8_idregs[] =3D { + /* + * ID_AA64PFR0_EL1 is not a plain ARM_CP_CONST in system + * emulation because we don't know the right value for the + * GIC field until after we define these regs. + */ + { .name =3D "ID_AA64PFR0_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 0, + .access =3D PL1_R, +#ifdef CONFIG_USER_ONLY + .type =3D ARM_CP_CONST, + .resetvalue =3D cpu->isar.id_aa64pfr0 +#else + .type =3D ARM_CP_NO_RAW, + .accessfn =3D access_aa64_tid3, + .readfn =3D id_aa64pfr0_read, + .writefn =3D arm_cp_write_ignore +#endif + }, + { .name =3D "ID_AA64PFR1_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 1, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.id_aa64pfr1}, + { .name =3D "ID_AA64PFR2_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 2, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64PFR3_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 3, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64ZFR0_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 4, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.id_aa64zfr0 }, + { .name =3D "ID_AA64SMFR0_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 5, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.id_aa64smfr0 }, + { .name =3D "ID_AA64PFR6_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 6, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64PFR7_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 7, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64DFR0_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 0, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.id_aa64dfr0 }, + { .name =3D "ID_AA64DFR1_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 1, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.id_aa64dfr1 }, + { .name =3D "ID_AA64DFR2_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 2, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64DFR3_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 3, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64AFR0_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 4, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->id_aa64afr0 }, + { .name =3D "ID_AA64AFR1_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 5, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->id_aa64afr1 }, + { .name =3D "ID_AA64AFR2_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 6, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64AFR3_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 7, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64ISAR0_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 0, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.id_aa64isar0 }, + { .name =3D "ID_AA64ISAR1_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 1, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.id_aa64isar1 }, + { .name =3D "ID_AA64ISAR2_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 2, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64ISAR3_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 3, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64ISAR4_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 4, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64ISAR5_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 5, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64ISAR6_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 6, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64ISAR7_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 7, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64MMFR0_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 0, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.id_aa64mmfr0 }, + { .name =3D "ID_AA64MMFR1_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 1, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.id_aa64mmfr1 }, + { .name =3D "ID_AA64MMFR2_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 2, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.id_aa64mmfr2 }, + { .name =3D "ID_AA64MMFR3_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 3, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64MMFR4_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 4, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64MMFR5_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 5, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64MMFR6_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 6, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_AA64MMFR7_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 7, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "MVFR0_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 0, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.mvfr0 }, + { .name =3D "MVFR1_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 1, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.mvfr1 }, + { .name =3D "MVFR2_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 2, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.mvfr2 }, + /* + * "0, c0, c3, {0,1,2}" are the encodings corresponding to + * AArch64 MVFR[012]_EL1. Define the STATE_AA32 encoding + * as RAZ, since it is in the "reserved for future ID + * registers, RAZ" part of the AArch32 encoding space. + */ + { .name =3D "RES_0_C0_C3_0", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D 0, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "RES_0_C0_C3_1", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D 1, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "RES_0_C0_C3_2", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D 2, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + /* + * Other encodings in "0, c0, c3, ..." are STATE_BOTH because + * they're also RAZ for AArch64, and in v8 are gradually + * being filled with AArch64-view-of-AArch32-ID-register + * for new ID registers. + */ + { .name =3D "RES_0_C0_C3_3", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 3, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "ID_PFR2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 4, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.id_pfr2 }, + { .name =3D "ID_DFR1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 5, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.id_dfr1 }, + { .name =3D "ID_MMFR5", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 6, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D cpu->isar.id_mmfr5 }, + { .name =3D "RES_0_C0_C3_7", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 7, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }, + { .name =3D "PMCEID0", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 12, .opc2 =3D = 6, + .access =3D PL0_R, .accessfn =3D pmreg_access, .type =3D ARM= _CP_CONST, + .resetvalue =3D extract64(cpu->pmceid0, 0, 32) }, + { .name =3D "PMCEID0_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D= 6, + .access =3D PL0_R, .accessfn =3D pmreg_access, .type =3D ARM= _CP_CONST, + .resetvalue =3D cpu->pmceid0 }, + { .name =3D "PMCEID1", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 12, .opc2 =3D = 7, + .access =3D PL0_R, .accessfn =3D pmreg_access, .type =3D ARM= _CP_CONST, + .resetvalue =3D extract64(cpu->pmceid1, 0, 32) }, + { .name =3D "PMCEID1_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D= 7, + .access =3D PL0_R, .accessfn =3D pmreg_access, .type =3D ARM= _CP_CONST, + .resetvalue =3D cpu->pmceid1 }, + }; +#ifdef CONFIG_USER_ONLY + static const ARMCPRegUserSpaceInfo v8_user_idregs[] =3D { + { .name =3D "ID_AA64PFR0_EL1", + .exported_bits =3D R_ID_AA64PFR0_FP_MASK | + R_ID_AA64PFR0_ADVSIMD_MASK | + R_ID_AA64PFR0_SVE_MASK | + R_ID_AA64PFR0_DIT_MASK, + .fixed_bits =3D (0x1u << R_ID_AA64PFR0_EL0_SHIFT) | + (0x1u << R_ID_AA64PFR0_EL1_SHIFT) }, + { .name =3D "ID_AA64PFR1_EL1", + .exported_bits =3D R_ID_AA64PFR1_BT_MASK | + R_ID_AA64PFR1_SSBS_MASK | + R_ID_AA64PFR1_MTE_MASK | + R_ID_AA64PFR1_SME_MASK }, + { .name =3D "ID_AA64PFR*_EL1_RESERVED", + .is_glob =3D true }, + { .name =3D "ID_AA64ZFR0_EL1", + .exported_bits =3D R_ID_AA64ZFR0_SVEVER_MASK | + R_ID_AA64ZFR0_AES_MASK | + R_ID_AA64ZFR0_BITPERM_MASK | + R_ID_AA64ZFR0_BFLOAT16_MASK | + R_ID_AA64ZFR0_SHA3_MASK | + R_ID_AA64ZFR0_SM4_MASK | + R_ID_AA64ZFR0_I8MM_MASK | + R_ID_AA64ZFR0_F32MM_MASK | + R_ID_AA64ZFR0_F64MM_MASK }, + { .name =3D "ID_AA64SMFR0_EL1", + .exported_bits =3D R_ID_AA64SMFR0_F32F32_MASK | + R_ID_AA64SMFR0_B16F32_MASK | + R_ID_AA64SMFR0_F16F32_MASK | + R_ID_AA64SMFR0_I8I32_MASK | + R_ID_AA64SMFR0_F64F64_MASK | + R_ID_AA64SMFR0_I16I64_MASK | + R_ID_AA64SMFR0_FA64_MASK }, + { .name =3D "ID_AA64MMFR0_EL1", + .exported_bits =3D R_ID_AA64MMFR0_ECV_MASK, + .fixed_bits =3D (0xfu << R_ID_AA64MMFR0_TGRAN64_SHIFT) | + (0xfu << R_ID_AA64MMFR0_TGRAN4_SHIFT) }, + { .name =3D "ID_AA64MMFR1_EL1", + .exported_bits =3D R_ID_AA64MMFR1_AFP_MASK }, + { .name =3D "ID_AA64MMFR2_EL1", + .exported_bits =3D R_ID_AA64MMFR2_AT_MASK }, + { .name =3D "ID_AA64MMFR*_EL1_RESERVED", + .is_glob =3D true }, + { .name =3D "ID_AA64DFR0_EL1", + .fixed_bits =3D (0x6u << R_ID_AA64DFR0_DEBUGVER_SHIFT) }, + { .name =3D "ID_AA64DFR1_EL1" }, + { .name =3D "ID_AA64DFR*_EL1_RESERVED", + .is_glob =3D true }, + { .name =3D "ID_AA64AFR*", + .is_glob =3D true }, + { .name =3D "ID_AA64ISAR0_EL1", + .exported_bits =3D R_ID_AA64ISAR0_AES_MASK | + R_ID_AA64ISAR0_SHA1_MASK | + R_ID_AA64ISAR0_SHA2_MASK | + R_ID_AA64ISAR0_CRC32_MASK | + R_ID_AA64ISAR0_ATOMIC_MASK | + R_ID_AA64ISAR0_RDM_MASK | + R_ID_AA64ISAR0_SHA3_MASK | + R_ID_AA64ISAR0_SM3_MASK | + R_ID_AA64ISAR0_SM4_MASK | + R_ID_AA64ISAR0_DP_MASK | + R_ID_AA64ISAR0_FHM_MASK | + R_ID_AA64ISAR0_TS_MASK | + R_ID_AA64ISAR0_RNDR_MASK }, + { .name =3D "ID_AA64ISAR1_EL1", + .exported_bits =3D R_ID_AA64ISAR1_DPB_MASK | + R_ID_AA64ISAR1_APA_MASK | + R_ID_AA64ISAR1_API_MASK | + R_ID_AA64ISAR1_JSCVT_MASK | + R_ID_AA64ISAR1_FCMA_MASK | + R_ID_AA64ISAR1_LRCPC_MASK | + R_ID_AA64ISAR1_GPA_MASK | + R_ID_AA64ISAR1_GPI_MASK | + R_ID_AA64ISAR1_FRINTTS_MASK | + R_ID_AA64ISAR1_SB_MASK | + R_ID_AA64ISAR1_BF16_MASK | + R_ID_AA64ISAR1_DGH_MASK | + R_ID_AA64ISAR1_I8MM_MASK }, + { .name =3D "ID_AA64ISAR2_EL1", + .exported_bits =3D R_ID_AA64ISAR2_WFXT_MASK | + R_ID_AA64ISAR2_RPRES_MASK | + R_ID_AA64ISAR2_GPA3_MASK | + R_ID_AA64ISAR2_APA3_MASK }, + { .name =3D "ID_AA64ISAR*_EL1_RESERVED", + .is_glob =3D true }, + }; + modify_arm_cp_regs(v8_idregs, v8_user_idregs); +#endif + /* RVBAR_EL1 is only implemented if EL1 is the highest EL */ + if (!arm_feature(env, ARM_FEATURE_EL3) && + !arm_feature(env, ARM_FEATURE_EL2)) { + ARMCPRegInfo rvbar =3D { + .name =3D "RVBAR_EL1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 12, .crm =3D 0, .opc2 = =3D 1, + .access =3D PL1_R, + .fieldoffset =3D offsetof(CPUARMState, cp15.rvbar), + }; + define_one_arm_cp_reg(cpu, &rvbar); + } + define_arm_cp_regs(cpu, v8_idregs); + define_arm_cp_regs(cpu, v8_cp_reginfo); + + for (i =3D 4; i < 16; i++) { + /* + * Encodings in "0, c0, {c4-c7}, {0-7}" are RAZ for AArch32. + * For pre-v8 cores there are RAZ patterns for these in + * id_pre_v8_midr_cp_reginfo[]; for v8 we do that here. + * v8 extends the "must RAZ" part of the ID register space + * to also cover c0, 0, c{8-15}, {0-7}. + * These are STATE_AA32 because in the AArch64 sysreg space + * c4-c7 is where the AArch64 ID registers live (and we've + * already defined those in v8_idregs[]), and c8-c15 are not + * "must RAZ" for AArch64. + */ + g_autofree char *name =3D g_strdup_printf("RES_0_C0_C%d_X", i); + ARMCPRegInfo v8_aa32_raz_idregs =3D { + .name =3D name, + .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 0, .crn =3D 0, .crm =3D i, .opc2 =3D= CP_ANY, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .accessfn =3D access_aa64_tid3, + .resetvalue =3D 0 }; + define_one_arm_cp_reg(cpu, &v8_aa32_raz_idregs); + } + } + + /* + * Register the base EL2 cpregs. + * Pre v8, these registers are implemented only as part of the + * Virtualization Extensions (EL2 present). Beginning with v8, + * if EL2 is missing but EL3 is enabled, mostly these become + * RES0 from EL3, with some specific exceptions. + */ + if (arm_feature(env, ARM_FEATURE_EL2) + || (arm_feature(env, ARM_FEATURE_EL3) + && arm_feature(env, ARM_FEATURE_V8))) { + uint64_t vmpidr_def =3D mpidr_read_val(env); + ARMCPRegInfo vpidr_regs[] =3D { + { .name =3D "VPIDR", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 4, .crn =3D 0, .crm =3D 0, .opc2 =3D 0, + .access =3D PL2_RW, .accessfn =3D access_el3_aa32ns, + .resetvalue =3D cpu->midr, + .type =3D ARM_CP_ALIAS | ARM_CP_EL3_NO_EL2_C_NZ, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.vpidr_el2) = }, + { .name =3D "VPIDR_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 0, .crm =3D 0, .opc2 =3D = 0, + .access =3D PL2_RW, .resetvalue =3D cpu->midr, + .type =3D ARM_CP_EL3_NO_EL2_C_NZ, + .fieldoffset =3D offsetof(CPUARMState, cp15.vpidr_el2) }, + { .name =3D "VMPIDR", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 4, .crn =3D 0, .crm =3D 0, .opc2 =3D 5, + .access =3D PL2_RW, .accessfn =3D access_el3_aa32ns, + .resetvalue =3D vmpidr_def, + .type =3D ARM_CP_ALIAS | ARM_CP_EL3_NO_EL2_C_NZ, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.vmpidr_el2)= }, + { .name =3D "VMPIDR_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 0, .crm =3D 0, .opc2 =3D = 5, + .access =3D PL2_RW, .resetvalue =3D vmpidr_def, + .type =3D ARM_CP_EL3_NO_EL2_C_NZ, + .fieldoffset =3D offsetof(CPUARMState, cp15.vmpidr_el2) }, + }; + /* + * The only field of MDCR_EL2 that has a defined architectural res= et + * value is MDCR_EL2.HPMN which should reset to the value of PMCR_= EL0.N. + */ + ARMCPRegInfo mdcr_el2 =3D { + .name =3D "MDCR_EL2", .state =3D ARM_CP_STATE_BOTH, .type =3D = ARM_CP_IO, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 1, .opc2 =3D 1, + .writefn =3D mdcr_el2_write, + .access =3D PL2_RW, .resetvalue =3D pmu_num_counters(env), + .fieldoffset =3D offsetof(CPUARMState, cp15.mdcr_el2), + }; + define_one_arm_cp_reg(cpu, &mdcr_el2); + define_arm_cp_regs(cpu, vpidr_regs); + define_arm_cp_regs(cpu, el2_cp_reginfo); + if (arm_feature(env, ARM_FEATURE_V8)) { + define_arm_cp_regs(cpu, el2_v8_cp_reginfo); + } + if (cpu_isar_feature(aa64_sel2, cpu)) { + define_arm_cp_regs(cpu, el2_sec_cp_reginfo); + } + /* RVBAR_EL2 is only implemented if EL2 is the highest EL */ + if (!arm_feature(env, ARM_FEATURE_EL3)) { + ARMCPRegInfo rvbar[] =3D { + { + .name =3D "RVBAR_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 12, .crm =3D 0, .op= c2 =3D 1, + .access =3D PL2_R, + .fieldoffset =3D offsetof(CPUARMState, cp15.rvbar), + }, + { .name =3D "RVBAR", .type =3D ARM_CP_ALIAS, + .cp =3D 15, .opc1 =3D 0, .crn =3D 12, .crm =3D 0, .opc= 2 =3D 1, + .access =3D PL2_R, + .fieldoffset =3D offsetof(CPUARMState, cp15.rvbar), + }, + }; + define_arm_cp_regs(cpu, rvbar); + } + } + + /* Register the base EL3 cpregs. */ + if (arm_feature(env, ARM_FEATURE_EL3)) { + define_arm_cp_regs(cpu, el3_cp_reginfo); + ARMCPRegInfo el3_regs[] =3D { + { .name =3D "RVBAR_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 12, .crm =3D 0, .opc2 =3D= 1, + .access =3D PL3_R, + .fieldoffset =3D offsetof(CPUARMState, cp15.rvbar), + }, + { .name =3D "SCTLR_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 0, .opc2 =3D = 0, + .access =3D PL3_RW, + .raw_writefn =3D raw_write, .writefn =3D sctlr_write, + .fieldoffset =3D offsetof(CPUARMState, cp15.sctlr_el[3]), + .resetvalue =3D cpu->reset_sctlr }, + }; + + define_arm_cp_regs(cpu, el3_regs); + } + /* + * The behaviour of NSACR is sufficiently various that we don't + * try to describe it in a single reginfo: + * if EL3 is 64 bit, then trap to EL3 from S EL1, + * reads as constant 0xc00 from NS EL1 and NS EL2 + * if EL3 is 32 bit, then RW at EL3, RO at NS EL1 and NS EL2 + * if v7 without EL3, register doesn't exist + * if v8 without EL3, reads as constant 0xc00 from NS EL1 and NS EL2 + */ + if (arm_feature(env, ARM_FEATURE_EL3)) { + if (arm_feature(env, ARM_FEATURE_AARCH64)) { + static const ARMCPRegInfo nsacr =3D { + .name =3D "NSACR", .type =3D ARM_CP_CONST, + .cp =3D 15, .opc1 =3D 0, .crn =3D 1, .crm =3D 1, .opc2 =3D= 2, + .access =3D PL1_RW, .accessfn =3D nsacr_access, + .resetvalue =3D 0xc00 + }; + define_one_arm_cp_reg(cpu, &nsacr); + } else { + static const ARMCPRegInfo nsacr =3D { + .name =3D "NSACR", + .cp =3D 15, .opc1 =3D 0, .crn =3D 1, .crm =3D 1, .opc2 =3D= 2, + .access =3D PL3_RW | PL1_R, + .resetvalue =3D 0, + .fieldoffset =3D offsetof(CPUARMState, cp15.nsacr) + }; + define_one_arm_cp_reg(cpu, &nsacr); + } + } else { + if (arm_feature(env, ARM_FEATURE_V8)) { + static const ARMCPRegInfo nsacr =3D { + .name =3D "NSACR", .type =3D ARM_CP_CONST, + .cp =3D 15, .opc1 =3D 0, .crn =3D 1, .crm =3D 1, .opc2 =3D= 2, + .access =3D PL1_R, + .resetvalue =3D 0xc00 + }; + define_one_arm_cp_reg(cpu, &nsacr); + } + } + + if (arm_feature(env, ARM_FEATURE_PMSA)) { + if (arm_feature(env, ARM_FEATURE_V6)) { + /* PMSAv6 not implemented */ + assert(arm_feature(env, ARM_FEATURE_V7)); + define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo); + define_arm_cp_regs(cpu, pmsav7_cp_reginfo); + } else { + define_arm_cp_regs(cpu, pmsav5_cp_reginfo); + } + } else { + define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo); + define_arm_cp_regs(cpu, vmsa_cp_reginfo); + /* TTCBR2 is introduced with ARMv8.2-AA32HPD. */ + if (cpu_isar_feature(aa32_hpd, cpu)) { + define_one_arm_cp_reg(cpu, &ttbcr2_reginfo); + } + } + if (arm_feature(env, ARM_FEATURE_THUMB2EE)) { + define_arm_cp_regs(cpu, t2ee_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) { + define_arm_cp_regs(cpu, generic_timer_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_VAPA)) { + define_arm_cp_regs(cpu, vapa_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_CACHE_TEST_CLEAN)) { + define_arm_cp_regs(cpu, cache_test_clean_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_CACHE_DIRTY_REG)) { + define_arm_cp_regs(cpu, cache_dirty_status_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_CACHE_BLOCK_OPS)) { + define_arm_cp_regs(cpu, cache_block_ops_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_OMAPCP)) { + define_arm_cp_regs(cpu, omap_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_STRONGARM)) { + define_arm_cp_regs(cpu, strongarm_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_XSCALE)) { + define_arm_cp_regs(cpu, xscale_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_DUMMY_C15_REGS)) { + define_arm_cp_regs(cpu, dummy_c15_cp_reginfo); + } + if (arm_feature(env, ARM_FEATURE_LPAE)) { + define_arm_cp_regs(cpu, lpae_cp_reginfo); + } + if (cpu_isar_feature(aa32_jazelle, cpu)) { + define_arm_cp_regs(cpu, jazelle_regs); + } + /* + * Slightly awkwardly, the OMAP and StrongARM cores need all of + * cp15 crn=3D0 to be writes-ignored, whereas for other cores they sho= uld + * be read-only (ie write causes UNDEF exception). + */ + { + ARMCPRegInfo id_pre_v8_midr_cp_reginfo[] =3D { + /* + * Pre-v8 MIDR space. + * Note that the MIDR isn't a simple constant register because + * of the TI925 behaviour where writes to another register can + * cause the MIDR value to change. + * + * Unimplemented registers in the c15 0 0 0 space default to + * MIDR. Define MIDR first as this entire space, then CTR, TCM= TR + * and friends override accordingly. + */ + { .name =3D "MIDR", + .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D C= P_ANY, + .access =3D PL1_R, .resetvalue =3D cpu->midr, + .writefn =3D arm_cp_write_ignore, .raw_writefn =3D raw_write, + .readfn =3D midr_read, + .fieldoffset =3D offsetof(CPUARMState, cp15.c0_cpuid), + .type =3D ARM_CP_OVERRIDE }, + /* crn =3D 0 op1 =3D 0 crm =3D 3..7 : currently unassigned; we= RAZ. */ + { .name =3D "DUMMY", + .cp =3D 15, .crn =3D 0, .crm =3D 3, .opc1 =3D 0, .opc2 =3D C= P_ANY, + .access =3D PL1_R, .type =3D ARM_CP_CONST, .resetvalue =3D 0= }, + { .name =3D "DUMMY", + .cp =3D 15, .crn =3D 0, .crm =3D 4, .opc1 =3D 0, .opc2 =3D C= P_ANY, + .access =3D PL1_R, .type =3D ARM_CP_CONST, .resetvalue =3D 0= }, + { .name =3D "DUMMY", + .cp =3D 15, .crn =3D 0, .crm =3D 5, .opc1 =3D 0, .opc2 =3D C= P_ANY, + .access =3D PL1_R, .type =3D ARM_CP_CONST, .resetvalue =3D 0= }, + { .name =3D "DUMMY", + .cp =3D 15, .crn =3D 0, .crm =3D 6, .opc1 =3D 0, .opc2 =3D C= P_ANY, + .access =3D PL1_R, .type =3D ARM_CP_CONST, .resetvalue =3D 0= }, + { .name =3D "DUMMY", + .cp =3D 15, .crn =3D 0, .crm =3D 7, .opc1 =3D 0, .opc2 =3D C= P_ANY, + .access =3D PL1_R, .type =3D ARM_CP_CONST, .resetvalue =3D 0= }, + }; + ARMCPRegInfo id_v8_midr_cp_reginfo[] =3D { + { .name =3D "MIDR_EL1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 0, .opc2 =3D = 0, + .access =3D PL1_R, .type =3D ARM_CP_NO_RAW, .resetvalue =3D = cpu->midr, + .fieldoffset =3D offsetof(CPUARMState, cp15.c0_cpuid), + .readfn =3D midr_read }, + /* crn =3D 0 op1 =3D 0 crm =3D 0 op2 =3D 7 : AArch32 aliases o= f MIDR */ + { .name =3D "MIDR", .type =3D ARM_CP_ALIAS | ARM_CP_CONST, + .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 7, + .access =3D PL1_R, .resetvalue =3D cpu->midr }, + { .name =3D "REVIDR_EL1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 0, .opc2 =3D = 6, + .access =3D PL1_R, + .accessfn =3D access_aa64_tid1, + .type =3D ARM_CP_CONST, .resetvalue =3D cpu->revidr }, + }; + ARMCPRegInfo id_v8_midr_alias_cp_reginfo =3D { + .name =3D "MIDR", .type =3D ARM_CP_ALIAS | ARM_CP_CONST, + .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 4, + .access =3D PL1_R, .resetvalue =3D cpu->midr + }; + ARMCPRegInfo id_cp_reginfo[] =3D { + /* These are common to v8 and pre-v8 */ + { .name =3D "CTR", + .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 1, + .access =3D PL1_R, .accessfn =3D ctr_el0_access, + .type =3D ARM_CP_CONST, .resetvalue =3D cpu->ctr }, + { .name =3D "CTR_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 1, .crn =3D 0, .crm =3D = 0, + .access =3D PL0_R, .accessfn =3D ctr_el0_access, + .type =3D ARM_CP_CONST, .resetvalue =3D cpu->ctr }, + /* TCMTR and TLBTR exist in v8 but have no 64-bit versions */ + { .name =3D "TCMTR", + .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 2, + .access =3D PL1_R, + .accessfn =3D access_aa32_tid1, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + }; + /* TLBTR is specific to VMSA */ + ARMCPRegInfo id_tlbtr_reginfo =3D { + .name =3D "TLBTR", + .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 3, + .access =3D PL1_R, + .accessfn =3D access_aa32_tid1, + .type =3D ARM_CP_CONST, .resetvalue =3D 0, + }; + /* MPUIR is specific to PMSA V6+ */ + ARMCPRegInfo id_mpuir_reginfo =3D { + .name =3D "MPUIR", + .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 4, + .access =3D PL1_R, .type =3D ARM_CP_CONST, + .resetvalue =3D cpu->pmsav7_dregion << 8 + }; + /* HMPUIR is specific to PMSA V8 */ + ARMCPRegInfo id_hmpuir_reginfo =3D { + .name =3D "HMPUIR", + .cp =3D 15, .opc1 =3D 4, .crn =3D 0, .crm =3D 0, .opc2 =3D 4, + .access =3D PL2_R, .type =3D ARM_CP_CONST, + .resetvalue =3D cpu->pmsav8r_hdregion + }; + static const ARMCPRegInfo crn0_wi_reginfo =3D { + .name =3D "CRN0_WI", .cp =3D 15, .crn =3D 0, .crm =3D CP_ANY, + .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, .access =3D PL1_W, + .type =3D ARM_CP_NOP | ARM_CP_OVERRIDE + }; +#ifdef CONFIG_USER_ONLY + static const ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = =3D { + { .name =3D "MIDR_EL1", + .exported_bits =3D R_MIDR_EL1_REVISION_MASK | + R_MIDR_EL1_PARTNUM_MASK | + R_MIDR_EL1_ARCHITECTURE_MASK | + R_MIDR_EL1_VARIANT_MASK | + R_MIDR_EL1_IMPLEMENTER_MASK }, + { .name =3D "REVIDR_EL1" }, + }; + modify_arm_cp_regs(id_v8_midr_cp_reginfo, id_v8_user_midr_cp_regin= fo); +#endif + if (arm_feature(env, ARM_FEATURE_OMAPCP) || + arm_feature(env, ARM_FEATURE_STRONGARM)) { + size_t i; + /* + * Register the blanket "writes ignored" value first to cover = the + * whole space. Then update the specific ID registers to allow= write + * access, so that they ignore writes rather than causing them= to + * UNDEF. + */ + define_one_arm_cp_reg(cpu, &crn0_wi_reginfo); + for (i =3D 0; i < ARRAY_SIZE(id_pre_v8_midr_cp_reginfo); ++i) { + id_pre_v8_midr_cp_reginfo[i].access =3D PL1_RW; + } + for (i =3D 0; i < ARRAY_SIZE(id_cp_reginfo); ++i) { + id_cp_reginfo[i].access =3D PL1_RW; + } + id_mpuir_reginfo.access =3D PL1_RW; + id_tlbtr_reginfo.access =3D PL1_RW; + } + if (arm_feature(env, ARM_FEATURE_V8)) { + define_arm_cp_regs(cpu, id_v8_midr_cp_reginfo); + if (!arm_feature(env, ARM_FEATURE_PMSA)) { + define_one_arm_cp_reg(cpu, &id_v8_midr_alias_cp_reginfo); + } + } else { + define_arm_cp_regs(cpu, id_pre_v8_midr_cp_reginfo); + } + define_arm_cp_regs(cpu, id_cp_reginfo); + if (!arm_feature(env, ARM_FEATURE_PMSA)) { + define_one_arm_cp_reg(cpu, &id_tlbtr_reginfo); + } else if (arm_feature(env, ARM_FEATURE_PMSA) && + arm_feature(env, ARM_FEATURE_V8)) { + uint32_t i =3D 0; + char *tmp_string; + + define_one_arm_cp_reg(cpu, &id_mpuir_reginfo); + define_one_arm_cp_reg(cpu, &id_hmpuir_reginfo); + define_arm_cp_regs(cpu, pmsav8r_cp_reginfo); + + /* Register alias is only valid for first 32 indexes */ + for (i =3D 0; i < MIN(cpu->pmsav7_dregion, 32); ++i) { + uint8_t crm =3D 0b1000 | extract32(i, 1, 3); + uint8_t opc1 =3D extract32(i, 4, 1); + uint8_t opc2 =3D extract32(i, 0, 1) << 2; + + tmp_string =3D g_strdup_printf("PRBAR%u", i); + ARMCPRegInfo tmp_prbarn_reginfo =3D { + .name =3D tmp_string, .type =3D ARM_CP_ALIAS | ARM_CP_= NO_RAW, + .cp =3D 15, .opc1 =3D opc1, .crn =3D 6, .crm =3D crm, = .opc2 =3D opc2, + .access =3D PL1_RW, .resetvalue =3D 0, + .accessfn =3D access_tvm_trvm, + .writefn =3D pmsav8r_regn_write, .readfn =3D pmsav8r_r= egn_read + }; + define_one_arm_cp_reg(cpu, &tmp_prbarn_reginfo); + g_free(tmp_string); + + opc2 =3D extract32(i, 0, 1) << 2 | 0x1; + tmp_string =3D g_strdup_printf("PRLAR%u", i); + ARMCPRegInfo tmp_prlarn_reginfo =3D { + .name =3D tmp_string, .type =3D ARM_CP_ALIAS | ARM_CP_= NO_RAW, + .cp =3D 15, .opc1 =3D opc1, .crn =3D 6, .crm =3D crm, = .opc2 =3D opc2, + .access =3D PL1_RW, .resetvalue =3D 0, + .accessfn =3D access_tvm_trvm, + .writefn =3D pmsav8r_regn_write, .readfn =3D pmsav8r_r= egn_read + }; + define_one_arm_cp_reg(cpu, &tmp_prlarn_reginfo); + g_free(tmp_string); + } + + /* Register alias is only valid for first 32 indexes */ + for (i =3D 0; i < MIN(cpu->pmsav8r_hdregion, 32); ++i) { + uint8_t crm =3D 0b1000 | extract32(i, 1, 3); + uint8_t opc1 =3D 0b100 | extract32(i, 4, 1); + uint8_t opc2 =3D extract32(i, 0, 1) << 2; + + tmp_string =3D g_strdup_printf("HPRBAR%u", i); + ARMCPRegInfo tmp_hprbarn_reginfo =3D { + .name =3D tmp_string, + .type =3D ARM_CP_NO_RAW, + .cp =3D 15, .opc1 =3D opc1, .crn =3D 6, .crm =3D crm, = .opc2 =3D opc2, + .access =3D PL2_RW, .resetvalue =3D 0, + .writefn =3D pmsav8r_regn_write, .readfn =3D pmsav8r_r= egn_read + }; + define_one_arm_cp_reg(cpu, &tmp_hprbarn_reginfo); + g_free(tmp_string); + + opc2 =3D extract32(i, 0, 1) << 2 | 0x1; + tmp_string =3D g_strdup_printf("HPRLAR%u", i); + ARMCPRegInfo tmp_hprlarn_reginfo =3D { + .name =3D tmp_string, + .type =3D ARM_CP_NO_RAW, + .cp =3D 15, .opc1 =3D opc1, .crn =3D 6, .crm =3D crm, = .opc2 =3D opc2, + .access =3D PL2_RW, .resetvalue =3D 0, + .writefn =3D pmsav8r_regn_write, .readfn =3D pmsav8r_r= egn_read + }; + define_one_arm_cp_reg(cpu, &tmp_hprlarn_reginfo); + g_free(tmp_string); + } + } else if (arm_feature(env, ARM_FEATURE_V7)) { + define_one_arm_cp_reg(cpu, &id_mpuir_reginfo); + } + } + + if (arm_feature(env, ARM_FEATURE_MPIDR)) { + ARMCPRegInfo mpidr_cp_reginfo[] =3D { + { .name =3D "MPIDR_EL1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D = 5, + .access =3D PL1_R, .readfn =3D mpidr_read, .type =3D ARM_CP_= NO_RAW }, + }; +#ifdef CONFIG_USER_ONLY + static const ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] =3D { + { .name =3D "MPIDR_EL1", + .fixed_bits =3D 0x0000000080000000 }, + }; + modify_arm_cp_regs(mpidr_cp_reginfo, mpidr_user_cp_reginfo); +#endif + define_arm_cp_regs(cpu, mpidr_cp_reginfo); + } + + if (arm_feature(env, ARM_FEATURE_AUXCR)) { + ARMCPRegInfo auxcr_reginfo[] =3D { + { .name =3D "ACTLR_EL1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 1, .crm =3D 0, .opc2 =3D = 1, + .access =3D PL1_RW, .accessfn =3D access_tacr, + .type =3D ARM_CP_CONST, .resetvalue =3D cpu->reset_auxcr }, + { .name =3D "ACTLR_EL2", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 0, .opc2 =3D = 1, + .access =3D PL2_RW, .type =3D ARM_CP_CONST, + .resetvalue =3D 0 }, + { .name =3D "ACTLR_EL3", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 0, .opc2 =3D = 1, + .access =3D PL3_RW, .type =3D ARM_CP_CONST, + .resetvalue =3D 0 }, + }; + define_arm_cp_regs(cpu, auxcr_reginfo); + if (cpu_isar_feature(aa32_ac2, cpu)) { + define_arm_cp_regs(cpu, actlr2_hactlr2_reginfo); + } + } + + if (arm_feature(env, ARM_FEATURE_CBAR)) { + /* + * CBAR is IMPDEF, but common on Arm Cortex-A implementations. + * There are two flavours: + * (1) older 32-bit only cores have a simple 32-bit CBAR + * (2) 64-bit cores have a 64-bit CBAR visible to AArch64, plus a + * 32-bit register visible to AArch32 at a different encoding + * to the "flavour 1" register and with the bits rearranged to + * be able to squash a 64-bit address into the 32-bit view. + * We distinguish the two via the ARM_FEATURE_AARCH64 flag, but + * in future if we support AArch32-only configs of some of the + * AArch64 cores we might need to add a specific feature flag + * to indicate cores with "flavour 2" CBAR. + */ + if (arm_feature(env, ARM_FEATURE_AARCH64)) { + /* 32 bit view is [31:18] 0...0 [43:32]. */ + uint32_t cbar32 =3D (extract64(cpu->reset_cbar, 18, 14) << 18) + | extract64(cpu->reset_cbar, 32, 12); + ARMCPRegInfo cbar_reginfo[] =3D { + { .name =3D "CBAR", + .type =3D ARM_CP_CONST, + .cp =3D 15, .crn =3D 15, .crm =3D 3, .opc1 =3D 1, .opc2 = =3D 0, + .access =3D PL1_R, .resetvalue =3D cbar32 }, + { .name =3D "CBAR_EL1", .state =3D ARM_CP_STATE_AA64, + .type =3D ARM_CP_CONST, + .opc0 =3D 3, .opc1 =3D 1, .crn =3D 15, .crm =3D 3, .opc2= =3D 0, + .access =3D PL1_R, .resetvalue =3D cpu->reset_cbar }, + }; + /* We don't implement a r/w 64 bit CBAR currently */ + assert(arm_feature(env, ARM_FEATURE_CBAR_RO)); + define_arm_cp_regs(cpu, cbar_reginfo); + } else { + ARMCPRegInfo cbar =3D { + .name =3D "CBAR", + .cp =3D 15, .crn =3D 15, .crm =3D 0, .opc1 =3D 4, .opc2 = =3D 0, + .access =3D PL1_R | PL3_W, .resetvalue =3D cpu->reset_cbar, + .fieldoffset =3D offsetof(CPUARMState, + cp15.c15_config_base_address) + }; + if (arm_feature(env, ARM_FEATURE_CBAR_RO)) { + cbar.access =3D PL1_R; + cbar.fieldoffset =3D 0; + cbar.type =3D ARM_CP_CONST; + } + define_one_arm_cp_reg(cpu, &cbar); + } + } + + if (arm_feature(env, ARM_FEATURE_VBAR)) { + static const ARMCPRegInfo vbar_cp_reginfo[] =3D { + { .name =3D "VBAR", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .crn =3D 12, .crm =3D 0, .opc1 =3D 0, .opc2 =3D= 0, + .access =3D PL1_RW, .writefn =3D vbar_write, + .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.vbar_s), + offsetof(CPUARMState, cp15.vbar_ns) }, + .resetvalue =3D 0 }, + }; + define_arm_cp_regs(cpu, vbar_cp_reginfo); + } + + /* Generic registers whose values depend on the implementation */ + { + ARMCPRegInfo sctlr =3D { + .name =3D "SCTLR", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 1, .crm =3D 0, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, + .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.sctlr_s), + offsetof(CPUARMState, cp15.sctlr_ns) }, + .writefn =3D sctlr_write, .resetvalue =3D cpu->reset_sctlr, + .raw_writefn =3D raw_write, + }; + if (arm_feature(env, ARM_FEATURE_XSCALE)) { + /* + * Normally we would always end the TB on an SCTLR write, but = Linux + * arch/arm/mach-pxa/sleep.S expects two instructions following + * an MMU enable to execute from cache. Imitate this behaviou= r. + */ + sctlr.type |=3D ARM_CP_SUPPRESS_TB_END; + } + define_one_arm_cp_reg(cpu, &sctlr); + + if (arm_feature(env, ARM_FEATURE_PMSA) && + arm_feature(env, ARM_FEATURE_V8)) { + ARMCPRegInfo vsctlr =3D { + .name =3D "VSCTLR", .state =3D ARM_CP_STATE_AA32, + .cp =3D 15, .opc1 =3D 4, .crn =3D 2, .crm =3D 0, .opc2 =3D= 0, + .access =3D PL2_RW, .resetvalue =3D 0x0, + .fieldoffset =3D offsetoflow32(CPUARMState, cp15.vsctlr), + }; + define_one_arm_cp_reg(cpu, &vsctlr); + } + } + + if (cpu_isar_feature(aa64_lor, cpu)) { + define_arm_cp_regs(cpu, lor_reginfo); + } + if (cpu_isar_feature(aa64_pan, cpu)) { + define_one_arm_cp_reg(cpu, &pan_reginfo); + } +#ifndef CONFIG_USER_ONLY + if (cpu_isar_feature(aa64_ats1e1, cpu)) { + define_arm_cp_regs(cpu, ats1e1_reginfo); + } + if (cpu_isar_feature(aa32_ats1e1, cpu)) { + define_arm_cp_regs(cpu, ats1cp_reginfo); + } +#endif + if (cpu_isar_feature(aa64_uao, cpu)) { + define_one_arm_cp_reg(cpu, &uao_reginfo); + } + + if (cpu_isar_feature(aa64_dit, cpu)) { + define_one_arm_cp_reg(cpu, &dit_reginfo); + } + if (cpu_isar_feature(aa64_ssbs, cpu)) { + define_one_arm_cp_reg(cpu, &ssbs_reginfo); + } + if (cpu_isar_feature(any_ras, cpu)) { + define_arm_cp_regs(cpu, minimal_ras_reginfo); + } + + if (cpu_isar_feature(aa64_vh, cpu) || + cpu_isar_feature(aa64_debugv8p2, cpu)) { + define_one_arm_cp_reg(cpu, &contextidr_el2); + } + if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu= )) { + define_arm_cp_regs(cpu, vhe_reginfo); + } + + if (cpu_isar_feature(aa64_sve, cpu)) { + define_arm_cp_regs(cpu, zcr_reginfo); + } + + if (cpu_isar_feature(aa64_hcx, cpu)) { + define_one_arm_cp_reg(cpu, &hcrx_el2_reginfo); + } + +#ifdef TARGET_AARCH64 + if (cpu_isar_feature(aa64_sme, cpu)) { + define_arm_cp_regs(cpu, sme_reginfo); + } + if (cpu_isar_feature(aa64_pauth, cpu)) { + define_arm_cp_regs(cpu, pauth_reginfo); + } + if (cpu_isar_feature(aa64_rndr, cpu)) { + define_arm_cp_regs(cpu, rndr_reginfo); + } + if (cpu_isar_feature(aa64_tlbirange, cpu)) { + define_arm_cp_regs(cpu, tlbirange_reginfo); + } + if (cpu_isar_feature(aa64_tlbios, cpu)) { + define_arm_cp_regs(cpu, tlbios_reginfo); + } +#ifndef CONFIG_USER_ONLY + /* Data Cache clean instructions up to PoP */ + if (cpu_isar_feature(aa64_dcpop, cpu)) { + define_one_arm_cp_reg(cpu, dcpop_reg); + + if (cpu_isar_feature(aa64_dcpodp, cpu)) { + define_one_arm_cp_reg(cpu, dcpodp_reg); + } + } +#endif /*CONFIG_USER_ONLY*/ + + /* + * If full MTE is enabled, add all of the system registers. + * If only "instructions available at EL0" are enabled, + * then define only a RAZ/WI version of PSTATE.TCO. + */ + if (cpu_isar_feature(aa64_mte, cpu)) { + define_arm_cp_regs(cpu, mte_reginfo); + define_arm_cp_regs(cpu, mte_el0_cacheop_reginfo); + } else if (cpu_isar_feature(aa64_mte_insn_reg, cpu)) { + define_arm_cp_regs(cpu, mte_tco_ro_reginfo); + define_arm_cp_regs(cpu, mte_el0_cacheop_reginfo); + } + + if (cpu_isar_feature(aa64_scxtnum, cpu)) { + define_arm_cp_regs(cpu, scxtnum_reginfo); + } +#endif + + if (cpu_isar_feature(any_predinv, cpu)) { + define_arm_cp_regs(cpu, predinv_reginfo); + } + + if (cpu_isar_feature(any_ccidx, cpu)) { + define_arm_cp_regs(cpu, ccsidr2_reginfo); + } + +#ifndef CONFIG_USER_ONLY + /* + * Register redirections and aliases must be done last, + * after the registers from the other extensions have been defined. + */ + if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu= )) { + define_arm_vh_e2h_redirects_aliases(cpu); + } +#endif +} + +/* + * Private utility function for define_one_arm_cp_reg_with_opaque(): + * add a single reginfo struct to the hash table. + */ +static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r, + void *opaque, CPState state, + CPSecureState secstate, + int crm, int opc1, int opc2, + const char *name) +{ + CPUARMState *env =3D &cpu->env; + uint32_t key; + ARMCPRegInfo *r2; + bool is64 =3D r->type & ARM_CP_64BIT; + bool ns =3D secstate & ARM_CP_SECSTATE_NS; + int cp =3D r->cp; + size_t name_len; + bool make_const; + + switch (state) { + case ARM_CP_STATE_AA32: + /* We assume it is a cp15 register if the .cp field is left unset.= */ + if (cp =3D=3D 0 && r->state =3D=3D ARM_CP_STATE_BOTH) { + cp =3D 15; + } + key =3D ENCODE_CP_REG(cp, is64, ns, r->crn, crm, opc1, opc2); + break; + case ARM_CP_STATE_AA64: + /* + * To allow abbreviation of ARMCPRegInfo definitions, we treat + * cp =3D=3D 0 as equivalent to the value for "standard guest-visi= ble + * sysreg". STATE_BOTH definitions are also always "standard sysr= eg" + * in their AArch64 view (the .cp value may be non-zero for the + * benefit of the AArch32 view). + */ + if (cp =3D=3D 0 || r->state =3D=3D ARM_CP_STATE_BOTH) { + cp =3D CP_REG_ARM64_SYSREG_CP; + } + key =3D ENCODE_AA64_CP_REG(cp, r->crn, crm, r->opc0, opc1, opc2); + break; + default: + g_assert_not_reached(); + } + + /* Overriding of an existing definition must be explicitly requested. = */ + if (!(r->type & ARM_CP_OVERRIDE)) { + const ARMCPRegInfo *oldreg =3D get_arm_cp_reginfo(cpu->cp_regs, ke= y); + if (oldreg) { + assert(oldreg->type & ARM_CP_OVERRIDE); + } + } + + /* + * Eliminate registers that are not present because the EL is missing. + * Doing this here makes it easier to put all registers for a given + * feature into the same ARMCPRegInfo array and define them all at onc= e. + */ + make_const =3D false; + if (arm_feature(env, ARM_FEATURE_EL3)) { + /* + * An EL2 register without EL2 but with EL3 is (usually) RES0. + * See rule RJFFP in section D1.1.3 of DDI0487H.a. + */ + int min_el =3D ctz32(r->access) / 2; + if (min_el =3D=3D 2 && !arm_feature(env, ARM_FEATURE_EL2)) { + if (r->type & ARM_CP_EL3_NO_EL2_UNDEF) { + return; + } + make_const =3D !(r->type & ARM_CP_EL3_NO_EL2_KEEP); + } + } else { + CPAccessRights max_el =3D (arm_feature(env, ARM_FEATURE_EL2) + ? PL2_RW : PL1_RW); + if ((r->access & max_el) =3D=3D 0) { + return; + } + } + + /* Combine cpreg and name into one allocation. */ + name_len =3D strlen(name) + 1; + r2 =3D g_malloc(sizeof(*r2) + name_len); + *r2 =3D *r; + r2->name =3D memcpy(r2 + 1, name, name_len); + + /* + * Update fields to match the instantiation, overwiting wildcards + * such as CP_ANY, ARM_CP_STATE_BOTH, or ARM_CP_SECSTATE_BOTH. + */ + r2->cp =3D cp; + r2->crm =3D crm; + r2->opc1 =3D opc1; + r2->opc2 =3D opc2; + r2->state =3D state; + r2->secure =3D secstate; + if (opaque) { + r2->opaque =3D opaque; + } + + if (make_const) { + /* This should not have been a very special register to begin. */ + int old_special =3D r2->type & ARM_CP_SPECIAL_MASK; + assert(old_special =3D=3D 0 || old_special =3D=3D ARM_CP_NOP); + /* + * Set the special function to CONST, retaining the other flags. + * This is important for e.g. ARM_CP_SVE so that we still + * take the SVE trap if CPTR_EL3.EZ =3D=3D 0. + */ + r2->type =3D (r2->type & ~ARM_CP_SPECIAL_MASK) | ARM_CP_CONST; + /* + * Usually, these registers become RES0, but there are a few + * special cases like VPIDR_EL2 which have a constant non-zero + * value with writes ignored. + */ + if (!(r->type & ARM_CP_EL3_NO_EL2_C_NZ)) { + r2->resetvalue =3D 0; + } + /* + * ARM_CP_CONST has precedence, so removing the callbacks and + * offsets are not strictly necessary, but it is potentially + * less confusing to debug later. + */ + r2->readfn =3D NULL; + r2->writefn =3D NULL; + r2->raw_readfn =3D NULL; + r2->raw_writefn =3D NULL; + r2->resetfn =3D NULL; + r2->fieldoffset =3D 0; + r2->bank_fieldoffsets[0] =3D 0; + r2->bank_fieldoffsets[1] =3D 0; + } else { + bool isbanked =3D r->bank_fieldoffsets[0] && r->bank_fieldoffsets[= 1]; + + if (isbanked) { + /* + * Register is banked (using both entries in array). + * Overwriting fieldoffset as the array is only used to define + * banked registers but later only fieldoffset is used. + */ + r2->fieldoffset =3D r->bank_fieldoffsets[ns]; + } + if (state =3D=3D ARM_CP_STATE_AA32) { + if (isbanked) { + /* + * If the register is banked then we don't need to migrate= or + * reset the 32-bit instance in certain cases: + * + * 1) If the register has both 32-bit and 64-bit instances + * then we can count on the 64-bit instance taking care + * of the non-secure bank. + * 2) If ARMv8 is enabled then we can count on a 64-bit + * version taking care of the secure bank. This requir= es + * that separate 32 and 64-bit definitions are provided. + */ + if ((r->state =3D=3D ARM_CP_STATE_BOTH && ns) || + (arm_feature(env, ARM_FEATURE_V8) && !ns)) { + r2->type |=3D ARM_CP_ALIAS; + } + } else if ((secstate !=3D r->secure) && !ns) { + /* + * The register is not banked so we only want to allow + * migration of the non-secure instance. + */ + r2->type |=3D ARM_CP_ALIAS; + } + + if (HOST_BIG_ENDIAN && + r->state =3D=3D ARM_CP_STATE_BOTH && r2->fieldoffset) { + r2->fieldoffset +=3D sizeof(uint32_t); + } + } + } + + /* + * By convention, for wildcarded registers only the first + * entry is used for migration; the others are marked as + * ALIAS so we don't try to transfer the register + * multiple times. Special registers (ie NOP/WFI) are + * never migratable and not even raw-accessible. + */ + if (r2->type & ARM_CP_SPECIAL_MASK) { + r2->type |=3D ARM_CP_NO_RAW; + } + if (((r->crm =3D=3D CP_ANY) && crm !=3D 0) || + ((r->opc1 =3D=3D CP_ANY) && opc1 !=3D 0) || + ((r->opc2 =3D=3D CP_ANY) && opc2 !=3D 0)) { + r2->type |=3D ARM_CP_ALIAS | ARM_CP_NO_GDB; + } + + /* + * Check that raw accesses are either forbidden or handled. Note that + * we can't assert this earlier because the setup of fieldoffset for + * banked registers has to be done first. + */ + if (!(r2->type & ARM_CP_NO_RAW)) { + assert(!raw_accessors_invalid(r2)); + } + + g_hash_table_insert(cpu->cp_regs, (gpointer)(uintptr_t)key, r2); +} + + +void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu, + const ARMCPRegInfo *r, void *opaque) +{ + /* + * Define implementations of coprocessor registers. + * We store these in a hashtable because typically + * there are less than 150 registers in a space which + * is 16*16*16*8*8 =3D 262144 in size. + * Wildcarding is supported for the crm, opc1 and opc2 fields. + * If a register is defined twice then the second definition is + * used, so this can be used to define some generic registers and + * then override them with implementation specific variations. + * At least one of the original and the second definition should + * include ARM_CP_OVERRIDE in its type bits -- this is just a guard + * against accidental use. + * + * The state field defines whether the register is to be + * visible in the AArch32 or AArch64 execution state. If the + * state is set to ARM_CP_STATE_BOTH then we synthesise a + * reginfo structure for the AArch32 view, which sees the lower + * 32 bits of the 64 bit register. + * + * Only registers visible in AArch64 may set r->opc0; opc0 cannot + * be wildcarded. AArch64 registers are always considered to be 64 + * bits; the ARM_CP_64BIT* flag applies only to the AArch32 view of + * the register, if any. + */ + int crm, opc1, opc2; + int crmmin =3D (r->crm =3D=3D CP_ANY) ? 0 : r->crm; + int crmmax =3D (r->crm =3D=3D CP_ANY) ? 15 : r->crm; + int opc1min =3D (r->opc1 =3D=3D CP_ANY) ? 0 : r->opc1; + int opc1max =3D (r->opc1 =3D=3D CP_ANY) ? 7 : r->opc1; + int opc2min =3D (r->opc2 =3D=3D CP_ANY) ? 0 : r->opc2; + int opc2max =3D (r->opc2 =3D=3D CP_ANY) ? 7 : r->opc2; + CPState state; + + /* 64 bit registers have only CRm and Opc1 fields */ + assert(!((r->type & ARM_CP_64BIT) && (r->opc2 || r->crn))); + /* op0 only exists in the AArch64 encodings */ + assert((r->state !=3D ARM_CP_STATE_AA32) || (r->opc0 =3D=3D 0)); + /* AArch64 regs are all 64 bit so ARM_CP_64BIT is meaningless */ + assert((r->state !=3D ARM_CP_STATE_AA64) || !(r->type & ARM_CP_64BIT)); + /* + * This API is only for Arm's system coprocessors (14 and 15) or + * (M-profile or v7A-and-earlier only) for implementation defined + * coprocessors in the range 0..7. Our decode assumes this, since + * 8..13 can be used for other insns including VFP and Neon. See + * valid_cp() in translate.c. Assert here that we haven't tried + * to use an invalid coprocessor number. + */ + switch (r->state) { + case ARM_CP_STATE_BOTH: + /* 0 has a special meaning, but otherwise the same rules as AA32. = */ + if (r->cp =3D=3D 0) { + break; + } + /* fall through */ + case ARM_CP_STATE_AA32: + if (arm_feature(&cpu->env, ARM_FEATURE_V8) && + !arm_feature(&cpu->env, ARM_FEATURE_M)) { + assert(r->cp >=3D 14 && r->cp <=3D 15); + } else { + assert(r->cp < 8 || (r->cp >=3D 14 && r->cp <=3D 15)); + } + break; + case ARM_CP_STATE_AA64: + assert(r->cp =3D=3D 0 || r->cp =3D=3D CP_REG_ARM64_SYSREG_CP); + break; + default: + g_assert_not_reached(); + } + /* + * The AArch64 pseudocode CheckSystemAccess() specifies that op1 + * encodes a minimum access level for the register. We roll this + * runtime check into our general permission check code, so check + * here that the reginfo's specified permissions are strict enough + * to encompass the generic architectural permission check. + */ + if (r->state !=3D ARM_CP_STATE_AA32) { + CPAccessRights mask; + switch (r->opc1) { + case 0: + /* min_EL EL1, but some accessible to EL0 via kernel ABI */ + mask =3D PL0U_R | PL1_RW; + break; + case 1: case 2: + /* min_EL EL1 */ + mask =3D PL1_RW; + break; + case 3: + /* min_EL EL0 */ + mask =3D PL0_RW; + break; + case 4: + case 5: + /* min_EL EL2 */ + mask =3D PL2_RW; + break; + case 6: + /* min_EL EL3 */ + mask =3D PL3_RW; + break; + case 7: + /* min_EL EL1, secure mode only (we don't check the latter) */ + mask =3D PL1_RW; + break; + default: + /* broken reginfo with out-of-range opc1 */ + g_assert_not_reached(); + } + /* assert our permissions are not too lax (stricter is fine) */ + assert((r->access & ~mask) =3D=3D 0); + } + + /* + * Check that the register definition has enough info to handle + * reads and writes if they are permitted. + */ + if (!(r->type & (ARM_CP_SPECIAL_MASK | ARM_CP_CONST))) { + if (r->access & PL3_R) { + assert((r->fieldoffset || + (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) || + r->readfn); + } + if (r->access & PL3_W) { + assert((r->fieldoffset || + (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) || + r->writefn); + } + } + + for (crm =3D crmmin; crm <=3D crmmax; crm++) { + for (opc1 =3D opc1min; opc1 <=3D opc1max; opc1++) { + for (opc2 =3D opc2min; opc2 <=3D opc2max; opc2++) { + for (state =3D ARM_CP_STATE_AA32; + state <=3D ARM_CP_STATE_AA64; state++) { + if (r->state !=3D state && r->state !=3D ARM_CP_STATE_= BOTH) { + continue; + } + if (state =3D=3D ARM_CP_STATE_AA32) { + /* + * Under AArch32 CP registers can be common + * (same for secure and non-secure world) or banke= d. + */ + char *name; + + switch (r->secure) { + case ARM_CP_SECSTATE_S: + case ARM_CP_SECSTATE_NS: + add_cpreg_to_hashtable(cpu, r, opaque, state, + r->secure, crm, opc1, o= pc2, + r->name); + break; + case ARM_CP_SECSTATE_BOTH: + name =3D g_strdup_printf("%s_S", r->name); + add_cpreg_to_hashtable(cpu, r, opaque, state, + ARM_CP_SECSTATE_S, + crm, opc1, opc2, name); + g_free(name); + add_cpreg_to_hashtable(cpu, r, opaque, state, + ARM_CP_SECSTATE_NS, + crm, opc1, opc2, r->nam= e); + break; + default: + g_assert_not_reached(); + } + } else { + /* + * AArch64 registers get mapped to non-secure inst= ance + * of AArch32 + */ + add_cpreg_to_hashtable(cpu, r, opaque, state, + ARM_CP_SECSTATE_NS, + crm, opc1, opc2, r->name); + } + } + } + } + } +} + +/* Define a whole list of registers */ +void define_arm_cp_regs_with_opaque_len(ARMCPU *cpu, const ARMCPRegInfo *r= egs, + void *opaque, size_t len) +{ + size_t i; + for (i =3D 0; i < len; ++i) { + define_one_arm_cp_reg_with_opaque(cpu, regs + i, opaque); + } +} + +/* + * Modify ARMCPRegInfo for access from userspace. + * + * This is a data driven modification directed by + * ARMCPRegUserSpaceInfo. All registers become ARM_CP_CONST as + * user-space cannot alter any values and dynamic values pertaining to + * execution state are hidden from user space view anyway. + */ +void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len, + const ARMCPRegUserSpaceInfo *mods, + size_t mods_len) +{ + for (size_t mi =3D 0; mi < mods_len; ++mi) { + const ARMCPRegUserSpaceInfo *m =3D mods + mi; + GPatternSpec *pat =3D NULL; + + if (m->is_glob) { + pat =3D g_pattern_spec_new(m->name); + } + for (size_t ri =3D 0; ri < regs_len; ++ri) { + ARMCPRegInfo *r =3D regs + ri; + + if (pat && g_pattern_match_string(pat, r->name)) { + r->type =3D ARM_CP_CONST; + r->access =3D PL0U_R; + r->resetvalue =3D 0; + /* continue */ + } else if (strcmp(r->name, m->name) =3D=3D 0) { + r->type =3D ARM_CP_CONST; + r->access =3D PL0U_R; + r->resetvalue &=3D m->exported_bits; + r->resetvalue |=3D m->fixed_bits; + break; + } + } + if (pat) { + g_pattern_spec_free(pat); + } + } +} + +const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encode= d_cp) +{ + return g_hash_table_lookup(cpregs, (gpointer)(uintptr_t)encoded_cp); +} + +void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Helper coprocessor write function for write-ignore registers */ +} + +uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri) +{ + /* Helper coprocessor write function for read-as-zero registers */ + return 0; +} + +void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque) +{ + /* Helper coprocessor reset function for do-nothing-on-reset registers= */ +} diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 5f63316dbf..fd337e1788 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -27,6 +27,7 @@ #include "qemu/module.h" #include "qapi/error.h" #include "cpu.h" +#include "cpregs.h" #ifdef CONFIG_TCG #include "hw/core/tcg-cpu-ops.h" #endif /* CONFIG_TCG */ diff --git a/target/arm/helper.c b/target/arm/helper.c index ddb0d76b70..1809df829b 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -31,5614 +31,9 @@ #endif #include "cpregs.h" =20 -#define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */ =20 static void switch_mode(CPUARMState *env, int mode); =20 -static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - assert(ri->fieldoffset); - if (cpreg_field_is_64bit(ri)) { - return CPREG_FIELD64(env, ri); - } else { - return CPREG_FIELD32(env, ri); - } -} - -void raw_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) -{ - assert(ri->fieldoffset); - if (cpreg_field_is_64bit(ri)) { - CPREG_FIELD64(env, ri) =3D value; - } else { - CPREG_FIELD32(env, ri) =3D value; - } -} - -static void *raw_ptr(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return (char *)env + ri->fieldoffset; -} - -uint64_t read_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri) -{ - /* Raw read of a coprocessor register (as needed for migration, etc). = */ - if (ri->type & ARM_CP_CONST) { - return ri->resetvalue; - } else if (ri->raw_readfn) { - return ri->raw_readfn(env, ri); - } else if (ri->readfn) { - return ri->readfn(env, ri); - } else { - return raw_read(env, ri); - } -} - -static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t v) -{ - /* - * Raw write of a coprocessor register (as needed for migration, etc). - * Note that constant registers are treated as write-ignored; the - * caller should check for success by whether a readback gives the - * value written. - */ - if (ri->type & ARM_CP_CONST) { - return; - } else if (ri->raw_writefn) { - ri->raw_writefn(env, ri, v); - } else if (ri->writefn) { - ri->writefn(env, ri, v); - } else { - raw_write(env, ri, v); - } -} - -static bool raw_accessors_invalid(const ARMCPRegInfo *ri) -{ - /* - * Return true if the regdef would cause an assertion if you called - * read_raw_cp_reg() or write_raw_cp_reg() on it (ie if it is a - * program bug for it not to have the NO_RAW flag). - * NB that returning false here doesn't necessarily mean that calling - * read/write_raw_cp_reg() is safe, because we can't distinguish "has - * read/write access functions which are safe for raw use" from "has - * read/write access functions which have side effects but has forgotten - * to provide raw access functions". - * The tests here line up with the conditions in read/write_raw_cp_reg() - * and assertions in raw_read()/raw_write(). - */ - if ((ri->type & ARM_CP_CONST) || - ri->fieldoffset || - ((ri->raw_writefn || ri->writefn) && (ri->raw_readfn || ri->readfn= ))) { - return false; - } - return true; -} - -bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync) -{ - /* Write the coprocessor state from cpu->env to the (index,value) list= . */ - int i; - bool ok =3D true; - - for (i =3D 0; i < cpu->cpreg_array_len; i++) { - uint32_t regidx =3D kvm_to_cpreg_id(cpu->cpreg_indexes[i]); - const ARMCPRegInfo *ri; - uint64_t newval; - - ri =3D get_arm_cp_reginfo(cpu->cp_regs, regidx); - if (!ri) { - ok =3D false; - continue; - } - if (ri->type & ARM_CP_NO_RAW) { - continue; - } - - newval =3D read_raw_cp_reg(&cpu->env, ri); - if (kvm_sync) { - /* - * Only sync if the previous list->cpustate sync succeeded. - * Rather than tracking the success/failure state for every - * item in the list, we just recheck "does the raw write we mu= st - * have made in write_list_to_cpustate() read back OK" here. - */ - uint64_t oldval =3D cpu->cpreg_values[i]; - - if (oldval =3D=3D newval) { - continue; - } - - write_raw_cp_reg(&cpu->env, ri, oldval); - if (read_raw_cp_reg(&cpu->env, ri) !=3D oldval) { - continue; - } - - write_raw_cp_reg(&cpu->env, ri, newval); - } - cpu->cpreg_values[i] =3D newval; - } - return ok; -} - -bool write_list_to_cpustate(ARMCPU *cpu) -{ - int i; - bool ok =3D true; - - for (i =3D 0; i < cpu->cpreg_array_len; i++) { - uint32_t regidx =3D kvm_to_cpreg_id(cpu->cpreg_indexes[i]); - uint64_t v =3D cpu->cpreg_values[i]; - const ARMCPRegInfo *ri; - - ri =3D get_arm_cp_reginfo(cpu->cp_regs, regidx); - if (!ri) { - ok =3D false; - continue; - } - if (ri->type & ARM_CP_NO_RAW) { - continue; - } - /* - * Write value and confirm it reads back as written - * (to catch read-only registers and partially read-only - * registers where the incoming migration value doesn't match) - */ - write_raw_cp_reg(&cpu->env, ri, v); - if (read_raw_cp_reg(&cpu->env, ri) !=3D v) { - ok =3D false; - } - } - return ok; -} - -static void add_cpreg_to_list(gpointer key, gpointer opaque) -{ - ARMCPU *cpu =3D opaque; - uint32_t regidx =3D (uintptr_t)key; - const ARMCPRegInfo *ri =3D get_arm_cp_reginfo(cpu->cp_regs, regidx); - - if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_ALIAS))) { - cpu->cpreg_indexes[cpu->cpreg_array_len] =3D cpreg_to_kvm_id(regid= x); - /* The value array need not be initialized at this point */ - cpu->cpreg_array_len++; - } -} - -static void count_cpreg(gpointer key, gpointer opaque) -{ - ARMCPU *cpu =3D opaque; - const ARMCPRegInfo *ri; - - ri =3D g_hash_table_lookup(cpu->cp_regs, key); - - if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_ALIAS))) { - cpu->cpreg_array_len++; - } -} - -static gint cpreg_key_compare(gconstpointer a, gconstpointer b) -{ - uint64_t aidx =3D cpreg_to_kvm_id((uintptr_t)a); - uint64_t bidx =3D cpreg_to_kvm_id((uintptr_t)b); - - if (aidx > bidx) { - return 1; - } - if (aidx < bidx) { - return -1; - } - return 0; -} - -void init_cpreg_list(ARMCPU *cpu) -{ - /* - * Initialise the cpreg_tuples[] array based on the cp_regs hash. - * Note that we require cpreg_tuples[] to be sorted by key ID. - */ - GList *keys; - int arraylen; - - keys =3D g_hash_table_get_keys(cpu->cp_regs); - keys =3D g_list_sort(keys, cpreg_key_compare); - - cpu->cpreg_array_len =3D 0; - - g_list_foreach(keys, count_cpreg, cpu); - - arraylen =3D cpu->cpreg_array_len; - cpu->cpreg_indexes =3D g_new(uint64_t, arraylen); - cpu->cpreg_values =3D g_new(uint64_t, arraylen); - cpu->cpreg_vmstate_indexes =3D g_new(uint64_t, arraylen); - cpu->cpreg_vmstate_values =3D g_new(uint64_t, arraylen); - cpu->cpreg_vmstate_array_len =3D cpu->cpreg_array_len; - cpu->cpreg_array_len =3D 0; - - g_list_foreach(keys, add_cpreg_to_list, cpu); - - assert(cpu->cpreg_array_len =3D=3D arraylen); - - g_list_free(keys); -} - -/* - * Some registers are not accessible from AArch32 EL3 if SCR.NS =3D=3D 0. - */ -static CPAccessResult access_el3_aa32ns(CPUARMState *env, - const ARMCPRegInfo *ri, - bool isread) -{ - if (!is_a64(env) && arm_current_el(env) =3D=3D 3 && - arm_is_secure_below_el3(env)) { - return CP_ACCESS_TRAP_UNCATEGORIZED; - } - return CP_ACCESS_OK; -} - -/* - * Some secure-only AArch32 registers trap to EL3 if used from - * Secure EL1 (but are just ordinary UNDEF in other non-EL3 contexts). - * Note that an access from Secure EL1 can only happen if EL3 is AArch64. - * We assume that the .access field is set to PL1_RW. - */ -static CPAccessResult access_trap_aa32s_el1(CPUARMState *env, - const ARMCPRegInfo *ri, - bool isread) -{ - if (arm_current_el(env) =3D=3D 3) { - return CP_ACCESS_OK; - } - if (arm_is_secure_below_el3(env)) { - if (env->cp15.scr_el3 & SCR_EEL2) { - return CP_ACCESS_TRAP_EL2; - } - return CP_ACCESS_TRAP_EL3; - } - /* This will be EL1 NS and EL2 NS, which just UNDEF */ - return CP_ACCESS_TRAP_UNCATEGORIZED; -} - -/* - * Check for traps to performance monitor registers, which are controlled - * by MDCR_EL2.TPM for EL2 and MDCR_EL3.TPM for EL3. - */ -static CPAccessResult access_tpm(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - int el =3D arm_current_el(env); - uint64_t mdcr_el2 =3D arm_mdcr_el2_eff(env); - - if (el < 2 && (mdcr_el2 & MDCR_TPM)) { - return CP_ACCESS_TRAP_EL2; - } - if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -/* Check for traps from EL1 due to HCR_EL2.TVM and HCR_EL2.TRVM. */ -static CPAccessResult access_tvm_trvm(CPUARMState *env, const ARMCPRegInfo= *ri, - bool isread) -{ - if (arm_current_el(env) =3D=3D 1) { - uint64_t trap =3D isread ? HCR_TRVM : HCR_TVM; - if (arm_hcr_el2_eff(env) & trap) { - return CP_ACCESS_TRAP_EL2; - } - } - return CP_ACCESS_OK; -} - -/* Check for traps from EL1 due to HCR_EL2.TSW. */ -static CPAccessResult access_tsw(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - if (arm_current_el(env) =3D=3D 1 && (arm_hcr_el2_eff(env) & HCR_TSW)) { - return CP_ACCESS_TRAP_EL2; - } - return CP_ACCESS_OK; -} - -/* Check for traps from EL1 due to HCR_EL2.TACR. */ -static CPAccessResult access_tacr(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - if (arm_current_el(env) =3D=3D 1 && (arm_hcr_el2_eff(env) & HCR_TACR))= { - return CP_ACCESS_TRAP_EL2; - } - return CP_ACCESS_OK; -} - -/* Check for traps from EL1 due to HCR_EL2.TTLB. */ -static CPAccessResult access_ttlb(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - if (arm_current_el(env) =3D=3D 1 && (arm_hcr_el2_eff(env) & HCR_TTLB))= { - return CP_ACCESS_TRAP_EL2; - } - return CP_ACCESS_OK; -} - -/* Check for traps from EL1 due to HCR_EL2.TTLB or TTLBIS. */ -static CPAccessResult access_ttlbis(CPUARMState *env, const ARMCPRegInfo *= ri, - bool isread) -{ - if (arm_current_el(env) =3D=3D 1 && - (arm_hcr_el2_eff(env) & (HCR_TTLB | HCR_TTLBIS))) { - return CP_ACCESS_TRAP_EL2; - } - return CP_ACCESS_OK; -} - -#ifdef TARGET_AARCH64 -/* Check for traps from EL1 due to HCR_EL2.TTLB or TTLBOS. */ -static CPAccessResult access_ttlbos(CPUARMState *env, const ARMCPRegInfo *= ri, - bool isread) -{ - if (arm_current_el(env) =3D=3D 1 && - (arm_hcr_el2_eff(env) & (HCR_TTLB | HCR_TTLBOS))) { - return CP_ACCESS_TRAP_EL2; - } - return CP_ACCESS_OK; -} -#endif - -static void dacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t = value) -{ - ARMCPU *cpu =3D env_archcpu(env); - - raw_write(env, ri, value); - tlb_flush(CPU(cpu)); /* Flush TLB as domain not tracked in TLB */ -} - -static void fcse_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t = value) -{ - ARMCPU *cpu =3D env_archcpu(env); - - if (raw_read(env, ri) !=3D value) { - /* - * Unlike real hardware the qemu TLB uses virtual addresses, - * not modified virtual addresses, so this causes a TLB flush. - */ - tlb_flush(CPU(cpu)); - raw_write(env, ri, value); - } -} - -static void contextidr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - - if (raw_read(env, ri) !=3D value && !arm_feature(env, ARM_FEATURE_PMSA) - && !extended_addresses_enabled(env)) { - /* - * For VMSA (when not using the LPAE long descriptor page table - * format) this register includes the ASID, so do a TLB flush. - * For PMSA it is purely a process ID and no action is needed. - */ - tlb_flush(CPU(cpu)); - } - raw_write(env, ri, value); -} - -static int alle1_tlbmask(CPUARMState *env) -{ - /* - * Note that the 'ALL' scope must invalidate both stage 1 and - * stage 2 translations, whereas most other scopes only invalidate - * stage 1 translations. - */ - return (ARMMMUIdxBit_E10_1 | - ARMMMUIdxBit_E10_1_PAN | - ARMMMUIdxBit_E10_0 | - ARMMMUIdxBit_Stage2 | - ARMMMUIdxBit_Stage2_S); -} - - -/* IS variants of TLB operations must affect all cores */ -static void tlbiall_is_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - - tlb_flush_all_cpus_synced(cs); -} - -static void tlbiasid_is_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - - tlb_flush_all_cpus_synced(cs); -} - -static void tlbimva_is_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - - tlb_flush_page_all_cpus_synced(cs, value & TARGET_PAGE_MASK); -} - -static void tlbimvaa_is_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - - tlb_flush_page_all_cpus_synced(cs, value & TARGET_PAGE_MASK); -} - -/* - * Non-IS variants of TLB operations are upgraded to - * IS versions if we are at EL1 and HCR_EL2.FB is effectively set to - * force broadcast of these operations. - */ -static bool tlb_force_broadcast(CPUARMState *env) -{ - return arm_current_el(env) =3D=3D 1 && (arm_hcr_el2_eff(env) & HCR_FB); -} - -static void tlbiall_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* Invalidate all (TLBIALL) */ - CPUState *cs =3D env_cpu(env); - - if (tlb_force_broadcast(env)) { - tlb_flush_all_cpus_synced(cs); - } else { - tlb_flush(cs); - } -} - -static void tlbimva_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* Invalidate single TLB entry by MVA and ASID (TLBIMVA) */ - CPUState *cs =3D env_cpu(env); - - value &=3D TARGET_PAGE_MASK; - if (tlb_force_broadcast(env)) { - tlb_flush_page_all_cpus_synced(cs, value); - } else { - tlb_flush_page(cs, value); - } -} - -static void tlbiasid_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* Invalidate by ASID (TLBIASID) */ - CPUState *cs =3D env_cpu(env); - - if (tlb_force_broadcast(env)) { - tlb_flush_all_cpus_synced(cs); - } else { - tlb_flush(cs); - } -} - -static void tlbimvaa_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* Invalidate single entry by MVA, all ASIDs (TLBIMVAA) */ - CPUState *cs =3D env_cpu(env); - - value &=3D TARGET_PAGE_MASK; - if (tlb_force_broadcast(env)) { - tlb_flush_page_all_cpus_synced(cs, value); - } else { - tlb_flush_page(cs, value); - } -} - -static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - - tlb_flush_by_mmuidx(cs, alle1_tlbmask(env)); -} - -static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - - tlb_flush_by_mmuidx_all_cpus_synced(cs, alle1_tlbmask(env)); -} - - -static void tlbiall_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - - tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E2); -} - -static void tlbiall_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - - tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E2); -} - -static void tlbimva_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - uint64_t pageaddr =3D value & ~MAKE_64BIT_MASK(0, 12); - - tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E2); -} - -static void tlbimva_hyp_is_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - uint64_t pageaddr =3D value & ~MAKE_64BIT_MASK(0, 12); - - tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, - ARMMMUIdxBit_E2); -} - -static void tlbiipas2_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - uint64_t pageaddr =3D (value & MAKE_64BIT_MASK(0, 28)) << 12; - - tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_Stage2); -} - -static void tlbiipas2is_hyp_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - uint64_t pageaddr =3D (value & MAKE_64BIT_MASK(0, 28)) << 12; - - tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, ARMMMUIdxBit_St= age2); -} - -static const ARMCPRegInfo cp_reginfo[] =3D { - /* - * Define the secure and non-secure FCSE identifier CP registers - * separately because there is no secure bank in V8 (no _EL3). This a= llows - * the secure register to be properly reset and migrated. There is als= o no - * v8 EL1 version of the register so the non-secure instance stands al= one. - */ - { .name =3D "FCSEIDR", - .cp =3D 15, .opc1 =3D 0, .crn =3D 13, .crm =3D 0, .opc2 =3D 0, - .access =3D PL1_RW, .secure =3D ARM_CP_SECSTATE_NS, - .fieldoffset =3D offsetof(CPUARMState, cp15.fcseidr_ns), - .resetvalue =3D 0, .writefn =3D fcse_write, .raw_writefn =3D raw_wri= te, }, - { .name =3D "FCSEIDR_S", - .cp =3D 15, .opc1 =3D 0, .crn =3D 13, .crm =3D 0, .opc2 =3D 0, - .access =3D PL1_RW, .secure =3D ARM_CP_SECSTATE_S, - .fieldoffset =3D offsetof(CPUARMState, cp15.fcseidr_s), - .resetvalue =3D 0, .writefn =3D fcse_write, .raw_writefn =3D raw_wri= te, }, - /* - * Define the secure and non-secure context identifier CP registers - * separately because there is no secure bank in V8 (no _EL3). This a= llows - * the secure register to be properly reset and migrated. In the - * non-secure case, the 32-bit register will have reset and migration - * disabled during registration as it is handled by the 64-bit instanc= e. - */ - { .name =3D "CONTEXTIDR_EL1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 13, .crm =3D 0, .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .secure =3D ARM_CP_SECSTATE_NS, - .fieldoffset =3D offsetof(CPUARMState, cp15.contextidr_el[1]), - .resetvalue =3D 0, .writefn =3D contextidr_write, .raw_writefn =3D r= aw_write, }, - { .name =3D "CONTEXTIDR_S", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 0, .crn =3D 13, .crm =3D 0, .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .secure =3D ARM_CP_SECSTATE_S, - .fieldoffset =3D offsetof(CPUARMState, cp15.contextidr_s), - .resetvalue =3D 0, .writefn =3D contextidr_write, .raw_writefn =3D r= aw_write, }, -}; - -static const ARMCPRegInfo not_v8_cp_reginfo[] =3D { - /* - * NB: Some of these registers exist in v8 but with more precise - * definitions that don't use CP_ANY wildcards (mostly in v8_cp_reginf= o[]). - */ - /* MMU Domain access control / MPU write buffer control */ - { .name =3D "DACR", - .cp =3D 15, .opc1 =3D CP_ANY, .crn =3D 3, .crm =3D CP_ANY, .opc2 =3D= CP_ANY, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, .resetvalue =3D 0, - .writefn =3D dacr_write, .raw_writefn =3D raw_write, - .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.dacr_s), - offsetoflow32(CPUARMState, cp15.dacr_ns) } }, - /* - * ARMv7 allocates a range of implementation defined TLB LOCKDOWN regs. - * For v6 and v5, these mappings are overly broad. - */ - { .name =3D "TLB_LOCKDOWN", .cp =3D 15, .crn =3D 10, .crm =3D 0, - .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, .access =3D PL1_RW, .type =3D AR= M_CP_NOP }, - { .name =3D "TLB_LOCKDOWN", .cp =3D 15, .crn =3D 10, .crm =3D 1, - .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, .access =3D PL1_RW, .type =3D AR= M_CP_NOP }, - { .name =3D "TLB_LOCKDOWN", .cp =3D 15, .crn =3D 10, .crm =3D 4, - .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, .access =3D PL1_RW, .type =3D AR= M_CP_NOP }, - { .name =3D "TLB_LOCKDOWN", .cp =3D 15, .crn =3D 10, .crm =3D 8, - .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, .access =3D PL1_RW, .type =3D AR= M_CP_NOP }, - /* Cache maintenance ops; some of this space may be overridden later. = */ - { .name =3D "CACHEMAINT", .cp =3D 15, .crn =3D 7, .crm =3D CP_ANY, - .opc1 =3D 0, .opc2 =3D CP_ANY, .access =3D PL1_W, - .type =3D ARM_CP_NOP | ARM_CP_OVERRIDE }, -}; - -static const ARMCPRegInfo not_v6_cp_reginfo[] =3D { - /* - * Not all pre-v6 cores implemented this WFI, so this is slightly - * over-broad. - */ - { .name =3D "WFI_v5", .cp =3D 15, .crn =3D 7, .crm =3D 8, .opc1 =3D 0,= .opc2 =3D 2, - .access =3D PL1_W, .type =3D ARM_CP_WFI }, -}; - -static const ARMCPRegInfo not_v7_cp_reginfo[] =3D { - /* - * Standard v6 WFI (also used in some pre-v6 cores); not in v7 (which - * is UNPREDICTABLE; we choose to NOP as most implementations do). - */ - { .name =3D "WFI_v6", .cp =3D 15, .crn =3D 7, .crm =3D 0, .opc1 =3D 0,= .opc2 =3D 4, - .access =3D PL1_W, .type =3D ARM_CP_WFI }, - /* - * L1 cache lockdown. Not architectural in v6 and earlier but in pract= ice - * implemented in 926, 946, 1026, 1136, 1176 and 11MPCore. StrongARM a= nd - * OMAPCP will override this space. - */ - { .name =3D "DLOCKDOWN", .cp =3D 15, .crn =3D 9, .crm =3D 0, .opc1 =3D= 0, .opc2 =3D 0, - .access =3D PL1_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.c9_d= ata), - .resetvalue =3D 0 }, - { .name =3D "ILOCKDOWN", .cp =3D 15, .crn =3D 9, .crm =3D 0, .opc1 =3D= 0, .opc2 =3D 1, - .access =3D PL1_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.c9_i= nsn), - .resetvalue =3D 0 }, - /* v6 doesn't have the cache ID registers but Linux reads them anyway = */ - { .name =3D "DUMMY", .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 1, = .opc2 =3D CP_ANY, - .access =3D PL1_R, .type =3D ARM_CP_CONST | ARM_CP_NO_RAW, - .resetvalue =3D 0 }, - /* - * We don't implement pre-v7 debug but most CPUs had at least a DBGDID= R; - * implementing it as RAZ means the "debug architecture version" bits - * will read as a reserved value, which should cause Linux to not try - * to use the debug hardware. - */ - { .name =3D "DBGDIDR", .cp =3D 14, .crn =3D 0, .crm =3D 0, .opc1 =3D 0= , .opc2 =3D 0, - .access =3D PL0_R, .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - /* - * MMU TLB control. Note that the wildcarding means we cover not just - * the unified TLB ops but also the dside/iside/inner-shareable varian= ts. - */ - { .name =3D "TLBIALL", .cp =3D 15, .crn =3D 8, .crm =3D CP_ANY, - .opc1 =3D CP_ANY, .opc2 =3D 0, .access =3D PL1_W, .writefn =3D tlbia= ll_write, - .type =3D ARM_CP_NO_RAW }, - { .name =3D "TLBIMVA", .cp =3D 15, .crn =3D 8, .crm =3D CP_ANY, - .opc1 =3D CP_ANY, .opc2 =3D 1, .access =3D PL1_W, .writefn =3D tlbim= va_write, - .type =3D ARM_CP_NO_RAW }, - { .name =3D "TLBIASID", .cp =3D 15, .crn =3D 8, .crm =3D CP_ANY, - .opc1 =3D CP_ANY, .opc2 =3D 2, .access =3D PL1_W, .writefn =3D tlbia= sid_write, - .type =3D ARM_CP_NO_RAW }, - { .name =3D "TLBIMVAA", .cp =3D 15, .crn =3D 8, .crm =3D CP_ANY, - .opc1 =3D CP_ANY, .opc2 =3D 3, .access =3D PL1_W, .writefn =3D tlbim= vaa_write, - .type =3D ARM_CP_NO_RAW }, - { .name =3D "PRRR", .cp =3D 15, .crn =3D 10, .crm =3D 2, - .opc1 =3D 0, .opc2 =3D 0, .access =3D PL1_RW, .type =3D ARM_CP_NOP }, - { .name =3D "NMRR", .cp =3D 15, .crn =3D 10, .crm =3D 2, - .opc1 =3D 0, .opc2 =3D 1, .access =3D PL1_RW, .type =3D ARM_CP_NOP }, -}; - -static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - uint32_t mask =3D 0; - - /* In ARMv8 most bits of CPACR_EL1 are RES0. */ - if (!arm_feature(env, ARM_FEATURE_V8)) { - /* - * ARMv7 defines bits for unimplemented coprocessors as RAZ/WI. - * ASEDIS [31] and D32DIS [30] are both UNK/SBZP without VFP. - * TRCDIS [28] is RAZ/WI since we do not implement a trace macroce= ll. - */ - if (cpu_isar_feature(aa32_vfp_simd, env_archcpu(env))) { - /* VFP coprocessor: cp10 & cp11 [23:20] */ - mask |=3D R_CPACR_ASEDIS_MASK | - R_CPACR_D32DIS_MASK | - R_CPACR_CP11_MASK | - R_CPACR_CP10_MASK; - - if (!arm_feature(env, ARM_FEATURE_NEON)) { - /* ASEDIS [31] bit is RAO/WI */ - value |=3D R_CPACR_ASEDIS_MASK; - } - - /* - * VFPv3 and upwards with NEON implement 32 double precision - * registers (D0-D31). - */ - if (!cpu_isar_feature(aa32_simd_r32, env_archcpu(env))) { - /* D32DIS [30] is RAO/WI if D16-31 are not implemented. */ - value |=3D R_CPACR_D32DIS_MASK; - } - } - value &=3D mask; - } - - /* - * For A-profile AArch32 EL3 (but not M-profile secure mode), if NSACR= .CP10 - * is 0 then CPACR.{CP11,CP10} ignore writes and read as 0b00. - */ - if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) && - !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) { - mask =3D R_CPACR_CP11_MASK | R_CPACR_CP10_MASK; - value =3D (value & ~mask) | (env->cp15.cpacr_el1 & mask); - } - - env->cp15.cpacr_el1 =3D value; -} - -static uint64_t cpacr_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - /* - * For A-profile AArch32 EL3 (but not M-profile secure mode), if NSACR= .CP10 - * is 0 then CPACR.{CP11,CP10} ignore writes and read as 0b00. - */ - uint64_t value =3D env->cp15.cpacr_el1; - - if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) && - !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) { - value =3D ~(R_CPACR_CP11_MASK | R_CPACR_CP10_MASK); - } - return value; -} - - -static void cpacr_reset(CPUARMState *env, const ARMCPRegInfo *ri) -{ - /* - * Call cpacr_write() so that we reset with the correct RAO bits set - * for our CPU features. - */ - cpacr_write(env, ri, 0); -} - -static CPAccessResult cpacr_access(CPUARMState *env, const ARMCPRegInfo *r= i, - bool isread) -{ - if (arm_feature(env, ARM_FEATURE_V8)) { - /* Check if CPACR accesses are to be trapped to EL2 */ - if (arm_current_el(env) =3D=3D 1 && arm_is_el2_enabled(env) && - FIELD_EX64(env->cp15.cptr_el[2], CPTR_EL2, TCPAC)) { - return CP_ACCESS_TRAP_EL2; - /* Check if CPACR accesses are to be trapped to EL3 */ - } else if (arm_current_el(env) < 3 && - FIELD_EX64(env->cp15.cptr_el[3], CPTR_EL3, TCPAC)) { - return CP_ACCESS_TRAP_EL3; - } - } - - return CP_ACCESS_OK; -} - -static CPAccessResult cptr_access(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - /* Check if CPTR accesses are set to trap to EL3 */ - if (arm_current_el(env) =3D=3D 2 && - FIELD_EX64(env->cp15.cptr_el[3], CPTR_EL3, TCPAC)) { - return CP_ACCESS_TRAP_EL3; - } - - return CP_ACCESS_OK; -} - -static const ARMCPRegInfo v6_cp_reginfo[] =3D { - /* prefetch by MVA in v6, NOP in v7 */ - { .name =3D "MVA_prefetch", - .cp =3D 15, .crn =3D 7, .crm =3D 13, .opc1 =3D 0, .opc2 =3D 1, - .access =3D PL1_W, .type =3D ARM_CP_NOP }, - /* - * We need to break the TB after ISB to execute self-modifying code - * correctly and also to take any pending interrupts immediately. - * So use arm_cp_write_ignore() function instead of ARM_CP_NOP flag. - */ - { .name =3D "ISB", .cp =3D 15, .crn =3D 7, .crm =3D 5, .opc1 =3D 0, .o= pc2 =3D 4, - .access =3D PL0_W, .type =3D ARM_CP_NO_RAW, .writefn =3D arm_cp_writ= e_ignore }, - { .name =3D "DSB", .cp =3D 15, .crn =3D 7, .crm =3D 10, .opc1 =3D 0, .= opc2 =3D 4, - .access =3D PL0_W, .type =3D ARM_CP_NOP }, - { .name =3D "DMB", .cp =3D 15, .crn =3D 7, .crm =3D 10, .opc1 =3D 0, .= opc2 =3D 5, - .access =3D PL0_W, .type =3D ARM_CP_NOP }, - { .name =3D "IFAR", .cp =3D 15, .crn =3D 6, .crm =3D 0, .opc1 =3D 0, .= opc2 =3D 2, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.ifar_s), - offsetof(CPUARMState, cp15.ifar_ns) }, - .resetvalue =3D 0, }, - /* - * Watchpoint Fault Address Register : should actually only be present - * for 1136, 1176, 11MPCore. - */ - { .name =3D "WFAR", .cp =3D 15, .crn =3D 6, .crm =3D 0, .opc1 =3D 0, .= opc2 =3D 1, - .access =3D PL1_RW, .type =3D ARM_CP_CONST, .resetvalue =3D 0, }, - { .name =3D "CPACR", .state =3D ARM_CP_STATE_BOTH, .opc0 =3D 3, - .crn =3D 1, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 2, .accessfn =3D cpac= r_access, - .access =3D PL1_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.cpac= r_el1), - .resetfn =3D cpacr_reset, .writefn =3D cpacr_write, .readfn =3D cpac= r_read }, -}; - -typedef struct pm_event { - uint16_t number; /* PMEVTYPER.evtCount is 16 bits wide */ - /* If the event is supported on this CPU (used to generate PMCEID[01])= */ - bool (*supported)(CPUARMState *); - /* - * Retrieve the current count of the underlying event. The programmed - * counters hold a difference from the return value from this function - */ - uint64_t (*get_count)(CPUARMState *); - /* - * Return how many nanoseconds it will take (at a minimum) for count e= vents - * to occur. A negative value indicates the counter will never overflo= w, or - * that the counter has otherwise arranged for the overflow bit to be = set - * and the PMU interrupt to be raised on overflow. - */ - int64_t (*ns_per_count)(uint64_t); -} pm_event; - -static bool event_always_supported(CPUARMState *env) -{ - return true; -} - -static uint64_t swinc_get_count(CPUARMState *env) -{ - /* - * SW_INCR events are written directly to the pmevcntr's by writes to - * PMSWINC, so there is no underlying count maintained by the PMU itse= lf - */ - return 0; -} - -static int64_t swinc_ns_per(uint64_t ignored) -{ - return -1; -} - -/* - * Return the underlying cycle count for the PMU cycle counters. If we're = in - * usermode, simply return 0. - */ -static uint64_t cycles_get_count(CPUARMState *env) -{ -#ifndef CONFIG_USER_ONLY - return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - ARM_CPU_FREQ, NANOSECONDS_PER_SECOND); -#else - return cpu_get_host_ticks(); -#endif -} - -#ifndef CONFIG_USER_ONLY -static int64_t cycles_ns_per(uint64_t cycles) -{ - return (ARM_CPU_FREQ / NANOSECONDS_PER_SECOND) * cycles; -} - -static bool instructions_supported(CPUARMState *env) -{ - return icount_enabled() =3D=3D 1; /* Precise instruction counting */ -} - -static uint64_t instructions_get_count(CPUARMState *env) -{ - return (uint64_t)icount_get_raw(); -} - -static int64_t instructions_ns_per(uint64_t icount) -{ - return icount_to_ns((int64_t)icount); -} -#endif - -static bool pmuv3p1_events_supported(CPUARMState *env) -{ - /* For events which are supported in any v8.1 PMU */ - return cpu_isar_feature(any_pmuv3p1, env_archcpu(env)); -} - -static bool pmuv3p4_events_supported(CPUARMState *env) -{ - /* For events which are supported in any v8.1 PMU */ - return cpu_isar_feature(any_pmuv3p4, env_archcpu(env)); -} - -static uint64_t zero_event_get_count(CPUARMState *env) -{ - /* For events which on QEMU never fire, so their count is always zero = */ - return 0; -} - -static int64_t zero_event_ns_per(uint64_t cycles) -{ - /* An event which never fires can never overflow */ - return -1; -} - -static const pm_event pm_events[] =3D { - { .number =3D 0x000, /* SW_INCR */ - .supported =3D event_always_supported, - .get_count =3D swinc_get_count, - .ns_per_count =3D swinc_ns_per, - }, -#ifndef CONFIG_USER_ONLY - { .number =3D 0x008, /* INST_RETIRED, Instruction architecturally exec= uted */ - .supported =3D instructions_supported, - .get_count =3D instructions_get_count, - .ns_per_count =3D instructions_ns_per, - }, - { .number =3D 0x011, /* CPU_CYCLES, Cycle */ - .supported =3D event_always_supported, - .get_count =3D cycles_get_count, - .ns_per_count =3D cycles_ns_per, - }, -#endif - { .number =3D 0x023, /* STALL_FRONTEND */ - .supported =3D pmuv3p1_events_supported, - .get_count =3D zero_event_get_count, - .ns_per_count =3D zero_event_ns_per, - }, - { .number =3D 0x024, /* STALL_BACKEND */ - .supported =3D pmuv3p1_events_supported, - .get_count =3D zero_event_get_count, - .ns_per_count =3D zero_event_ns_per, - }, - { .number =3D 0x03c, /* STALL */ - .supported =3D pmuv3p4_events_supported, - .get_count =3D zero_event_get_count, - .ns_per_count =3D zero_event_ns_per, - }, -}; - -/* - * Note: Before increasing MAX_EVENT_ID beyond 0x3f into the 0x40xx range = of - * events (i.e. the statistical profiling extension), this implementation - * should first be updated to something sparse instead of the current - * supported_event_map[] array. - */ -#define MAX_EVENT_ID 0x3c -#define UNSUPPORTED_EVENT UINT16_MAX -static uint16_t supported_event_map[MAX_EVENT_ID + 1]; - -/* - * Called upon CPU initialization to initialize PMCEID[01]_EL0 and build a= map - * of ARM event numbers to indices in our pm_events array. - * - * Note: Events in the 0x40XX range are not currently supported. - */ -void pmu_init(ARMCPU *cpu) -{ - unsigned int i; - - /* - * Empty supported_event_map and cpu->pmceid[01] before adding support= ed - * events to them - */ - for (i =3D 0; i < ARRAY_SIZE(supported_event_map); i++) { - supported_event_map[i] =3D UNSUPPORTED_EVENT; - } - cpu->pmceid0 =3D 0; - cpu->pmceid1 =3D 0; - - for (i =3D 0; i < ARRAY_SIZE(pm_events); i++) { - const pm_event *cnt =3D &pm_events[i]; - assert(cnt->number <=3D MAX_EVENT_ID); - /* We do not currently support events in the 0x40xx range */ - assert(cnt->number <=3D 0x3f); - - if (cnt->supported(&cpu->env)) { - supported_event_map[cnt->number] =3D i; - uint64_t event_mask =3D 1ULL << (cnt->number & 0x1f); - if (cnt->number & 0x20) { - cpu->pmceid1 |=3D event_mask; - } else { - cpu->pmceid0 |=3D event_mask; - } - } - } -} - -/* - * Check at runtime whether a PMU event is supported for the current machi= ne - */ -static bool event_supported(uint16_t number) -{ - if (number > MAX_EVENT_ID) { - return false; - } - return supported_event_map[number] !=3D UNSUPPORTED_EVENT; -} - -static CPAccessResult pmreg_access(CPUARMState *env, const ARMCPRegInfo *r= i, - bool isread) -{ - /* - * Performance monitor registers user accessibility is controlled - * by PMUSERENR. MDCR_EL2.TPM and MDCR_EL3.TPM allow configurable - * trapping to EL2 or EL3 for other accesses. - */ - int el =3D arm_current_el(env); - uint64_t mdcr_el2 =3D arm_mdcr_el2_eff(env); - - if (el =3D=3D 0 && !(env->cp15.c9_pmuserenr & 1)) { - return CP_ACCESS_TRAP; - } - if (el < 2 && (mdcr_el2 & MDCR_TPM)) { - return CP_ACCESS_TRAP_EL2; - } - if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TPM)) { - return CP_ACCESS_TRAP_EL3; - } - - return CP_ACCESS_OK; -} - -static CPAccessResult pmreg_access_xevcntr(CPUARMState *env, - const ARMCPRegInfo *ri, - bool isread) -{ - /* ER: event counter read trap control */ - if (arm_feature(env, ARM_FEATURE_V8) - && arm_current_el(env) =3D=3D 0 - && (env->cp15.c9_pmuserenr & (1 << 3)) !=3D 0 - && isread) { - return CP_ACCESS_OK; - } - - return pmreg_access(env, ri, isread); -} - -static CPAccessResult pmreg_access_swinc(CPUARMState *env, - const ARMCPRegInfo *ri, - bool isread) -{ - /* SW: software increment write trap control */ - if (arm_feature(env, ARM_FEATURE_V8) - && arm_current_el(env) =3D=3D 0 - && (env->cp15.c9_pmuserenr & (1 << 1)) !=3D 0 - && !isread) { - return CP_ACCESS_OK; - } - - return pmreg_access(env, ri, isread); -} - -static CPAccessResult pmreg_access_selr(CPUARMState *env, - const ARMCPRegInfo *ri, - bool isread) -{ - /* ER: event counter read trap control */ - if (arm_feature(env, ARM_FEATURE_V8) - && arm_current_el(env) =3D=3D 0 - && (env->cp15.c9_pmuserenr & (1 << 3)) !=3D 0) { - return CP_ACCESS_OK; - } - - return pmreg_access(env, ri, isread); -} - -static CPAccessResult pmreg_access_ccntr(CPUARMState *env, - const ARMCPRegInfo *ri, - bool isread) -{ - /* CR: cycle counter read trap control */ - if (arm_feature(env, ARM_FEATURE_V8) - && arm_current_el(env) =3D=3D 0 - && (env->cp15.c9_pmuserenr & (1 << 2)) !=3D 0 - && isread) { - return CP_ACCESS_OK; - } - - return pmreg_access(env, ri, isread); -} - -/* - * Bits in MDCR_EL2 and MDCR_EL3 which pmu_counter_enabled() looks at. - * We use these to decide whether we need to wrap a write to MDCR_EL2 - * or MDCR_EL3 in pmu_op_start()/pmu_op_finish() calls. - */ -#define MDCR_EL2_PMU_ENABLE_BITS \ - (MDCR_HPME | MDCR_HPMD | MDCR_HPMN | MDCR_HCCD | MDCR_HLP) -#define MDCR_EL3_PMU_ENABLE_BITS (MDCR_SPME | MDCR_SCCD) - -/* - * Returns true if the counter (pass 31 for PMCCNTR) should count events u= sing - * the current EL, security state, and register configuration. - */ -static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter) -{ - uint64_t filter; - bool e, p, u, nsk, nsu, nsh, m; - bool enabled, prohibited =3D false, filtered; - bool secure =3D arm_is_secure(env); - int el =3D arm_current_el(env); - uint64_t mdcr_el2 =3D arm_mdcr_el2_eff(env); - uint8_t hpmn =3D mdcr_el2 & MDCR_HPMN; - - if (!arm_feature(env, ARM_FEATURE_PMU)) { - return false; - } - - if (!arm_feature(env, ARM_FEATURE_EL2) || - (counter < hpmn || counter =3D=3D 31)) { - e =3D env->cp15.c9_pmcr & PMCRE; - } else { - e =3D mdcr_el2 & MDCR_HPME; - } - enabled =3D e && (env->cp15.c9_pmcnten & (1 << counter)); - - /* Is event counting prohibited? */ - if (el =3D=3D 2 && (counter < hpmn || counter =3D=3D 31)) { - prohibited =3D mdcr_el2 & MDCR_HPMD; - } - if (secure) { - prohibited =3D prohibited || !(env->cp15.mdcr_el3 & MDCR_SPME); - } - - if (counter =3D=3D 31) { - /* - * The cycle counter defaults to running. PMCR.DP says "disable - * the cycle counter when event counting is prohibited". - * Some MDCR bits disable the cycle counter specifically. - */ - prohibited =3D prohibited && env->cp15.c9_pmcr & PMCRDP; - if (cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) { - if (secure) { - prohibited =3D prohibited || (env->cp15.mdcr_el3 & MDCR_SC= CD); - } - if (el =3D=3D 2) { - prohibited =3D prohibited || (mdcr_el2 & MDCR_HCCD); - } - } - } - - if (counter =3D=3D 31) { - filter =3D env->cp15.pmccfiltr_el0; - } else { - filter =3D env->cp15.c14_pmevtyper[counter]; - } - - p =3D filter & PMXEVTYPER_P; - u =3D filter & PMXEVTYPER_U; - nsk =3D arm_feature(env, ARM_FEATURE_EL3) && (filter & PMXEVTYPER_NSK); - nsu =3D arm_feature(env, ARM_FEATURE_EL3) && (filter & PMXEVTYPER_NSU); - nsh =3D arm_feature(env, ARM_FEATURE_EL2) && (filter & PMXEVTYPER_NSH); - m =3D arm_el_is_aa64(env, 1) && - arm_feature(env, ARM_FEATURE_EL3) && (filter & PMXEVTYPER_M); - - if (el =3D=3D 0) { - filtered =3D secure ? u : u !=3D nsu; - } else if (el =3D=3D 1) { - filtered =3D secure ? p : p !=3D nsk; - } else if (el =3D=3D 2) { - filtered =3D !nsh; - } else { /* EL3 */ - filtered =3D m !=3D p; - } - - if (counter !=3D 31) { - /* - * If not checking PMCCNTR, ensure the counter is setup to an even= t we - * support - */ - uint16_t event =3D filter & PMXEVTYPER_EVTCOUNT; - if (!event_supported(event)) { - return false; - } - } - - return enabled && !prohibited && !filtered; -} - -static void pmu_update_irq(CPUARMState *env) -{ - ARMCPU *cpu =3D env_archcpu(env); - qemu_set_irq(cpu->pmu_interrupt, (env->cp15.c9_pmcr & PMCRE) && - (env->cp15.c9_pminten & env->cp15.c9_pmovsr)); -} - -static bool pmccntr_clockdiv_enabled(CPUARMState *env) -{ - /* - * Return true if the clock divider is enabled and the cycle counter - * is supposed to tick only once every 64 clock cycles. This is - * controlled by PMCR.D, but if PMCR.LC is set to enable the long - * (64-bit) cycle counter PMCR.D has no effect. - */ - return (env->cp15.c9_pmcr & (PMCRD | PMCRLC)) =3D=3D PMCRD; -} - -static bool pmevcntr_is_64_bit(CPUARMState *env, int counter) -{ - /* Return true if the specified event counter is configured to be 64 b= it */ - - /* This isn't intended to be used with the cycle counter */ - assert(counter < 31); - - if (!cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) { - return false; - } - - if (arm_feature(env, ARM_FEATURE_EL2)) { - /* - * MDCR_EL2.HLP still applies even when EL2 is disabled in the - * current security state, so we don't use arm_mdcr_el2_eff() here. - */ - bool hlp =3D env->cp15.mdcr_el2 & MDCR_HLP; - int hpmn =3D env->cp15.mdcr_el2 & MDCR_HPMN; - - if (hpmn !=3D 0 && counter >=3D hpmn) { - return hlp; - } - } - return env->cp15.c9_pmcr & PMCRLP; -} - -/* - * Ensure c15_ccnt is the guest-visible count so that operations such as - * enabling/disabling the counter or filtering, modifying the count itself, - * etc. can be done logically. This is essentially a no-op if the counter = is - * not enabled at the time of the call. - */ -static void pmccntr_op_start(CPUARMState *env) -{ - uint64_t cycles =3D cycles_get_count(env); - - if (pmu_counter_enabled(env, 31)) { - uint64_t eff_cycles =3D cycles; - if (pmccntr_clockdiv_enabled(env)) { - eff_cycles /=3D 64; - } - - uint64_t new_pmccntr =3D eff_cycles - env->cp15.c15_ccnt_delta; - - uint64_t overflow_mask =3D env->cp15.c9_pmcr & PMCRLC ? \ - 1ull << 63 : 1ull << 31; - if (env->cp15.c15_ccnt & ~new_pmccntr & overflow_mask) { - env->cp15.c9_pmovsr |=3D (1ULL << 31); - pmu_update_irq(env); - } - - env->cp15.c15_ccnt =3D new_pmccntr; - } - env->cp15.c15_ccnt_delta =3D cycles; -} - -/* - * If PMCCNTR is enabled, recalculate the delta between the clock and the - * guest-visible count. A call to pmccntr_op_finish should follow every ca= ll to - * pmccntr_op_start. - */ -static void pmccntr_op_finish(CPUARMState *env) -{ - if (pmu_counter_enabled(env, 31)) { -#ifndef CONFIG_USER_ONLY - /* Calculate when the counter will next overflow */ - uint64_t remaining_cycles =3D -env->cp15.c15_ccnt; - if (!(env->cp15.c9_pmcr & PMCRLC)) { - remaining_cycles =3D (uint32_t)remaining_cycles; - } - int64_t overflow_in =3D cycles_ns_per(remaining_cycles); - - if (overflow_in > 0) { - int64_t overflow_at; - - if (!sadd64_overflow(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - overflow_in, &overflow_at)) { - ARMCPU *cpu =3D env_archcpu(env); - timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at); - } - } -#endif - - uint64_t prev_cycles =3D env->cp15.c15_ccnt_delta; - if (pmccntr_clockdiv_enabled(env)) { - prev_cycles /=3D 64; - } - env->cp15.c15_ccnt_delta =3D prev_cycles - env->cp15.c15_ccnt; - } -} - -static void pmevcntr_op_start(CPUARMState *env, uint8_t counter) -{ - - uint16_t event =3D env->cp15.c14_pmevtyper[counter] & PMXEVTYPER_EVTCO= UNT; - uint64_t count =3D 0; - if (event_supported(event)) { - uint16_t event_idx =3D supported_event_map[event]; - count =3D pm_events[event_idx].get_count(env); - } - - if (pmu_counter_enabled(env, counter)) { - uint64_t new_pmevcntr =3D count - env->cp15.c14_pmevcntr_delta[cou= nter]; - uint64_t overflow_mask =3D pmevcntr_is_64_bit(env, counter) ? - 1ULL << 63 : 1ULL << 31; - - if (env->cp15.c14_pmevcntr[counter] & ~new_pmevcntr & overflow_mas= k) { - env->cp15.c9_pmovsr |=3D (1 << counter); - pmu_update_irq(env); - } - env->cp15.c14_pmevcntr[counter] =3D new_pmevcntr; - } - env->cp15.c14_pmevcntr_delta[counter] =3D count; -} - -static void pmevcntr_op_finish(CPUARMState *env, uint8_t counter) -{ - if (pmu_counter_enabled(env, counter)) { -#ifndef CONFIG_USER_ONLY - uint16_t event =3D env->cp15.c14_pmevtyper[counter] & PMXEVTYPER_E= VTCOUNT; - uint16_t event_idx =3D supported_event_map[event]; - uint64_t delta =3D -(env->cp15.c14_pmevcntr[counter] + 1); - int64_t overflow_in; - - if (!pmevcntr_is_64_bit(env, counter)) { - delta =3D (uint32_t)delta; - } - overflow_in =3D pm_events[event_idx].ns_per_count(delta); - - if (overflow_in > 0) { - int64_t overflow_at; - - if (!sadd64_overflow(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), - overflow_in, &overflow_at)) { - ARMCPU *cpu =3D env_archcpu(env); - timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at); - } - } -#endif - - env->cp15.c14_pmevcntr_delta[counter] -=3D - env->cp15.c14_pmevcntr[counter]; - } -} - -void pmu_op_start(CPUARMState *env) -{ - unsigned int i; - pmccntr_op_start(env); - for (i =3D 0; i < pmu_num_counters(env); i++) { - pmevcntr_op_start(env, i); - } -} - -void pmu_op_finish(CPUARMState *env) -{ - unsigned int i; - pmccntr_op_finish(env); - for (i =3D 0; i < pmu_num_counters(env); i++) { - pmevcntr_op_finish(env, i); - } -} - -void pmu_pre_el_change(ARMCPU *cpu, void *ignored) -{ - pmu_op_start(&cpu->env); -} - -void pmu_post_el_change(ARMCPU *cpu, void *ignored) -{ - pmu_op_finish(&cpu->env); -} - -void arm_pmu_timer_cb(void *opaque) -{ - ARMCPU *cpu =3D opaque; - - /* - * Update all the counter values based on the current underlying count= s, - * triggering interrupts to be raised, if necessary. pmu_op_finish() a= lso - * has the effect of setting the cpu->pmu_timer to the next earliest t= ime a - * counter may expire. - */ - pmu_op_start(&cpu->env); - pmu_op_finish(&cpu->env); -} - -static void pmcr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - pmu_op_start(env); - - if (value & PMCRC) { - /* The counter has been reset */ - env->cp15.c15_ccnt =3D 0; - } - - if (value & PMCRP) { - unsigned int i; - for (i =3D 0; i < pmu_num_counters(env); i++) { - env->cp15.c14_pmevcntr[i] =3D 0; - } - } - - env->cp15.c9_pmcr &=3D ~PMCR_WRITABLE_MASK; - env->cp15.c9_pmcr |=3D (value & PMCR_WRITABLE_MASK); - - pmu_op_finish(env); -} - -static void pmswinc_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - unsigned int i; - uint64_t overflow_mask, new_pmswinc; - - for (i =3D 0; i < pmu_num_counters(env); i++) { - /* Increment a counter's count iff: */ - if ((value & (1 << i)) && /* counter's bit is set */ - /* counter is enabled and not filtered */ - pmu_counter_enabled(env, i) && - /* counter is SW_INCR */ - (env->cp15.c14_pmevtyper[i] & PMXEVTYPER_EVTCOUNT) =3D=3D = 0x0) { - pmevcntr_op_start(env, i); - - /* - * Detect if this write causes an overflow since we can't pred= ict - * PMSWINC overflows like we can for other events - */ - new_pmswinc =3D env->cp15.c14_pmevcntr[i] + 1; - - overflow_mask =3D pmevcntr_is_64_bit(env, i) ? - 1ULL << 63 : 1ULL << 31; - - if (env->cp15.c14_pmevcntr[i] & ~new_pmswinc & overflow_mask) { - env->cp15.c9_pmovsr |=3D (1 << i); - pmu_update_irq(env); - } - - env->cp15.c14_pmevcntr[i] =3D new_pmswinc; - - pmevcntr_op_finish(env, i); - } - } -} - -static uint64_t pmccntr_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - uint64_t ret; - pmccntr_op_start(env); - ret =3D env->cp15.c15_ccnt; - pmccntr_op_finish(env); - return ret; -} - -static void pmselr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * The value of PMSELR.SEL affects the behavior of PMXEVTYPER and - * PMXEVCNTR. We allow [0..31] to be written to PMSELR here; in the - * meanwhile, we check PMSELR.SEL when PMXEVTYPER and PMXEVCNTR are - * accessed. - */ - env->cp15.c9_pmselr =3D value & 0x1f; -} - -static void pmccntr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - pmccntr_op_start(env); - env->cp15.c15_ccnt =3D value; - pmccntr_op_finish(env); -} - -static void pmccntr_write32(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - uint64_t cur_val =3D pmccntr_read(env, NULL); - - pmccntr_write(env, ri, deposit64(cur_val, 0, 32, value)); -} - -static void pmccfiltr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - pmccntr_op_start(env); - env->cp15.pmccfiltr_el0 =3D value & PMCCFILTR_EL0; - pmccntr_op_finish(env); -} - -static void pmccfiltr_write_a32(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - pmccntr_op_start(env); - /* M is not accessible from AArch32 */ - env->cp15.pmccfiltr_el0 =3D (env->cp15.pmccfiltr_el0 & PMCCFILTR_M) | - (value & PMCCFILTR); - pmccntr_op_finish(env); -} - -static uint64_t pmccfiltr_read_a32(CPUARMState *env, const ARMCPRegInfo *r= i) -{ - /* M is not visible in AArch32 */ - return env->cp15.pmccfiltr_el0 & PMCCFILTR; -} - -static void pmcntenset_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - pmu_op_start(env); - value &=3D pmu_counter_mask(env); - env->cp15.c9_pmcnten |=3D value; - pmu_op_finish(env); -} - -static void pmcntenclr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - pmu_op_start(env); - value &=3D pmu_counter_mask(env); - env->cp15.c9_pmcnten &=3D ~value; - pmu_op_finish(env); -} - -static void pmovsr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - value &=3D pmu_counter_mask(env); - env->cp15.c9_pmovsr &=3D ~value; - pmu_update_irq(env); -} - -static void pmovsset_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - value &=3D pmu_counter_mask(env); - env->cp15.c9_pmovsr |=3D value; - pmu_update_irq(env); -} - -static void pmevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value, const uint8_t counter) -{ - if (counter =3D=3D 31) { - pmccfiltr_write(env, ri, value); - } else if (counter < pmu_num_counters(env)) { - pmevcntr_op_start(env, counter); - - /* - * If this counter's event type is changing, store the current - * underlying count for the new type in c14_pmevcntr_delta[counter= ] so - * pmevcntr_op_finish has the correct baseline when it converts ba= ck to - * a delta. - */ - uint16_t old_event =3D env->cp15.c14_pmevtyper[counter] & - PMXEVTYPER_EVTCOUNT; - uint16_t new_event =3D value & PMXEVTYPER_EVTCOUNT; - if (old_event !=3D new_event) { - uint64_t count =3D 0; - if (event_supported(new_event)) { - uint16_t event_idx =3D supported_event_map[new_event]; - count =3D pm_events[event_idx].get_count(env); - } - env->cp15.c14_pmevcntr_delta[counter] =3D count; - } - - env->cp15.c14_pmevtyper[counter] =3D value & PMXEVTYPER_MASK; - pmevcntr_op_finish(env, counter); - } - /* - * Attempts to access PMXEVTYPER are CONSTRAINED UNPREDICTABLE when - * PMSELR value is equal to or greater than the number of implemented - * counters, but not equal to 0x1f. We opt to behave as a RAZ/WI. - */ -} - -static uint64_t pmevtyper_read(CPUARMState *env, const ARMCPRegInfo *ri, - const uint8_t counter) -{ - if (counter =3D=3D 31) { - return env->cp15.pmccfiltr_el0; - } else if (counter < pmu_num_counters(env)) { - return env->cp15.c14_pmevtyper[counter]; - } else { - /* - * We opt to behave as a RAZ/WI when attempts to access PMXEVTYPER - * are CONSTRAINED UNPREDICTABLE. See comments in pmevtyper_write(). - */ - return 0; - } -} - -static void pmevtyper_writefn(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - uint8_t counter =3D ((ri->crm & 3) << 3) | (ri->opc2 & 7); - pmevtyper_write(env, ri, value, counter); -} - -static void pmevtyper_rawwrite(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - uint8_t counter =3D ((ri->crm & 3) << 3) | (ri->opc2 & 7); - env->cp15.c14_pmevtyper[counter] =3D value; - - /* - * pmevtyper_rawwrite is called between a pair of pmu_op_start and - * pmu_op_finish calls when loading saved state for a migration. Becau= se - * we're potentially updating the type of event here, the value writte= n to - * c14_pmevcntr_delta by the preceeding pmu_op_start call may be for a - * different counter type. Therefore, we need to set this value to the - * current count for the counter type we're writing so that pmu_op_fin= ish - * has the correct count for its calculation. - */ - uint16_t event =3D value & PMXEVTYPER_EVTCOUNT; - if (event_supported(event)) { - uint16_t event_idx =3D supported_event_map[event]; - env->cp15.c14_pmevcntr_delta[counter] =3D - pm_events[event_idx].get_count(env); - } -} - -static uint64_t pmevtyper_readfn(CPUARMState *env, const ARMCPRegInfo *ri) -{ - uint8_t counter =3D ((ri->crm & 3) << 3) | (ri->opc2 & 7); - return pmevtyper_read(env, ri, counter); -} - -static void pmxevtyper_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - pmevtyper_write(env, ri, value, env->cp15.c9_pmselr & 31); -} - -static uint64_t pmxevtyper_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return pmevtyper_read(env, ri, env->cp15.c9_pmselr & 31); -} - -static void pmevcntr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value, uint8_t counter) -{ - if (!cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) { - /* Before FEAT_PMUv3p5, top 32 bits of event counters are RES0 */ - value &=3D MAKE_64BIT_MASK(0, 32); - } - if (counter < pmu_num_counters(env)) { - pmevcntr_op_start(env, counter); - env->cp15.c14_pmevcntr[counter] =3D value; - pmevcntr_op_finish(env, counter); - } - /* - * We opt to behave as a RAZ/WI when attempts to access PM[X]EVCNTR - * are CONSTRAINED UNPREDICTABLE. - */ -} - -static uint64_t pmevcntr_read(CPUARMState *env, const ARMCPRegInfo *ri, - uint8_t counter) -{ - if (counter < pmu_num_counters(env)) { - uint64_t ret; - pmevcntr_op_start(env, counter); - ret =3D env->cp15.c14_pmevcntr[counter]; - pmevcntr_op_finish(env, counter); - if (!cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) { - /* Before FEAT_PMUv3p5, top 32 bits of event counters are RES0= */ - ret &=3D MAKE_64BIT_MASK(0, 32); - } - return ret; - } else { - /* - * We opt to behave as a RAZ/WI when attempts to access PM[X]EVCNTR - * are CONSTRAINED UNPREDICTABLE. - */ - return 0; - } -} - -static void pmevcntr_writefn(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - uint8_t counter =3D ((ri->crm & 3) << 3) | (ri->opc2 & 7); - pmevcntr_write(env, ri, value, counter); -} - -static uint64_t pmevcntr_readfn(CPUARMState *env, const ARMCPRegInfo *ri) -{ - uint8_t counter =3D ((ri->crm & 3) << 3) | (ri->opc2 & 7); - return pmevcntr_read(env, ri, counter); -} - -static void pmevcntr_rawwrite(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - uint8_t counter =3D ((ri->crm & 3) << 3) | (ri->opc2 & 7); - assert(counter < pmu_num_counters(env)); - env->cp15.c14_pmevcntr[counter] =3D value; - pmevcntr_write(env, ri, value, counter); -} - -static uint64_t pmevcntr_rawread(CPUARMState *env, const ARMCPRegInfo *ri) -{ - uint8_t counter =3D ((ri->crm & 3) << 3) | (ri->opc2 & 7); - assert(counter < pmu_num_counters(env)); - return env->cp15.c14_pmevcntr[counter]; -} - -static void pmxevcntr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - pmevcntr_write(env, ri, value, env->cp15.c9_pmselr & 31); -} - -static uint64_t pmxevcntr_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return pmevcntr_read(env, ri, env->cp15.c9_pmselr & 31); -} - -static void pmuserenr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - if (arm_feature(env, ARM_FEATURE_V8)) { - env->cp15.c9_pmuserenr =3D value & 0xf; - } else { - env->cp15.c9_pmuserenr =3D value & 1; - } -} - -static void pmintenset_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* We have no event counters so only the C bit can be changed */ - value &=3D pmu_counter_mask(env); - env->cp15.c9_pminten |=3D value; - pmu_update_irq(env); -} - -static void pmintenclr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - value &=3D pmu_counter_mask(env); - env->cp15.c9_pminten &=3D ~value; - pmu_update_irq(env); -} - -static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * Note that even though the AArch64 view of this register has bits - * [10:0] all RES0 we can only mask the bottom 5, to comply with the - * architectural requirements for bits which are RES0 only in some - * contexts. (ARMv8 would permit us to do no masking at all, but ARMv7 - * requires the bottom five bits to be RAZ/WI because they're UNK/SBZP= .) - */ - raw_write(env, ri, value & ~0x1FULL); -} - -static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t v= alue) -{ - /* Begin with base v8.0 state. */ - uint64_t valid_mask =3D 0x3fff; - ARMCPU *cpu =3D env_archcpu(env); - uint64_t changed; - - /* - * Because SCR_EL3 is the "real" cpreg and SCR is the alias, reset alw= ays - * passes the reginfo for SCR_EL3, which has type ARM_CP_STATE_AA64. - * Instead, choose the format based on the mode of EL3. - */ - if (arm_el_is_aa64(env, 3)) { - value |=3D SCR_FW | SCR_AW; /* RES1 */ - valid_mask &=3D ~SCR_NET; /* RES0 */ - - if (!cpu_isar_feature(aa64_aa32_el1, cpu) && - !cpu_isar_feature(aa64_aa32_el2, cpu)) { - value |=3D SCR_RW; /* RAO/WI */ - } - if (cpu_isar_feature(aa64_ras, cpu)) { - valid_mask |=3D SCR_TERR; - } - if (cpu_isar_feature(aa64_lor, cpu)) { - valid_mask |=3D SCR_TLOR; - } - if (cpu_isar_feature(aa64_pauth, cpu)) { - valid_mask |=3D SCR_API | SCR_APK; - } - if (cpu_isar_feature(aa64_sel2, cpu)) { - valid_mask |=3D SCR_EEL2; - } - if (cpu_isar_feature(aa64_mte, cpu)) { - valid_mask |=3D SCR_ATA; - } - if (cpu_isar_feature(aa64_scxtnum, cpu)) { - valid_mask |=3D SCR_ENSCXT; - } - if (cpu_isar_feature(aa64_doublefault, cpu)) { - valid_mask |=3D SCR_EASE | SCR_NMEA; - } - if (cpu_isar_feature(aa64_sme, cpu)) { - valid_mask |=3D SCR_ENTP2; - } - } else { - valid_mask &=3D ~(SCR_RW | SCR_ST); - if (cpu_isar_feature(aa32_ras, cpu)) { - valid_mask |=3D SCR_TERR; - } - } - - if (!arm_feature(env, ARM_FEATURE_EL2)) { - valid_mask &=3D ~SCR_HCE; - - /* - * On ARMv7, SMD (or SCD as it is called in v7) is only - * supported if EL2 exists. The bit is UNK/SBZP when - * EL2 is unavailable. In QEMU ARMv7, we force it to always zero - * when EL2 is unavailable. - * On ARMv8, this bit is always available. - */ - if (arm_feature(env, ARM_FEATURE_V7) && - !arm_feature(env, ARM_FEATURE_V8)) { - valid_mask &=3D ~SCR_SMD; - } - } - - /* Clear all-context RES0 bits. */ - value &=3D valid_mask; - changed =3D env->cp15.scr_el3 ^ value; - env->cp15.scr_el3 =3D value; - - /* - * If SCR_EL3.NS changes, i.e. arm_is_secure_below_el3, then - * we must invalidate all TLBs below EL3. - */ - if (changed & SCR_NS) { - tlb_flush_by_mmuidx(env_cpu(env), (ARMMMUIdxBit_E10_0 | - ARMMMUIdxBit_E20_0 | - ARMMMUIdxBit_E10_1 | - ARMMMUIdxBit_E20_2 | - ARMMMUIdxBit_E10_1_PAN | - ARMMMUIdxBit_E20_2_PAN | - ARMMMUIdxBit_E2)); - } -} - -static void scr_reset(CPUARMState *env, const ARMCPRegInfo *ri) -{ - /* - * scr_write will set the RES1 bits on an AArch64-only CPU. - * The reset value will be 0x30 on an AArch64-only CPU and 0 otherwise. - */ - scr_write(env, ri, 0); -} - -static CPAccessResult access_tid4(CPUARMState *env, - const ARMCPRegInfo *ri, - bool isread) -{ - if (arm_current_el(env) =3D=3D 1 && - (arm_hcr_el2_eff(env) & (HCR_TID2 | HCR_TID4))) { - return CP_ACCESS_TRAP_EL2; - } - - return CP_ACCESS_OK; -} - -static uint64_t ccsidr_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - ARMCPU *cpu =3D env_archcpu(env); - - /* - * Acquire the CSSELR index from the bank corresponding to the CCSIDR - * bank - */ - uint32_t index =3D A32_BANKED_REG_GET(env, csselr, - ri->secure & ARM_CP_SECSTATE_S); - - return cpu->ccsidr[index]; -} - -static void csselr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - raw_write(env, ri, value & 0xf); -} - -static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - CPUState *cs =3D env_cpu(env); - bool el1 =3D arm_current_el(env) =3D=3D 1; - uint64_t hcr_el2 =3D el1 ? arm_hcr_el2_eff(env) : 0; - uint64_t ret =3D 0; - - if (hcr_el2 & HCR_IMO) { - if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) { - ret |=3D CPSR_I; - } - } else { - if (cs->interrupt_request & CPU_INTERRUPT_HARD) { - ret |=3D CPSR_I; - } - } - - if (hcr_el2 & HCR_FMO) { - if (cs->interrupt_request & CPU_INTERRUPT_VFIQ) { - ret |=3D CPSR_F; - } - } else { - if (cs->interrupt_request & CPU_INTERRUPT_FIQ) { - ret |=3D CPSR_F; - } - } - - if (hcr_el2 & HCR_AMO) { - if (cs->interrupt_request & CPU_INTERRUPT_VSERR) { - ret |=3D CPSR_A; - } - } - - return ret; -} - -static CPAccessResult access_aa64_tid1(CPUARMState *env, const ARMCPRegInf= o *ri, - bool isread) -{ - if (arm_current_el(env) =3D=3D 1 && (arm_hcr_el2_eff(env) & HCR_TID1))= { - return CP_ACCESS_TRAP_EL2; - } - - return CP_ACCESS_OK; -} - -static CPAccessResult access_aa32_tid1(CPUARMState *env, const ARMCPRegInf= o *ri, - bool isread) -{ - if (arm_feature(env, ARM_FEATURE_V8)) { - return access_aa64_tid1(env, ri, isread); - } - - return CP_ACCESS_OK; -} - -static const ARMCPRegInfo v7_cp_reginfo[] =3D { - /* the old v6 WFI, UNPREDICTABLE in v7 but we choose to NOP */ - { .name =3D "NOP", .cp =3D 15, .crn =3D 7, .crm =3D 0, .opc1 =3D 0, .o= pc2 =3D 4, - .access =3D PL1_W, .type =3D ARM_CP_NOP }, - /* - * Performance monitors are implementation defined in v7, - * but with an ARM recommended set of registers, which we - * follow. - * - * Performance registers fall into three categories: - * (a) always UNDEF in PL0, RW in PL1 (PMINTENSET, PMINTENCLR) - * (b) RO in PL0 (ie UNDEF on write), RW in PL1 (PMUSERENR) - * (c) UNDEF in PL0 if PMUSERENR.EN=3D=3D0, otherwise accessible (all= others) - * For the cases controlled by PMUSERENR we must set .access to PL0_RW - * or PL0_RO as appropriate and then check PMUSERENR in the helper fn. - */ - { .name =3D "PMCNTENSET", .cp =3D 15, .crn =3D 9, .crm =3D 12, .opc1 = =3D 0, .opc2 =3D 1, - .access =3D PL0_RW, .type =3D ARM_CP_ALIAS | ARM_CP_IO, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pmcnten), - .writefn =3D pmcntenset_write, - .accessfn =3D pmreg_access, - .raw_writefn =3D raw_write }, - { .name =3D "PMCNTENSET_EL0", .state =3D ARM_CP_STATE_AA64, .type =3D = ARM_CP_IO, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D 1, - .access =3D PL0_RW, .accessfn =3D pmreg_access, - .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pmcnten), .resetvalue= =3D 0, - .writefn =3D pmcntenset_write, .raw_writefn =3D raw_write }, - { .name =3D "PMCNTENCLR", .cp =3D 15, .crn =3D 9, .crm =3D 12, .opc1 = =3D 0, .opc2 =3D 2, - .access =3D PL0_RW, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pmcnten), - .accessfn =3D pmreg_access, - .writefn =3D pmcntenclr_write, - .type =3D ARM_CP_ALIAS | ARM_CP_IO }, - { .name =3D "PMCNTENCLR_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D 2, - .access =3D PL0_RW, .accessfn =3D pmreg_access, - .type =3D ARM_CP_ALIAS | ARM_CP_IO, - .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pmcnten), - .writefn =3D pmcntenclr_write }, - { .name =3D "PMOVSR", .cp =3D 15, .crn =3D 9, .crm =3D 12, .opc1 =3D 0= , .opc2 =3D 3, - .access =3D PL0_RW, .type =3D ARM_CP_IO, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pmovsr), - .accessfn =3D pmreg_access, - .writefn =3D pmovsr_write, - .raw_writefn =3D raw_write }, - { .name =3D "PMOVSCLR_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D 3, - .access =3D PL0_RW, .accessfn =3D pmreg_access, - .type =3D ARM_CP_ALIAS | ARM_CP_IO, - .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pmovsr), - .writefn =3D pmovsr_write, - .raw_writefn =3D raw_write }, - { .name =3D "PMSWINC", .cp =3D 15, .crn =3D 9, .crm =3D 12, .opc1 =3D = 0, .opc2 =3D 4, - .access =3D PL0_W, .accessfn =3D pmreg_access_swinc, - .type =3D ARM_CP_NO_RAW | ARM_CP_IO, - .writefn =3D pmswinc_write }, - { .name =3D "PMSWINC_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D 4, - .access =3D PL0_W, .accessfn =3D pmreg_access_swinc, - .type =3D ARM_CP_NO_RAW | ARM_CP_IO, - .writefn =3D pmswinc_write }, - { .name =3D "PMSELR", .cp =3D 15, .crn =3D 9, .crm =3D 12, .opc1 =3D 0= , .opc2 =3D 5, - .access =3D PL0_RW, .type =3D ARM_CP_ALIAS, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pmselr), - .accessfn =3D pmreg_access_selr, .writefn =3D pmselr_write, - .raw_writefn =3D raw_write}, - { .name =3D "PMSELR_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D 5, - .access =3D PL0_RW, .accessfn =3D pmreg_access_selr, - .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pmselr), - .writefn =3D pmselr_write, .raw_writefn =3D raw_write, }, - { .name =3D "PMCCNTR", .cp =3D 15, .crn =3D 9, .crm =3D 13, .opc1 =3D = 0, .opc2 =3D 0, - .access =3D PL0_RW, .resetvalue =3D 0, .type =3D ARM_CP_ALIAS | ARM_= CP_IO, - .readfn =3D pmccntr_read, .writefn =3D pmccntr_write32, - .accessfn =3D pmreg_access_ccntr }, - { .name =3D "PMCCNTR_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 13, .opc2 =3D 0, - .access =3D PL0_RW, .accessfn =3D pmreg_access_ccntr, - .type =3D ARM_CP_IO, - .fieldoffset =3D offsetof(CPUARMState, cp15.c15_ccnt), - .readfn =3D pmccntr_read, .writefn =3D pmccntr_write, - .raw_readfn =3D raw_read, .raw_writefn =3D raw_write, }, - { .name =3D "PMCCFILTR", .cp =3D 15, .opc1 =3D 0, .crn =3D 14, .crm = =3D 15, .opc2 =3D 7, - .writefn =3D pmccfiltr_write_a32, .readfn =3D pmccfiltr_read_a32, - .access =3D PL0_RW, .accessfn =3D pmreg_access, - .type =3D ARM_CP_ALIAS | ARM_CP_IO, - .resetvalue =3D 0, }, - { .name =3D "PMCCFILTR_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 15, .opc2 =3D 7, - .writefn =3D pmccfiltr_write, .raw_writefn =3D raw_write, - .access =3D PL0_RW, .accessfn =3D pmreg_access, - .type =3D ARM_CP_IO, - .fieldoffset =3D offsetof(CPUARMState, cp15.pmccfiltr_el0), - .resetvalue =3D 0, }, - { .name =3D "PMXEVTYPER", .cp =3D 15, .crn =3D 9, .crm =3D 13, .opc1 = =3D 0, .opc2 =3D 1, - .access =3D PL0_RW, .type =3D ARM_CP_NO_RAW | ARM_CP_IO, - .accessfn =3D pmreg_access, - .writefn =3D pmxevtyper_write, .readfn =3D pmxevtyper_read }, - { .name =3D "PMXEVTYPER_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 13, .opc2 =3D 1, - .access =3D PL0_RW, .type =3D ARM_CP_NO_RAW | ARM_CP_IO, - .accessfn =3D pmreg_access, - .writefn =3D pmxevtyper_write, .readfn =3D pmxevtyper_read }, - { .name =3D "PMXEVCNTR", .cp =3D 15, .crn =3D 9, .crm =3D 13, .opc1 = =3D 0, .opc2 =3D 2, - .access =3D PL0_RW, .type =3D ARM_CP_NO_RAW | ARM_CP_IO, - .accessfn =3D pmreg_access_xevcntr, - .writefn =3D pmxevcntr_write, .readfn =3D pmxevcntr_read }, - { .name =3D "PMXEVCNTR_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 13, .opc2 =3D 2, - .access =3D PL0_RW, .type =3D ARM_CP_NO_RAW | ARM_CP_IO, - .accessfn =3D pmreg_access_xevcntr, - .writefn =3D pmxevcntr_write, .readfn =3D pmxevcntr_read }, - { .name =3D "PMUSERENR", .cp =3D 15, .crn =3D 9, .crm =3D 14, .opc1 = =3D 0, .opc2 =3D 0, - .access =3D PL0_R | PL1_RW, .accessfn =3D access_tpm, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pmuserenr), - .resetvalue =3D 0, - .writefn =3D pmuserenr_write, .raw_writefn =3D raw_write }, - { .name =3D "PMUSERENR_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 14, .opc2 =3D 0, - .access =3D PL0_R | PL1_RW, .accessfn =3D access_tpm, .type =3D ARM_= CP_ALIAS, - .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pmuserenr), - .resetvalue =3D 0, - .writefn =3D pmuserenr_write, .raw_writefn =3D raw_write }, - { .name =3D "PMINTENSET", .cp =3D 15, .crn =3D 9, .crm =3D 14, .opc1 = =3D 0, .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_tpm, - .type =3D ARM_CP_ALIAS | ARM_CP_IO, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pminten), - .resetvalue =3D 0, - .writefn =3D pmintenset_write, .raw_writefn =3D raw_write }, - { .name =3D "PMINTENSET_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 9, .crm =3D 14, .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_tpm, - .type =3D ARM_CP_IO, - .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pminten), - .writefn =3D pmintenset_write, .raw_writefn =3D raw_write, - .resetvalue =3D 0x0 }, - { .name =3D "PMINTENCLR", .cp =3D 15, .crn =3D 9, .crm =3D 14, .opc1 = =3D 0, .opc2 =3D 2, - .access =3D PL1_RW, .accessfn =3D access_tpm, - .type =3D ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW, - .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pminten), - .writefn =3D pmintenclr_write, }, - { .name =3D "PMINTENCLR_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 9, .crm =3D 14, .opc2 =3D 2, - .access =3D PL1_RW, .accessfn =3D access_tpm, - .type =3D ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW, - .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pminten), - .writefn =3D pmintenclr_write }, - { .name =3D "CCSIDR", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .crn =3D 0, .crm =3D 0, .opc1 =3D 1, .opc2 =3D 0, - .access =3D PL1_R, - .accessfn =3D access_tid4, - .readfn =3D ccsidr_read, .type =3D ARM_CP_NO_RAW }, - { .name =3D "CSSELR", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .crn =3D 0, .crm =3D 0, .opc1 =3D 2, .opc2 =3D 0, - .access =3D PL1_RW, - .accessfn =3D access_tid4, - .writefn =3D csselr_write, .resetvalue =3D 0, - .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.csselr_s), - offsetof(CPUARMState, cp15.csselr_ns) } }, - /* - * Auxiliary ID register: this actually has an IMPDEF value but for now - * just RAZ for all cores: - */ - { .name =3D "AIDR", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 1, .crn =3D 0, .crm =3D 0, .opc2 =3D 7, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid1, - .resetvalue =3D 0 }, - /* - * Auxiliary fault status registers: these also are IMPDEF, and we - * choose to RAZ/WI for all cores. - */ - { .name =3D "AFSR0_EL1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 5, .crm =3D 1, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - { .name =3D "AFSR1_EL1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 5, .crm =3D 1, .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - /* - * MAIR can just read-as-written because we don't implement caches - * and so don't need to care about memory attributes. - */ - { .name =3D "MAIR_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 10, .crm =3D 2, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .fieldoffset =3D offsetof(CPUARMState, cp15.mair_el[1]), - .resetvalue =3D 0 }, - { .name =3D "MAIR_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 10, .crm =3D 2, .opc2 =3D 0, - .access =3D PL3_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.mair= _el[3]), - .resetvalue =3D 0 }, - /* - * For non-long-descriptor page tables these are PRRR and NMRR; - * regardless they still act as reads-as-written for QEMU. - */ - /* - * MAIR0/1 are defined separately from their 64-bit counterpart which - * allows them to assign the correct fieldoffset based on the endiann= ess - * handled in the field definitions. - */ - { .name =3D "MAIR0", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 0, .crn =3D 10, .crm =3D 2, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.mair0_s), - offsetof(CPUARMState, cp15.mair0_ns) }, - .resetfn =3D arm_cp_reset_ignore }, - { .name =3D "MAIR1", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 0, .crn =3D 10, .crm =3D 2, .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.mair1_s), - offsetof(CPUARMState, cp15.mair1_ns) }, - .resetfn =3D arm_cp_reset_ignore }, - { .name =3D "ISR_EL1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 12, .crm =3D 1, .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_R, .readfn =3D isr_read }, - /* 32 bit ITLB invalidates */ - { .name =3D "ITLBIALL", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D = 5, .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, - .writefn =3D tlbiall_write }, - { .name =3D "ITLBIMVA", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D = 5, .opc2 =3D 1, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, - .writefn =3D tlbimva_write }, - { .name =3D "ITLBIASID", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D= 5, .opc2 =3D 2, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, - .writefn =3D tlbiasid_write }, - /* 32 bit DTLB invalidates */ - { .name =3D "DTLBIALL", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D = 6, .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, - .writefn =3D tlbiall_write }, - { .name =3D "DTLBIMVA", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D = 6, .opc2 =3D 1, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, - .writefn =3D tlbimva_write }, - { .name =3D "DTLBIASID", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D= 6, .opc2 =3D 2, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, - .writefn =3D tlbiasid_write }, - /* 32 bit TLB invalidates */ - { .name =3D "TLBIALL", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D 7= , .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, - .writefn =3D tlbiall_write }, - { .name =3D "TLBIMVA", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D 7= , .opc2 =3D 1, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, - .writefn =3D tlbimva_write }, - { .name =3D "TLBIASID", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D = 7, .opc2 =3D 2, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, - .writefn =3D tlbiasid_write }, - { .name =3D "TLBIMVAA", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D = 7, .opc2 =3D 3, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, - .writefn =3D tlbimvaa_write }, -}; - -static const ARMCPRegInfo v7mp_cp_reginfo[] =3D { - /* 32 bit TLB invalidates, Inner Shareable */ - { .name =3D "TLBIALLIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D= 3, .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= bis, - .writefn =3D tlbiall_is_write }, - { .name =3D "TLBIMVAIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D= 3, .opc2 =3D 1, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= bis, - .writefn =3D tlbimva_is_write }, - { .name =3D "TLBIASIDIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm = =3D 3, .opc2 =3D 2, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= bis, - .writefn =3D tlbiasid_is_write }, - { .name =3D "TLBIMVAAIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm = =3D 3, .opc2 =3D 3, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= bis, - .writefn =3D tlbimvaa_is_write }, -}; - -static const ARMCPRegInfo pmovsset_cp_reginfo[] =3D { - /* PMOVSSET is not implemented in v7 before v7ve */ - { .name =3D "PMOVSSET", .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D = 14, .opc2 =3D 3, - .access =3D PL0_RW, .accessfn =3D pmreg_access, - .type =3D ARM_CP_ALIAS | ARM_CP_IO, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pmovsr), - .writefn =3D pmovsset_write, - .raw_writefn =3D raw_write }, - { .name =3D "PMOVSSET_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 14, .opc2 =3D 3, - .access =3D PL0_RW, .accessfn =3D pmreg_access, - .type =3D ARM_CP_ALIAS | ARM_CP_IO, - .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pmovsr), - .writefn =3D pmovsset_write, - .raw_writefn =3D raw_write }, -}; - -static void teecr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - value &=3D 1; - env->teecr =3D value; -} - -static CPAccessResult teecr_access(CPUARMState *env, const ARMCPRegInfo *r= i, - bool isread) -{ - /* - * HSTR.TTEE only exists in v7A, not v8A, but v8A doesn't have T2EE - * at all, so we don't need to check whether we're v8A. - */ - if (arm_current_el(env) < 2 && !arm_is_secure_below_el3(env) && - (env->cp15.hstr_el2 & HSTR_TTEE)) { - return CP_ACCESS_TRAP_EL2; - } - return CP_ACCESS_OK; -} - -static CPAccessResult teehbr_access(CPUARMState *env, const ARMCPRegInfo *= ri, - bool isread) -{ - if (arm_current_el(env) =3D=3D 0 && (env->teecr & 1)) { - return CP_ACCESS_TRAP; - } - return teecr_access(env, ri, isread); -} - -static const ARMCPRegInfo t2ee_cp_reginfo[] =3D { - { .name =3D "TEECR", .cp =3D 14, .crn =3D 0, .crm =3D 0, .opc1 =3D 6, = .opc2 =3D 0, - .access =3D PL1_RW, .fieldoffset =3D offsetof(CPUARMState, teecr), - .resetvalue =3D 0, - .writefn =3D teecr_write, .accessfn =3D teecr_access }, - { .name =3D "TEEHBR", .cp =3D 14, .crn =3D 1, .crm =3D 0, .opc1 =3D 6,= .opc2 =3D 0, - .access =3D PL0_RW, .fieldoffset =3D offsetof(CPUARMState, teehbr), - .accessfn =3D teehbr_access, .resetvalue =3D 0 }, -}; - -static const ARMCPRegInfo v6k_cp_reginfo[] =3D { - { .name =3D "TPIDR_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 2, .crn =3D 13, .crm =3D 0, - .access =3D PL0_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.tpidr_el[0]), .resetvalu= e =3D 0 }, - { .name =3D "TPIDRURW", .cp =3D 15, .crn =3D 13, .crm =3D 0, .opc1 =3D= 0, .opc2 =3D 2, - .access =3D PL0_RW, - .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.tpidrurw_s), - offsetoflow32(CPUARMState, cp15.tpidrurw_ns) = }, - .resetfn =3D arm_cp_reset_ignore }, - { .name =3D "TPIDRRO_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 3, .crn =3D 13, .crm =3D 0, - .access =3D PL0_R | PL1_W, - .fieldoffset =3D offsetof(CPUARMState, cp15.tpidrro_el[0]), - .resetvalue =3D 0}, - { .name =3D "TPIDRURO", .cp =3D 15, .crn =3D 13, .crm =3D 0, .opc1 =3D= 0, .opc2 =3D 3, - .access =3D PL0_R | PL1_W, - .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.tpidruro_s), - offsetoflow32(CPUARMState, cp15.tpidruro_ns) = }, - .resetfn =3D arm_cp_reset_ignore }, - { .name =3D "TPIDR_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .opc2 =3D 4, .crn =3D 13, .crm =3D 0, - .access =3D PL1_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.tpidr_el[1]), .resetvalu= e =3D 0 }, - { .name =3D "TPIDRPRW", .opc1 =3D 0, .cp =3D 15, .crn =3D 13, .crm =3D= 0, .opc2 =3D 4, - .access =3D PL1_RW, - .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.tpidrprw_s), - offsetoflow32(CPUARMState, cp15.tpidrprw_ns) = }, - .resetvalue =3D 0 }, -}; - -#ifndef CONFIG_USER_ONLY - -static CPAccessResult gt_cntfrq_access(CPUARMState *env, const ARMCPRegInf= o *ri, - bool isread) -{ - /* - * CNTFRQ: not visible from PL0 if both PL0PCTEN and PL0VCTEN are zero. - * Writable only at the highest implemented exception level. - */ - int el =3D arm_current_el(env); - uint64_t hcr; - uint32_t cntkctl; - - switch (el) { - case 0: - hcr =3D arm_hcr_el2_eff(env); - if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { - cntkctl =3D env->cp15.cnthctl_el2; - } else { - cntkctl =3D env->cp15.c14_cntkctl; - } - if (!extract32(cntkctl, 0, 2)) { - return CP_ACCESS_TRAP; - } - break; - case 1: - if (!isread && ri->state =3D=3D ARM_CP_STATE_AA32 && - arm_is_secure_below_el3(env)) { - /* Accesses from 32-bit Secure EL1 UNDEF (*not* trap to EL3!) = */ - return CP_ACCESS_TRAP_UNCATEGORIZED; - } - break; - case 2: - case 3: - break; - } - - if (!isread && el < arm_highest_el(env)) { - return CP_ACCESS_TRAP_UNCATEGORIZED; - } - - return CP_ACCESS_OK; -} - -static CPAccessResult gt_counter_access(CPUARMState *env, int timeridx, - bool isread) -{ - unsigned int cur_el =3D arm_current_el(env); - bool has_el2 =3D arm_is_el2_enabled(env); - uint64_t hcr =3D arm_hcr_el2_eff(env); - - switch (cur_el) { - case 0: - /* If HCR_EL2. =3D=3D '11': check CNTHCTL_EL2.EL0[PV]CTEN= . */ - if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { - return (extract32(env->cp15.cnthctl_el2, timeridx, 1) - ? CP_ACCESS_OK : CP_ACCESS_TRAP_EL2); - } - - /* CNT[PV]CT: not visible from PL0 if EL0[PV]CTEN is zero */ - if (!extract32(env->cp15.c14_cntkctl, timeridx, 1)) { - return CP_ACCESS_TRAP; - } - - /* If HCR_EL2. =3D=3D '10': check CNTHCTL_EL2.EL1PCTEN. */ - if (hcr & HCR_E2H) { - if (timeridx =3D=3D GTIMER_PHYS && - !extract32(env->cp15.cnthctl_el2, 10, 1)) { - return CP_ACCESS_TRAP_EL2; - } - } else { - /* If HCR_EL2. =3D=3D 0: check CNTHCTL_EL2.EL1PCEN. */ - if (has_el2 && timeridx =3D=3D GTIMER_PHYS && - !extract32(env->cp15.cnthctl_el2, 1, 1)) { - return CP_ACCESS_TRAP_EL2; - } - } - break; - - case 1: - /* Check CNTHCTL_EL2.EL1PCTEN, which changes location based on E2H= . */ - if (has_el2 && timeridx =3D=3D GTIMER_PHYS && - (hcr & HCR_E2H - ? !extract32(env->cp15.cnthctl_el2, 10, 1) - : !extract32(env->cp15.cnthctl_el2, 0, 1))) { - return CP_ACCESS_TRAP_EL2; - } - break; - } - return CP_ACCESS_OK; -} - -static CPAccessResult gt_timer_access(CPUARMState *env, int timeridx, - bool isread) -{ - unsigned int cur_el =3D arm_current_el(env); - bool has_el2 =3D arm_is_el2_enabled(env); - uint64_t hcr =3D arm_hcr_el2_eff(env); - - switch (cur_el) { - case 0: - if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { - /* If HCR_EL2. =3D=3D '11': check CNTHCTL_EL2.EL0[PV]= TEN. */ - return (extract32(env->cp15.cnthctl_el2, 9 - timeridx, 1) - ? CP_ACCESS_OK : CP_ACCESS_TRAP_EL2); - } - - /* - * CNT[PV]_CVAL, CNT[PV]_CTL, CNT[PV]_TVAL: not visible from - * EL0 if EL0[PV]TEN is zero. - */ - if (!extract32(env->cp15.c14_cntkctl, 9 - timeridx, 1)) { - return CP_ACCESS_TRAP; - } - /* fall through */ - - case 1: - if (has_el2 && timeridx =3D=3D GTIMER_PHYS) { - if (hcr & HCR_E2H) { - /* If HCR_EL2. =3D=3D '10': check CNTHCTL_EL2.EL1= PTEN. */ - if (!extract32(env->cp15.cnthctl_el2, 11, 1)) { - return CP_ACCESS_TRAP_EL2; - } - } else { - /* If HCR_EL2. =3D=3D 0: check CNTHCTL_EL2.EL1PCEN. */ - if (!extract32(env->cp15.cnthctl_el2, 1, 1)) { - return CP_ACCESS_TRAP_EL2; - } - } - } - break; - } - return CP_ACCESS_OK; -} - -static CPAccessResult gt_pct_access(CPUARMState *env, - const ARMCPRegInfo *ri, - bool isread) -{ - return gt_counter_access(env, GTIMER_PHYS, isread); -} - -static CPAccessResult gt_vct_access(CPUARMState *env, - const ARMCPRegInfo *ri, - bool isread) -{ - return gt_counter_access(env, GTIMER_VIRT, isread); -} - -static CPAccessResult gt_ptimer_access(CPUARMState *env, const ARMCPRegInf= o *ri, - bool isread) -{ - return gt_timer_access(env, GTIMER_PHYS, isread); -} - -static CPAccessResult gt_vtimer_access(CPUARMState *env, const ARMCPRegInf= o *ri, - bool isread) -{ - return gt_timer_access(env, GTIMER_VIRT, isread); -} - -static CPAccessResult gt_stimer_access(CPUARMState *env, - const ARMCPRegInfo *ri, - bool isread) -{ - /* - * The AArch64 register view of the secure physical timer is - * always accessible from EL3, and configurably accessible from - * Secure EL1. - */ - switch (arm_current_el(env)) { - case 1: - if (!arm_is_secure(env)) { - return CP_ACCESS_TRAP; - } - if (!(env->cp15.scr_el3 & SCR_ST)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; - case 0: - case 2: - return CP_ACCESS_TRAP; - case 3: - return CP_ACCESS_OK; - default: - g_assert_not_reached(); - } -} - -static uint64_t gt_get_countervalue(CPUARMState *env) -{ - ARMCPU *cpu =3D env_archcpu(env); - - return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / gt_cntfrq_period_ns(cpu= ); -} - -static void gt_recalc_timer(ARMCPU *cpu, int timeridx) -{ - ARMGenericTimer *gt =3D &cpu->env.cp15.c14_timer[timeridx]; - - if (gt->ctl & 1) { - /* - * Timer enabled: calculate and set current ISTATUS, irq, and - * reset timer to when ISTATUS next has to change - */ - uint64_t offset =3D timeridx =3D=3D GTIMER_VIRT ? - cpu->env.cp15.cntvoff_el2 : 0; - uint64_t count =3D gt_get_countervalue(&cpu->env); - /* Note that this must be unsigned 64 bit arithmetic: */ - int istatus =3D count - offset >=3D gt->cval; - uint64_t nexttick; - int irqstate; - - gt->ctl =3D deposit32(gt->ctl, 2, 1, istatus); - - irqstate =3D (istatus && !(gt->ctl & 2)); - qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate); - - if (istatus) { - /* Next transition is when count rolls back over to zero */ - nexttick =3D UINT64_MAX; - } else { - /* Next transition is when we hit cval */ - nexttick =3D gt->cval + offset; - } - /* - * Note that the desired next expiry time might be beyond the - * signed-64-bit range of a QEMUTimer -- in this case we just - * set the timer for as far in the future as possible. When the - * timer expires we will reset the timer for any remaining period. - */ - if (nexttick > INT64_MAX / gt_cntfrq_period_ns(cpu)) { - timer_mod_ns(cpu->gt_timer[timeridx], INT64_MAX); - } else { - timer_mod(cpu->gt_timer[timeridx], nexttick); - } - trace_arm_gt_recalc(timeridx, irqstate, nexttick); - } else { - /* Timer disabled: ISTATUS and timer output always clear */ - gt->ctl &=3D ~4; - qemu_set_irq(cpu->gt_timer_outputs[timeridx], 0); - timer_del(cpu->gt_timer[timeridx]); - trace_arm_gt_recalc_disabled(timeridx); - } -} - -static void gt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri, - int timeridx) -{ - ARMCPU *cpu =3D env_archcpu(env); - - timer_del(cpu->gt_timer[timeridx]); -} - -static uint64_t gt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return gt_get_countervalue(env); -} - -static uint64_t gt_virt_cnt_offset(CPUARMState *env) -{ - uint64_t hcr; - - switch (arm_current_el(env)) { - case 2: - hcr =3D arm_hcr_el2_eff(env); - if (hcr & HCR_E2H) { - return 0; - } - break; - case 0: - hcr =3D arm_hcr_el2_eff(env); - if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { - return 0; - } - break; - } - - return env->cp15.cntvoff_el2; -} - -static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return gt_get_countervalue(env) - gt_virt_cnt_offset(env); -} - -static void gt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri, - int timeridx, - uint64_t value) -{ - trace_arm_gt_cval_write(timeridx, value); - env->cp15.c14_timer[timeridx].cval =3D value; - gt_recalc_timer(env_archcpu(env), timeridx); -} - -static uint64_t gt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri, - int timeridx) -{ - uint64_t offset =3D 0; - - switch (timeridx) { - case GTIMER_VIRT: - case GTIMER_HYPVIRT: - offset =3D gt_virt_cnt_offset(env); - break; - } - - return (uint32_t)(env->cp15.c14_timer[timeridx].cval - - (gt_get_countervalue(env) - offset)); -} - -static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri, - int timeridx, - uint64_t value) -{ - uint64_t offset =3D 0; - - switch (timeridx) { - case GTIMER_VIRT: - case GTIMER_HYPVIRT: - offset =3D gt_virt_cnt_offset(env); - break; - } - - trace_arm_gt_tval_write(timeridx, value); - env->cp15.c14_timer[timeridx].cval =3D gt_get_countervalue(env) - offs= et + - sextract64(value, 0, 32); - gt_recalc_timer(env_archcpu(env), timeridx); -} - -static void gt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri, - int timeridx, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - uint32_t oldval =3D env->cp15.c14_timer[timeridx].ctl; - - trace_arm_gt_ctl_write(timeridx, value); - env->cp15.c14_timer[timeridx].ctl =3D deposit64(oldval, 0, 2, value); - if ((oldval ^ value) & 1) { - /* Enable toggled */ - gt_recalc_timer(cpu, timeridx); - } else if ((oldval ^ value) & 2) { - /* - * IMASK toggled: don't need to recalculate, - * just set the interrupt line based on ISTATUS - */ - int irqstate =3D (oldval & 4) && !(value & 2); - - trace_arm_gt_imask_toggle(timeridx, irqstate); - qemu_set_irq(cpu->gt_timer_outputs[timeridx], irqstate); - } -} - -static void gt_phys_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri) -{ - gt_timer_reset(env, ri, GTIMER_PHYS); -} - -static void gt_phys_cval_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - gt_cval_write(env, ri, GTIMER_PHYS, value); -} - -static uint64_t gt_phys_tval_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return gt_tval_read(env, ri, GTIMER_PHYS); -} - -static void gt_phys_tval_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - gt_tval_write(env, ri, GTIMER_PHYS, value); -} - -static void gt_phys_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - gt_ctl_write(env, ri, GTIMER_PHYS, value); -} - -static int gt_phys_redir_timeridx(CPUARMState *env) -{ - switch (arm_mmu_idx(env)) { - case ARMMMUIdx_E20_0: - case ARMMMUIdx_E20_2: - case ARMMMUIdx_E20_2_PAN: - return GTIMER_HYP; - default: - return GTIMER_PHYS; - } -} - -static int gt_virt_redir_timeridx(CPUARMState *env) -{ - switch (arm_mmu_idx(env)) { - case ARMMMUIdx_E20_0: - case ARMMMUIdx_E20_2: - case ARMMMUIdx_E20_2_PAN: - return GTIMER_HYPVIRT; - default: - return GTIMER_VIRT; - } -} - -static uint64_t gt_phys_redir_cval_read(CPUARMState *env, - const ARMCPRegInfo *ri) -{ - int timeridx =3D gt_phys_redir_timeridx(env); - return env->cp15.c14_timer[timeridx].cval; -} - -static void gt_phys_redir_cval_write(CPUARMState *env, const ARMCPRegInfo = *ri, - uint64_t value) -{ - int timeridx =3D gt_phys_redir_timeridx(env); - gt_cval_write(env, ri, timeridx, value); -} - -static uint64_t gt_phys_redir_tval_read(CPUARMState *env, - const ARMCPRegInfo *ri) -{ - int timeridx =3D gt_phys_redir_timeridx(env); - return gt_tval_read(env, ri, timeridx); -} - -static void gt_phys_redir_tval_write(CPUARMState *env, const ARMCPRegInfo = *ri, - uint64_t value) -{ - int timeridx =3D gt_phys_redir_timeridx(env); - gt_tval_write(env, ri, timeridx, value); -} - -static uint64_t gt_phys_redir_ctl_read(CPUARMState *env, - const ARMCPRegInfo *ri) -{ - int timeridx =3D gt_phys_redir_timeridx(env); - return env->cp15.c14_timer[timeridx].ctl; -} - -static void gt_phys_redir_ctl_write(CPUARMState *env, const ARMCPRegInfo *= ri, - uint64_t value) -{ - int timeridx =3D gt_phys_redir_timeridx(env); - gt_ctl_write(env, ri, timeridx, value); -} - -static void gt_virt_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri) -{ - gt_timer_reset(env, ri, GTIMER_VIRT); -} - -static void gt_virt_cval_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - gt_cval_write(env, ri, GTIMER_VIRT, value); -} - -static uint64_t gt_virt_tval_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return gt_tval_read(env, ri, GTIMER_VIRT); -} - -static void gt_virt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - gt_tval_write(env, ri, GTIMER_VIRT, value); -} - -static void gt_virt_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - gt_ctl_write(env, ri, GTIMER_VIRT, value); -} - -static void gt_cntvoff_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - - trace_arm_gt_cntvoff_write(value); - raw_write(env, ri, value); - gt_recalc_timer(cpu, GTIMER_VIRT); -} - -static uint64_t gt_virt_redir_cval_read(CPUARMState *env, - const ARMCPRegInfo *ri) -{ - int timeridx =3D gt_virt_redir_timeridx(env); - return env->cp15.c14_timer[timeridx].cval; -} - -static void gt_virt_redir_cval_write(CPUARMState *env, const ARMCPRegInfo = *ri, - uint64_t value) -{ - int timeridx =3D gt_virt_redir_timeridx(env); - gt_cval_write(env, ri, timeridx, value); -} - -static uint64_t gt_virt_redir_tval_read(CPUARMState *env, - const ARMCPRegInfo *ri) -{ - int timeridx =3D gt_virt_redir_timeridx(env); - return gt_tval_read(env, ri, timeridx); -} - -static void gt_virt_redir_tval_write(CPUARMState *env, const ARMCPRegInfo = *ri, - uint64_t value) -{ - int timeridx =3D gt_virt_redir_timeridx(env); - gt_tval_write(env, ri, timeridx, value); -} - -static uint64_t gt_virt_redir_ctl_read(CPUARMState *env, - const ARMCPRegInfo *ri) -{ - int timeridx =3D gt_virt_redir_timeridx(env); - return env->cp15.c14_timer[timeridx].ctl; -} - -static void gt_virt_redir_ctl_write(CPUARMState *env, const ARMCPRegInfo *= ri, - uint64_t value) -{ - int timeridx =3D gt_virt_redir_timeridx(env); - gt_ctl_write(env, ri, timeridx, value); -} - -static void gt_hyp_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri) -{ - gt_timer_reset(env, ri, GTIMER_HYP); -} - -static void gt_hyp_cval_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - gt_cval_write(env, ri, GTIMER_HYP, value); -} - -static uint64_t gt_hyp_tval_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return gt_tval_read(env, ri, GTIMER_HYP); -} - -static void gt_hyp_tval_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - gt_tval_write(env, ri, GTIMER_HYP, value); -} - -static void gt_hyp_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - gt_ctl_write(env, ri, GTIMER_HYP, value); -} - -static void gt_sec_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri) -{ - gt_timer_reset(env, ri, GTIMER_SEC); -} - -static void gt_sec_cval_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - gt_cval_write(env, ri, GTIMER_SEC, value); -} - -static uint64_t gt_sec_tval_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return gt_tval_read(env, ri, GTIMER_SEC); -} - -static void gt_sec_tval_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - gt_tval_write(env, ri, GTIMER_SEC, value); -} - -static void gt_sec_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - gt_ctl_write(env, ri, GTIMER_SEC, value); -} - -static void gt_hv_timer_reset(CPUARMState *env, const ARMCPRegInfo *ri) -{ - gt_timer_reset(env, ri, GTIMER_HYPVIRT); -} - -static void gt_hv_cval_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - gt_cval_write(env, ri, GTIMER_HYPVIRT, value); -} - -static uint64_t gt_hv_tval_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return gt_tval_read(env, ri, GTIMER_HYPVIRT); -} - -static void gt_hv_tval_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - gt_tval_write(env, ri, GTIMER_HYPVIRT, value); -} - -static void gt_hv_ctl_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - gt_ctl_write(env, ri, GTIMER_HYPVIRT, value); -} - -void arm_gt_ptimer_cb(void *opaque) -{ - ARMCPU *cpu =3D opaque; - - gt_recalc_timer(cpu, GTIMER_PHYS); -} - -void arm_gt_vtimer_cb(void *opaque) -{ - ARMCPU *cpu =3D opaque; - - gt_recalc_timer(cpu, GTIMER_VIRT); -} - -void arm_gt_htimer_cb(void *opaque) -{ - ARMCPU *cpu =3D opaque; - - gt_recalc_timer(cpu, GTIMER_HYP); -} - -void arm_gt_stimer_cb(void *opaque) -{ - ARMCPU *cpu =3D opaque; - - gt_recalc_timer(cpu, GTIMER_SEC); -} - -void arm_gt_hvtimer_cb(void *opaque) -{ - ARMCPU *cpu =3D opaque; - - gt_recalc_timer(cpu, GTIMER_HYPVIRT); -} - -static void arm_gt_cntfrq_reset(CPUARMState *env, const ARMCPRegInfo *opaq= ue) -{ - ARMCPU *cpu =3D env_archcpu(env); - - cpu->env.cp15.c14_cntfrq =3D cpu->gt_cntfrq_hz; -} - -static const ARMCPRegInfo generic_timer_cp_reginfo[] =3D { - /* - * Note that CNTFRQ is purely reads-as-written for the benefit - * of software; writing it doesn't actually change the timer frequency. - * Our reset value matches the fixed frequency we implement the timer = at. - */ - { .name =3D "CNTFRQ", .cp =3D 15, .crn =3D 14, .crm =3D 0, .opc1 =3D 0= , .opc2 =3D 0, - .type =3D ARM_CP_ALIAS, - .access =3D PL1_RW | PL0_R, .accessfn =3D gt_cntfrq_access, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c14_cntfrq), - }, - { .name =3D "CNTFRQ_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 0, .opc2 =3D 0, - .access =3D PL1_RW | PL0_R, .accessfn =3D gt_cntfrq_access, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_cntfrq), - .resetfn =3D arm_gt_cntfrq_reset, - }, - /* overall control: mostly access permissions */ - { .name =3D "CNTKCTL", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 14, .crm =3D 1, .opc2 =3D 0, - .access =3D PL1_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_cntkctl), - .resetvalue =3D 0, - }, - /* per-timer control */ - { .name =3D "CNTP_CTL", .cp =3D 15, .crn =3D 14, .crm =3D 2, .opc1 =3D= 0, .opc2 =3D 1, - .secure =3D ARM_CP_SECSTATE_NS, - .type =3D ARM_CP_IO | ARM_CP_ALIAS, .access =3D PL0_RW, - .accessfn =3D gt_ptimer_access, - .fieldoffset =3D offsetoflow32(CPUARMState, - cp15.c14_timer[GTIMER_PHYS].ctl), - .readfn =3D gt_phys_redir_ctl_read, .raw_readfn =3D raw_read, - .writefn =3D gt_phys_redir_ctl_write, .raw_writefn =3D raw_write, - }, - { .name =3D "CNTP_CTL_S", - .cp =3D 15, .crn =3D 14, .crm =3D 2, .opc1 =3D 0, .opc2 =3D 1, - .secure =3D ARM_CP_SECSTATE_S, - .type =3D ARM_CP_IO | ARM_CP_ALIAS, .access =3D PL0_RW, - .accessfn =3D gt_ptimer_access, - .fieldoffset =3D offsetoflow32(CPUARMState, - cp15.c14_timer[GTIMER_SEC].ctl), - .writefn =3D gt_sec_ctl_write, .raw_writefn =3D raw_write, - }, - { .name =3D "CNTP_CTL_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 2, .opc2 =3D 1, - .type =3D ARM_CP_IO, .access =3D PL0_RW, - .accessfn =3D gt_ptimer_access, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].c= tl), - .resetvalue =3D 0, - .readfn =3D gt_phys_redir_ctl_read, .raw_readfn =3D raw_read, - .writefn =3D gt_phys_redir_ctl_write, .raw_writefn =3D raw_write, - }, - { .name =3D "CNTV_CTL", .cp =3D 15, .crn =3D 14, .crm =3D 3, .opc1 =3D= 0, .opc2 =3D 1, - .type =3D ARM_CP_IO | ARM_CP_ALIAS, .access =3D PL0_RW, - .accessfn =3D gt_vtimer_access, - .fieldoffset =3D offsetoflow32(CPUARMState, - cp15.c14_timer[GTIMER_VIRT].ctl), - .readfn =3D gt_virt_redir_ctl_read, .raw_readfn =3D raw_read, - .writefn =3D gt_virt_redir_ctl_write, .raw_writefn =3D raw_write, - }, - { .name =3D "CNTV_CTL_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 3, .opc2 =3D 1, - .type =3D ARM_CP_IO, .access =3D PL0_RW, - .accessfn =3D gt_vtimer_access, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].c= tl), - .resetvalue =3D 0, - .readfn =3D gt_virt_redir_ctl_read, .raw_readfn =3D raw_read, - .writefn =3D gt_virt_redir_ctl_write, .raw_writefn =3D raw_write, - }, - /* TimerValue views: a 32 bit downcounting view of the underlying stat= e */ - { .name =3D "CNTP_TVAL", .cp =3D 15, .crn =3D 14, .crm =3D 2, .opc1 = =3D 0, .opc2 =3D 0, - .secure =3D ARM_CP_SECSTATE_NS, - .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL0_RW, - .accessfn =3D gt_ptimer_access, - .readfn =3D gt_phys_redir_tval_read, .writefn =3D gt_phys_redir_tval= _write, - }, - { .name =3D "CNTP_TVAL_S", - .cp =3D 15, .crn =3D 14, .crm =3D 2, .opc1 =3D 0, .opc2 =3D 0, - .secure =3D ARM_CP_SECSTATE_S, - .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL0_RW, - .accessfn =3D gt_ptimer_access, - .readfn =3D gt_sec_tval_read, .writefn =3D gt_sec_tval_write, - }, - { .name =3D "CNTP_TVAL_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 2, .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL0_RW, - .accessfn =3D gt_ptimer_access, .resetfn =3D gt_phys_timer_reset, - .readfn =3D gt_phys_redir_tval_read, .writefn =3D gt_phys_redir_tval= _write, - }, - { .name =3D "CNTV_TVAL", .cp =3D 15, .crn =3D 14, .crm =3D 3, .opc1 = =3D 0, .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL0_RW, - .accessfn =3D gt_vtimer_access, - .readfn =3D gt_virt_redir_tval_read, .writefn =3D gt_virt_redir_tval= _write, - }, - { .name =3D "CNTV_TVAL_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 3, .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL0_RW, - .accessfn =3D gt_vtimer_access, .resetfn =3D gt_virt_timer_reset, - .readfn =3D gt_virt_redir_tval_read, .writefn =3D gt_virt_redir_tval= _write, - }, - /* The counter itself */ - { .name =3D "CNTPCT", .cp =3D 15, .crm =3D 14, .opc1 =3D 0, - .access =3D PL0_R, .type =3D ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_I= O, - .accessfn =3D gt_pct_access, - .readfn =3D gt_cnt_read, .resetfn =3D arm_cp_reset_ignore, - }, - { .name =3D "CNTPCT_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 0, .opc2 =3D 1, - .access =3D PL0_R, .type =3D ARM_CP_NO_RAW | ARM_CP_IO, - .accessfn =3D gt_pct_access, .readfn =3D gt_cnt_read, - }, - { .name =3D "CNTVCT", .cp =3D 15, .crm =3D 14, .opc1 =3D 1, - .access =3D PL0_R, .type =3D ARM_CP_64BIT | ARM_CP_NO_RAW | ARM_CP_I= O, - .accessfn =3D gt_vct_access, - .readfn =3D gt_virt_cnt_read, .resetfn =3D arm_cp_reset_ignore, - }, - { .name =3D "CNTVCT_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 0, .opc2 =3D 2, - .access =3D PL0_R, .type =3D ARM_CP_NO_RAW | ARM_CP_IO, - .accessfn =3D gt_vct_access, .readfn =3D gt_virt_cnt_read, - }, - /* Comparison value, indicating when the timer goes off */ - { .name =3D "CNTP_CVAL", .cp =3D 15, .crm =3D 14, .opc1 =3D 2, - .secure =3D ARM_CP_SECSTATE_NS, - .access =3D PL0_RW, - .type =3D ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].c= val), - .accessfn =3D gt_ptimer_access, - .readfn =3D gt_phys_redir_cval_read, .raw_readfn =3D raw_read, - .writefn =3D gt_phys_redir_cval_write, .raw_writefn =3D raw_write, - }, - { .name =3D "CNTP_CVAL_S", .cp =3D 15, .crm =3D 14, .opc1 =3D 2, - .secure =3D ARM_CP_SECSTATE_S, - .access =3D PL0_RW, - .type =3D ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].cv= al), - .accessfn =3D gt_ptimer_access, - .writefn =3D gt_sec_cval_write, .raw_writefn =3D raw_write, - }, - { .name =3D "CNTP_CVAL_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 2, .opc2 =3D 2, - .access =3D PL0_RW, - .type =3D ARM_CP_IO, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].c= val), - .resetvalue =3D 0, .accessfn =3D gt_ptimer_access, - .readfn =3D gt_phys_redir_cval_read, .raw_readfn =3D raw_read, - .writefn =3D gt_phys_redir_cval_write, .raw_writefn =3D raw_write, - }, - { .name =3D "CNTV_CVAL", .cp =3D 15, .crm =3D 14, .opc1 =3D 3, - .access =3D PL0_RW, - .type =3D ARM_CP_64BIT | ARM_CP_IO | ARM_CP_ALIAS, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].c= val), - .accessfn =3D gt_vtimer_access, - .readfn =3D gt_virt_redir_cval_read, .raw_readfn =3D raw_read, - .writefn =3D gt_virt_redir_cval_write, .raw_writefn =3D raw_write, - }, - { .name =3D "CNTV_CVAL_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 3, .opc2 =3D 2, - .access =3D PL0_RW, - .type =3D ARM_CP_IO, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].c= val), - .resetvalue =3D 0, .accessfn =3D gt_vtimer_access, - .readfn =3D gt_virt_redir_cval_read, .raw_readfn =3D raw_read, - .writefn =3D gt_virt_redir_cval_write, .raw_writefn =3D raw_write, - }, - /* - * Secure timer -- this is actually restricted to only EL3 - * and configurably Secure-EL1 via the accessfn. - */ - { .name =3D "CNTPS_TVAL_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 7, .crn =3D 14, .crm =3D 2, .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL1_RW, - .accessfn =3D gt_stimer_access, - .readfn =3D gt_sec_tval_read, - .writefn =3D gt_sec_tval_write, - .resetfn =3D gt_sec_timer_reset, - }, - { .name =3D "CNTPS_CTL_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 7, .crn =3D 14, .crm =3D 2, .opc2 =3D 1, - .type =3D ARM_CP_IO, .access =3D PL1_RW, - .accessfn =3D gt_stimer_access, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].ct= l), - .resetvalue =3D 0, - .writefn =3D gt_sec_ctl_write, .raw_writefn =3D raw_write, - }, - { .name =3D "CNTPS_CVAL_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 7, .crn =3D 14, .crm =3D 2, .opc2 =3D 2, - .type =3D ARM_CP_IO, .access =3D PL1_RW, - .accessfn =3D gt_stimer_access, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_SEC].cv= al), - .writefn =3D gt_sec_cval_write, .raw_writefn =3D raw_write, - }, -}; - -static CPAccessResult e2h_access(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - if (!(arm_hcr_el2_eff(env) & HCR_E2H)) { - return CP_ACCESS_TRAP; - } - return CP_ACCESS_OK; -} - -#else - -/* - * In user-mode most of the generic timer registers are inaccessible - * however modern kernels (4.12+) allow access to cntvct_el0 - */ - -static uint64_t gt_virt_cnt_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - ARMCPU *cpu =3D env_archcpu(env); - - /* - * Currently we have no support for QEMUTimer in linux-user so we - * can't call gt_get_countervalue(env), instead we directly - * call the lower level functions. - */ - return cpu_get_clock() / gt_cntfrq_period_ns(cpu); -} - -static const ARMCPRegInfo generic_timer_cp_reginfo[] =3D { - { .name =3D "CNTFRQ_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 0, .opc2 =3D 0, - .type =3D ARM_CP_CONST, .access =3D PL0_R /* no PL1_RW in linux-user= */, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_cntfrq), - .resetvalue =3D NANOSECONDS_PER_SECOND / GTIMER_SCALE, - }, - { .name =3D "CNTVCT_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 0, .opc2 =3D 2, - .access =3D PL0_R, .type =3D ARM_CP_NO_RAW | ARM_CP_IO, - .readfn =3D gt_virt_cnt_read, - }, -}; - -#endif - -static void par_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t v= alue) -{ - if (arm_feature(env, ARM_FEATURE_LPAE)) { - raw_write(env, ri, value); - } else if (arm_feature(env, ARM_FEATURE_V7)) { - raw_write(env, ri, value & 0xfffff6ff); - } else { - raw_write(env, ri, value & 0xfffff1ff); - } -} - -#ifndef CONFIG_USER_ONLY -/* get_phys_addr() isn't present for user-mode-only targets */ - -static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - if (ri->opc2 & 4) { - /* - * The ATS12NSO* operations must trap to EL3 or EL2 if executed in - * Secure EL1 (which can only happen if EL3 is AArch64). - * They are simply UNDEF if executed from NS EL1. - * They function normally from EL2 or EL3. - */ - if (arm_current_el(env) =3D=3D 1) { - if (arm_is_secure_below_el3(env)) { - if (env->cp15.scr_el3 & SCR_EEL2) { - return CP_ACCESS_TRAP_UNCATEGORIZED_EL2; - } - return CP_ACCESS_TRAP_UNCATEGORIZED_EL3; - } - return CP_ACCESS_TRAP_UNCATEGORIZED; - } - } - return CP_ACCESS_OK; -} - -#ifdef CONFIG_TCG -static uint64_t do_ats_write(CPUARMState *env, uint64_t value, - MMUAccessType access_type, ARMMMUIdx mmu_idx, - bool is_secure) -{ - bool ret; - uint64_t par64; - bool format64 =3D false; - ARMMMUFaultInfo fi =3D {}; - GetPhysAddrResult res =3D {}; - - ret =3D get_phys_addr_with_secure(env, value, access_type, mmu_idx, - is_secure, &res, &fi); - - /* - * ATS operations only do S1 or S1+S2 translations, so we never - * have to deal with the ARMCacheAttrs format for S2 only. - */ - assert(!res.cacheattrs.is_s2_format); - - if (ret) { - /* - * Some kinds of translation fault must cause exceptions rather - * than being reported in the PAR. - */ - int current_el =3D arm_current_el(env); - int target_el; - uint32_t syn, fsr, fsc; - bool take_exc =3D false; - - if (fi.s1ptw && current_el =3D=3D 1 - && arm_mmu_idx_is_stage1_of_2(mmu_idx)) { - /* - * Synchronous stage 2 fault on an access made as part of the - * translation table walk for AT S1E0* or AT S1E1* insn - * executed from NS EL1. If this is a synchronous external abo= rt - * and SCR_EL3.EA =3D=3D 1, then we take a synchronous externa= l abort - * to EL3. Otherwise the fault is taken as an exception to EL2, - * and HPFAR_EL2 holds the faulting IPA. - */ - if (fi.type =3D=3D ARMFault_SyncExternalOnWalk && - (env->cp15.scr_el3 & SCR_EA)) { - target_el =3D 3; - } else { - env->cp15.hpfar_el2 =3D extract64(fi.s2addr, 12, 47) << 4; - if (arm_is_secure_below_el3(env) && fi.s1ns) { - env->cp15.hpfar_el2 |=3D HPFAR_NS; - } - target_el =3D 2; - } - take_exc =3D true; - } else if (fi.type =3D=3D ARMFault_SyncExternalOnWalk) { - /* - * Synchronous external aborts during a translation table walk - * are taken as Data Abort exceptions. - */ - if (fi.stage2) { - if (current_el =3D=3D 3) { - target_el =3D 3; - } else { - target_el =3D 2; - } - } else { - target_el =3D exception_target_el(env); - } - take_exc =3D true; - } - - if (take_exc) { - /* Construct FSR and FSC using same logic as arm_deliver_fault= () */ - if (target_el =3D=3D 2 || arm_el_is_aa64(env, target_el) || - arm_s1_regime_using_lpae_format(env, mmu_idx)) { - fsr =3D arm_fi_to_lfsc(&fi); - fsc =3D extract32(fsr, 0, 6); - } else { - fsr =3D arm_fi_to_sfsc(&fi); - fsc =3D 0x3f; - } - /* - * Report exception with ESR indicating a fault due to a - * translation table walk for a cache maintenance instruction. - */ - syn =3D syn_data_abort_no_iss(current_el =3D=3D target_el, 0, - fi.ea, 1, fi.s1ptw, 1, fsc); - env->exception.vaddress =3D value; - env->exception.fsr =3D fsr; - raise_exception(env, EXCP_DATA_ABORT, syn, target_el); - } - } - - if (is_a64(env)) { - format64 =3D true; - } else if (arm_feature(env, ARM_FEATURE_LPAE)) { - /* - * ATS1Cxx: - * * TTBCR.EAE determines whether the result is returned using the - * 32-bit or the 64-bit PAR format - * * Instructions executed in Hyp mode always use the 64bit format - * - * ATS1S2NSOxx uses the 64bit format if any of the following is tr= ue: - * * The Non-secure TTBCR.EAE bit is set to 1 - * * The implementation includes EL2, and the value of HCR.VM is 1 - * - * (Note that HCR.DC makes HCR.VM behave as if it is 1.) - * - * ATS1Hx always uses the 64bit format. - */ - format64 =3D arm_s1_regime_using_lpae_format(env, mmu_idx); - - if (arm_feature(env, ARM_FEATURE_EL2)) { - if (mmu_idx =3D=3D ARMMMUIdx_E10_0 || - mmu_idx =3D=3D ARMMMUIdx_E10_1 || - mmu_idx =3D=3D ARMMMUIdx_E10_1_PAN) { - format64 |=3D env->cp15.hcr_el2 & (HCR_VM | HCR_DC); - } else { - format64 |=3D arm_current_el(env) =3D=3D 2; - } - } - } - - if (format64) { - /* Create a 64-bit PAR */ - par64 =3D (1 << 11); /* LPAE bit always set */ - if (!ret) { - par64 |=3D res.f.phys_addr & ~0xfffULL; - if (!res.f.attrs.secure) { - par64 |=3D (1 << 9); /* NS */ - } - par64 |=3D (uint64_t)res.cacheattrs.attrs << 56; /* ATTR */ - par64 |=3D res.cacheattrs.shareability << 7; /* SH */ - } else { - uint32_t fsr =3D arm_fi_to_lfsc(&fi); - - par64 |=3D 1; /* F */ - par64 |=3D (fsr & 0x3f) << 1; /* FS */ - if (fi.stage2) { - par64 |=3D (1 << 9); /* S */ - } - if (fi.s1ptw) { - par64 |=3D (1 << 8); /* PTW */ - } - } - } else { - /* - * fsr is a DFSR/IFSR value for the short descriptor - * translation table format (with WnR always clear). - * Convert it to a 32-bit PAR. - */ - if (!ret) { - /* We do not set any attribute bits in the PAR */ - if (res.f.lg_page_size =3D=3D 24 - && arm_feature(env, ARM_FEATURE_V7)) { - par64 =3D (res.f.phys_addr & 0xff000000) | (1 << 1); - } else { - par64 =3D res.f.phys_addr & 0xfffff000; - } - if (!res.f.attrs.secure) { - par64 |=3D (1 << 9); /* NS */ - } - } else { - uint32_t fsr =3D arm_fi_to_sfsc(&fi); - - par64 =3D ((fsr & (1 << 10)) >> 5) | ((fsr & (1 << 12)) >> 6) | - ((fsr & 0xf) << 1) | 1; - } - } - return par64; -} -#endif /* CONFIG_TCG */ - -static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t v= alue) -{ -#ifdef CONFIG_TCG - MMUAccessType access_type =3D ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA= _LOAD; - uint64_t par64; - ARMMMUIdx mmu_idx; - int el =3D arm_current_el(env); - bool secure =3D arm_is_secure_below_el3(env); - - switch (ri->opc2 & 6) { - case 0: - /* stage 1 current state PL1: ATS1CPR, ATS1CPW, ATS1CPRP, ATS1CPWP= */ - switch (el) { - case 3: - mmu_idx =3D ARMMMUIdx_E3; - secure =3D true; - break; - case 2: - g_assert(!secure); /* ARMv8.4-SecEL2 is 64-bit only */ - /* fall through */ - case 1: - if (ri->crm =3D=3D 9 && (env->uncached_cpsr & CPSR_PAN)) { - mmu_idx =3D ARMMMUIdx_Stage1_E1_PAN; - } else { - mmu_idx =3D ARMMMUIdx_Stage1_E1; - } - break; - default: - g_assert_not_reached(); - } - break; - case 2: - /* stage 1 current state PL0: ATS1CUR, ATS1CUW */ - switch (el) { - case 3: - mmu_idx =3D ARMMMUIdx_E10_0; - secure =3D true; - break; - case 2: - g_assert(!secure); /* ARMv8.4-SecEL2 is 64-bit only */ - mmu_idx =3D ARMMMUIdx_Stage1_E0; - break; - case 1: - mmu_idx =3D ARMMMUIdx_Stage1_E0; - break; - default: - g_assert_not_reached(); - } - break; - case 4: - /* stage 1+2 NonSecure PL1: ATS12NSOPR, ATS12NSOPW */ - mmu_idx =3D ARMMMUIdx_E10_1; - secure =3D false; - break; - case 6: - /* stage 1+2 NonSecure PL0: ATS12NSOUR, ATS12NSOUW */ - mmu_idx =3D ARMMMUIdx_E10_0; - secure =3D false; - break; - default: - g_assert_not_reached(); - } - - par64 =3D do_ats_write(env, value, access_type, mmu_idx, secure); - - A32_BANKED_CURRENT_REG_SET(env, par, par64); -#else - /* Handled by hardware accelerator. */ - g_assert_not_reached(); -#endif /* CONFIG_TCG */ -} - -static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ -#ifdef CONFIG_TCG - MMUAccessType access_type =3D ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA= _LOAD; - uint64_t par64; - - /* There is no SecureEL2 for AArch32. */ - par64 =3D do_ats_write(env, value, access_type, ARMMMUIdx_E2, false); - - A32_BANKED_CURRENT_REG_SET(env, par, par64); -#else - /* Handled by hardware accelerator. */ - g_assert_not_reached(); -#endif /* CONFIG_TCG */ -} - -static CPAccessResult at_s1e2_access(CPUARMState *env, const ARMCPRegInfo = *ri, - bool isread) -{ - if (arm_current_el(env) =3D=3D 3 && - !(env->cp15.scr_el3 & (SCR_NS | SCR_EEL2))) { - return CP_ACCESS_TRAP; - } - return CP_ACCESS_OK; -} - -static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ -#ifdef CONFIG_TCG - MMUAccessType access_type =3D ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA= _LOAD; - ARMMMUIdx mmu_idx; - int secure =3D arm_is_secure_below_el3(env); - uint64_t hcr_el2 =3D arm_hcr_el2_eff(env); - bool regime_e20 =3D (hcr_el2 & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | = HCR_TGE); - - switch (ri->opc2 & 6) { - case 0: - switch (ri->opc1) { - case 0: /* AT S1E1R, AT S1E1W, AT S1E1RP, AT S1E1WP */ - if (ri->crm =3D=3D 9 && (env->pstate & PSTATE_PAN)) { - mmu_idx =3D regime_e20 ? - ARMMMUIdx_E20_2_PAN : ARMMMUIdx_Stage1_E1_PAN; - } else { - mmu_idx =3D regime_e20 ? ARMMMUIdx_E20_2 : ARMMMUIdx_Stage= 1_E1; - } - break; - case 4: /* AT S1E2R, AT S1E2W */ - mmu_idx =3D hcr_el2 & HCR_E2H ? ARMMMUIdx_E20_2 : ARMMMUIdx_E2; - break; - case 6: /* AT S1E3R, AT S1E3W */ - mmu_idx =3D ARMMMUIdx_E3; - secure =3D true; - break; - default: - g_assert_not_reached(); - } - break; - case 2: /* AT S1E0R, AT S1E0W */ - mmu_idx =3D regime_e20 ? ARMMMUIdx_E20_0 : ARMMMUIdx_Stage1_E0; - break; - case 4: /* AT S12E1R, AT S12E1W */ - mmu_idx =3D regime_e20 ? ARMMMUIdx_E20_2 : ARMMMUIdx_E10_1; - break; - case 6: /* AT S12E0R, AT S12E0W */ - mmu_idx =3D regime_e20 ? ARMMMUIdx_E20_0 : ARMMMUIdx_E10_0; - break; - default: - g_assert_not_reached(); - } - - env->cp15.par_el[1] =3D do_ats_write(env, value, access_type, - mmu_idx, secure); -#else - /* Handled by hardware accelerator. */ - g_assert_not_reached(); -#endif /* CONFIG_TCG */ -} -#endif - -static const ARMCPRegInfo vapa_cp_reginfo[] =3D { - { .name =3D "PAR", .cp =3D 15, .crn =3D 7, .crm =3D 4, .opc1 =3D 0, .o= pc2 =3D 0, - .access =3D PL1_RW, .resetvalue =3D 0, - .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.par_s), - offsetoflow32(CPUARMState, cp15.par_ns) }, - .writefn =3D par_write }, -#ifndef CONFIG_USER_ONLY - /* This underdecoding is safe because the reginfo is NO_RAW. */ - { .name =3D "ATS", .cp =3D 15, .crn =3D 7, .crm =3D 8, .opc1 =3D 0, .o= pc2 =3D CP_ANY, - .access =3D PL1_W, .accessfn =3D ats_access, - .writefn =3D ats_write, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC = }, -#endif -}; - -/* Return basic MPU access permission bits. */ -static uint32_t simple_mpu_ap_bits(uint32_t val) -{ - uint32_t ret; - uint32_t mask; - int i; - ret =3D 0; - mask =3D 3; - for (i =3D 0; i < 16; i +=3D 2) { - ret |=3D (val >> i) & mask; - mask <<=3D 2; - } - return ret; -} - -/* Pad basic MPU access permission bits to extended format. */ -static uint32_t extended_mpu_ap_bits(uint32_t val) -{ - uint32_t ret; - uint32_t mask; - int i; - ret =3D 0; - mask =3D 3; - for (i =3D 0; i < 16; i +=3D 2) { - ret |=3D (val & mask) << i; - mask <<=3D 2; - } - return ret; -} - -static void pmsav5_data_ap_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - env->cp15.pmsav5_data_ap =3D extended_mpu_ap_bits(value); -} - -static uint64_t pmsav5_data_ap_read(CPUARMState *env, const ARMCPRegInfo *= ri) -{ - return simple_mpu_ap_bits(env->cp15.pmsav5_data_ap); -} - -static void pmsav5_insn_ap_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - env->cp15.pmsav5_insn_ap =3D extended_mpu_ap_bits(value); -} - -static uint64_t pmsav5_insn_ap_read(CPUARMState *env, const ARMCPRegInfo *= ri) -{ - return simple_mpu_ap_bits(env->cp15.pmsav5_insn_ap); -} - -static uint64_t pmsav7_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - uint32_t *u32p =3D *(uint32_t **)raw_ptr(env, ri); - - if (!u32p) { - return 0; - } - - u32p +=3D env->pmsav7.rnr[M_REG_NS]; - return *u32p; -} - -static void pmsav7_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - uint32_t *u32p =3D *(uint32_t **)raw_ptr(env, ri); - - if (!u32p) { - return; - } - - u32p +=3D env->pmsav7.rnr[M_REG_NS]; - tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */ - *u32p =3D value; -} - -static void pmsav7_rgnr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - uint32_t nrgs =3D cpu->pmsav7_dregion; - - if (value >=3D nrgs) { - qemu_log_mask(LOG_GUEST_ERROR, - "PMSAv7 RGNR write >=3D # supported regions, %" PRIu= 32 - " > %" PRIu32 "\n", (uint32_t)value, nrgs); - return; - } - - raw_write(env, ri, value); -} - -static void prbar_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - - tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */ - env->pmsav8.rbar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]] =3D value; -} - -static uint64_t prbar_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return env->pmsav8.rbar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]]; -} - -static void prlar_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - - tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */ - env->pmsav8.rlar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]] =3D value; -} - -static uint64_t prlar_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return env->pmsav8.rlar[M_REG_NS][env->pmsav7.rnr[M_REG_NS]]; -} - -static void prselr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - - /* - * Ignore writes that would select not implemented region. - * This is architecturally UNPREDICTABLE. - */ - if (value >=3D cpu->pmsav7_dregion) { - return; - } - - env->pmsav7.rnr[M_REG_NS] =3D value; -} - -static void hprbar_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - - tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */ - env->pmsav8.hprbar[env->pmsav8.hprselr] =3D value; -} - -static uint64_t hprbar_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return env->pmsav8.hprbar[env->pmsav8.hprselr]; -} - -static void hprlar_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - - tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */ - env->pmsav8.hprlar[env->pmsav8.hprselr] =3D value; -} - -static uint64_t hprlar_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return env->pmsav8.hprlar[env->pmsav8.hprselr]; -} - -static void hprenr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - uint32_t n; - uint32_t bit; - ARMCPU *cpu =3D env_archcpu(env); - - /* Ignore writes to unimplemented regions */ - int rmax =3D MIN(cpu->pmsav8r_hdregion, 32); - value &=3D MAKE_64BIT_MASK(0, rmax); - - tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */ - - /* Register alias is only valid for first 32 indexes */ - for (n =3D 0; n < rmax; ++n) { - bit =3D extract32(value, n, 1); - env->pmsav8.hprlar[n] =3D deposit32( - env->pmsav8.hprlar[n], 0, 1, bit); - } -} - -static uint64_t hprenr_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - uint32_t n; - uint32_t result =3D 0x0; - ARMCPU *cpu =3D env_archcpu(env); - - /* Register alias is only valid for first 32 indexes */ - for (n =3D 0; n < MIN(cpu->pmsav8r_hdregion, 32); ++n) { - if (env->pmsav8.hprlar[n] & 0x1) { - result |=3D (0x1 << n); - } - } - return result; -} - -static void hprselr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - - /* - * Ignore writes that would select not implemented region. - * This is architecturally UNPREDICTABLE. - */ - if (value >=3D cpu->pmsav8r_hdregion) { - return; - } - - env->pmsav8.hprselr =3D value; -} - -static void pmsav8r_regn_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - uint8_t index =3D (extract32(ri->opc0, 0, 1) << 4) | - (extract32(ri->crm, 0, 3) << 1) | extract32(ri->opc2, = 2, 1); - - tlb_flush(CPU(cpu)); /* Mappings may have changed - purge! */ - - if (ri->opc1 & 4) { - if (index >=3D cpu->pmsav8r_hdregion) { - return; - } - if (ri->opc2 & 0x1) { - env->pmsav8.hprlar[index] =3D value; - } else { - env->pmsav8.hprbar[index] =3D value; - } - } else { - if (index >=3D cpu->pmsav7_dregion) { - return; - } - if (ri->opc2 & 0x1) { - env->pmsav8.rlar[M_REG_NS][index] =3D value; - } else { - env->pmsav8.rbar[M_REG_NS][index] =3D value; - } - } -} - -static uint64_t pmsav8r_regn_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - ARMCPU *cpu =3D env_archcpu(env); - uint8_t index =3D (extract32(ri->opc0, 0, 1) << 4) | - (extract32(ri->crm, 0, 3) << 1) | extract32(ri->opc2, = 2, 1); - - if (ri->opc1 & 4) { - if (index >=3D cpu->pmsav8r_hdregion) { - return 0x0; - } - if (ri->opc2 & 0x1) { - return env->pmsav8.hprlar[index]; - } else { - return env->pmsav8.hprbar[index]; - } - } else { - if (index >=3D cpu->pmsav7_dregion) { - return 0x0; - } - if (ri->opc2 & 0x1) { - return env->pmsav8.rlar[M_REG_NS][index]; - } else { - return env->pmsav8.rbar[M_REG_NS][index]; - } - } -} - -static const ARMCPRegInfo pmsav8r_cp_reginfo[] =3D { - { .name =3D "PRBAR", - .cp =3D 15, .opc1 =3D 0, .crn =3D 6, .crm =3D 3, .opc2 =3D 0, - .access =3D PL1_RW, .type =3D ARM_CP_NO_RAW, - .accessfn =3D access_tvm_trvm, - .readfn =3D prbar_read, .writefn =3D prbar_write }, - { .name =3D "PRLAR", - .cp =3D 15, .opc1 =3D 0, .crn =3D 6, .crm =3D 3, .opc2 =3D 1, - .access =3D PL1_RW, .type =3D ARM_CP_NO_RAW, - .accessfn =3D access_tvm_trvm, - .readfn =3D prlar_read, .writefn =3D prlar_write }, - { .name =3D "PRSELR", .resetvalue =3D 0, - .cp =3D 15, .opc1 =3D 0, .crn =3D 6, .crm =3D 2, .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .writefn =3D prselr_write, - .fieldoffset =3D offsetof(CPUARMState, pmsav7.rnr[M_REG_NS]) }, - { .name =3D "HPRBAR", .resetvalue =3D 0, - .cp =3D 15, .opc1 =3D 4, .crn =3D 6, .crm =3D 3, .opc2 =3D 0, - .access =3D PL2_RW, .type =3D ARM_CP_NO_RAW, - .readfn =3D hprbar_read, .writefn =3D hprbar_write }, - { .name =3D "HPRLAR", - .cp =3D 15, .opc1 =3D 4, .crn =3D 6, .crm =3D 3, .opc2 =3D 1, - .access =3D PL2_RW, .type =3D ARM_CP_NO_RAW, - .readfn =3D hprlar_read, .writefn =3D hprlar_write }, - { .name =3D "HPRSELR", .resetvalue =3D 0, - .cp =3D 15, .opc1 =3D 4, .crn =3D 6, .crm =3D 2, .opc2 =3D 1, - .access =3D PL2_RW, - .writefn =3D hprselr_write, - .fieldoffset =3D offsetof(CPUARMState, pmsav8.hprselr) }, - { .name =3D "HPRENR", - .cp =3D 15, .opc1 =3D 4, .crn =3D 6, .crm =3D 1, .opc2 =3D 1, - .access =3D PL2_RW, .type =3D ARM_CP_NO_RAW, - .readfn =3D hprenr_read, .writefn =3D hprenr_write }, -}; - -static const ARMCPRegInfo pmsav7_cp_reginfo[] =3D { - /* - * Reset for all these registers is handled in arm_cpu_reset(), - * because the PMSAv7 is also used by M-profile CPUs, which do - * not register cpregs but still need the state to be reset. - */ - { .name =3D "DRBAR", .cp =3D 15, .crn =3D 6, .opc1 =3D 0, .crm =3D 1, = .opc2 =3D 0, - .access =3D PL1_RW, .type =3D ARM_CP_NO_RAW, - .fieldoffset =3D offsetof(CPUARMState, pmsav7.drbar), - .readfn =3D pmsav7_read, .writefn =3D pmsav7_write, - .resetfn =3D arm_cp_reset_ignore }, - { .name =3D "DRSR", .cp =3D 15, .crn =3D 6, .opc1 =3D 0, .crm =3D 1, .= opc2 =3D 2, - .access =3D PL1_RW, .type =3D ARM_CP_NO_RAW, - .fieldoffset =3D offsetof(CPUARMState, pmsav7.drsr), - .readfn =3D pmsav7_read, .writefn =3D pmsav7_write, - .resetfn =3D arm_cp_reset_ignore }, - { .name =3D "DRACR", .cp =3D 15, .crn =3D 6, .opc1 =3D 0, .crm =3D 1, = .opc2 =3D 4, - .access =3D PL1_RW, .type =3D ARM_CP_NO_RAW, - .fieldoffset =3D offsetof(CPUARMState, pmsav7.dracr), - .readfn =3D pmsav7_read, .writefn =3D pmsav7_write, - .resetfn =3D arm_cp_reset_ignore }, - { .name =3D "RGNR", .cp =3D 15, .crn =3D 6, .opc1 =3D 0, .crm =3D 2, .= opc2 =3D 0, - .access =3D PL1_RW, - .fieldoffset =3D offsetof(CPUARMState, pmsav7.rnr[M_REG_NS]), - .writefn =3D pmsav7_rgnr_write, - .resetfn =3D arm_cp_reset_ignore }, -}; - -static const ARMCPRegInfo pmsav5_cp_reginfo[] =3D { - { .name =3D "DATA_AP", .cp =3D 15, .crn =3D 5, .crm =3D 0, .opc1 =3D 0= , .opc2 =3D 0, - .access =3D PL1_RW, .type =3D ARM_CP_ALIAS, - .fieldoffset =3D offsetof(CPUARMState, cp15.pmsav5_data_ap), - .readfn =3D pmsav5_data_ap_read, .writefn =3D pmsav5_data_ap_write, = }, - { .name =3D "INSN_AP", .cp =3D 15, .crn =3D 5, .crm =3D 0, .opc1 =3D 0= , .opc2 =3D 1, - .access =3D PL1_RW, .type =3D ARM_CP_ALIAS, - .fieldoffset =3D offsetof(CPUARMState, cp15.pmsav5_insn_ap), - .readfn =3D pmsav5_insn_ap_read, .writefn =3D pmsav5_insn_ap_write, = }, - { .name =3D "DATA_EXT_AP", .cp =3D 15, .crn =3D 5, .crm =3D 0, .opc1 = =3D 0, .opc2 =3D 2, - .access =3D PL1_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.pmsav5_data_ap), - .resetvalue =3D 0, }, - { .name =3D "INSN_EXT_AP", .cp =3D 15, .crn =3D 5, .crm =3D 0, .opc1 = =3D 0, .opc2 =3D 3, - .access =3D PL1_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.pmsav5_insn_ap), - .resetvalue =3D 0, }, - { .name =3D "DCACHE_CFG", .cp =3D 15, .crn =3D 2, .crm =3D 0, .opc1 = =3D 0, .opc2 =3D 0, - .access =3D PL1_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.c2_data), .resetvalue = =3D 0, }, - { .name =3D "ICACHE_CFG", .cp =3D 15, .crn =3D 2, .crm =3D 0, .opc1 = =3D 0, .opc2 =3D 1, - .access =3D PL1_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.c2_insn), .resetvalue = =3D 0, }, - /* Protection region base and size registers */ - { .name =3D "946_PRBS0", .cp =3D 15, .crn =3D 6, .crm =3D 0, .opc1 =3D= 0, - .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[0]) }, - { .name =3D "946_PRBS1", .cp =3D 15, .crn =3D 6, .crm =3D 1, .opc1 =3D= 0, - .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[1]) }, - { .name =3D "946_PRBS2", .cp =3D 15, .crn =3D 6, .crm =3D 2, .opc1 =3D= 0, - .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[2]) }, - { .name =3D "946_PRBS3", .cp =3D 15, .crn =3D 6, .crm =3D 3, .opc1 =3D= 0, - .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[3]) }, - { .name =3D "946_PRBS4", .cp =3D 15, .crn =3D 6, .crm =3D 4, .opc1 =3D= 0, - .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[4]) }, - { .name =3D "946_PRBS5", .cp =3D 15, .crn =3D 6, .crm =3D 5, .opc1 =3D= 0, - .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[5]) }, - { .name =3D "946_PRBS6", .cp =3D 15, .crn =3D 6, .crm =3D 6, .opc1 =3D= 0, - .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[6]) }, - { .name =3D "946_PRBS7", .cp =3D 15, .crn =3D 6, .crm =3D 7, .opc1 =3D= 0, - .opc2 =3D CP_ANY, .access =3D PL1_RW, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.c6_region[7]) }, -}; - -static void vmsa_ttbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - - if (!arm_feature(env, ARM_FEATURE_V8)) { - if (arm_feature(env, ARM_FEATURE_LPAE) && (value & TTBCR_EAE)) { - /* - * Pre ARMv8 bits [21:19], [15:14] and [6:3] are UNK/SBZP when - * using Long-descriptor translation table format - */ - value &=3D ~((7 << 19) | (3 << 14) | (0xf << 3)); - } else if (arm_feature(env, ARM_FEATURE_EL3)) { - /* - * In an implementation that includes the Security Extensions - * TTBCR has additional fields PD0 [4] and PD1 [5] for - * Short-descriptor translation table format. - */ - value &=3D TTBCR_PD1 | TTBCR_PD0 | TTBCR_N; - } else { - value &=3D TTBCR_N; - } - } - - if (arm_feature(env, ARM_FEATURE_LPAE)) { - /* - * With LPAE the TTBCR could result in a change of ASID - * via the TTBCR.A1 bit, so do a TLB flush. - */ - tlb_flush(CPU(cpu)); - } - raw_write(env, ri, value); -} - -static void vmsa_tcr_el12_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - - /* For AArch64 the A1 bit could result in a change of ASID, so TLB flu= sh. */ - tlb_flush(CPU(cpu)); - raw_write(env, ri, value); -} - -static void vmsa_ttbr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* If the ASID changes (with a 64-bit write), we must flush the TLB. = */ - if (cpreg_field_is_64bit(ri) && - extract64(raw_read(env, ri) ^ value, 48, 16) !=3D 0) { - ARMCPU *cpu =3D env_archcpu(env); - tlb_flush(CPU(cpu)); - } - raw_write(env, ri, value); -} - -static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *= ri, - uint64_t value) -{ - /* - * If we are running with E2&0 regime, then an ASID is active. - * Flush if that might be changing. Note we're not checking - * TCR_EL2.A1 to know if this is really the TTBRx_EL2 that - * holds the active ASID, only checking the field that might. - */ - if (extract64(raw_read(env, ri) ^ value, 48, 16) && - (arm_hcr_el2_eff(env) & HCR_E2H)) { - uint16_t mask =3D ARMMMUIdxBit_E20_2 | - ARMMMUIdxBit_E20_2_PAN | - ARMMMUIdxBit_E20_0; - tlb_flush_by_mmuidx(env_cpu(env), mask); - } - raw_write(env, ri, value); -} - -static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - CPUState *cs =3D CPU(cpu); - - /* - * A change in VMID to the stage2 page table (Stage2) invalidates - * the stage2 and combined stage 1&2 tlbs (EL10_1 and EL10_0). - */ - if (extract64(raw_read(env, ri) ^ value, 48, 16) !=3D 0) { - tlb_flush_by_mmuidx(cs, alle1_tlbmask(env)); - } - raw_write(env, ri, value); -} - -static const ARMCPRegInfo vmsa_pmsa_cp_reginfo[] =3D { - { .name =3D "DFSR", .cp =3D 15, .crn =3D 5, .crm =3D 0, .opc1 =3D 0, .= opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, .type =3D ARM_CP_= ALIAS, - .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.dfsr_s), - offsetoflow32(CPUARMState, cp15.dfsr_ns) }, }, - { .name =3D "IFSR", .cp =3D 15, .crn =3D 5, .crm =3D 0, .opc1 =3D 0, .= opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, .resetvalue =3D 0, - .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.ifsr_s), - offsetoflow32(CPUARMState, cp15.ifsr_ns) } }, - { .name =3D "DFAR", .cp =3D 15, .opc1 =3D 0, .crn =3D 6, .crm =3D 0, .= opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, .resetvalue =3D 0, - .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.dfar_s), - offsetof(CPUARMState, cp15.dfar_ns) } }, - { .name =3D "FAR_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .crn =3D 6, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .fieldoffset =3D offsetof(CPUARMState, cp15.far_el[1]), - .resetvalue =3D 0, }, -}; - -static const ARMCPRegInfo vmsa_cp_reginfo[] =3D { - { .name =3D "ESR_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .crn =3D 5, .crm =3D 2, .opc1 =3D 0, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .fieldoffset =3D offsetof(CPUARMState, cp15.esr_el[1]), .resetvalue = =3D 0, }, - { .name =3D "TTBR0_EL1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 0, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .writefn =3D vmsa_ttbr_write, .resetvalue =3D 0, - .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.ttbr0_s), - offsetof(CPUARMState, cp15.ttbr0_ns) } }, - { .name =3D "TTBR1_EL1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 0, .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .writefn =3D vmsa_ttbr_write, .resetvalue =3D 0, - .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.ttbr1_s), - offsetof(CPUARMState, cp15.ttbr1_ns) } }, - { .name =3D "TCR_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .crn =3D 2, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 2, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .writefn =3D vmsa_tcr_el12_write, - .raw_writefn =3D raw_write, - .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.tcr_el[1]) }, - { .name =3D "TTBCR", .cp =3D 15, .crn =3D 2, .crm =3D 0, .opc1 =3D 0, = .opc2 =3D 2, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .type =3D ARM_CP_ALIAS, .writefn =3D vmsa_ttbcr_write, - .raw_writefn =3D raw_write, - .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.tcr_el[3]), - offsetoflow32(CPUARMState, cp15.tcr_el[1])} }, -}; - -/* - * Note that unlike TTBCR, writing to TTBCR2 does not require flushing - * qemu tlbs nor adjusting cached masks. - */ -static const ARMCPRegInfo ttbcr2_reginfo =3D { - .name =3D "TTBCR2", .cp =3D 15, .opc1 =3D 0, .crn =3D 2, .crm =3D 0, .= opc2 =3D 3, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .type =3D ARM_CP_ALIAS, - .bank_fieldoffsets =3D { - offsetofhigh32(CPUARMState, cp15.tcr_el[3]), - offsetofhigh32(CPUARMState, cp15.tcr_el[1]), - }, -}; - -static void omap_ticonfig_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - env->cp15.c15_ticonfig =3D value & 0xe7; - /* The OS_TYPE bit in this register changes the reported CPUID! */ - env->cp15.c0_cpuid =3D (value & (1 << 5)) ? - ARM_CPUID_TI915T : ARM_CPUID_TI925T; -} - -static void omap_threadid_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - env->cp15.c15_threadid =3D value & 0xffff; -} - -static void omap_wfi_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* Wait-for-interrupt (deprecated) */ - cpu_interrupt(env_cpu(env), CPU_INTERRUPT_HALT); -} - -static void omap_cachemaint_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * On OMAP there are registers indicating the max/min index of dcache = lines - * containing a dirty line; cache flush operations have to reset these. - */ - env->cp15.c15_i_max =3D 0x000; - env->cp15.c15_i_min =3D 0xff0; -} - -static const ARMCPRegInfo omap_cp_reginfo[] =3D { - { .name =3D "DFSR", .cp =3D 15, .crn =3D 5, .crm =3D CP_ANY, - .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, .access =3D PL1_RW, .type =3D AR= M_CP_OVERRIDE, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.esr_el[1]), - .resetvalue =3D 0, }, - { .name =3D "", .cp =3D 15, .crn =3D 15, .crm =3D 0, .opc1 =3D 0, .opc= 2 =3D 0, - .access =3D PL1_RW, .type =3D ARM_CP_NOP }, - { .name =3D "TICONFIG", .cp =3D 15, .crn =3D 15, .crm =3D 1, .opc1 =3D= 0, .opc2 =3D 0, - .access =3D PL1_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.c15_ticonfig), .resetval= ue =3D 0, - .writefn =3D omap_ticonfig_write }, - { .name =3D "IMAX", .cp =3D 15, .crn =3D 15, .crm =3D 2, .opc1 =3D 0, = .opc2 =3D 0, - .access =3D PL1_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.c15_i_max), .resetvalue = =3D 0, }, - { .name =3D "IMIN", .cp =3D 15, .crn =3D 15, .crm =3D 3, .opc1 =3D 0, = .opc2 =3D 0, - .access =3D PL1_RW, .resetvalue =3D 0xff0, - .fieldoffset =3D offsetof(CPUARMState, cp15.c15_i_min) }, - { .name =3D "THREADID", .cp =3D 15, .crn =3D 15, .crm =3D 4, .opc1 =3D= 0, .opc2 =3D 0, - .access =3D PL1_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.c15_threadid), .resetval= ue =3D 0, - .writefn =3D omap_threadid_write }, - { .name =3D "TI925T_STATUS", .cp =3D 15, .crn =3D 15, - .crm =3D 8, .opc1 =3D 0, .opc2 =3D 0, .access =3D PL1_RW, - .type =3D ARM_CP_NO_RAW, - .readfn =3D arm_cp_read_zero, .writefn =3D omap_wfi_write, }, - /* - * TODO: Peripheral port remap register: - * On OMAP2 mcr p15, 0, rn, c15, c2, 4 sets up the interrupt controller - * base address at $rn & ~0xfff and map size of 0x200 << ($rn & 0xfff), - * when MMU is off. - */ - { .name =3D "OMAP_CACHEMAINT", .cp =3D 15, .crn =3D 7, .crm =3D CP_ANY, - .opc1 =3D 0, .opc2 =3D CP_ANY, .access =3D PL1_W, - .type =3D ARM_CP_OVERRIDE | ARM_CP_NO_RAW, - .writefn =3D omap_cachemaint_write }, - { .name =3D "C9", .cp =3D 15, .crn =3D 9, - .crm =3D CP_ANY, .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, .access =3D PL1= _RW, - .type =3D ARM_CP_CONST | ARM_CP_OVERRIDE, .resetvalue =3D 0 }, -}; - -static void xscale_cpar_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - env->cp15.c15_cpar =3D value & 0x3fff; -} - -static const ARMCPRegInfo xscale_cp_reginfo[] =3D { - { .name =3D "XSCALE_CPAR", - .cp =3D 15, .crn =3D 15, .crm =3D 1, .opc1 =3D 0, .opc2 =3D 0, .acce= ss =3D PL1_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.c15_cpar), .resetvalue = =3D 0, - .writefn =3D xscale_cpar_write, }, - { .name =3D "XSCALE_AUXCR", - .cp =3D 15, .crn =3D 1, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 1, .acces= s =3D PL1_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.c1_xscaleauxcr), - .resetvalue =3D 0, }, - /* - * XScale specific cache-lockdown: since we have no cache we NOP these - * and hope the guest does not really rely on cache behaviour. - */ - { .name =3D "XSCALE_LOCK_ICACHE_LINE", - .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 1, .opc2 =3D 0, - .access =3D PL1_W, .type =3D ARM_CP_NOP }, - { .name =3D "XSCALE_UNLOCK_ICACHE", - .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 1, .opc2 =3D 1, - .access =3D PL1_W, .type =3D ARM_CP_NOP }, - { .name =3D "XSCALE_DCACHE_LOCK", - .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 2, .opc2 =3D 0, - .access =3D PL1_RW, .type =3D ARM_CP_NOP }, - { .name =3D "XSCALE_UNLOCK_DCACHE", - .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 2, .opc2 =3D 1, - .access =3D PL1_W, .type =3D ARM_CP_NOP }, -}; - -static const ARMCPRegInfo dummy_c15_cp_reginfo[] =3D { - /* - * RAZ/WI the whole crn=3D15 space, when we don't have a more specific - * implementation of this implementation-defined space. - * Ideally this should eventually disappear in favour of actually - * implementing the correct behaviour for all cores. - */ - { .name =3D "C15_IMPDEF", .cp =3D 15, .crn =3D 15, - .crm =3D CP_ANY, .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, - .access =3D PL1_RW, - .type =3D ARM_CP_CONST | ARM_CP_NO_RAW | ARM_CP_OVERRIDE, - .resetvalue =3D 0 }, -}; - -static const ARMCPRegInfo cache_dirty_status_cp_reginfo[] =3D { - /* Cache status: RAZ because we have no cache so it's always clean */ - { .name =3D "CDSR", .cp =3D 15, .crn =3D 7, .crm =3D 10, .opc1 =3D 0, = .opc2 =3D 6, - .access =3D PL1_R, .type =3D ARM_CP_CONST | ARM_CP_NO_RAW, - .resetvalue =3D 0 }, -}; - -static const ARMCPRegInfo cache_block_ops_cp_reginfo[] =3D { - /* We never have a block transfer operation in progress */ - { .name =3D "BXSR", .cp =3D 15, .crn =3D 7, .crm =3D 12, .opc1 =3D 0, = .opc2 =3D 4, - .access =3D PL0_R, .type =3D ARM_CP_CONST | ARM_CP_NO_RAW, - .resetvalue =3D 0 }, - /* The cache ops themselves: these all NOP for QEMU */ - { .name =3D "IICR", .cp =3D 15, .crm =3D 5, .opc1 =3D 0, - .access =3D PL1_W, .type =3D ARM_CP_NOP | ARM_CP_64BIT }, - { .name =3D "IDCR", .cp =3D 15, .crm =3D 6, .opc1 =3D 0, - .access =3D PL1_W, .type =3D ARM_CP_NOP | ARM_CP_64BIT }, - { .name =3D "CDCR", .cp =3D 15, .crm =3D 12, .opc1 =3D 0, - .access =3D PL0_W, .type =3D ARM_CP_NOP | ARM_CP_64BIT }, - { .name =3D "PIR", .cp =3D 15, .crm =3D 12, .opc1 =3D 1, - .access =3D PL0_W, .type =3D ARM_CP_NOP | ARM_CP_64BIT }, - { .name =3D "PDR", .cp =3D 15, .crm =3D 12, .opc1 =3D 2, - .access =3D PL0_W, .type =3D ARM_CP_NOP | ARM_CP_64BIT }, - { .name =3D "CIDCR", .cp =3D 15, .crm =3D 14, .opc1 =3D 0, - .access =3D PL1_W, .type =3D ARM_CP_NOP | ARM_CP_64BIT }, -}; - -static const ARMCPRegInfo cache_test_clean_cp_reginfo[] =3D { - /* - * The cache test-and-clean instructions always return (1 << 30) - * to indicate that there are no dirty cache lines. - */ - { .name =3D "TC_DCACHE", .cp =3D 15, .crn =3D 7, .crm =3D 10, .opc1 = =3D 0, .opc2 =3D 3, - .access =3D PL0_R, .type =3D ARM_CP_CONST | ARM_CP_NO_RAW, - .resetvalue =3D (1 << 30) }, - { .name =3D "TCI_DCACHE", .cp =3D 15, .crn =3D 7, .crm =3D 14, .opc1 = =3D 0, .opc2 =3D 3, - .access =3D PL0_R, .type =3D ARM_CP_CONST | ARM_CP_NO_RAW, - .resetvalue =3D (1 << 30) }, -}; - -static const ARMCPRegInfo strongarm_cp_reginfo[] =3D { - /* Ignore ReadBuffer accesses */ - { .name =3D "C9_READBUFFER", .cp =3D 15, .crn =3D 9, - .crm =3D CP_ANY, .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, - .access =3D PL1_RW, .resetvalue =3D 0, - .type =3D ARM_CP_CONST | ARM_CP_OVERRIDE | ARM_CP_NO_RAW }, -}; - -static uint64_t midr_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - unsigned int cur_el =3D arm_current_el(env); - - if (arm_is_el2_enabled(env) && cur_el =3D=3D 1) { - return env->cp15.vpidr_el2; - } - return raw_read(env, ri); -} - -static uint64_t mpidr_read_val(CPUARMState *env) -{ - ARMCPU *cpu =3D env_archcpu(env); - uint64_t mpidr =3D cpu->mp_affinity; - - if (arm_feature(env, ARM_FEATURE_V7MP)) { - mpidr |=3D (1U << 31); - /* - * Cores which are uniprocessor (non-coherent) - * but still implement the MP extensions set - * bit 30. (For instance, Cortex-R5). - */ - if (cpu->mp_is_up) { - mpidr |=3D (1u << 30); - } - } - return mpidr; -} - -static uint64_t mpidr_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - unsigned int cur_el =3D arm_current_el(env); - - if (arm_is_el2_enabled(env) && cur_el =3D=3D 1) { - return env->cp15.vmpidr_el2; - } - return mpidr_read_val(env); -} - -static const ARMCPRegInfo lpae_cp_reginfo[] =3D { - /* NOP AMAIR0/1 */ - { .name =3D "AMAIR0", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .crn =3D 10, .crm =3D 3, .opc1 =3D 0, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - /* AMAIR1 is mapped to AMAIR_EL1[63:32] */ - { .name =3D "AMAIR1", .cp =3D 15, .crn =3D 10, .crm =3D 3, .opc1 =3D 0= , .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - { .name =3D "PAR", .cp =3D 15, .crm =3D 7, .opc1 =3D 0, - .access =3D PL1_RW, .type =3D ARM_CP_64BIT, .resetvalue =3D 0, - .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.par_s), - offsetof(CPUARMState, cp15.par_ns)} }, - { .name =3D "TTBR0", .cp =3D 15, .crm =3D 2, .opc1 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .type =3D ARM_CP_64BIT | ARM_CP_ALIAS, - .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.ttbr0_s), - offsetof(CPUARMState, cp15.ttbr0_ns) }, - .writefn =3D vmsa_ttbr_write, }, - { .name =3D "TTBR1", .cp =3D 15, .crm =3D 2, .opc1 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .type =3D ARM_CP_64BIT | ARM_CP_ALIAS, - .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.ttbr1_s), - offsetof(CPUARMState, cp15.ttbr1_ns) }, - .writefn =3D vmsa_ttbr_write, }, -}; - -static uint64_t aa64_fpcr_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return vfp_get_fpcr(env); -} - -static void aa64_fpcr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - vfp_set_fpcr(env, value); -} - -static uint64_t aa64_fpsr_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return vfp_get_fpsr(env); -} - -static void aa64_fpsr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - vfp_set_fpsr(env, value); -} - -static CPAccessResult aa64_daif_access(CPUARMState *env, const ARMCPRegInf= o *ri, - bool isread) -{ - if (arm_current_el(env) =3D=3D 0 && !(arm_sctlr(env, 0) & SCTLR_UMA)) { - return CP_ACCESS_TRAP; - } - return CP_ACCESS_OK; -} - -static void aa64_daif_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - env->daif =3D value & PSTATE_DAIF; -} - -static uint64_t aa64_pan_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return env->pstate & PSTATE_PAN; -} - -static void aa64_pan_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - env->pstate =3D (env->pstate & ~PSTATE_PAN) | (value & PSTATE_PAN); -} - -static const ARMCPRegInfo pan_reginfo =3D { - .name =3D "PAN", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 4, .crm =3D 2, .opc2 =3D 3, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_RW, - .readfn =3D aa64_pan_read, .writefn =3D aa64_pan_write -}; - -static uint64_t aa64_uao_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return env->pstate & PSTATE_UAO; -} - -static void aa64_uao_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - env->pstate =3D (env->pstate & ~PSTATE_UAO) | (value & PSTATE_UAO); -} - -static const ARMCPRegInfo uao_reginfo =3D { - .name =3D "UAO", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 4, .crm =3D 2, .opc2 =3D 4, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_RW, - .readfn =3D aa64_uao_read, .writefn =3D aa64_uao_write -}; - -static uint64_t aa64_dit_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return env->pstate & PSTATE_DIT; -} - -static void aa64_dit_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - env->pstate =3D (env->pstate & ~PSTATE_DIT) | (value & PSTATE_DIT); -} - -static const ARMCPRegInfo dit_reginfo =3D { - .name =3D "DIT", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 4, .crm =3D 2, .opc2 =3D 5, - .type =3D ARM_CP_NO_RAW, .access =3D PL0_RW, - .readfn =3D aa64_dit_read, .writefn =3D aa64_dit_write -}; - -static uint64_t aa64_ssbs_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return env->pstate & PSTATE_SSBS; -} - -static void aa64_ssbs_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - env->pstate =3D (env->pstate & ~PSTATE_SSBS) | (value & PSTATE_SSBS); -} - -static const ARMCPRegInfo ssbs_reginfo =3D { - .name =3D "SSBS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 4, .crm =3D 2, .opc2 =3D 6, - .type =3D ARM_CP_NO_RAW, .access =3D PL0_RW, - .readfn =3D aa64_ssbs_read, .writefn =3D aa64_ssbs_write -}; - -static CPAccessResult aa64_cacheop_poc_access(CPUARMState *env, - const ARMCPRegInfo *ri, - bool isread) -{ - /* Cache invalidate/clean to Point of Coherency or Persistence... */ - switch (arm_current_el(env)) { - case 0: - /* ... EL0 must UNDEF unless SCTLR_EL1.UCI is set. */ - if (!(arm_sctlr(env, 0) & SCTLR_UCI)) { - return CP_ACCESS_TRAP; - } - /* fall through */ - case 1: - /* ... EL1 must trap to EL2 if HCR_EL2.TPCP is set. */ - if (arm_hcr_el2_eff(env) & HCR_TPCP) { - return CP_ACCESS_TRAP_EL2; - } - break; - } - return CP_ACCESS_OK; -} - -static CPAccessResult do_cacheop_pou_access(CPUARMState *env, uint64_t hcr= flags) -{ - /* Cache invalidate/clean to Point of Unification... */ - switch (arm_current_el(env)) { - case 0: - /* ... EL0 must UNDEF unless SCTLR_EL1.UCI is set. */ - if (!(arm_sctlr(env, 0) & SCTLR_UCI)) { - return CP_ACCESS_TRAP; - } - /* fall through */ - case 1: - /* ... EL1 must trap to EL2 if relevant HCR_EL2 flags are set. */ - if (arm_hcr_el2_eff(env) & hcrflags) { - return CP_ACCESS_TRAP_EL2; - } - break; - } - return CP_ACCESS_OK; -} - -static CPAccessResult access_ticab(CPUARMState *env, const ARMCPRegInfo *r= i, - bool isread) -{ - return do_cacheop_pou_access(env, HCR_TICAB | HCR_TPU); -} - -static CPAccessResult access_tocu(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - return do_cacheop_pou_access(env, HCR_TOCU | HCR_TPU); -} - -/* - * See: D4.7.2 TLB maintenance requirements and the TLB maintenance instru= ctions - * Page D4-1736 (DDI0487A.b) - */ - -static int vae1_tlbmask(CPUARMState *env) -{ - uint64_t hcr =3D arm_hcr_el2_eff(env); - uint16_t mask; - - if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { - mask =3D ARMMMUIdxBit_E20_2 | - ARMMMUIdxBit_E20_2_PAN | - ARMMMUIdxBit_E20_0; - } else { - mask =3D ARMMMUIdxBit_E10_1 | - ARMMMUIdxBit_E10_1_PAN | - ARMMMUIdxBit_E10_0; - } - return mask; -} - -/* Return 56 if TBI is enabled, 64 otherwise. */ -static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx, - uint64_t addr) -{ - uint64_t tcr =3D regime_tcr(env, mmu_idx); - int tbi =3D aa64_va_parameter_tbi(tcr, mmu_idx); - int select =3D extract64(addr, 55, 1); - - return (tbi >> select) & 1 ? 56 : 64; -} - -static int vae1_tlbbits(CPUARMState *env, uint64_t addr) -{ - uint64_t hcr =3D arm_hcr_el2_eff(env); - ARMMMUIdx mmu_idx; - - /* Only the regime of the mmu_idx below is significant. */ - if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { - mmu_idx =3D ARMMMUIdx_E20_0; - } else { - mmu_idx =3D ARMMMUIdx_E10_0; - } - - return tlbbits_for_regime(env, mmu_idx, addr); -} - -static void tlbi_aa64_vmalle1is_write(CPUARMState *env, const ARMCPRegInfo= *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - int mask =3D vae1_tlbmask(env); - - tlb_flush_by_mmuidx_all_cpus_synced(cs, mask); -} - -static void tlbi_aa64_vmalle1_write(CPUARMState *env, const ARMCPRegInfo *= ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - int mask =3D vae1_tlbmask(env); - - if (tlb_force_broadcast(env)) { - tlb_flush_by_mmuidx_all_cpus_synced(cs, mask); - } else { - tlb_flush_by_mmuidx(cs, mask); - } -} - -static int e2_tlbmask(CPUARMState *env) -{ - return (ARMMMUIdxBit_E20_0 | - ARMMMUIdxBit_E20_2 | - ARMMMUIdxBit_E20_2_PAN | - ARMMMUIdxBit_E2); -} - -static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - int mask =3D alle1_tlbmask(env); - - tlb_flush_by_mmuidx(cs, mask); -} - -static void tlbi_aa64_alle2_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - int mask =3D e2_tlbmask(env); - - tlb_flush_by_mmuidx(cs, mask); -} - -static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - CPUState *cs =3D CPU(cpu); - - tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E3); -} - -static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *= ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - int mask =3D alle1_tlbmask(env); - - tlb_flush_by_mmuidx_all_cpus_synced(cs, mask); -} - -static void tlbi_aa64_alle2is_write(CPUARMState *env, const ARMCPRegInfo *= ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - int mask =3D e2_tlbmask(env); - - tlb_flush_by_mmuidx_all_cpus_synced(cs, mask); -} - -static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *= ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - - tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E3); -} - -static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * Invalidate by VA, EL2 - * Currently handles both VAE2 and VALE2, since we don't support - * flush-last-level-only. - */ - CPUState *cs =3D env_cpu(env); - int mask =3D e2_tlbmask(env); - uint64_t pageaddr =3D sextract64(value << 12, 0, 56); - - tlb_flush_page_by_mmuidx(cs, pageaddr, mask); -} - -static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * Invalidate by VA, EL3 - * Currently handles both VAE3 and VALE3, since we don't support - * flush-last-level-only. - */ - ARMCPU *cpu =3D env_archcpu(env); - CPUState *cs =3D CPU(cpu); - uint64_t pageaddr =3D sextract64(value << 12, 0, 56); - - tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E3); -} - -static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *r= i, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - int mask =3D vae1_tlbmask(env); - uint64_t pageaddr =3D sextract64(value << 12, 0, 56); - int bits =3D vae1_tlbbits(env, pageaddr); - - tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits= ); -} - -static void tlbi_aa64_vae1_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * Invalidate by VA, EL1&0 (AArch64 version). - * Currently handles all of VAE1, VAAE1, VAALE1 and VALE1, - * since we don't support flush-for-specific-ASID-only or - * flush-last-level-only. - */ - CPUState *cs =3D env_cpu(env); - int mask =3D vae1_tlbmask(env); - uint64_t pageaddr =3D sextract64(value << 12, 0, 56); - int bits =3D vae1_tlbbits(env, pageaddr); - - if (tlb_force_broadcast(env)) { - tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, = bits); - } else { - tlb_flush_page_bits_by_mmuidx(cs, pageaddr, mask, bits); - } -} - -static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *r= i, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - uint64_t pageaddr =3D sextract64(value << 12, 0, 56); - int bits =3D tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr); - - tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, - ARMMMUIdxBit_E2, bits); -} - -static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *r= i, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - uint64_t pageaddr =3D sextract64(value << 12, 0, 56); - int bits =3D tlbbits_for_regime(env, ARMMMUIdx_E3, pageaddr); - - tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, - ARMMMUIdxBit_E3, bits); -} - -static int ipas2e1_tlbmask(CPUARMState *env, int64_t value) -{ - /* - * The MSB of value is the NS field, which only applies if SEL2 - * is implemented and SCR_EL3.NS is not set (i.e. in secure mode). - */ - return (value >=3D 0 - && cpu_isar_feature(aa64_sel2, env_archcpu(env)) - && arm_is_secure_below_el3(env) - ? ARMMMUIdxBit_Stage2_S - : ARMMMUIdxBit_Stage2); -} - -static void tlbi_aa64_ipas2e1_write(CPUARMState *env, const ARMCPRegInfo *= ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - int mask =3D ipas2e1_tlbmask(env, value); - uint64_t pageaddr =3D sextract64(value << 12, 0, 56); - - if (tlb_force_broadcast(env)) { - tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask); - } else { - tlb_flush_page_by_mmuidx(cs, pageaddr, mask); - } -} - -static void tlbi_aa64_ipas2e1is_write(CPUARMState *env, const ARMCPRegInfo= *ri, - uint64_t value) -{ - CPUState *cs =3D env_cpu(env); - int mask =3D ipas2e1_tlbmask(env, value); - uint64_t pageaddr =3D sextract64(value << 12, 0, 56); - - tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr, mask); -} - -#ifdef TARGET_AARCH64 -typedef struct { - uint64_t base; - uint64_t length; -} TLBIRange; - -static ARMGranuleSize tlbi_range_tg_to_gran_size(int tg) -{ - /* - * Note that the TLBI range TG field encoding differs from both - * TG0 and TG1 encodings. - */ - switch (tg) { - case 1: - return Gran4K; - case 2: - return Gran16K; - case 3: - return Gran64K; - default: - return GranInvalid; - } -} - -static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx, - uint64_t value) -{ - unsigned int page_size_granule, page_shift, num, scale, exponent; - /* Extract one bit to represent the va selector in use. */ - uint64_t select =3D sextract64(value, 36, 1); - ARMVAParameters param =3D aa64_va_parameters(env, select, mmuidx, true= ); - TLBIRange ret =3D { }; - ARMGranuleSize gran; - - page_size_granule =3D extract64(value, 46, 2); - gran =3D tlbi_range_tg_to_gran_size(page_size_granule); - - /* The granule encoded in value must match the granule in use. */ - if (gran !=3D param.gran) { - qemu_log_mask(LOG_GUEST_ERROR, "Invalid tlbi page size granule %d\= n", - page_size_granule); - return ret; - } - - page_shift =3D arm_granule_bits(gran); - num =3D extract64(value, 39, 5); - scale =3D extract64(value, 44, 2); - exponent =3D (5 * scale) + 1; - - ret.length =3D (num + 1) << (exponent + page_shift); - - if (param.select) { - ret.base =3D sextract64(value, 0, 37); - } else { - ret.base =3D extract64(value, 0, 37); - } - if (param.ds) { - /* - * With DS=3D1, BaseADDR is always shifted 16 so that it is able - * to address all 52 va bits. The input address is perforce - * aligned on a 64k boundary regardless of translation granule. - */ - page_shift =3D 16; - } - ret.base <<=3D page_shift; - - return ret; -} - -static void do_rvae_write(CPUARMState *env, uint64_t value, - int idxmap, bool synced) -{ - ARMMMUIdx one_idx =3D ARM_MMU_IDX_A | ctz32(idxmap); - TLBIRange range; - int bits; - - range =3D tlbi_aa64_get_range(env, one_idx, value); - bits =3D tlbbits_for_regime(env, one_idx, range.base); - - if (synced) { - tlb_flush_range_by_mmuidx_all_cpus_synced(env_cpu(env), - range.base, - range.length, - idxmap, - bits); - } else { - tlb_flush_range_by_mmuidx(env_cpu(env), range.base, - range.length, idxmap, bits); - } -} - -static void tlbi_aa64_rvae1_write(CPUARMState *env, - const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * Invalidate by VA range, EL1&0. - * Currently handles all of RVAE1, RVAAE1, RVAALE1 and RVALE1, - * since we don't support flush-for-specific-ASID-only or - * flush-last-level-only. - */ - - do_rvae_write(env, value, vae1_tlbmask(env), - tlb_force_broadcast(env)); -} - -static void tlbi_aa64_rvae1is_write(CPUARMState *env, - const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * Invalidate by VA range, Inner/Outer Shareable EL1&0. - * Currently handles all of RVAE1IS, RVAE1OS, RVAAE1IS, RVAAE1OS, - * RVAALE1IS, RVAALE1OS, RVALE1IS and RVALE1OS, since we don't support - * flush-for-specific-ASID-only, flush-last-level-only or inner/outer - * shareable specific flushes. - */ - - do_rvae_write(env, value, vae1_tlbmask(env), true); -} - -static int vae2_tlbmask(CPUARMState *env) -{ - return ARMMMUIdxBit_E2; -} - -static void tlbi_aa64_rvae2_write(CPUARMState *env, - const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * Invalidate by VA range, EL2. - * Currently handles all of RVAE2 and RVALE2, - * since we don't support flush-for-specific-ASID-only or - * flush-last-level-only. - */ - - do_rvae_write(env, value, vae2_tlbmask(env), - tlb_force_broadcast(env)); - - -} - -static void tlbi_aa64_rvae2is_write(CPUARMState *env, - const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * Invalidate by VA range, Inner/Outer Shareable, EL2. - * Currently handles all of RVAE2IS, RVAE2OS, RVALE2IS and RVALE2OS, - * since we don't support flush-for-specific-ASID-only, - * flush-last-level-only or inner/outer shareable specific flushes. - */ - - do_rvae_write(env, value, vae2_tlbmask(env), true); - -} - -static void tlbi_aa64_rvae3_write(CPUARMState *env, - const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * Invalidate by VA range, EL3. - * Currently handles all of RVAE3 and RVALE3, - * since we don't support flush-for-specific-ASID-only or - * flush-last-level-only. - */ - - do_rvae_write(env, value, ARMMMUIdxBit_E3, tlb_force_broadcast(env)); -} - -static void tlbi_aa64_rvae3is_write(CPUARMState *env, - const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * Invalidate by VA range, EL3, Inner/Outer Shareable. - * Currently handles all of RVAE3IS, RVAE3OS, RVALE3IS and RVALE3OS, - * since we don't support flush-for-specific-ASID-only, - * flush-last-level-only or inner/outer specific flushes. - */ - - do_rvae_write(env, value, ARMMMUIdxBit_E3, true); -} - -static void tlbi_aa64_ripas2e1_write(CPUARMState *env, const ARMCPRegInfo = *ri, - uint64_t value) -{ - do_rvae_write(env, value, ipas2e1_tlbmask(env, value), - tlb_force_broadcast(env)); -} - -static void tlbi_aa64_ripas2e1is_write(CPUARMState *env, - const ARMCPRegInfo *ri, - uint64_t value) -{ - do_rvae_write(env, value, ipas2e1_tlbmask(env, value), true); -} -#endif - -static CPAccessResult aa64_zva_access(CPUARMState *env, const ARMCPRegInfo= *ri, - bool isread) -{ - int cur_el =3D arm_current_el(env); - - if (cur_el < 2) { - uint64_t hcr =3D arm_hcr_el2_eff(env); - - if (cur_el =3D=3D 0) { - if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { - if (!(env->cp15.sctlr_el[2] & SCTLR_DZE)) { - return CP_ACCESS_TRAP_EL2; - } - } else { - if (!(env->cp15.sctlr_el[1] & SCTLR_DZE)) { - return CP_ACCESS_TRAP; - } - if (hcr & HCR_TDZ) { - return CP_ACCESS_TRAP_EL2; - } - } - } else if (hcr & HCR_TDZ) { - return CP_ACCESS_TRAP_EL2; - } - } - return CP_ACCESS_OK; -} - -static uint64_t aa64_dczid_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - ARMCPU *cpu =3D env_archcpu(env); - int dzp_bit =3D 1 << 4; - - /* DZP indicates whether DC ZVA access is allowed */ - if (aa64_zva_access(env, NULL, false) =3D=3D CP_ACCESS_OK) { - dzp_bit =3D 0; - } - return cpu->dcz_blocksize | dzp_bit; -} - -static CPAccessResult sp_el0_access(CPUARMState *env, const ARMCPRegInfo *= ri, - bool isread) -{ - if (!(env->pstate & PSTATE_SP)) { - /* - * Access to SP_EL0 is undefined if it's being used as - * the stack pointer. - */ - return CP_ACCESS_TRAP_UNCATEGORIZED; - } - return CP_ACCESS_OK; -} - -static uint64_t spsel_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return env->pstate & PSTATE_SP; -} - -static void spsel_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t= val) -{ - update_spsel(env, val); -} - -static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - - if (arm_feature(env, ARM_FEATURE_PMSA) && !cpu->has_mpu) { - /* M bit is RAZ/WI for PMSA with no MPU implemented */ - value &=3D ~SCTLR_M; - } - - /* ??? Lots of these bits are not implemented. */ - - if (ri->state =3D=3D ARM_CP_STATE_AA64 && !cpu_isar_feature(aa64_mte, = cpu)) { - if (ri->opc1 =3D=3D 6) { /* SCTLR_EL3 */ - value &=3D ~(SCTLR_ITFSB | SCTLR_TCF | SCTLR_ATA); - } else { - value &=3D ~(SCTLR_ITFSB | SCTLR_TCF0 | SCTLR_TCF | - SCTLR_ATA0 | SCTLR_ATA); - } - } - - if (raw_read(env, ri) =3D=3D value) { - /* - * Skip the TLB flush if nothing actually changed; Linux likes - * to do a lot of pointless SCTLR writes. - */ - return; - } - - raw_write(env, ri, value); - - /* This may enable/disable the MMU, so do a TLB flush. */ - tlb_flush(CPU(cpu)); - - if (ri->type & ARM_CP_SUPPRESS_TB_END) { - /* - * Normally we would always end the TB on an SCTLR write; see the - * comment in ARMCPRegInfo sctlr initialization below for why Xsca= le - * is special. Setting ARM_CP_SUPPRESS_TB_END also stops the rebu= ild - * of hflags from the translator, so do it here. - */ - arm_rebuild_hflags(env); - } -} - -static void mdcr_el3_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * Some MDCR_EL3 bits affect whether PMU counters are running: - * if we are trying to change any of those then we must - * bracket this update with PMU start/finish calls. - */ - bool pmu_op =3D (env->cp15.mdcr_el3 ^ value) & MDCR_EL3_PMU_ENABLE_BIT= S; - - if (pmu_op) { - pmu_op_start(env); - } - env->cp15.mdcr_el3 =3D value; - if (pmu_op) { - pmu_op_finish(env); - } -} - -static void sdcr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* Not all bits defined for MDCR_EL3 exist in the AArch32 SDCR */ - mdcr_el3_write(env, ri, value & SDCR_VALID_MASK); -} - -static void mdcr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * Some MDCR_EL2 bits affect whether PMU counters are running: - * if we are trying to change any of those then we must - * bracket this update with PMU start/finish calls. - */ - bool pmu_op =3D (env->cp15.mdcr_el2 ^ value) & MDCR_EL2_PMU_ENABLE_BIT= S; - - if (pmu_op) { - pmu_op_start(env); - } - env->cp15.mdcr_el2 =3D value; - if (pmu_op) { - pmu_op_finish(env); - } -} - -static const ARMCPRegInfo v8_cp_reginfo[] =3D { - /* - * Minimal set of EL0-visible registers. This will need to be expanded - * significantly for system emulation of AArch64 CPUs. - */ - { .name =3D "NZCV", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 0, .crn =3D 4, .crm =3D 2, - .access =3D PL0_RW, .type =3D ARM_CP_NZCV }, - { .name =3D "DAIF", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 1, .crn =3D 4, .crm =3D 2, - .type =3D ARM_CP_NO_RAW, - .access =3D PL0_RW, .accessfn =3D aa64_daif_access, - .fieldoffset =3D offsetof(CPUARMState, daif), - .writefn =3D aa64_daif_write, .resetfn =3D arm_cp_reset_ignore }, - { .name =3D "FPCR", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 0, .crn =3D 4, .crm =3D 4, - .access =3D PL0_RW, .type =3D ARM_CP_FPU | ARM_CP_SUPPRESS_TB_END, - .readfn =3D aa64_fpcr_read, .writefn =3D aa64_fpcr_write }, - { .name =3D "FPSR", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 1, .crn =3D 4, .crm =3D 4, - .access =3D PL0_RW, .type =3D ARM_CP_FPU | ARM_CP_SUPPRESS_TB_END, - .readfn =3D aa64_fpsr_read, .writefn =3D aa64_fpsr_write }, - { .name =3D "DCZID_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 7, .crn =3D 0, .crm =3D 0, - .access =3D PL0_R, .type =3D ARM_CP_NO_RAW, - .readfn =3D aa64_dczid_read }, - { .name =3D "DC_ZVA", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 4, .opc2 =3D 1, - .access =3D PL0_W, .type =3D ARM_CP_DC_ZVA, -#ifndef CONFIG_USER_ONLY - /* Avoid overhead of an access check that always passes in user-mode= */ - .accessfn =3D aa64_zva_access, -#endif - }, - { .name =3D "CURRENTEL", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .opc2 =3D 2, .crn =3D 4, .crm =3D 2, - .access =3D PL1_R, .type =3D ARM_CP_CURRENTEL }, - /* Cache ops: all NOPs since we don't emulate caches */ - { .name =3D "IC_IALLUIS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 1, .opc2 =3D 0, - .access =3D PL1_W, .type =3D ARM_CP_NOP, - .accessfn =3D access_ticab }, - { .name =3D "IC_IALLU", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 5, .opc2 =3D 0, - .access =3D PL1_W, .type =3D ARM_CP_NOP, - .accessfn =3D access_tocu }, - { .name =3D "IC_IVAU", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 5, .opc2 =3D 1, - .access =3D PL0_W, .type =3D ARM_CP_NOP, - .accessfn =3D access_tocu }, - { .name =3D "DC_IVAC", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 6, .opc2 =3D 1, - .access =3D PL1_W, .accessfn =3D aa64_cacheop_poc_access, - .type =3D ARM_CP_NOP }, - { .name =3D "DC_ISW", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 6, .opc2 =3D 2, - .access =3D PL1_W, .accessfn =3D access_tsw, .type =3D ARM_CP_NOP }, - { .name =3D "DC_CVAC", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 10, .opc2 =3D 1, - .access =3D PL0_W, .type =3D ARM_CP_NOP, - .accessfn =3D aa64_cacheop_poc_access }, - { .name =3D "DC_CSW", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 10, .opc2 =3D 2, - .access =3D PL1_W, .accessfn =3D access_tsw, .type =3D ARM_CP_NOP }, - { .name =3D "DC_CVAU", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 11, .opc2 =3D 1, - .access =3D PL0_W, .type =3D ARM_CP_NOP, - .accessfn =3D access_tocu }, - { .name =3D "DC_CIVAC", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 14, .opc2 =3D 1, - .access =3D PL0_W, .type =3D ARM_CP_NOP, - .accessfn =3D aa64_cacheop_poc_access }, - { .name =3D "DC_CISW", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 14, .opc2 =3D 2, - .access =3D PL1_W, .accessfn =3D access_tsw, .type =3D ARM_CP_NOP }, - /* TLBI operations */ - { .name =3D "TLBI_VMALLE1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 3, .opc2 =3D 0, - .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_vmalle1is_write }, - { .name =3D "TLBI_VAE1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 3, .opc2 =3D 1, - .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_vae1is_write }, - { .name =3D "TLBI_ASIDE1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 3, .opc2 =3D 2, - .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_vmalle1is_write }, - { .name =3D "TLBI_VAAE1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 3, .opc2 =3D 3, - .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_vae1is_write }, - { .name =3D "TLBI_VALE1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 3, .opc2 =3D 5, - .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_vae1is_write }, - { .name =3D "TLBI_VAALE1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 3, .opc2 =3D 7, - .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_vae1is_write }, - { .name =3D "TLBI_VMALLE1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 7, .opc2 =3D 0, - .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, - .writefn =3D tlbi_aa64_vmalle1_write }, - { .name =3D "TLBI_VAE1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 7, .opc2 =3D 1, - .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, - .writefn =3D tlbi_aa64_vae1_write }, - { .name =3D "TLBI_ASIDE1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 7, .opc2 =3D 2, - .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, - .writefn =3D tlbi_aa64_vmalle1_write }, - { .name =3D "TLBI_VAAE1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 7, .opc2 =3D 3, - .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, - .writefn =3D tlbi_aa64_vae1_write }, - { .name =3D "TLBI_VALE1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 7, .opc2 =3D 5, - .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, - .writefn =3D tlbi_aa64_vae1_write }, - { .name =3D "TLBI_VAALE1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 7, .opc2 =3D 7, - .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, - .writefn =3D tlbi_aa64_vae1_write }, - { .name =3D "TLBI_IPAS2E1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 0, .opc2 =3D 1, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_ipas2e1is_write }, - { .name =3D "TLBI_IPAS2LE1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 0, .opc2 =3D 5, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_ipas2e1is_write }, - { .name =3D "TLBI_ALLE1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 3, .opc2 =3D 4, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_alle1is_write }, - { .name =3D "TLBI_VMALLS12E1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 3, .opc2 =3D 6, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_alle1is_write }, - { .name =3D "TLBI_IPAS2E1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 1, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_ipas2e1_write }, - { .name =3D "TLBI_IPAS2LE1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 5, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_ipas2e1_write }, - { .name =3D "TLBI_ALLE1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 7, .opc2 =3D 4, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_alle1_write }, - { .name =3D "TLBI_VMALLS12E1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 7, .opc2 =3D 6, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_alle1is_write }, -#ifndef CONFIG_USER_ONLY - /* 64 bit address translation operations */ - { .name =3D "AT_S1E1R", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 8, .opc2 =3D 0, - .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, - .writefn =3D ats_write64 }, - { .name =3D "AT_S1E1W", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 8, .opc2 =3D 1, - .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, - .writefn =3D ats_write64 }, - { .name =3D "AT_S1E0R", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 8, .opc2 =3D 2, - .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, - .writefn =3D ats_write64 }, - { .name =3D "AT_S1E0W", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 8, .opc2 =3D 3, - .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, - .writefn =3D ats_write64 }, - { .name =3D "AT_S12E1R", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 7, .crm =3D 8, .opc2 =3D 4, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, - .writefn =3D ats_write64 }, - { .name =3D "AT_S12E1W", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 7, .crm =3D 8, .opc2 =3D 5, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, - .writefn =3D ats_write64 }, - { .name =3D "AT_S12E0R", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 7, .crm =3D 8, .opc2 =3D 6, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, - .writefn =3D ats_write64 }, - { .name =3D "AT_S12E0W", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 7, .crm =3D 8, .opc2 =3D 7, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, - .writefn =3D ats_write64 }, - /* AT S1E2* are elsewhere as they UNDEF from EL3 if EL2 is not present= */ - { .name =3D "AT_S1E3R", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 7, .crm =3D 8, .opc2 =3D 0, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, - .writefn =3D ats_write64 }, - { .name =3D "AT_S1E3W", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 7, .crm =3D 8, .opc2 =3D 1, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, - .writefn =3D ats_write64 }, - { .name =3D "PAR_EL1", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_ALIAS, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 7, .crm =3D 4, .opc2 =3D 0, - .access =3D PL1_RW, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.par_el[1]), - .writefn =3D par_write }, -#endif - /* TLB invalidate last level of translation table walk */ - { .name =3D "TLBIMVALIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm = =3D 3, .opc2 =3D 5, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= bis, - .writefn =3D tlbimva_is_write }, - { .name =3D "TLBIMVAALIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm = =3D 3, .opc2 =3D 7, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= bis, - .writefn =3D tlbimvaa_is_write }, - { .name =3D "TLBIMVAL", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D = 7, .opc2 =3D 5, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, - .writefn =3D tlbimva_write }, - { .name =3D "TLBIMVAAL", .cp =3D 15, .opc1 =3D 0, .crn =3D 8, .crm =3D= 7, .opc2 =3D 7, - .type =3D ARM_CP_NO_RAW, .access =3D PL1_W, .accessfn =3D access_ttl= b, - .writefn =3D tlbimvaa_write }, - { .name =3D "TLBIMVALH", .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D= 7, .opc2 =3D 5, - .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, - .writefn =3D tlbimva_hyp_write }, - { .name =3D "TLBIMVALHIS", - .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D 3, .opc2 =3D 5, - .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, - .writefn =3D tlbimva_hyp_is_write }, - { .name =3D "TLBIIPAS2", - .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 1, - .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, - .writefn =3D tlbiipas2_hyp_write }, - { .name =3D "TLBIIPAS2IS", - .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D 0, .opc2 =3D 1, - .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, - .writefn =3D tlbiipas2is_hyp_write }, - { .name =3D "TLBIIPAS2L", - .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 5, - .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, - .writefn =3D tlbiipas2_hyp_write }, - { .name =3D "TLBIIPAS2LIS", - .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D 0, .opc2 =3D 5, - .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, - .writefn =3D tlbiipas2is_hyp_write }, - /* 32 bit cache operations */ - { .name =3D "ICIALLUIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D= 1, .opc2 =3D 0, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_ticab = }, - { .name =3D "BPIALLUIS", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D= 1, .opc2 =3D 6, - .type =3D ARM_CP_NOP, .access =3D PL1_W }, - { .name =3D "ICIALLU", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 5= , .opc2 =3D 0, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tocu }, - { .name =3D "ICIMVAU", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 5= , .opc2 =3D 1, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tocu }, - { .name =3D "BPIALL", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 5,= .opc2 =3D 6, - .type =3D ARM_CP_NOP, .access =3D PL1_W }, - { .name =3D "BPIMVA", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 5,= .opc2 =3D 7, - .type =3D ARM_CP_NOP, .access =3D PL1_W }, - { .name =3D "DCIMVAC", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 6= , .opc2 =3D 1, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D aa64_cacheop_= poc_access }, - { .name =3D "DCISW", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 6, = .opc2 =3D 2, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, - { .name =3D "DCCMVAC", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 1= 0, .opc2 =3D 1, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D aa64_cacheop_= poc_access }, - { .name =3D "DCCSW", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 10,= .opc2 =3D 2, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, - { .name =3D "DCCMVAU", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 1= 1, .opc2 =3D 1, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tocu }, - { .name =3D "DCCIMVAC", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D = 14, .opc2 =3D 1, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D aa64_cacheop_= poc_access }, - { .name =3D "DCCISW", .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 14= , .opc2 =3D 2, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, - /* MMU Domain access control / MPU write buffer control */ - { .name =3D "DACR", .cp =3D 15, .opc1 =3D 0, .crn =3D 3, .crm =3D 0, .= opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, .resetvalue =3D 0, - .writefn =3D dacr_write, .raw_writefn =3D raw_write, - .bank_fieldoffsets =3D { offsetoflow32(CPUARMState, cp15.dacr_s), - offsetoflow32(CPUARMState, cp15.dacr_ns) } }, - { .name =3D "ELR_EL1", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_ALIAS, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 4, .crm =3D 0, .opc2 =3D 1, - .access =3D PL1_RW, - .fieldoffset =3D offsetof(CPUARMState, elr_el[1]) }, - { .name =3D "SPSR_EL1", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_ALIAS, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 4, .crm =3D 0, .opc2 =3D 0, - .access =3D PL1_RW, - .fieldoffset =3D offsetof(CPUARMState, banked_spsr[BANK_SVC]) }, - /* - * We rely on the access checks not allowing the guest to write to the - * state field when SPSel indicates that it's being used as the stack - * pointer. - */ - { .name =3D "SP_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 4, .crm =3D 1, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D sp_el0_access, - .type =3D ARM_CP_ALIAS, - .fieldoffset =3D offsetof(CPUARMState, sp_el[0]) }, - { .name =3D "SP_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 4, .crm =3D 1, .opc2 =3D 0, - .access =3D PL2_RW, .type =3D ARM_CP_ALIAS | ARM_CP_EL3_NO_EL2_KEEP, - .fieldoffset =3D offsetof(CPUARMState, sp_el[1]) }, - { .name =3D "SPSel", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 4, .crm =3D 2, .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW, - .access =3D PL1_RW, .readfn =3D spsel_read, .writefn =3D spsel_write= }, - { .name =3D "FPEXC32_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 5, .crm =3D 3, .opc2 =3D 0, - .access =3D PL2_RW, - .type =3D ARM_CP_ALIAS | ARM_CP_FPU | ARM_CP_EL3_NO_EL2_KEEP, - .fieldoffset =3D offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPEXC]) }, - { .name =3D "DACR32_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 3, .crm =3D 0, .opc2 =3D 0, - .access =3D PL2_RW, .resetvalue =3D 0, .type =3D ARM_CP_EL3_NO_EL2_K= EEP, - .writefn =3D dacr_write, .raw_writefn =3D raw_write, - .fieldoffset =3D offsetof(CPUARMState, cp15.dacr32_el2) }, - { .name =3D "IFSR32_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 5, .crm =3D 0, .opc2 =3D 1, - .access =3D PL2_RW, .resetvalue =3D 0, .type =3D ARM_CP_EL3_NO_EL2_K= EEP, - .fieldoffset =3D offsetof(CPUARMState, cp15.ifsr32_el2) }, - { .name =3D "SPSR_IRQ", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_ALIAS, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 4, .crm =3D 3, .opc2 =3D 0, - .access =3D PL2_RW, - .fieldoffset =3D offsetof(CPUARMState, banked_spsr[BANK_IRQ]) }, - { .name =3D "SPSR_ABT", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_ALIAS, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 4, .crm =3D 3, .opc2 =3D 1, - .access =3D PL2_RW, - .fieldoffset =3D offsetof(CPUARMState, banked_spsr[BANK_ABT]) }, - { .name =3D "SPSR_UND", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_ALIAS, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 4, .crm =3D 3, .opc2 =3D 2, - .access =3D PL2_RW, - .fieldoffset =3D offsetof(CPUARMState, banked_spsr[BANK_UND]) }, - { .name =3D "SPSR_FIQ", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_ALIAS, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 4, .crm =3D 3, .opc2 =3D 3, - .access =3D PL2_RW, - .fieldoffset =3D offsetof(CPUARMState, banked_spsr[BANK_FIQ]) }, - { .name =3D "MDCR_EL3", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_IO, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 3, .opc2 =3D 1, - .resetvalue =3D 0, - .access =3D PL3_RW, - .writefn =3D mdcr_el3_write, - .fieldoffset =3D offsetof(CPUARMState, cp15.mdcr_el3) }, - { .name =3D "SDCR", .type =3D ARM_CP_ALIAS | ARM_CP_IO, - .cp =3D 15, .opc1 =3D 0, .crn =3D 1, .crm =3D 3, .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_trap_aa32s_el1, - .writefn =3D sdcr_write, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.mdcr_el3) }, -}; - -static void do_hcr_write(CPUARMState *env, uint64_t value, uint64_t valid_= mask) -{ - ARMCPU *cpu =3D env_archcpu(env); - - if (arm_feature(env, ARM_FEATURE_V8)) { - valid_mask |=3D MAKE_64BIT_MASK(0, 34); /* ARMv8.0 */ - } else { - valid_mask |=3D MAKE_64BIT_MASK(0, 28); /* ARMv7VE */ - } - - if (arm_feature(env, ARM_FEATURE_EL3)) { - valid_mask &=3D ~HCR_HCD; - } else if (cpu->psci_conduit !=3D QEMU_PSCI_CONDUIT_SMC) { - /* - * Architecturally HCR.TSC is RES0 if EL3 is not implemented. - * However, if we're using the SMC PSCI conduit then QEMU is - * effectively acting like EL3 firmware and so the guest at - * EL2 should retain the ability to prevent EL1 from being - * able to make SMC calls into the ersatz firmware, so in - * that case HCR.TSC should be read/write. - */ - valid_mask &=3D ~HCR_TSC; - } - - if (arm_feature(env, ARM_FEATURE_AARCH64)) { - if (cpu_isar_feature(aa64_vh, cpu)) { - valid_mask |=3D HCR_E2H; - } - if (cpu_isar_feature(aa64_ras, cpu)) { - valid_mask |=3D HCR_TERR | HCR_TEA; - } - if (cpu_isar_feature(aa64_lor, cpu)) { - valid_mask |=3D HCR_TLOR; - } - if (cpu_isar_feature(aa64_pauth, cpu)) { - valid_mask |=3D HCR_API | HCR_APK; - } - if (cpu_isar_feature(aa64_mte, cpu)) { - valid_mask |=3D HCR_ATA | HCR_DCT | HCR_TID5; - } - if (cpu_isar_feature(aa64_scxtnum, cpu)) { - valid_mask |=3D HCR_ENSCXT; - } - if (cpu_isar_feature(aa64_fwb, cpu)) { - valid_mask |=3D HCR_FWB; - } - } - - if (cpu_isar_feature(any_evt, cpu)) { - valid_mask |=3D HCR_TTLBIS | HCR_TTLBOS | HCR_TICAB | HCR_TOCU | H= CR_TID4; - } else if (cpu_isar_feature(any_half_evt, cpu)) { - valid_mask |=3D HCR_TICAB | HCR_TOCU | HCR_TID4; - } - - /* Clear RES0 bits. */ - value &=3D valid_mask; - - /* - * These bits change the MMU setup: - * HCR_VM enables stage 2 translation - * HCR_PTW forbids certain page-table setups - * HCR_DC disables stage1 and enables stage2 translation - * HCR_DCT enables tagging on (disabled) stage1 translation - * HCR_FWB changes the interpretation of stage2 descriptor bits - */ - if ((env->cp15.hcr_el2 ^ value) & - (HCR_VM | HCR_PTW | HCR_DC | HCR_DCT | HCR_FWB)) { - tlb_flush(CPU(cpu)); - } - env->cp15.hcr_el2 =3D value; - - /* - * Updates to VI and VF require us to update the status of - * virtual interrupts, which are the logical OR of these bits - * and the state of the input lines from the GIC. (This requires - * that we have the iothread lock, which is done by marking the - * reginfo structs as ARM_CP_IO.) - * Note that if a write to HCR pends a VIRQ or VFIQ it is never - * possible for it to be taken immediately, because VIRQ and - * VFIQ are masked unless running at EL0 or EL1, and HCR - * can only be written at EL2. - */ - g_assert(qemu_mutex_iothread_locked()); - arm_cpu_update_virq(cpu); - arm_cpu_update_vfiq(cpu); - arm_cpu_update_vserr(cpu); -} - -static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t v= alue) -{ - do_hcr_write(env, value, 0); -} - -static void hcr_writehigh(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* Handle HCR2 write, i.e. write to high half of HCR_EL2 */ - value =3D deposit64(env->cp15.hcr_el2, 32, 32, value); - do_hcr_write(env, value, MAKE_64BIT_MASK(0, 32)); -} - -static void hcr_writelow(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* Handle HCR write, i.e. write to low half of HCR_EL2 */ - value =3D deposit64(env->cp15.hcr_el2, 0, 32, value); - do_hcr_write(env, value, MAKE_64BIT_MASK(32, 32)); -} - /* * Return the effective value of HCR_EL2, at the given security state. * Bits that are not included here: @@ -5740,747 +135,6 @@ bool el_is_in_host(CPUARMState *env, int el) return arm_is_el2_enabled(env) && arm_el_is_aa64(env, 2); } =20 -static void hcrx_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - uint64_t valid_mask =3D 0; - - /* No features adding bits to HCRX are implemented. */ - - /* Clear RES0 bits. */ - env->cp15.hcrx_el2 =3D value & valid_mask; -} - -static CPAccessResult access_hxen(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - if (arm_current_el(env) < 3 - && arm_feature(env, ARM_FEATURE_EL3) - && !(env->cp15.scr_el3 & SCR_HXEN)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -static const ARMCPRegInfo hcrx_el2_reginfo =3D { - .name =3D "HCRX_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 2, .opc2 =3D 2, - .access =3D PL2_RW, .writefn =3D hcrx_write, .accessfn =3D access_hxen, - .fieldoffset =3D offsetof(CPUARMState, cp15.hcrx_el2), -}; - -/* Return the effective value of HCRX_EL2. */ -uint64_t arm_hcrx_el2_eff(CPUARMState *env) -{ - /* - * The bits in this register behave as 0 for all purposes other than - * direct reads of the register if: - * - EL2 is not enabled in the current security state, - * - SCR_EL3.HXEn is 0. - */ - if (!arm_is_el2_enabled(env) - || (arm_feature(env, ARM_FEATURE_EL3) - && !(env->cp15.scr_el3 & SCR_HXEN))) { - return 0; - } - return env->cp15.hcrx_el2; -} - -static void cptr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * For A-profile AArch32 EL3, if NSACR.CP10 - * is 0 then HCPTR.{TCP11,TCP10} ignore writes and read as 1. - */ - if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) && - !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) { - uint64_t mask =3D R_HCPTR_TCP11_MASK | R_HCPTR_TCP10_MASK; - value =3D (value & ~mask) | (env->cp15.cptr_el[2] & mask); - } - env->cp15.cptr_el[2] =3D value; -} - -static uint64_t cptr_el2_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - /* - * For A-profile AArch32 EL3, if NSACR.CP10 - * is 0 then HCPTR.{TCP11,TCP10} ignore writes and read as 1. - */ - uint64_t value =3D env->cp15.cptr_el[2]; - - if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) && - !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) { - value |=3D R_HCPTR_TCP11_MASK | R_HCPTR_TCP10_MASK; - } - return value; -} - -static const ARMCPRegInfo el2_cp_reginfo[] =3D { - { .name =3D "HCR_EL2", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_IO, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 1, .opc2 =3D 0, - .access =3D PL2_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.hcr_= el2), - .writefn =3D hcr_write }, - { .name =3D "HCR", .state =3D ARM_CP_STATE_AA32, - .type =3D ARM_CP_ALIAS | ARM_CP_IO, - .cp =3D 15, .opc1 =3D 4, .crn =3D 1, .crm =3D 1, .opc2 =3D 0, - .access =3D PL2_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.hcr_= el2), - .writefn =3D hcr_writelow }, - { .name =3D "HACR_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 1, .opc2 =3D 7, - .access =3D PL2_RW, .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - { .name =3D "ELR_EL2", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_ALIAS, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 4, .crm =3D 0, .opc2 =3D 1, - .access =3D PL2_RW, - .fieldoffset =3D offsetof(CPUARMState, elr_el[2]) }, - { .name =3D "ESR_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 5, .crm =3D 2, .opc2 =3D 0, - .access =3D PL2_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.esr_= el[2]) }, - { .name =3D "FAR_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 6, .crm =3D 0, .opc2 =3D 0, - .access =3D PL2_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.far_= el[2]) }, - { .name =3D "HIFAR", .state =3D ARM_CP_STATE_AA32, - .type =3D ARM_CP_ALIAS, - .cp =3D 15, .opc1 =3D 4, .crn =3D 6, .crm =3D 0, .opc2 =3D 2, - .access =3D PL2_RW, - .fieldoffset =3D offsetofhigh32(CPUARMState, cp15.far_el[2]) }, - { .name =3D "SPSR_EL2", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_ALIAS, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 4, .crm =3D 0, .opc2 =3D 0, - .access =3D PL2_RW, - .fieldoffset =3D offsetof(CPUARMState, banked_spsr[BANK_HYP]) }, - { .name =3D "VBAR_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 12, .crm =3D 0, .opc2 =3D 0, - .access =3D PL2_RW, .writefn =3D vbar_write, - .fieldoffset =3D offsetof(CPUARMState, cp15.vbar_el[2]), - .resetvalue =3D 0 }, - { .name =3D "SP_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 4, .crm =3D 1, .opc2 =3D 0, - .access =3D PL3_RW, .type =3D ARM_CP_ALIAS, - .fieldoffset =3D offsetof(CPUARMState, sp_el[2]) }, - { .name =3D "CPTR_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 1, .opc2 =3D 2, - .access =3D PL2_RW, .accessfn =3D cptr_access, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.cptr_el[2]), - .readfn =3D cptr_el2_read, .writefn =3D cptr_el2_write }, - { .name =3D "MAIR_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 10, .crm =3D 2, .opc2 =3D 0, - .access =3D PL2_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.mair= _el[2]), - .resetvalue =3D 0 }, - { .name =3D "HMAIR1", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 4, .crn =3D 10, .crm =3D 2, .opc2 =3D 1, - .access =3D PL2_RW, .type =3D ARM_CP_ALIAS, - .fieldoffset =3D offsetofhigh32(CPUARMState, cp15.mair_el[2]) }, - { .name =3D "AMAIR_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 10, .crm =3D 3, .opc2 =3D 0, - .access =3D PL2_RW, .type =3D ARM_CP_CONST, - .resetvalue =3D 0 }, - /* HAMAIR1 is mapped to AMAIR_EL2[63:32] */ - { .name =3D "HAMAIR1", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 4, .crn =3D 10, .crm =3D 3, .opc2 =3D 1, - .access =3D PL2_RW, .type =3D ARM_CP_CONST, - .resetvalue =3D 0 }, - { .name =3D "AFSR0_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 5, .crm =3D 1, .opc2 =3D 0, - .access =3D PL2_RW, .type =3D ARM_CP_CONST, - .resetvalue =3D 0 }, - { .name =3D "AFSR1_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 5, .crm =3D 1, .opc2 =3D 1, - .access =3D PL2_RW, .type =3D ARM_CP_CONST, - .resetvalue =3D 0 }, - { .name =3D "TCR_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 2, .crm =3D 0, .opc2 =3D 2, - .access =3D PL2_RW, .writefn =3D vmsa_tcr_el12_write, - .fieldoffset =3D offsetof(CPUARMState, cp15.tcr_el[2]) }, - { .name =3D "VTCR", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 4, .crn =3D 2, .crm =3D 1, .opc2 =3D 2, - .type =3D ARM_CP_ALIAS, - .access =3D PL2_RW, .accessfn =3D access_el3_aa32ns, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.vtcr_el2) }, - { .name =3D "VTCR_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 2, .crm =3D 1, .opc2 =3D 2, - .access =3D PL2_RW, - /* no .writefn needed as this can't cause an ASID change */ - .fieldoffset =3D offsetof(CPUARMState, cp15.vtcr_el2) }, - { .name =3D "VTTBR", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 6, .crm =3D 2, - .type =3D ARM_CP_64BIT | ARM_CP_ALIAS, - .access =3D PL2_RW, .accessfn =3D access_el3_aa32ns, - .fieldoffset =3D offsetof(CPUARMState, cp15.vttbr_el2), - .writefn =3D vttbr_write }, - { .name =3D "VTTBR_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 2, .crm =3D 1, .opc2 =3D 0, - .access =3D PL2_RW, .writefn =3D vttbr_write, - .fieldoffset =3D offsetof(CPUARMState, cp15.vttbr_el2) }, - { .name =3D "SCTLR_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 0, .opc2 =3D 0, - .access =3D PL2_RW, .raw_writefn =3D raw_write, .writefn =3D sctlr_w= rite, - .fieldoffset =3D offsetof(CPUARMState, cp15.sctlr_el[2]) }, - { .name =3D "TPIDR_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 13, .crm =3D 0, .opc2 =3D 2, - .access =3D PL2_RW, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.tpidr_el[2]) }, - { .name =3D "TTBR0_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 2, .crm =3D 0, .opc2 =3D 0, - .access =3D PL2_RW, .resetvalue =3D 0, .writefn =3D vmsa_tcr_ttbr_el= 2_write, - .fieldoffset =3D offsetof(CPUARMState, cp15.ttbr0_el[2]) }, - { .name =3D "HTTBR", .cp =3D 15, .opc1 =3D 4, .crm =3D 2, - .access =3D PL2_RW, .type =3D ARM_CP_64BIT | ARM_CP_ALIAS, - .fieldoffset =3D offsetof(CPUARMState, cp15.ttbr0_el[2]) }, - { .name =3D "TLBIALLNSNH", - .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D 7, .opc2 =3D 4, - .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, - .writefn =3D tlbiall_nsnh_write }, - { .name =3D "TLBIALLNSNHIS", - .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D 3, .opc2 =3D 4, - .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, - .writefn =3D tlbiall_nsnh_is_write }, - { .name =3D "TLBIALLH", .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D = 7, .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, - .writefn =3D tlbiall_hyp_write }, - { .name =3D "TLBIALLHIS", .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm = =3D 3, .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, - .writefn =3D tlbiall_hyp_is_write }, - { .name =3D "TLBIMVAH", .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm =3D = 7, .opc2 =3D 1, - .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, - .writefn =3D tlbimva_hyp_write }, - { .name =3D "TLBIMVAHIS", .cp =3D 15, .opc1 =3D 4, .crn =3D 8, .crm = =3D 3, .opc2 =3D 1, - .type =3D ARM_CP_NO_RAW, .access =3D PL2_W, - .writefn =3D tlbimva_hyp_is_write }, - { .name =3D "TLBI_ALLE2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 7, .opc2 =3D 0, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, - .writefn =3D tlbi_aa64_alle2_write }, - { .name =3D "TLBI_VAE2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 7, .opc2 =3D 1, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, - .writefn =3D tlbi_aa64_vae2_write }, - { .name =3D "TLBI_VALE2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 7, .opc2 =3D 5, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, - .writefn =3D tlbi_aa64_vae2_write }, - { .name =3D "TLBI_ALLE2IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 3, .opc2 =3D 0, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, - .writefn =3D tlbi_aa64_alle2is_write }, - { .name =3D "TLBI_VAE2IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 3, .opc2 =3D 1, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, - .writefn =3D tlbi_aa64_vae2is_write }, - { .name =3D "TLBI_VALE2IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 3, .opc2 =3D 5, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, - .writefn =3D tlbi_aa64_vae2is_write }, -#ifndef CONFIG_USER_ONLY - /* - * Unlike the other EL2-related AT operations, these must - * UNDEF from EL3 if EL2 is not implemented, which is why we - * define them here rather than with the rest of the AT ops. - */ - { .name =3D "AT_S1E2R", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 7, .crm =3D 8, .opc2 =3D 0, - .access =3D PL2_W, .accessfn =3D at_s1e2_access, - .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC | ARM_CP_EL3_NO_EL2_UNDE= F, - .writefn =3D ats_write64 }, - { .name =3D "AT_S1E2W", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 7, .crm =3D 8, .opc2 =3D 1, - .access =3D PL2_W, .accessfn =3D at_s1e2_access, - .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC | ARM_CP_EL3_NO_EL2_UNDE= F, - .writefn =3D ats_write64 }, - /* - * The AArch32 ATS1H* operations are CONSTRAINED UNPREDICTABLE - * if EL2 is not implemented; we choose to UNDEF. Behaviour at EL3 - * with SCR.NS =3D=3D 0 outside Monitor mode is UNPREDICTABLE; we choo= se - * to behave as if SCR.NS was 1. - */ - { .name =3D "ATS1HR", .cp =3D 15, .opc1 =3D 4, .crn =3D 7, .crm =3D 8,= .opc2 =3D 0, - .access =3D PL2_W, - .writefn =3D ats1h_write, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EX= C }, - { .name =3D "ATS1HW", .cp =3D 15, .opc1 =3D 4, .crn =3D 7, .crm =3D 8,= .opc2 =3D 1, - .access =3D PL2_W, - .writefn =3D ats1h_write, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EX= C }, - { .name =3D "CNTHCTL_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 1, .opc2 =3D 0, - /* - * ARMv7 requires bit 0 and 1 to reset to 1. ARMv8 defines the - * reset values as IMPDEF. We choose to reset to 3 to comply with - * both ARMv7 and ARMv8. - */ - .access =3D PL2_RW, .resetvalue =3D 3, - .fieldoffset =3D offsetof(CPUARMState, cp15.cnthctl_el2) }, - { .name =3D "CNTVOFF_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 0, .opc2 =3D 3, - .access =3D PL2_RW, .type =3D ARM_CP_IO, .resetvalue =3D 0, - .writefn =3D gt_cntvoff_write, - .fieldoffset =3D offsetof(CPUARMState, cp15.cntvoff_el2) }, - { .name =3D "CNTVOFF", .cp =3D 15, .opc1 =3D 4, .crm =3D 14, - .access =3D PL2_RW, .type =3D ARM_CP_64BIT | ARM_CP_ALIAS | ARM_CP_I= O, - .writefn =3D gt_cntvoff_write, - .fieldoffset =3D offsetof(CPUARMState, cp15.cntvoff_el2) }, - { .name =3D "CNTHP_CVAL_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 2, .opc2 =3D 2, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYP].cv= al), - .type =3D ARM_CP_IO, .access =3D PL2_RW, - .writefn =3D gt_hyp_cval_write, .raw_writefn =3D raw_write }, - { .name =3D "CNTHP_CVAL", .cp =3D 15, .opc1 =3D 6, .crm =3D 14, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYP].cv= al), - .access =3D PL2_RW, .type =3D ARM_CP_64BIT | ARM_CP_IO, - .writefn =3D gt_hyp_cval_write, .raw_writefn =3D raw_write }, - { .name =3D "CNTHP_TVAL_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 2, .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL2_RW, - .resetfn =3D gt_hyp_timer_reset, - .readfn =3D gt_hyp_tval_read, .writefn =3D gt_hyp_tval_write }, - { .name =3D "CNTHP_CTL_EL2", .state =3D ARM_CP_STATE_BOTH, - .type =3D ARM_CP_IO, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 2, .opc2 =3D 1, - .access =3D PL2_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYP].ct= l), - .resetvalue =3D 0, - .writefn =3D gt_hyp_ctl_write, .raw_writefn =3D raw_write }, -#endif - { .name =3D "HPFAR", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 4, .crn =3D 6, .crm =3D 0, .opc2 =3D 4, - .access =3D PL2_RW, .accessfn =3D access_el3_aa32ns, - .fieldoffset =3D offsetof(CPUARMState, cp15.hpfar_el2) }, - { .name =3D "HPFAR_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 6, .crm =3D 0, .opc2 =3D 4, - .access =3D PL2_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.hpfar_el2) }, - { .name =3D "HSTR_EL2", .state =3D ARM_CP_STATE_BOTH, - .cp =3D 15, .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 1, .opc2 = =3D 3, - .access =3D PL2_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.hstr_el2) }, -}; - -static const ARMCPRegInfo el2_v8_cp_reginfo[] =3D { - { .name =3D "HCR2", .state =3D ARM_CP_STATE_AA32, - .type =3D ARM_CP_ALIAS | ARM_CP_IO, - .cp =3D 15, .opc1 =3D 4, .crn =3D 1, .crm =3D 1, .opc2 =3D 4, - .access =3D PL2_RW, - .fieldoffset =3D offsetofhigh32(CPUARMState, cp15.hcr_el2), - .writefn =3D hcr_writehigh }, -}; - -static CPAccessResult sel2_access(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - if (arm_current_el(env) =3D=3D 3 || arm_is_secure_below_el3(env)) { - return CP_ACCESS_OK; - } - return CP_ACCESS_TRAP_UNCATEGORIZED; -} - -static const ARMCPRegInfo el2_sec_cp_reginfo[] =3D { - { .name =3D "VSTTBR_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 2, .crm =3D 6, .opc2 =3D 0, - .access =3D PL2_RW, .accessfn =3D sel2_access, - .fieldoffset =3D offsetof(CPUARMState, cp15.vsttbr_el2) }, - { .name =3D "VSTCR_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 2, .crm =3D 6, .opc2 =3D 2, - .access =3D PL2_RW, .accessfn =3D sel2_access, - .fieldoffset =3D offsetof(CPUARMState, cp15.vstcr_el2) }, -}; - -static CPAccessResult nsacr_access(CPUARMState *env, const ARMCPRegInfo *r= i, - bool isread) -{ - /* - * The NSACR is RW at EL3, and RO for NS EL1 and NS EL2. - * At Secure EL1 it traps to EL3 or EL2. - */ - if (arm_current_el(env) =3D=3D 3) { - return CP_ACCESS_OK; - } - if (arm_is_secure_below_el3(env)) { - if (env->cp15.scr_el3 & SCR_EEL2) { - return CP_ACCESS_TRAP_EL2; - } - return CP_ACCESS_TRAP_EL3; - } - /* Accesses from EL1 NS and EL2 NS are UNDEF for write but allow reads= . */ - if (isread) { - return CP_ACCESS_OK; - } - return CP_ACCESS_TRAP_UNCATEGORIZED; -} - -static const ARMCPRegInfo el3_cp_reginfo[] =3D { - { .name =3D "SCR_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 1, .opc2 =3D 0, - .access =3D PL3_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.scr_= el3), - .resetfn =3D scr_reset, .writefn =3D scr_write }, - { .name =3D "SCR", .type =3D ARM_CP_ALIAS | ARM_CP_NEWEL, - .cp =3D 15, .opc1 =3D 0, .crn =3D 1, .crm =3D 1, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_trap_aa32s_el1, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.scr_el3), - .writefn =3D scr_write }, - { .name =3D "SDER32_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 1, .opc2 =3D 1, - .access =3D PL3_RW, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.sder) }, - { .name =3D "SDER", - .cp =3D 15, .opc1 =3D 0, .crn =3D 1, .crm =3D 1, .opc2 =3D 1, - .access =3D PL3_RW, .resetvalue =3D 0, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.sder) }, - { .name =3D "MVBAR", .cp =3D 15, .opc1 =3D 0, .crn =3D 12, .crm =3D 0,= .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_trap_aa32s_el1, - .writefn =3D vbar_write, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.mvbar) }, - { .name =3D "TTBR0_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 2, .crm =3D 0, .opc2 =3D 0, - .access =3D PL3_RW, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.ttbr0_el[3]) }, - { .name =3D "TCR_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 2, .crm =3D 0, .opc2 =3D 2, - .access =3D PL3_RW, - /* no .writefn needed as this can't cause an ASID change */ - .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.tcr_el[3]) }, - { .name =3D "ELR_EL3", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_ALIAS, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 4, .crm =3D 0, .opc2 =3D 1, - .access =3D PL3_RW, - .fieldoffset =3D offsetof(CPUARMState, elr_el[3]) }, - { .name =3D "ESR_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 5, .crm =3D 2, .opc2 =3D 0, - .access =3D PL3_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.esr_= el[3]) }, - { .name =3D "FAR_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 6, .crm =3D 0, .opc2 =3D 0, - .access =3D PL3_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.far_= el[3]) }, - { .name =3D "SPSR_EL3", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_ALIAS, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 4, .crm =3D 0, .opc2 =3D 0, - .access =3D PL3_RW, - .fieldoffset =3D offsetof(CPUARMState, banked_spsr[BANK_MON]) }, - { .name =3D "VBAR_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 12, .crm =3D 0, .opc2 =3D 0, - .access =3D PL3_RW, .writefn =3D vbar_write, - .fieldoffset =3D offsetof(CPUARMState, cp15.vbar_el[3]), - .resetvalue =3D 0 }, - { .name =3D "CPTR_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 1, .opc2 =3D 2, - .access =3D PL3_RW, .accessfn =3D cptr_access, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.cptr_el[3]) }, - { .name =3D "TPIDR_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 13, .crm =3D 0, .opc2 =3D 2, - .access =3D PL3_RW, .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.tpidr_el[3]) }, - { .name =3D "AMAIR_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 10, .crm =3D 3, .opc2 =3D 0, - .access =3D PL3_RW, .type =3D ARM_CP_CONST, - .resetvalue =3D 0 }, - { .name =3D "AFSR0_EL3", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 5, .crm =3D 1, .opc2 =3D 0, - .access =3D PL3_RW, .type =3D ARM_CP_CONST, - .resetvalue =3D 0 }, - { .name =3D "AFSR1_EL3", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 5, .crm =3D 1, .opc2 =3D 1, - .access =3D PL3_RW, .type =3D ARM_CP_CONST, - .resetvalue =3D 0 }, - { .name =3D "TLBI_ALLE3IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 3, .opc2 =3D 0, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_alle3is_write }, - { .name =3D "TLBI_VAE3IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 3, .opc2 =3D 1, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_vae3is_write }, - { .name =3D "TLBI_VALE3IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 3, .opc2 =3D 5, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_vae3is_write }, - { .name =3D "TLBI_ALLE3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 7, .opc2 =3D 0, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_alle3_write }, - { .name =3D "TLBI_VAE3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 7, .opc2 =3D 1, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_vae3_write }, - { .name =3D "TLBI_VALE3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 7, .opc2 =3D 5, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_vae3_write }, -}; - -#ifndef CONFIG_USER_ONLY -/* Test if system register redirection is to occur in the current state. = */ -static bool redirect_for_e2h(CPUARMState *env) -{ - return arm_current_el(env) =3D=3D 2 && (arm_hcr_el2_eff(env) & HCR_E2H= ); -} - -static uint64_t el2_e2h_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - CPReadFn *readfn; - - if (redirect_for_e2h(env)) { - /* Switch to the saved EL2 version of the register. */ - ri =3D ri->opaque; - readfn =3D ri->readfn; - } else { - readfn =3D ri->orig_readfn; - } - if (readfn =3D=3D NULL) { - readfn =3D raw_read; - } - return readfn(env, ri); -} - -static void el2_e2h_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - CPWriteFn *writefn; - - if (redirect_for_e2h(env)) { - /* Switch to the saved EL2 version of the register. */ - ri =3D ri->opaque; - writefn =3D ri->writefn; - } else { - writefn =3D ri->orig_writefn; - } - if (writefn =3D=3D NULL) { - writefn =3D raw_write; - } - writefn(env, ri, value); -} - -static void define_arm_vh_e2h_redirects_aliases(ARMCPU *cpu) -{ - struct E2HAlias { - uint32_t src_key, dst_key, new_key; - const char *src_name, *dst_name, *new_name; - bool (*feature)(const ARMISARegisters *id); - }; - -#define K(op0, op1, crn, crm, op2) \ - ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP, crn, crm, op0, op1, op2) - - static const struct E2HAlias aliases[] =3D { - { K(3, 0, 1, 0, 0), K(3, 4, 1, 0, 0), K(3, 5, 1, 0, 0), - "SCTLR", "SCTLR_EL2", "SCTLR_EL12" }, - { K(3, 0, 1, 0, 2), K(3, 4, 1, 1, 2), K(3, 5, 1, 0, 2), - "CPACR", "CPTR_EL2", "CPACR_EL12" }, - { K(3, 0, 2, 0, 0), K(3, 4, 2, 0, 0), K(3, 5, 2, 0, 0), - "TTBR0_EL1", "TTBR0_EL2", "TTBR0_EL12" }, - { K(3, 0, 2, 0, 1), K(3, 4, 2, 0, 1), K(3, 5, 2, 0, 1), - "TTBR1_EL1", "TTBR1_EL2", "TTBR1_EL12" }, - { K(3, 0, 2, 0, 2), K(3, 4, 2, 0, 2), K(3, 5, 2, 0, 2), - "TCR_EL1", "TCR_EL2", "TCR_EL12" }, - { K(3, 0, 4, 0, 0), K(3, 4, 4, 0, 0), K(3, 5, 4, 0, 0), - "SPSR_EL1", "SPSR_EL2", "SPSR_EL12" }, - { K(3, 0, 4, 0, 1), K(3, 4, 4, 0, 1), K(3, 5, 4, 0, 1), - "ELR_EL1", "ELR_EL2", "ELR_EL12" }, - { K(3, 0, 5, 1, 0), K(3, 4, 5, 1, 0), K(3, 5, 5, 1, 0), - "AFSR0_EL1", "AFSR0_EL2", "AFSR0_EL12" }, - { K(3, 0, 5, 1, 1), K(3, 4, 5, 1, 1), K(3, 5, 5, 1, 1), - "AFSR1_EL1", "AFSR1_EL2", "AFSR1_EL12" }, - { K(3, 0, 5, 2, 0), K(3, 4, 5, 2, 0), K(3, 5, 5, 2, 0), - "ESR_EL1", "ESR_EL2", "ESR_EL12" }, - { K(3, 0, 6, 0, 0), K(3, 4, 6, 0, 0), K(3, 5, 6, 0, 0), - "FAR_EL1", "FAR_EL2", "FAR_EL12" }, - { K(3, 0, 10, 2, 0), K(3, 4, 10, 2, 0), K(3, 5, 10, 2, 0), - "MAIR_EL1", "MAIR_EL2", "MAIR_EL12" }, - { K(3, 0, 10, 3, 0), K(3, 4, 10, 3, 0), K(3, 5, 10, 3, 0), - "AMAIR0", "AMAIR_EL2", "AMAIR_EL12" }, - { K(3, 0, 12, 0, 0), K(3, 4, 12, 0, 0), K(3, 5, 12, 0, 0), - "VBAR", "VBAR_EL2", "VBAR_EL12" }, - { K(3, 0, 13, 0, 1), K(3, 4, 13, 0, 1), K(3, 5, 13, 0, 1), - "CONTEXTIDR_EL1", "CONTEXTIDR_EL2", "CONTEXTIDR_EL12" }, - { K(3, 0, 14, 1, 0), K(3, 4, 14, 1, 0), K(3, 5, 14, 1, 0), - "CNTKCTL", "CNTHCTL_EL2", "CNTKCTL_EL12" }, - - /* - * Note that redirection of ZCR is mentioned in the description - * of ZCR_EL2, and aliasing in the description of ZCR_EL1, but - * not in the summary table. - */ - { K(3, 0, 1, 2, 0), K(3, 4, 1, 2, 0), K(3, 5, 1, 2, 0), - "ZCR_EL1", "ZCR_EL2", "ZCR_EL12", isar_feature_aa64_sve }, - { K(3, 0, 1, 2, 6), K(3, 4, 1, 2, 6), K(3, 5, 1, 2, 6), - "SMCR_EL1", "SMCR_EL2", "SMCR_EL12", isar_feature_aa64_sme }, - - { K(3, 0, 5, 6, 0), K(3, 4, 5, 6, 0), K(3, 5, 5, 6, 0), - "TFSR_EL1", "TFSR_EL2", "TFSR_EL12", isar_feature_aa64_mte }, - - { K(3, 0, 13, 0, 7), K(3, 4, 13, 0, 7), K(3, 5, 13, 0, 7), - "SCXTNUM_EL1", "SCXTNUM_EL2", "SCXTNUM_EL12", - isar_feature_aa64_scxtnum }, - - /* TODO: ARMv8.2-SPE -- PMSCR_EL2 */ - /* TODO: ARMv8.4-Trace -- TRFCR_EL2 */ - }; -#undef K - - size_t i; - - for (i =3D 0; i < ARRAY_SIZE(aliases); i++) { - const struct E2HAlias *a =3D &aliases[i]; - ARMCPRegInfo *src_reg, *dst_reg, *new_reg; - bool ok; - - if (a->feature && !a->feature(&cpu->isar)) { - continue; - } - - src_reg =3D g_hash_table_lookup(cpu->cp_regs, - (gpointer)(uintptr_t)a->src_key); - dst_reg =3D g_hash_table_lookup(cpu->cp_regs, - (gpointer)(uintptr_t)a->dst_key); - g_assert(src_reg !=3D NULL); - g_assert(dst_reg !=3D NULL); - - /* Cross-compare names to detect typos in the keys. */ - g_assert(strcmp(src_reg->name, a->src_name) =3D=3D 0); - g_assert(strcmp(dst_reg->name, a->dst_name) =3D=3D 0); - - /* None of the core system registers use opaque; we will. */ - g_assert(src_reg->opaque =3D=3D NULL); - - /* Create alias before redirection so we dup the right data. */ - new_reg =3D g_memdup(src_reg, sizeof(ARMCPRegInfo)); - - new_reg->name =3D a->new_name; - new_reg->type |=3D ARM_CP_ALIAS; - /* Remove PL1/PL0 access, leaving PL2/PL3 R/W in place. */ - new_reg->access &=3D PL2_RW | PL3_RW; - - ok =3D g_hash_table_insert(cpu->cp_regs, - (gpointer)(uintptr_t)a->new_key, new_reg); - g_assert(ok); - - src_reg->opaque =3D dst_reg; - src_reg->orig_readfn =3D src_reg->readfn ?: raw_read; - src_reg->orig_writefn =3D src_reg->writefn ?: raw_write; - if (!src_reg->raw_readfn) { - src_reg->raw_readfn =3D raw_read; - } - if (!src_reg->raw_writefn) { - src_reg->raw_writefn =3D raw_write; - } - src_reg->readfn =3D el2_e2h_read; - src_reg->writefn =3D el2_e2h_write; - } -} -#endif - -static CPAccessResult ctr_el0_access(CPUARMState *env, const ARMCPRegInfo = *ri, - bool isread) -{ - int cur_el =3D arm_current_el(env); - - if (cur_el < 2) { - uint64_t hcr =3D arm_hcr_el2_eff(env); - - if (cur_el =3D=3D 0) { - if ((hcr & (HCR_E2H | HCR_TGE)) =3D=3D (HCR_E2H | HCR_TGE)) { - if (!(env->cp15.sctlr_el[2] & SCTLR_UCT)) { - return CP_ACCESS_TRAP_EL2; - } - } else { - if (!(env->cp15.sctlr_el[1] & SCTLR_UCT)) { - return CP_ACCESS_TRAP; - } - if (hcr & HCR_TID2) { - return CP_ACCESS_TRAP_EL2; - } - } - } else if (hcr & HCR_TID2) { - return CP_ACCESS_TRAP_EL2; - } - } - - if (arm_current_el(env) < 2 && arm_hcr_el2_eff(env) & HCR_TID2) { - return CP_ACCESS_TRAP_EL2; - } - - return CP_ACCESS_OK; -} - -/* - * Check for traps to RAS registers, which are controlled - * by HCR_EL2.TERR and SCR_EL3.TERR. - */ -static CPAccessResult access_terr(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - int el =3D arm_current_el(env); - - if (el < 2 && (arm_hcr_el2_eff(env) & HCR_TERR)) { - return CP_ACCESS_TRAP_EL2; - } - if (el < 3 && (env->cp15.scr_el3 & SCR_TERR)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -static uint64_t disr_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - int el =3D arm_current_el(env); - - if (el < 2 && (arm_hcr_el2_eff(env) & HCR_AMO)) { - return env->cp15.vdisr_el2; - } - if (el < 3 && (env->cp15.scr_el3 & SCR_EA)) { - return 0; /* RAZ/WI */ - } - return env->cp15.disr_el1; -} - -static void disr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t = val) -{ - int el =3D arm_current_el(env); - - if (el < 2 && (arm_hcr_el2_eff(env) & HCR_AMO)) { - env->cp15.vdisr_el2 =3D val; - return; - } - if (el < 3 && (env->cp15.scr_el3 & SCR_EA)) { - return; /* RAZ/WI */ - } - env->cp15.disr_el1 =3D val; -} - -/* - * Minimal RAS implementation with no Error Records. - * Which means that all of the Error Record registers: - * ERXADDR_EL1 - * ERXCTLR_EL1 - * ERXFR_EL1 - * ERXMISC0_EL1 - * ERXMISC1_EL1 - * ERXMISC2_EL1 - * ERXMISC3_EL1 - * ERXPFGCDN_EL1 (RASv1p1) - * ERXPFGCTL_EL1 (RASv1p1) - * ERXPFGF_EL1 (RASv1p1) - * ERXSTATUS_EL1 - * and - * ERRSELR_EL1 - * may generate UNDEFINED, which is the effect we get by not - * listing them at all. - */ -static const ARMCPRegInfo minimal_ras_reginfo[] =3D { - { .name =3D "DISR_EL1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 12, .crm =3D 1, .opc2 =3D 1, - .access =3D PL1_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.disr= _el1), - .readfn =3D disr_read, .writefn =3D disr_write, .raw_writefn =3D raw= _write }, - { .name =3D "ERRIDR_EL1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 5, .crm =3D 3, .opc2 =3D 0, - .access =3D PL1_R, .accessfn =3D access_terr, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - { .name =3D "VDISR_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 12, .crm =3D 1, .opc2 =3D 1, - .access =3D PL2_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.vdis= r_el2) }, - { .name =3D "VSESR_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 5, .crm =3D 2, .opc2 =3D 3, - .access =3D PL2_RW, .fieldoffset =3D offsetof(CPUARMState, cp15.vses= r_el2) }, -}; - /* * Return the exception level to which exceptions should be taken * via SVEAccessTrap. This excludes the check for whether the exception @@ -6651,2272 +305,6 @@ uint32_t sve_vqm1_for_el(CPUARMState *env, int el) return sve_vqm1_for_el_sm(env, el, FIELD_EX64(env->svcr, SVCR, SM)); } =20 -static void zcr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - int cur_el =3D arm_current_el(env); - int old_len =3D sve_vqm1_for_el(env, cur_el); - int new_len; - - /* Bits other than [3:0] are RAZ/WI. */ - QEMU_BUILD_BUG_ON(ARM_MAX_VQ > 16); - raw_write(env, ri, value & 0xf); - - /* - * Because we arrived here, we know both FP and SVE are enabled; - * otherwise we would have trapped access to the ZCR_ELn register. - */ - new_len =3D sve_vqm1_for_el(env, cur_el); - if (new_len < old_len) { - aarch64_sve_narrow_vq(env, new_len + 1); - } -} - -static const ARMCPRegInfo zcr_reginfo[] =3D { - { .name =3D "ZCR_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 1, .crm =3D 2, .opc2 =3D 0, - .access =3D PL1_RW, .type =3D ARM_CP_SVE, - .fieldoffset =3D offsetof(CPUARMState, vfp.zcr_el[1]), - .writefn =3D zcr_write, .raw_writefn =3D raw_write }, - { .name =3D "ZCR_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 2, .opc2 =3D 0, - .access =3D PL2_RW, .type =3D ARM_CP_SVE, - .fieldoffset =3D offsetof(CPUARMState, vfp.zcr_el[2]), - .writefn =3D zcr_write, .raw_writefn =3D raw_write }, - { .name =3D "ZCR_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 2, .opc2 =3D 0, - .access =3D PL3_RW, .type =3D ARM_CP_SVE, - .fieldoffset =3D offsetof(CPUARMState, vfp.zcr_el[3]), - .writefn =3D zcr_write, .raw_writefn =3D raw_write }, -}; - -#ifdef TARGET_AARCH64 -static CPAccessResult access_tpidr2(CPUARMState *env, const ARMCPRegInfo *= ri, - bool isread) -{ - int el =3D arm_current_el(env); - - if (el =3D=3D 0) { - uint64_t sctlr =3D arm_sctlr(env, el); - if (!(sctlr & SCTLR_EnTP2)) { - return CP_ACCESS_TRAP; - } - } - /* TODO: FEAT_FGT */ - if (el < 3 - && arm_feature(env, ARM_FEATURE_EL3) - && !(env->cp15.scr_el3 & SCR_ENTP2)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -static CPAccessResult access_esm(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - /* TODO: FEAT_FGT for SMPRI_EL1 but not SMPRIMAP_EL2 */ - if (arm_current_el(env) < 3 - && arm_feature(env, ARM_FEATURE_EL3) - && !FIELD_EX64(env->cp15.cptr_el[3], CPTR_EL3, ESM)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -static void svcr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - helper_set_pstate_sm(env, FIELD_EX64(value, SVCR, SM)); - helper_set_pstate_za(env, FIELD_EX64(value, SVCR, ZA)); - arm_rebuild_hflags(env); -} - -static void smcr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - int cur_el =3D arm_current_el(env); - int old_len =3D sve_vqm1_for_el(env, cur_el); - int new_len; - - QEMU_BUILD_BUG_ON(ARM_MAX_VQ > R_SMCR_LEN_MASK + 1); - value &=3D R_SMCR_LEN_MASK | R_SMCR_FA64_MASK; - raw_write(env, ri, value); - - /* - * Note that it is CONSTRAINED UNPREDICTABLE what happens to ZA storage - * when SVL is widened (old values kept, or zeros). Choose to keep the - * current values for simplicity. But for QEMU internals, we must sti= ll - * apply the narrower SVL to the Zregs and Pregs -- see the comment - * above aarch64_sve_narrow_vq. - */ - new_len =3D sve_vqm1_for_el(env, cur_el); - if (new_len < old_len) { - aarch64_sve_narrow_vq(env, new_len + 1); - } -} - -static const ARMCPRegInfo sme_reginfo[] =3D { - { .name =3D "TPIDR2_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 13, .crm =3D 0, .opc2 =3D 5, - .access =3D PL0_RW, .accessfn =3D access_tpidr2, - .fieldoffset =3D offsetof(CPUARMState, cp15.tpidr2_el0) }, - { .name =3D "SVCR", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 4, .crm =3D 2, .opc2 =3D 2, - .access =3D PL0_RW, .type =3D ARM_CP_SME, - .fieldoffset =3D offsetof(CPUARMState, svcr), - .writefn =3D svcr_write, .raw_writefn =3D raw_write }, - { .name =3D "SMCR_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 1, .crm =3D 2, .opc2 =3D 6, - .access =3D PL1_RW, .type =3D ARM_CP_SME, - .fieldoffset =3D offsetof(CPUARMState, vfp.smcr_el[1]), - .writefn =3D smcr_write, .raw_writefn =3D raw_write }, - { .name =3D "SMCR_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 2, .opc2 =3D 6, - .access =3D PL2_RW, .type =3D ARM_CP_SME, - .fieldoffset =3D offsetof(CPUARMState, vfp.smcr_el[2]), - .writefn =3D smcr_write, .raw_writefn =3D raw_write }, - { .name =3D "SMCR_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 2, .opc2 =3D 6, - .access =3D PL3_RW, .type =3D ARM_CP_SME, - .fieldoffset =3D offsetof(CPUARMState, vfp.smcr_el[3]), - .writefn =3D smcr_write, .raw_writefn =3D raw_write }, - { .name =3D "SMIDR_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 1, .crn =3D 0, .crm =3D 0, .opc2 =3D 6, - .access =3D PL1_R, .accessfn =3D access_aa64_tid1, - /* - * IMPLEMENTOR =3D 0 (software) - * REVISION =3D 0 (implementation defined) - * SMPS =3D 0 (no streaming execution priority in QEMU) - * AFFINITY =3D 0 (streaming sve mode not shared with other PEs) - */ - .type =3D ARM_CP_CONST, .resetvalue =3D 0, }, - /* - * Because SMIDR_EL1.SMPS is 0, SMPRI_EL1 and SMPRIMAP_EL2 are RES 0. - */ - { .name =3D "SMPRI_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 1, .crm =3D 2, .opc2 =3D 4, - .access =3D PL1_RW, .accessfn =3D access_esm, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - { .name =3D "SMPRIMAP_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 2, .opc2 =3D 5, - .access =3D PL2_RW, .accessfn =3D access_esm, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, -}; -#endif /* TARGET_AARCH64 */ - -static void define_pmu_regs(ARMCPU *cpu) -{ - /* - * v7 performance monitor control register: same implementor - * field as main ID register, and we implement four counters in - * addition to the cycle count register. - */ - unsigned int i, pmcrn =3D pmu_num_counters(&cpu->env); - ARMCPRegInfo pmcr =3D { - .name =3D "PMCR", .cp =3D 15, .crn =3D 9, .crm =3D 12, .opc1 =3D 0= , .opc2 =3D 0, - .access =3D PL0_RW, - .type =3D ARM_CP_IO | ARM_CP_ALIAS, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.c9_pmcr), - .accessfn =3D pmreg_access, .writefn =3D pmcr_write, - .raw_writefn =3D raw_write, - }; - ARMCPRegInfo pmcr64 =3D { - .name =3D "PMCR_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D 0, - .access =3D PL0_RW, .accessfn =3D pmreg_access, - .type =3D ARM_CP_IO, - .fieldoffset =3D offsetof(CPUARMState, cp15.c9_pmcr), - .resetvalue =3D cpu->isar.reset_pmcr_el0, - .writefn =3D pmcr_write, .raw_writefn =3D raw_write, - }; - - define_one_arm_cp_reg(cpu, &pmcr); - define_one_arm_cp_reg(cpu, &pmcr64); - for (i =3D 0; i < pmcrn; i++) { - char *pmevcntr_name =3D g_strdup_printf("PMEVCNTR%d", i); - char *pmevcntr_el0_name =3D g_strdup_printf("PMEVCNTR%d_EL0", i); - char *pmevtyper_name =3D g_strdup_printf("PMEVTYPER%d", i); - char *pmevtyper_el0_name =3D g_strdup_printf("PMEVTYPER%d_EL0", i); - ARMCPRegInfo pmev_regs[] =3D { - { .name =3D pmevcntr_name, .cp =3D 15, .crn =3D 14, - .crm =3D 8 | (3 & (i >> 3)), .opc1 =3D 0, .opc2 =3D i & 7, - .access =3D PL0_RW, .type =3D ARM_CP_IO | ARM_CP_ALIAS, - .readfn =3D pmevcntr_readfn, .writefn =3D pmevcntr_writefn, - .accessfn =3D pmreg_access_xevcntr }, - { .name =3D pmevcntr_el0_name, .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 8 | (3 & (i = >> 3)), - .opc2 =3D i & 7, .access =3D PL0_RW, .accessfn =3D pmreg_acc= ess_xevcntr, - .type =3D ARM_CP_IO, - .readfn =3D pmevcntr_readfn, .writefn =3D pmevcntr_writefn, - .raw_readfn =3D pmevcntr_rawread, - .raw_writefn =3D pmevcntr_rawwrite }, - { .name =3D pmevtyper_name, .cp =3D 15, .crn =3D 14, - .crm =3D 12 | (3 & (i >> 3)), .opc1 =3D 0, .opc2 =3D i & 7, - .access =3D PL0_RW, .type =3D ARM_CP_IO | ARM_CP_ALIAS, - .readfn =3D pmevtyper_readfn, .writefn =3D pmevtyper_writefn, - .accessfn =3D pmreg_access }, - { .name =3D pmevtyper_el0_name, .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 14, .crm =3D 12 | (3 & (i= >> 3)), - .opc2 =3D i & 7, .access =3D PL0_RW, .accessfn =3D pmreg_acc= ess, - .type =3D ARM_CP_IO, - .readfn =3D pmevtyper_readfn, .writefn =3D pmevtyper_writefn, - .raw_writefn =3D pmevtyper_rawwrite }, - }; - define_arm_cp_regs(cpu, pmev_regs); - g_free(pmevcntr_name); - g_free(pmevcntr_el0_name); - g_free(pmevtyper_name); - g_free(pmevtyper_el0_name); - } - if (cpu_isar_feature(aa32_pmuv3p1, cpu)) { - ARMCPRegInfo v81_pmu_regs[] =3D { - { .name =3D "PMCEID2", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 14, .opc2 =3D = 4, - .access =3D PL0_R, .accessfn =3D pmreg_access, .type =3D ARM= _CP_CONST, - .resetvalue =3D extract64(cpu->pmceid0, 32, 32) }, - { .name =3D "PMCEID3", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 14, .opc2 =3D = 5, - .access =3D PL0_R, .accessfn =3D pmreg_access, .type =3D ARM= _CP_CONST, - .resetvalue =3D extract64(cpu->pmceid1, 32, 32) }, - }; - define_arm_cp_regs(cpu, v81_pmu_regs); - } - if (cpu_isar_feature(any_pmuv3p4, cpu)) { - static const ARMCPRegInfo v84_pmmir =3D { - .name =3D "PMMIR_EL1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 9, .crm =3D 14, .opc2 =3D 6, - .access =3D PL1_R, .accessfn =3D pmreg_access, .type =3D ARM_C= P_CONST, - .resetvalue =3D 0 - }; - define_one_arm_cp_reg(cpu, &v84_pmmir); - } -} - -/* - * We don't know until after realize whether there's a GICv3 - * attached, and that is what registers the gicv3 sysregs. - * So we have to fill in the GIC fields in ID_PFR/ID_PFR1_EL1/ID_AA64PFR0_= EL1 - * at runtime. - */ -static uint64_t id_pfr1_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - ARMCPU *cpu =3D env_archcpu(env); - uint64_t pfr1 =3D cpu->isar.id_pfr1; - - if (env->gicv3state) { - pfr1 |=3D 1 << 28; - } - return pfr1; -} - -#ifndef CONFIG_USER_ONLY -static uint64_t id_aa64pfr0_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - ARMCPU *cpu =3D env_archcpu(env); - uint64_t pfr0 =3D cpu->isar.id_aa64pfr0; - - if (env->gicv3state) { - pfr0 |=3D 1 << 24; - } - return pfr0; -} -#endif - -/* - * Shared logic between LORID and the rest of the LOR* registers. - * Secure state exclusion has already been dealt with. - */ -static CPAccessResult access_lor_ns(CPUARMState *env, - const ARMCPRegInfo *ri, bool isread) -{ - int el =3D arm_current_el(env); - - if (el < 2 && (arm_hcr_el2_eff(env) & HCR_TLOR)) { - return CP_ACCESS_TRAP_EL2; - } - if (el < 3 && (env->cp15.scr_el3 & SCR_TLOR)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -static CPAccessResult access_lor_other(CPUARMState *env, - const ARMCPRegInfo *ri, bool isread) -{ - if (arm_is_secure_below_el3(env)) { - /* Access denied in secure mode. */ - return CP_ACCESS_TRAP; - } - return access_lor_ns(env, ri, isread); -} - -/* - * A trivial implementation of ARMv8.1-LOR leaves all of these - * registers fixed at 0, which indicates that there are zero - * supported Limited Ordering regions. - */ -static const ARMCPRegInfo lor_reginfo[] =3D { - { .name =3D "LORSA_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 10, .crm =3D 4, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_lor_other, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - { .name =3D "LOREA_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 10, .crm =3D 4, .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_lor_other, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - { .name =3D "LORN_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 10, .crm =3D 4, .opc2 =3D 2, - .access =3D PL1_RW, .accessfn =3D access_lor_other, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - { .name =3D "LORC_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 10, .crm =3D 4, .opc2 =3D 3, - .access =3D PL1_RW, .accessfn =3D access_lor_other, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - { .name =3D "LORID_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 10, .crm =3D 4, .opc2 =3D 7, - .access =3D PL1_R, .accessfn =3D access_lor_ns, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, -}; - -#ifdef TARGET_AARCH64 -static CPAccessResult access_pauth(CPUARMState *env, const ARMCPRegInfo *r= i, - bool isread) -{ - int el =3D arm_current_el(env); - - if (el < 2 && - arm_is_el2_enabled(env) && - !(arm_hcr_el2_eff(env) & HCR_APK)) { - return CP_ACCESS_TRAP_EL2; - } - if (el < 3 && - arm_feature(env, ARM_FEATURE_EL3) && - !(env->cp15.scr_el3 & SCR_APK)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -static const ARMCPRegInfo pauth_reginfo[] =3D { - { .name =3D "APDAKEYLO_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 2, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_pauth, - .fieldoffset =3D offsetof(CPUARMState, keys.apda.lo) }, - { .name =3D "APDAKEYHI_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 2, .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_pauth, - .fieldoffset =3D offsetof(CPUARMState, keys.apda.hi) }, - { .name =3D "APDBKEYLO_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 2, .opc2 =3D 2, - .access =3D PL1_RW, .accessfn =3D access_pauth, - .fieldoffset =3D offsetof(CPUARMState, keys.apdb.lo) }, - { .name =3D "APDBKEYHI_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 2, .opc2 =3D 3, - .access =3D PL1_RW, .accessfn =3D access_pauth, - .fieldoffset =3D offsetof(CPUARMState, keys.apdb.hi) }, - { .name =3D "APGAKEYLO_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 3, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_pauth, - .fieldoffset =3D offsetof(CPUARMState, keys.apga.lo) }, - { .name =3D "APGAKEYHI_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 3, .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_pauth, - .fieldoffset =3D offsetof(CPUARMState, keys.apga.hi) }, - { .name =3D "APIAKEYLO_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 1, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_pauth, - .fieldoffset =3D offsetof(CPUARMState, keys.apia.lo) }, - { .name =3D "APIAKEYHI_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 1, .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_pauth, - .fieldoffset =3D offsetof(CPUARMState, keys.apia.hi) }, - { .name =3D "APIBKEYLO_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 1, .opc2 =3D 2, - .access =3D PL1_RW, .accessfn =3D access_pauth, - .fieldoffset =3D offsetof(CPUARMState, keys.apib.lo) }, - { .name =3D "APIBKEYHI_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 2, .crm =3D 1, .opc2 =3D 3, - .access =3D PL1_RW, .accessfn =3D access_pauth, - .fieldoffset =3D offsetof(CPUARMState, keys.apib.hi) }, -}; - -static const ARMCPRegInfo tlbirange_reginfo[] =3D { - { .name =3D "TLBI_RVAE1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 2, .opc2 =3D 1, - .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_rvae1is_write }, - { .name =3D "TLBI_RVAAE1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 2, .opc2 =3D 3, - .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_rvae1is_write }, - { .name =3D "TLBI_RVALE1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 2, .opc2 =3D 5, - .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_rvae1is_write }, - { .name =3D "TLBI_RVAALE1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 2, .opc2 =3D 7, - .access =3D PL1_W, .accessfn =3D access_ttlbis, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_rvae1is_write }, - { .name =3D "TLBI_RVAE1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 5, .opc2 =3D 1, - .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_rvae1is_write }, - { .name =3D "TLBI_RVAAE1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 5, .opc2 =3D 3, - .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_rvae1is_write }, - { .name =3D "TLBI_RVALE1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 5, .opc2 =3D 5, - .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_rvae1is_write }, - { .name =3D "TLBI_RVAALE1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 5, .opc2 =3D 7, - .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_rvae1is_write }, - { .name =3D "TLBI_RVAE1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 6, .opc2 =3D 1, - .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, - .writefn =3D tlbi_aa64_rvae1_write }, - { .name =3D "TLBI_RVAAE1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 6, .opc2 =3D 3, - .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, - .writefn =3D tlbi_aa64_rvae1_write }, - { .name =3D "TLBI_RVALE1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 6, .opc2 =3D 5, - .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, - .writefn =3D tlbi_aa64_rvae1_write }, - { .name =3D "TLBI_RVAALE1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 6, .opc2 =3D 7, - .access =3D PL1_W, .accessfn =3D access_ttlb, .type =3D ARM_CP_NO_RA= W, - .writefn =3D tlbi_aa64_rvae1_write }, - { .name =3D "TLBI_RIPAS2E1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 0, .opc2 =3D 2, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_ripas2e1is_write }, - { .name =3D "TLBI_RIPAS2LE1IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 0, .opc2 =3D 6, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_ripas2e1is_write }, - { .name =3D "TLBI_RVAE2IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 2, .opc2 =3D 1, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, - .writefn =3D tlbi_aa64_rvae2is_write }, - { .name =3D "TLBI_RVALE2IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 2, .opc2 =3D 5, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, - .writefn =3D tlbi_aa64_rvae2is_write }, - { .name =3D "TLBI_RIPAS2E1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 2, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_ripas2e1_write }, - { .name =3D "TLBI_RIPAS2LE1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 6, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_ripas2e1_write }, - { .name =3D "TLBI_RVAE2OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 5, .opc2 =3D 1, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, - .writefn =3D tlbi_aa64_rvae2is_write }, - { .name =3D "TLBI_RVALE2OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 5, .opc2 =3D 5, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, - .writefn =3D tlbi_aa64_rvae2is_write }, - { .name =3D "TLBI_RVAE2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 6, .opc2 =3D 1, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, - .writefn =3D tlbi_aa64_rvae2_write }, - { .name =3D "TLBI_RVALE2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 6, .opc2 =3D 5, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, - .writefn =3D tlbi_aa64_rvae2_write }, - { .name =3D "TLBI_RVAE3IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 2, .opc2 =3D 1, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_rvae3is_write }, - { .name =3D "TLBI_RVALE3IS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 2, .opc2 =3D 5, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_rvae3is_write }, - { .name =3D "TLBI_RVAE3OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 5, .opc2 =3D 1, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_rvae3is_write }, - { .name =3D "TLBI_RVALE3OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 5, .opc2 =3D 5, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_rvae3is_write }, - { .name =3D "TLBI_RVAE3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 6, .opc2 =3D 1, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_rvae3_write }, - { .name =3D "TLBI_RVALE3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 6, .opc2 =3D 5, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_rvae3_write }, -}; - -static const ARMCPRegInfo tlbios_reginfo[] =3D { - { .name =3D "TLBI_VMALLE1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 1, .opc2 =3D 0, - .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_vmalle1is_write }, - { .name =3D "TLBI_VAE1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 1, .opc2 =3D 1, - .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_vae1is_write }, - { .name =3D "TLBI_ASIDE1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 1, .opc2 =3D 2, - .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_vmalle1is_write }, - { .name =3D "TLBI_VAAE1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 1, .opc2 =3D 3, - .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_vae1is_write }, - { .name =3D "TLBI_VALE1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 1, .opc2 =3D 5, - .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_vae1is_write }, - { .name =3D "TLBI_VAALE1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 8, .crm =3D 1, .opc2 =3D 7, - .access =3D PL1_W, .accessfn =3D access_ttlbos, .type =3D ARM_CP_NO_= RAW, - .writefn =3D tlbi_aa64_vae1is_write }, - { .name =3D "TLBI_ALLE2OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 1, .opc2 =3D 0, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, - .writefn =3D tlbi_aa64_alle2is_write }, - { .name =3D "TLBI_VAE2OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 1, .opc2 =3D 1, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, - .writefn =3D tlbi_aa64_vae2is_write }, - { .name =3D "TLBI_ALLE1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 1, .opc2 =3D 4, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_alle1is_write }, - { .name =3D "TLBI_VALE2OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 1, .opc2 =3D 5, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW | ARM_CP_EL3_NO_EL2_UNDEF, - .writefn =3D tlbi_aa64_vae2is_write }, - { .name =3D "TLBI_VMALLS12E1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 1, .opc2 =3D 6, - .access =3D PL2_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_alle1is_write }, - { .name =3D "TLBI_IPAS2E1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 0, - .access =3D PL2_W, .type =3D ARM_CP_NOP }, - { .name =3D "TLBI_RIPAS2E1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 3, - .access =3D PL2_W, .type =3D ARM_CP_NOP }, - { .name =3D "TLBI_IPAS2LE1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 4, - .access =3D PL2_W, .type =3D ARM_CP_NOP }, - { .name =3D "TLBI_RIPAS2LE1OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 4, .crn =3D 8, .crm =3D 4, .opc2 =3D 7, - .access =3D PL2_W, .type =3D ARM_CP_NOP }, - { .name =3D "TLBI_ALLE3OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 1, .opc2 =3D 0, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_alle3is_write }, - { .name =3D "TLBI_VAE3OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 1, .opc2 =3D 1, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_vae3is_write }, - { .name =3D "TLBI_VALE3OS", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 6, .crn =3D 8, .crm =3D 1, .opc2 =3D 5, - .access =3D PL3_W, .type =3D ARM_CP_NO_RAW, - .writefn =3D tlbi_aa64_vae3is_write }, -}; - -static uint64_t rndr_readfn(CPUARMState *env, const ARMCPRegInfo *ri) -{ - Error *err =3D NULL; - uint64_t ret; - - /* Success sets NZCV =3D 0000. */ - env->NF =3D env->CF =3D env->VF =3D 0, env->ZF =3D 1; - - if (qemu_guest_getrandom(&ret, sizeof(ret), &err) < 0) { - /* - * ??? Failed, for unknown reasons in the crypto subsystem. - * The best we can do is log the reason and return the - * timed-out indication to the guest. There is no reason - * we know to expect this failure to be transitory, so the - * guest may well hang retrying the operation. - */ - qemu_log_mask(LOG_UNIMP, "%s: Crypto failure: %s", - ri->name, error_get_pretty(err)); - error_free(err); - - env->ZF =3D 0; /* NZCF =3D 0100 */ - return 0; - } - return ret; -} - -/* We do not support re-seeding, so the two registers operate the same. */ -static const ARMCPRegInfo rndr_reginfo[] =3D { - { .name =3D "RNDR", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END | ARM_CP_IO, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 2, .crm =3D 4, .opc2 =3D 0, - .access =3D PL0_R, .readfn =3D rndr_readfn }, - { .name =3D "RNDRRS", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END | ARM_CP_IO, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 2, .crm =3D 4, .opc2 =3D 1, - .access =3D PL0_R, .readfn =3D rndr_readfn }, -}; - -#ifndef CONFIG_USER_ONLY -static void dccvap_writefn(CPUARMState *env, const ARMCPRegInfo *opaque, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - /* CTR_EL0 System register -> DminLine, bits [19:16] */ - uint64_t dline_size =3D 4 << ((cpu->ctr >> 16) & 0xF); - uint64_t vaddr_in =3D (uint64_t) value; - uint64_t vaddr =3D vaddr_in & ~(dline_size - 1); - void *haddr; - int mem_idx =3D cpu_mmu_index(env, false); - - /* This won't be crossing page boundaries */ - haddr =3D probe_read(env, vaddr, dline_size, mem_idx, GETPC()); - if (haddr) { - - ram_addr_t offset; - MemoryRegion *mr; - - /* RCU lock is already being held */ - mr =3D memory_region_from_host(haddr, &offset); - - if (mr) { - memory_region_writeback(mr, offset, dline_size); - } - } -} - -static const ARMCPRegInfo dcpop_reg[] =3D { - { .name =3D "DC_CVAP", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 12, .opc2 =3D 1, - .access =3D PL0_W, .type =3D ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END, - .accessfn =3D aa64_cacheop_poc_access, .writefn =3D dccvap_writefn }, -}; - -static const ARMCPRegInfo dcpodp_reg[] =3D { - { .name =3D "DC_CVADP", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 13, .opc2 =3D 1, - .access =3D PL0_W, .type =3D ARM_CP_NO_RAW | ARM_CP_SUPPRESS_TB_END, - .accessfn =3D aa64_cacheop_poc_access, .writefn =3D dccvap_writefn }, -}; -#endif /*CONFIG_USER_ONLY*/ - -static CPAccessResult access_aa64_tid5(CPUARMState *env, const ARMCPRegInf= o *ri, - bool isread) -{ - if ((arm_current_el(env) < 2) && (arm_hcr_el2_eff(env) & HCR_TID5)) { - return CP_ACCESS_TRAP_EL2; - } - - return CP_ACCESS_OK; -} - -static CPAccessResult access_mte(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - int el =3D arm_current_el(env); - - if (el < 2 && arm_is_el2_enabled(env)) { - uint64_t hcr =3D arm_hcr_el2_eff(env); - if (!(hcr & HCR_ATA) && (!(hcr & HCR_E2H) || !(hcr & HCR_TGE))) { - return CP_ACCESS_TRAP_EL2; - } - } - if (el < 3 && - arm_feature(env, ARM_FEATURE_EL3) && - !(env->cp15.scr_el3 & SCR_ATA)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -static uint64_t tco_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - return env->pstate & PSTATE_TCO; -} - -static void tco_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t v= al) -{ - env->pstate =3D (env->pstate & ~PSTATE_TCO) | (val & PSTATE_TCO); -} - -static const ARMCPRegInfo mte_reginfo[] =3D { - { .name =3D "TFSRE0_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 5, .crm =3D 6, .opc2 =3D 1, - .access =3D PL1_RW, .accessfn =3D access_mte, - .fieldoffset =3D offsetof(CPUARMState, cp15.tfsr_el[0]) }, - { .name =3D "TFSR_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 5, .crm =3D 6, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_mte, - .fieldoffset =3D offsetof(CPUARMState, cp15.tfsr_el[1]) }, - { .name =3D "TFSR_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 5, .crm =3D 6, .opc2 =3D 0, - .access =3D PL2_RW, .accessfn =3D access_mte, - .fieldoffset =3D offsetof(CPUARMState, cp15.tfsr_el[2]) }, - { .name =3D "TFSR_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 5, .crm =3D 6, .opc2 =3D 0, - .access =3D PL3_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.tfsr_el[3]) }, - { .name =3D "RGSR_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 1, .crm =3D 0, .opc2 =3D 5, - .access =3D PL1_RW, .accessfn =3D access_mte, - .fieldoffset =3D offsetof(CPUARMState, cp15.rgsr_el1) }, - { .name =3D "GCR_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 1, .crm =3D 0, .opc2 =3D 6, - .access =3D PL1_RW, .accessfn =3D access_mte, - .fieldoffset =3D offsetof(CPUARMState, cp15.gcr_el1) }, - { .name =3D "GMID_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 1, .crn =3D 0, .crm =3D 0, .opc2 =3D 4, - .access =3D PL1_R, .accessfn =3D access_aa64_tid5, - .type =3D ARM_CP_CONST, .resetvalue =3D GMID_EL1_BS }, - { .name =3D "TCO", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 4, .crm =3D 2, .opc2 =3D 7, - .type =3D ARM_CP_NO_RAW, - .access =3D PL0_RW, .readfn =3D tco_read, .writefn =3D tco_write }, - { .name =3D "DC_IGVAC", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 6, .opc2 =3D 3, - .type =3D ARM_CP_NOP, .access =3D PL1_W, - .accessfn =3D aa64_cacheop_poc_access }, - { .name =3D "DC_IGSW", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 6, .opc2 =3D 4, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, - { .name =3D "DC_IGDVAC", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 6, .opc2 =3D 5, - .type =3D ARM_CP_NOP, .access =3D PL1_W, - .accessfn =3D aa64_cacheop_poc_access }, - { .name =3D "DC_IGDSW", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 6, .opc2 =3D 6, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, - { .name =3D "DC_CGSW", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 10, .opc2 =3D 4, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, - { .name =3D "DC_CGDSW", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 10, .opc2 =3D 6, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, - { .name =3D "DC_CIGSW", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 14, .opc2 =3D 4, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, - { .name =3D "DC_CIGDSW", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 14, .opc2 =3D 6, - .type =3D ARM_CP_NOP, .access =3D PL1_W, .accessfn =3D access_tsw }, -}; - -static const ARMCPRegInfo mte_tco_ro_reginfo[] =3D { - { .name =3D "TCO", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 4, .crm =3D 2, .opc2 =3D 7, - .type =3D ARM_CP_CONST, .access =3D PL0_RW, }, -}; - -static const ARMCPRegInfo mte_el0_cacheop_reginfo[] =3D { - { .name =3D "DC_CGVAC", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 10, .opc2 =3D 3, - .type =3D ARM_CP_NOP, .access =3D PL0_W, - .accessfn =3D aa64_cacheop_poc_access }, - { .name =3D "DC_CGDVAC", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 10, .opc2 =3D 5, - .type =3D ARM_CP_NOP, .access =3D PL0_W, - .accessfn =3D aa64_cacheop_poc_access }, - { .name =3D "DC_CGVAP", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 12, .opc2 =3D 3, - .type =3D ARM_CP_NOP, .access =3D PL0_W, - .accessfn =3D aa64_cacheop_poc_access }, - { .name =3D "DC_CGDVAP", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 12, .opc2 =3D 5, - .type =3D ARM_CP_NOP, .access =3D PL0_W, - .accessfn =3D aa64_cacheop_poc_access }, - { .name =3D "DC_CGVADP", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 13, .opc2 =3D 3, - .type =3D ARM_CP_NOP, .access =3D PL0_W, - .accessfn =3D aa64_cacheop_poc_access }, - { .name =3D "DC_CGDVADP", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 13, .opc2 =3D 5, - .type =3D ARM_CP_NOP, .access =3D PL0_W, - .accessfn =3D aa64_cacheop_poc_access }, - { .name =3D "DC_CIGVAC", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 14, .opc2 =3D 3, - .type =3D ARM_CP_NOP, .access =3D PL0_W, - .accessfn =3D aa64_cacheop_poc_access }, - { .name =3D "DC_CIGDVAC", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 14, .opc2 =3D 5, - .type =3D ARM_CP_NOP, .access =3D PL0_W, - .accessfn =3D aa64_cacheop_poc_access }, - { .name =3D "DC_GVA", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 4, .opc2 =3D 3, - .access =3D PL0_W, .type =3D ARM_CP_DC_GVA, -#ifndef CONFIG_USER_ONLY - /* Avoid overhead of an access check that always passes in user-mode= */ - .accessfn =3D aa64_zva_access, -#endif - }, - { .name =3D "DC_GZVA", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 4, .opc2 =3D 4, - .access =3D PL0_W, .type =3D ARM_CP_DC_GZVA, -#ifndef CONFIG_USER_ONLY - /* Avoid overhead of an access check that always passes in user-mode= */ - .accessfn =3D aa64_zva_access, -#endif - }, -}; - -static CPAccessResult access_scxtnum(CPUARMState *env, const ARMCPRegInfo = *ri, - bool isread) -{ - uint64_t hcr =3D arm_hcr_el2_eff(env); - int el =3D arm_current_el(env); - - if (el =3D=3D 0 && !((hcr & HCR_E2H) && (hcr & HCR_TGE))) { - if (env->cp15.sctlr_el[1] & SCTLR_TSCXT) { - if (hcr & HCR_TGE) { - return CP_ACCESS_TRAP_EL2; - } - return CP_ACCESS_TRAP; - } - } else if (el < 2 && (env->cp15.sctlr_el[2] & SCTLR_TSCXT)) { - return CP_ACCESS_TRAP_EL2; - } - if (el < 2 && arm_is_el2_enabled(env) && !(hcr & HCR_ENSCXT)) { - return CP_ACCESS_TRAP_EL2; - } - if (el < 3 - && arm_feature(env, ARM_FEATURE_EL3) - && !(env->cp15.scr_el3 & SCR_ENSCXT)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -static const ARMCPRegInfo scxtnum_reginfo[] =3D { - { .name =3D "SCXTNUM_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 13, .crm =3D 0, .opc2 =3D 7, - .access =3D PL0_RW, .accessfn =3D access_scxtnum, - .fieldoffset =3D offsetof(CPUARMState, scxtnum_el[0]) }, - { .name =3D "SCXTNUM_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 13, .crm =3D 0, .opc2 =3D 7, - .access =3D PL1_RW, .accessfn =3D access_scxtnum, - .fieldoffset =3D offsetof(CPUARMState, scxtnum_el[1]) }, - { .name =3D "SCXTNUM_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 13, .crm =3D 0, .opc2 =3D 7, - .access =3D PL2_RW, .accessfn =3D access_scxtnum, - .fieldoffset =3D offsetof(CPUARMState, scxtnum_el[2]) }, - { .name =3D "SCXTNUM_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 13, .crm =3D 0, .opc2 =3D 7, - .access =3D PL3_RW, - .fieldoffset =3D offsetof(CPUARMState, scxtnum_el[3]) }, -}; -#endif /* TARGET_AARCH64 */ - -static CPAccessResult access_predinv(CPUARMState *env, const ARMCPRegInfo = *ri, - bool isread) -{ - int el =3D arm_current_el(env); - - if (el =3D=3D 0) { - uint64_t sctlr =3D arm_sctlr(env, el); - if (!(sctlr & SCTLR_EnRCTX)) { - return CP_ACCESS_TRAP; - } - } else if (el =3D=3D 1) { - uint64_t hcr =3D arm_hcr_el2_eff(env); - if (hcr & HCR_NV) { - return CP_ACCESS_TRAP_EL2; - } - } - return CP_ACCESS_OK; -} - -static const ARMCPRegInfo predinv_reginfo[] =3D { - { .name =3D "CFP_RCTX", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 3, .opc2 =3D 4, - .type =3D ARM_CP_NOP, .access =3D PL0_W, .accessfn =3D access_predin= v }, - { .name =3D "DVP_RCTX", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 3, .opc2 =3D 5, - .type =3D ARM_CP_NOP, .access =3D PL0_W, .accessfn =3D access_predin= v }, - { .name =3D "CPP_RCTX", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 3, .crn =3D 7, .crm =3D 3, .opc2 =3D 7, - .type =3D ARM_CP_NOP, .access =3D PL0_W, .accessfn =3D access_predin= v }, - /* - * Note the AArch32 opcodes have a different OPC1. - */ - { .name =3D "CFPRCTX", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 3, .opc2 =3D 4, - .type =3D ARM_CP_NOP, .access =3D PL0_W, .accessfn =3D access_predin= v }, - { .name =3D "DVPRCTX", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 3, .opc2 =3D 5, - .type =3D ARM_CP_NOP, .access =3D PL0_W, .accessfn =3D access_predin= v }, - { .name =3D "CPPRCTX", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 3, .opc2 =3D 7, - .type =3D ARM_CP_NOP, .access =3D PL0_W, .accessfn =3D access_predin= v }, -}; - -static uint64_t ccsidr2_read(CPUARMState *env, const ARMCPRegInfo *ri) -{ - /* Read the high 32 bits of the current CCSIDR */ - return extract64(ccsidr_read(env, ri), 32, 32); -} - -static const ARMCPRegInfo ccsidr2_reginfo[] =3D { - { .name =3D "CCSIDR2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 1, .crn =3D 0, .crm =3D 0, .opc2 =3D 2, - .access =3D PL1_R, - .accessfn =3D access_tid4, - .readfn =3D ccsidr2_read, .type =3D ARM_CP_NO_RAW }, -}; - -static CPAccessResult access_aa64_tid3(CPUARMState *env, const ARMCPRegInf= o *ri, - bool isread) -{ - if ((arm_current_el(env) < 2) && (arm_hcr_el2_eff(env) & HCR_TID3)) { - return CP_ACCESS_TRAP_EL2; - } - - return CP_ACCESS_OK; -} - -static CPAccessResult access_aa32_tid3(CPUARMState *env, const ARMCPRegInf= o *ri, - bool isread) -{ - if (arm_feature(env, ARM_FEATURE_V8)) { - return access_aa64_tid3(env, ri, isread); - } - - return CP_ACCESS_OK; -} - -static CPAccessResult access_jazelle(CPUARMState *env, const ARMCPRegInfo = *ri, - bool isread) -{ - if (arm_current_el(env) =3D=3D 1 && (arm_hcr_el2_eff(env) & HCR_TID0))= { - return CP_ACCESS_TRAP_EL2; - } - - return CP_ACCESS_OK; -} - -static CPAccessResult access_joscr_jmcr(CPUARMState *env, - const ARMCPRegInfo *ri, bool isrea= d) -{ - /* - * HSTR.TJDBX traps JOSCR and JMCR accesses, but it exists only - * in v7A, not in v8A. - */ - if (!arm_feature(env, ARM_FEATURE_V8) && - arm_current_el(env) < 2 && !arm_is_secure_below_el3(env) && - (env->cp15.hstr_el2 & HSTR_TJDBX)) { - return CP_ACCESS_TRAP_EL2; - } - return CP_ACCESS_OK; -} - -static const ARMCPRegInfo jazelle_regs[] =3D { - { .name =3D "JIDR", - .cp =3D 14, .crn =3D 0, .crm =3D 0, .opc1 =3D 7, .opc2 =3D 0, - .access =3D PL1_R, .accessfn =3D access_jazelle, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - { .name =3D "JOSCR", - .cp =3D 14, .crn =3D 1, .crm =3D 0, .opc1 =3D 7, .opc2 =3D 0, - .accessfn =3D access_joscr_jmcr, - .access =3D PL1_RW, .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - { .name =3D "JMCR", - .cp =3D 14, .crn =3D 2, .crm =3D 0, .opc1 =3D 7, .opc2 =3D 0, - .accessfn =3D access_joscr_jmcr, - .access =3D PL1_RW, .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, -}; - -static const ARMCPRegInfo contextidr_el2 =3D { - .name =3D "CONTEXTIDR_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 13, .crm =3D 0, .opc2 =3D 1, - .access =3D PL2_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.contextidr_el[2]) -}; - -static const ARMCPRegInfo vhe_reginfo[] =3D { - { .name =3D "TTBR1_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 2, .crm =3D 0, .opc2 =3D 1, - .access =3D PL2_RW, .writefn =3D vmsa_tcr_ttbr_el2_write, - .fieldoffset =3D offsetof(CPUARMState, cp15.ttbr1_el[2]) }, -#ifndef CONFIG_USER_ONLY - { .name =3D "CNTHV_CVAL_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 3, .opc2 =3D 2, - .fieldoffset =3D - offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYPVIRT].cval), - .type =3D ARM_CP_IO, .access =3D PL2_RW, - .writefn =3D gt_hv_cval_write, .raw_writefn =3D raw_write }, - { .name =3D "CNTHV_TVAL_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 3, .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW | ARM_CP_IO, .access =3D PL2_RW, - .resetfn =3D gt_hv_timer_reset, - .readfn =3D gt_hv_tval_read, .writefn =3D gt_hv_tval_write }, - { .name =3D "CNTHV_CTL_EL2", .state =3D ARM_CP_STATE_BOTH, - .type =3D ARM_CP_IO, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 14, .crm =3D 3, .opc2 =3D 1, - .access =3D PL2_RW, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_HYPVIRT= ].ctl), - .writefn =3D gt_hv_ctl_write, .raw_writefn =3D raw_write }, - { .name =3D "CNTP_CTL_EL02", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 5, .crn =3D 14, .crm =3D 2, .opc2 =3D 1, - .type =3D ARM_CP_IO | ARM_CP_ALIAS, - .access =3D PL2_RW, .accessfn =3D e2h_access, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].c= tl), - .writefn =3D gt_phys_ctl_write, .raw_writefn =3D raw_write }, - { .name =3D "CNTV_CTL_EL02", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 5, .crn =3D 14, .crm =3D 3, .opc2 =3D 1, - .type =3D ARM_CP_IO | ARM_CP_ALIAS, - .access =3D PL2_RW, .accessfn =3D e2h_access, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].c= tl), - .writefn =3D gt_virt_ctl_write, .raw_writefn =3D raw_write }, - { .name =3D "CNTP_TVAL_EL02", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 5, .crn =3D 14, .crm =3D 2, .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW | ARM_CP_IO | ARM_CP_ALIAS, - .access =3D PL2_RW, .accessfn =3D e2h_access, - .readfn =3D gt_phys_tval_read, .writefn =3D gt_phys_tval_write }, - { .name =3D "CNTV_TVAL_EL02", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 5, .crn =3D 14, .crm =3D 3, .opc2 =3D 0, - .type =3D ARM_CP_NO_RAW | ARM_CP_IO | ARM_CP_ALIAS, - .access =3D PL2_RW, .accessfn =3D e2h_access, - .readfn =3D gt_virt_tval_read, .writefn =3D gt_virt_tval_write }, - { .name =3D "CNTP_CVAL_EL02", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 5, .crn =3D 14, .crm =3D 2, .opc2 =3D 2, - .type =3D ARM_CP_IO | ARM_CP_ALIAS, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].c= val), - .access =3D PL2_RW, .accessfn =3D e2h_access, - .writefn =3D gt_phys_cval_write, .raw_writefn =3D raw_write }, - { .name =3D "CNTV_CVAL_EL02", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 5, .crn =3D 14, .crm =3D 3, .opc2 =3D 2, - .type =3D ARM_CP_IO | ARM_CP_ALIAS, - .fieldoffset =3D offsetof(CPUARMState, cp15.c14_timer[GTIMER_VIRT].c= val), - .access =3D PL2_RW, .accessfn =3D e2h_access, - .writefn =3D gt_virt_cval_write, .raw_writefn =3D raw_write }, -#endif -}; - -#ifndef CONFIG_USER_ONLY -static const ARMCPRegInfo ats1e1_reginfo[] =3D { - { .name =3D "AT_S1E1R", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 9, .opc2 =3D 0, - .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, - .writefn =3D ats_write64 }, - { .name =3D "AT_S1E1W", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 1, .opc1 =3D 0, .crn =3D 7, .crm =3D 9, .opc2 =3D 1, - .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, - .writefn =3D ats_write64 }, -}; - -static const ARMCPRegInfo ats1cp_reginfo[] =3D { - { .name =3D "ATS1CPRP", - .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 9, .opc2 =3D 0, - .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, - .writefn =3D ats_write }, - { .name =3D "ATS1CPWP", - .cp =3D 15, .opc1 =3D 0, .crn =3D 7, .crm =3D 9, .opc2 =3D 1, - .access =3D PL1_W, .type =3D ARM_CP_NO_RAW | ARM_CP_RAISES_EXC, - .writefn =3D ats_write }, -}; -#endif - -/* - * ACTLR2 and HACTLR2 map to ACTLR_EL1[63:32] and - * ACTLR_EL2[63:32]. They exist only if the ID_MMFR4.AC2 field - * is non-zero, which is never for ARMv7, optionally in ARMv8 - * and mandatorily for ARMv8.2 and up. - * ACTLR2 is banked for S and NS if EL3 is AArch32. Since QEMU's - * implementation is RAZ/WI we can ignore this detail, as we - * do for ACTLR. - */ -static const ARMCPRegInfo actlr2_hactlr2_reginfo[] =3D { - { .name =3D "ACTLR2", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 0, .crn =3D 1, .crm =3D 0, .opc2 =3D 3, - .access =3D PL1_RW, .accessfn =3D access_tacr, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - { .name =3D "HACTLR2", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 4, .crn =3D 1, .crm =3D 0, .opc2 =3D 3, - .access =3D PL2_RW, .type =3D ARM_CP_CONST, - .resetvalue =3D 0 }, -}; - -void register_cp_regs_for_features(ARMCPU *cpu) -{ - /* Register all the coprocessor registers based on feature bits */ - CPUARMState *env =3D &cpu->env; - if (arm_feature(env, ARM_FEATURE_M)) { - /* M profile has no coprocessor registers */ - return; - } - - define_arm_cp_regs(cpu, cp_reginfo); - if (!arm_feature(env, ARM_FEATURE_V8)) { - /* - * Must go early as it is full of wildcards that may be - * overridden by later definitions. - */ - define_arm_cp_regs(cpu, not_v8_cp_reginfo); - } - - if (arm_feature(env, ARM_FEATURE_V6)) { - /* The ID registers all have impdef reset values */ - ARMCPRegInfo v6_idregs[] =3D { - { .name =3D "ID_PFR0", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 0, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa32_tid3, - .resetvalue =3D cpu->isar.id_pfr0 }, - /* - * ID_PFR1 is not a plain ARM_CP_CONST because we don't know - * the value of the GIC field until after we define these regs. - */ - { .name =3D "ID_PFR1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 1, - .access =3D PL1_R, .type =3D ARM_CP_NO_RAW, - .accessfn =3D access_aa32_tid3, - .readfn =3D id_pfr1_read, - .writefn =3D arm_cp_write_ignore }, - { .name =3D "ID_DFR0", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 2, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa32_tid3, - .resetvalue =3D cpu->isar.id_dfr0 }, - { .name =3D "ID_AFR0", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 3, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa32_tid3, - .resetvalue =3D cpu->id_afr0 }, - { .name =3D "ID_MMFR0", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 4, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa32_tid3, - .resetvalue =3D cpu->isar.id_mmfr0 }, - { .name =3D "ID_MMFR1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 5, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa32_tid3, - .resetvalue =3D cpu->isar.id_mmfr1 }, - { .name =3D "ID_MMFR2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 6, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa32_tid3, - .resetvalue =3D cpu->isar.id_mmfr2 }, - { .name =3D "ID_MMFR3", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D = 7, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa32_tid3, - .resetvalue =3D cpu->isar.id_mmfr3 }, - { .name =3D "ID_ISAR0", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 0, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa32_tid3, - .resetvalue =3D cpu->isar.id_isar0 }, - { .name =3D "ID_ISAR1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 1, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa32_tid3, - .resetvalue =3D cpu->isar.id_isar1 }, - { .name =3D "ID_ISAR2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 2, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa32_tid3, - .resetvalue =3D cpu->isar.id_isar2 }, - { .name =3D "ID_ISAR3", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 3, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa32_tid3, - .resetvalue =3D cpu->isar.id_isar3 }, - { .name =3D "ID_ISAR4", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 4, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa32_tid3, - .resetvalue =3D cpu->isar.id_isar4 }, - { .name =3D "ID_ISAR5", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 5, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa32_tid3, - .resetvalue =3D cpu->isar.id_isar5 }, - { .name =3D "ID_MMFR4", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 6, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa32_tid3, - .resetvalue =3D cpu->isar.id_mmfr4 }, - { .name =3D "ID_ISAR6", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 =3D = 7, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa32_tid3, - .resetvalue =3D cpu->isar.id_isar6 }, - }; - define_arm_cp_regs(cpu, v6_idregs); - define_arm_cp_regs(cpu, v6_cp_reginfo); - } else { - define_arm_cp_regs(cpu, not_v6_cp_reginfo); - } - if (arm_feature(env, ARM_FEATURE_V6K)) { - define_arm_cp_regs(cpu, v6k_cp_reginfo); - } - if (arm_feature(env, ARM_FEATURE_V7MP) && - !arm_feature(env, ARM_FEATURE_PMSA)) { - define_arm_cp_regs(cpu, v7mp_cp_reginfo); - } - if (arm_feature(env, ARM_FEATURE_V7VE)) { - define_arm_cp_regs(cpu, pmovsset_cp_reginfo); - } - if (arm_feature(env, ARM_FEATURE_V7)) { - ARMCPRegInfo clidr =3D { - .name =3D "CLIDR", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .crn =3D 0, .crm =3D 0, .opc1 =3D 1, .opc2 =3D 1, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_tid4, - .resetvalue =3D cpu->clidr - }; - define_one_arm_cp_reg(cpu, &clidr); - define_arm_cp_regs(cpu, v7_cp_reginfo); - define_debug_regs(cpu); - define_pmu_regs(cpu); - } else { - define_arm_cp_regs(cpu, not_v7_cp_reginfo); - } - if (arm_feature(env, ARM_FEATURE_V8)) { - /* - * v8 ID registers, which all have impdef reset values. - * Note that within the ID register ranges the unused slots - * must all RAZ, not UNDEF; future architecture versions may - * define new registers here. - * ID registers which are AArch64 views of the AArch32 ID registers - * which already existed in v6 and v7 are handled elsewhere, - * in v6_idregs[]. - */ - int i; - ARMCPRegInfo v8_idregs[] =3D { - /* - * ID_AA64PFR0_EL1 is not a plain ARM_CP_CONST in system - * emulation because we don't know the right value for the - * GIC field until after we define these regs. - */ - { .name =3D "ID_AA64PFR0_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 0, - .access =3D PL1_R, -#ifdef CONFIG_USER_ONLY - .type =3D ARM_CP_CONST, - .resetvalue =3D cpu->isar.id_aa64pfr0 -#else - .type =3D ARM_CP_NO_RAW, - .accessfn =3D access_aa64_tid3, - .readfn =3D id_aa64pfr0_read, - .writefn =3D arm_cp_write_ignore -#endif - }, - { .name =3D "ID_AA64PFR1_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 1, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.id_aa64pfr1}, - { .name =3D "ID_AA64PFR2_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 2, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64PFR3_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 3, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64ZFR0_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 4, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.id_aa64zfr0 }, - { .name =3D "ID_AA64SMFR0_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 5, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.id_aa64smfr0 }, - { .name =3D "ID_AA64PFR6_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 6, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64PFR7_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 4, .opc2 =3D = 7, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64DFR0_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 0, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.id_aa64dfr0 }, - { .name =3D "ID_AA64DFR1_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 1, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.id_aa64dfr1 }, - { .name =3D "ID_AA64DFR2_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 2, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64DFR3_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 3, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64AFR0_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 4, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->id_aa64afr0 }, - { .name =3D "ID_AA64AFR1_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 5, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->id_aa64afr1 }, - { .name =3D "ID_AA64AFR2_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 6, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64AFR3_EL1_RESERVED", .state =3D ARM_CP_STAT= E_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 5, .opc2 =3D = 7, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64ISAR0_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 0, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.id_aa64isar0 }, - { .name =3D "ID_AA64ISAR1_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 1, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.id_aa64isar1 }, - { .name =3D "ID_AA64ISAR2_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 2, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64ISAR3_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 3, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64ISAR4_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 4, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64ISAR5_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 5, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64ISAR6_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 6, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64ISAR7_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 6, .opc2 =3D = 7, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64MMFR0_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 0, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.id_aa64mmfr0 }, - { .name =3D "ID_AA64MMFR1_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 1, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.id_aa64mmfr1 }, - { .name =3D "ID_AA64MMFR2_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 2, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.id_aa64mmfr2 }, - { .name =3D "ID_AA64MMFR3_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 3, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64MMFR4_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 4, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64MMFR5_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 5, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64MMFR6_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 6, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_AA64MMFR7_EL1_RESERVED", .state =3D ARM_CP_STA= TE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D = 7, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "MVFR0_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 0, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.mvfr0 }, - { .name =3D "MVFR1_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 1, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.mvfr1 }, - { .name =3D "MVFR2_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 2, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.mvfr2 }, - /* - * "0, c0, c3, {0,1,2}" are the encodings corresponding to - * AArch64 MVFR[012]_EL1. Define the STATE_AA32 encoding - * as RAZ, since it is in the "reserved for future ID - * registers, RAZ" part of the AArch32 encoding space. - */ - { .name =3D "RES_0_C0_C3_0", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D 0, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "RES_0_C0_C3_1", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D 1, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "RES_0_C0_C3_2", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D 2, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - /* - * Other encodings in "0, c0, c3, ..." are STATE_BOTH because - * they're also RAZ for AArch64, and in v8 are gradually - * being filled with AArch64-view-of-AArch32-ID-register - * for new ID registers. - */ - { .name =3D "RES_0_C0_C3_3", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 3, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "ID_PFR2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 4, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.id_pfr2 }, - { .name =3D "ID_DFR1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 5, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.id_dfr1 }, - { .name =3D "ID_MMFR5", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 6, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D cpu->isar.id_mmfr5 }, - { .name =3D "RES_0_C0_C3_7", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 3, .opc2 =3D = 7, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }, - { .name =3D "PMCEID0", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 12, .opc2 =3D = 6, - .access =3D PL0_R, .accessfn =3D pmreg_access, .type =3D ARM= _CP_CONST, - .resetvalue =3D extract64(cpu->pmceid0, 0, 32) }, - { .name =3D "PMCEID0_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D= 6, - .access =3D PL0_R, .accessfn =3D pmreg_access, .type =3D ARM= _CP_CONST, - .resetvalue =3D cpu->pmceid0 }, - { .name =3D "PMCEID1", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 0, .crn =3D 9, .crm =3D 12, .opc2 =3D = 7, - .access =3D PL0_R, .accessfn =3D pmreg_access, .type =3D ARM= _CP_CONST, - .resetvalue =3D extract64(cpu->pmceid1, 0, 32) }, - { .name =3D "PMCEID1_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .crn =3D 9, .crm =3D 12, .opc2 =3D= 7, - .access =3D PL0_R, .accessfn =3D pmreg_access, .type =3D ARM= _CP_CONST, - .resetvalue =3D cpu->pmceid1 }, - }; -#ifdef CONFIG_USER_ONLY - static const ARMCPRegUserSpaceInfo v8_user_idregs[] =3D { - { .name =3D "ID_AA64PFR0_EL1", - .exported_bits =3D R_ID_AA64PFR0_FP_MASK | - R_ID_AA64PFR0_ADVSIMD_MASK | - R_ID_AA64PFR0_SVE_MASK | - R_ID_AA64PFR0_DIT_MASK, - .fixed_bits =3D (0x1u << R_ID_AA64PFR0_EL0_SHIFT) | - (0x1u << R_ID_AA64PFR0_EL1_SHIFT) }, - { .name =3D "ID_AA64PFR1_EL1", - .exported_bits =3D R_ID_AA64PFR1_BT_MASK | - R_ID_AA64PFR1_SSBS_MASK | - R_ID_AA64PFR1_MTE_MASK | - R_ID_AA64PFR1_SME_MASK }, - { .name =3D "ID_AA64PFR*_EL1_RESERVED", - .is_glob =3D true }, - { .name =3D "ID_AA64ZFR0_EL1", - .exported_bits =3D R_ID_AA64ZFR0_SVEVER_MASK | - R_ID_AA64ZFR0_AES_MASK | - R_ID_AA64ZFR0_BITPERM_MASK | - R_ID_AA64ZFR0_BFLOAT16_MASK | - R_ID_AA64ZFR0_SHA3_MASK | - R_ID_AA64ZFR0_SM4_MASK | - R_ID_AA64ZFR0_I8MM_MASK | - R_ID_AA64ZFR0_F32MM_MASK | - R_ID_AA64ZFR0_F64MM_MASK }, - { .name =3D "ID_AA64SMFR0_EL1", - .exported_bits =3D R_ID_AA64SMFR0_F32F32_MASK | - R_ID_AA64SMFR0_B16F32_MASK | - R_ID_AA64SMFR0_F16F32_MASK | - R_ID_AA64SMFR0_I8I32_MASK | - R_ID_AA64SMFR0_F64F64_MASK | - R_ID_AA64SMFR0_I16I64_MASK | - R_ID_AA64SMFR0_FA64_MASK }, - { .name =3D "ID_AA64MMFR0_EL1", - .exported_bits =3D R_ID_AA64MMFR0_ECV_MASK, - .fixed_bits =3D (0xfu << R_ID_AA64MMFR0_TGRAN64_SHIFT) | - (0xfu << R_ID_AA64MMFR0_TGRAN4_SHIFT) }, - { .name =3D "ID_AA64MMFR1_EL1", - .exported_bits =3D R_ID_AA64MMFR1_AFP_MASK }, - { .name =3D "ID_AA64MMFR2_EL1", - .exported_bits =3D R_ID_AA64MMFR2_AT_MASK }, - { .name =3D "ID_AA64MMFR*_EL1_RESERVED", - .is_glob =3D true }, - { .name =3D "ID_AA64DFR0_EL1", - .fixed_bits =3D (0x6u << R_ID_AA64DFR0_DEBUGVER_SHIFT) }, - { .name =3D "ID_AA64DFR1_EL1" }, - { .name =3D "ID_AA64DFR*_EL1_RESERVED", - .is_glob =3D true }, - { .name =3D "ID_AA64AFR*", - .is_glob =3D true }, - { .name =3D "ID_AA64ISAR0_EL1", - .exported_bits =3D R_ID_AA64ISAR0_AES_MASK | - R_ID_AA64ISAR0_SHA1_MASK | - R_ID_AA64ISAR0_SHA2_MASK | - R_ID_AA64ISAR0_CRC32_MASK | - R_ID_AA64ISAR0_ATOMIC_MASK | - R_ID_AA64ISAR0_RDM_MASK | - R_ID_AA64ISAR0_SHA3_MASK | - R_ID_AA64ISAR0_SM3_MASK | - R_ID_AA64ISAR0_SM4_MASK | - R_ID_AA64ISAR0_DP_MASK | - R_ID_AA64ISAR0_FHM_MASK | - R_ID_AA64ISAR0_TS_MASK | - R_ID_AA64ISAR0_RNDR_MASK }, - { .name =3D "ID_AA64ISAR1_EL1", - .exported_bits =3D R_ID_AA64ISAR1_DPB_MASK | - R_ID_AA64ISAR1_APA_MASK | - R_ID_AA64ISAR1_API_MASK | - R_ID_AA64ISAR1_JSCVT_MASK | - R_ID_AA64ISAR1_FCMA_MASK | - R_ID_AA64ISAR1_LRCPC_MASK | - R_ID_AA64ISAR1_GPA_MASK | - R_ID_AA64ISAR1_GPI_MASK | - R_ID_AA64ISAR1_FRINTTS_MASK | - R_ID_AA64ISAR1_SB_MASK | - R_ID_AA64ISAR1_BF16_MASK | - R_ID_AA64ISAR1_DGH_MASK | - R_ID_AA64ISAR1_I8MM_MASK }, - { .name =3D "ID_AA64ISAR2_EL1", - .exported_bits =3D R_ID_AA64ISAR2_WFXT_MASK | - R_ID_AA64ISAR2_RPRES_MASK | - R_ID_AA64ISAR2_GPA3_MASK | - R_ID_AA64ISAR2_APA3_MASK }, - { .name =3D "ID_AA64ISAR*_EL1_RESERVED", - .is_glob =3D true }, - }; - modify_arm_cp_regs(v8_idregs, v8_user_idregs); -#endif - /* RVBAR_EL1 is only implemented if EL1 is the highest EL */ - if (!arm_feature(env, ARM_FEATURE_EL3) && - !arm_feature(env, ARM_FEATURE_EL2)) { - ARMCPRegInfo rvbar =3D { - .name =3D "RVBAR_EL1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 12, .crm =3D 0, .opc2 = =3D 1, - .access =3D PL1_R, - .fieldoffset =3D offsetof(CPUARMState, cp15.rvbar), - }; - define_one_arm_cp_reg(cpu, &rvbar); - } - define_arm_cp_regs(cpu, v8_idregs); - define_arm_cp_regs(cpu, v8_cp_reginfo); - - for (i =3D 4; i < 16; i++) { - /* - * Encodings in "0, c0, {c4-c7}, {0-7}" are RAZ for AArch32. - * For pre-v8 cores there are RAZ patterns for these in - * id_pre_v8_midr_cp_reginfo[]; for v8 we do that here. - * v8 extends the "must RAZ" part of the ID register space - * to also cover c0, 0, c{8-15}, {0-7}. - * These are STATE_AA32 because in the AArch64 sysreg space - * c4-c7 is where the AArch64 ID registers live (and we've - * already defined those in v8_idregs[]), and c8-c15 are not - * "must RAZ" for AArch64. - */ - g_autofree char *name =3D g_strdup_printf("RES_0_C0_C%d_X", i); - ARMCPRegInfo v8_aa32_raz_idregs =3D { - .name =3D name, - .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 0, .crn =3D 0, .crm =3D i, .opc2 =3D= CP_ANY, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .accessfn =3D access_aa64_tid3, - .resetvalue =3D 0 }; - define_one_arm_cp_reg(cpu, &v8_aa32_raz_idregs); - } - } - - /* - * Register the base EL2 cpregs. - * Pre v8, these registers are implemented only as part of the - * Virtualization Extensions (EL2 present). Beginning with v8, - * if EL2 is missing but EL3 is enabled, mostly these become - * RES0 from EL3, with some specific exceptions. - */ - if (arm_feature(env, ARM_FEATURE_EL2) - || (arm_feature(env, ARM_FEATURE_EL3) - && arm_feature(env, ARM_FEATURE_V8))) { - uint64_t vmpidr_def =3D mpidr_read_val(env); - ARMCPRegInfo vpidr_regs[] =3D { - { .name =3D "VPIDR", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 4, .crn =3D 0, .crm =3D 0, .opc2 =3D 0, - .access =3D PL2_RW, .accessfn =3D access_el3_aa32ns, - .resetvalue =3D cpu->midr, - .type =3D ARM_CP_ALIAS | ARM_CP_EL3_NO_EL2_C_NZ, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.vpidr_el2) = }, - { .name =3D "VPIDR_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 0, .crm =3D 0, .opc2 =3D = 0, - .access =3D PL2_RW, .resetvalue =3D cpu->midr, - .type =3D ARM_CP_EL3_NO_EL2_C_NZ, - .fieldoffset =3D offsetof(CPUARMState, cp15.vpidr_el2) }, - { .name =3D "VMPIDR", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 4, .crn =3D 0, .crm =3D 0, .opc2 =3D 5, - .access =3D PL2_RW, .accessfn =3D access_el3_aa32ns, - .resetvalue =3D vmpidr_def, - .type =3D ARM_CP_ALIAS | ARM_CP_EL3_NO_EL2_C_NZ, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.vmpidr_el2)= }, - { .name =3D "VMPIDR_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 0, .crm =3D 0, .opc2 =3D = 5, - .access =3D PL2_RW, .resetvalue =3D vmpidr_def, - .type =3D ARM_CP_EL3_NO_EL2_C_NZ, - .fieldoffset =3D offsetof(CPUARMState, cp15.vmpidr_el2) }, - }; - /* - * The only field of MDCR_EL2 that has a defined architectural res= et - * value is MDCR_EL2.HPMN which should reset to the value of PMCR_= EL0.N. - */ - ARMCPRegInfo mdcr_el2 =3D { - .name =3D "MDCR_EL2", .state =3D ARM_CP_STATE_BOTH, .type =3D = ARM_CP_IO, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 1, .opc2 =3D 1, - .writefn =3D mdcr_el2_write, - .access =3D PL2_RW, .resetvalue =3D pmu_num_counters(env), - .fieldoffset =3D offsetof(CPUARMState, cp15.mdcr_el2), - }; - define_one_arm_cp_reg(cpu, &mdcr_el2); - define_arm_cp_regs(cpu, vpidr_regs); - define_arm_cp_regs(cpu, el2_cp_reginfo); - if (arm_feature(env, ARM_FEATURE_V8)) { - define_arm_cp_regs(cpu, el2_v8_cp_reginfo); - } - if (cpu_isar_feature(aa64_sel2, cpu)) { - define_arm_cp_regs(cpu, el2_sec_cp_reginfo); - } - /* RVBAR_EL2 is only implemented if EL2 is the highest EL */ - if (!arm_feature(env, ARM_FEATURE_EL3)) { - ARMCPRegInfo rvbar[] =3D { - { - .name =3D "RVBAR_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 12, .crm =3D 0, .op= c2 =3D 1, - .access =3D PL2_R, - .fieldoffset =3D offsetof(CPUARMState, cp15.rvbar), - }, - { .name =3D "RVBAR", .type =3D ARM_CP_ALIAS, - .cp =3D 15, .opc1 =3D 0, .crn =3D 12, .crm =3D 0, .opc= 2 =3D 1, - .access =3D PL2_R, - .fieldoffset =3D offsetof(CPUARMState, cp15.rvbar), - }, - }; - define_arm_cp_regs(cpu, rvbar); - } - } - - /* Register the base EL3 cpregs. */ - if (arm_feature(env, ARM_FEATURE_EL3)) { - define_arm_cp_regs(cpu, el3_cp_reginfo); - ARMCPRegInfo el3_regs[] =3D { - { .name =3D "RVBAR_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 12, .crm =3D 0, .opc2 =3D= 1, - .access =3D PL3_R, - .fieldoffset =3D offsetof(CPUARMState, cp15.rvbar), - }, - { .name =3D "SCTLR_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 0, .opc2 =3D = 0, - .access =3D PL3_RW, - .raw_writefn =3D raw_write, .writefn =3D sctlr_write, - .fieldoffset =3D offsetof(CPUARMState, cp15.sctlr_el[3]), - .resetvalue =3D cpu->reset_sctlr }, - }; - - define_arm_cp_regs(cpu, el3_regs); - } - /* - * The behaviour of NSACR is sufficiently various that we don't - * try to describe it in a single reginfo: - * if EL3 is 64 bit, then trap to EL3 from S EL1, - * reads as constant 0xc00 from NS EL1 and NS EL2 - * if EL3 is 32 bit, then RW at EL3, RO at NS EL1 and NS EL2 - * if v7 without EL3, register doesn't exist - * if v8 without EL3, reads as constant 0xc00 from NS EL1 and NS EL2 - */ - if (arm_feature(env, ARM_FEATURE_EL3)) { - if (arm_feature(env, ARM_FEATURE_AARCH64)) { - static const ARMCPRegInfo nsacr =3D { - .name =3D "NSACR", .type =3D ARM_CP_CONST, - .cp =3D 15, .opc1 =3D 0, .crn =3D 1, .crm =3D 1, .opc2 =3D= 2, - .access =3D PL1_RW, .accessfn =3D nsacr_access, - .resetvalue =3D 0xc00 - }; - define_one_arm_cp_reg(cpu, &nsacr); - } else { - static const ARMCPRegInfo nsacr =3D { - .name =3D "NSACR", - .cp =3D 15, .opc1 =3D 0, .crn =3D 1, .crm =3D 1, .opc2 =3D= 2, - .access =3D PL3_RW | PL1_R, - .resetvalue =3D 0, - .fieldoffset =3D offsetof(CPUARMState, cp15.nsacr) - }; - define_one_arm_cp_reg(cpu, &nsacr); - } - } else { - if (arm_feature(env, ARM_FEATURE_V8)) { - static const ARMCPRegInfo nsacr =3D { - .name =3D "NSACR", .type =3D ARM_CP_CONST, - .cp =3D 15, .opc1 =3D 0, .crn =3D 1, .crm =3D 1, .opc2 =3D= 2, - .access =3D PL1_R, - .resetvalue =3D 0xc00 - }; - define_one_arm_cp_reg(cpu, &nsacr); - } - } - - if (arm_feature(env, ARM_FEATURE_PMSA)) { - if (arm_feature(env, ARM_FEATURE_V6)) { - /* PMSAv6 not implemented */ - assert(arm_feature(env, ARM_FEATURE_V7)); - define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo); - define_arm_cp_regs(cpu, pmsav7_cp_reginfo); - } else { - define_arm_cp_regs(cpu, pmsav5_cp_reginfo); - } - } else { - define_arm_cp_regs(cpu, vmsa_pmsa_cp_reginfo); - define_arm_cp_regs(cpu, vmsa_cp_reginfo); - /* TTCBR2 is introduced with ARMv8.2-AA32HPD. */ - if (cpu_isar_feature(aa32_hpd, cpu)) { - define_one_arm_cp_reg(cpu, &ttbcr2_reginfo); - } - } - if (arm_feature(env, ARM_FEATURE_THUMB2EE)) { - define_arm_cp_regs(cpu, t2ee_cp_reginfo); - } - if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) { - define_arm_cp_regs(cpu, generic_timer_cp_reginfo); - } - if (arm_feature(env, ARM_FEATURE_VAPA)) { - define_arm_cp_regs(cpu, vapa_cp_reginfo); - } - if (arm_feature(env, ARM_FEATURE_CACHE_TEST_CLEAN)) { - define_arm_cp_regs(cpu, cache_test_clean_cp_reginfo); - } - if (arm_feature(env, ARM_FEATURE_CACHE_DIRTY_REG)) { - define_arm_cp_regs(cpu, cache_dirty_status_cp_reginfo); - } - if (arm_feature(env, ARM_FEATURE_CACHE_BLOCK_OPS)) { - define_arm_cp_regs(cpu, cache_block_ops_cp_reginfo); - } - if (arm_feature(env, ARM_FEATURE_OMAPCP)) { - define_arm_cp_regs(cpu, omap_cp_reginfo); - } - if (arm_feature(env, ARM_FEATURE_STRONGARM)) { - define_arm_cp_regs(cpu, strongarm_cp_reginfo); - } - if (arm_feature(env, ARM_FEATURE_XSCALE)) { - define_arm_cp_regs(cpu, xscale_cp_reginfo); - } - if (arm_feature(env, ARM_FEATURE_DUMMY_C15_REGS)) { - define_arm_cp_regs(cpu, dummy_c15_cp_reginfo); - } - if (arm_feature(env, ARM_FEATURE_LPAE)) { - define_arm_cp_regs(cpu, lpae_cp_reginfo); - } - if (cpu_isar_feature(aa32_jazelle, cpu)) { - define_arm_cp_regs(cpu, jazelle_regs); - } - /* - * Slightly awkwardly, the OMAP and StrongARM cores need all of - * cp15 crn=3D0 to be writes-ignored, whereas for other cores they sho= uld - * be read-only (ie write causes UNDEF exception). - */ - { - ARMCPRegInfo id_pre_v8_midr_cp_reginfo[] =3D { - /* - * Pre-v8 MIDR space. - * Note that the MIDR isn't a simple constant register because - * of the TI925 behaviour where writes to another register can - * cause the MIDR value to change. - * - * Unimplemented registers in the c15 0 0 0 space default to - * MIDR. Define MIDR first as this entire space, then CTR, TCM= TR - * and friends override accordingly. - */ - { .name =3D "MIDR", - .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D C= P_ANY, - .access =3D PL1_R, .resetvalue =3D cpu->midr, - .writefn =3D arm_cp_write_ignore, .raw_writefn =3D raw_write, - .readfn =3D midr_read, - .fieldoffset =3D offsetof(CPUARMState, cp15.c0_cpuid), - .type =3D ARM_CP_OVERRIDE }, - /* crn =3D 0 op1 =3D 0 crm =3D 3..7 : currently unassigned; we= RAZ. */ - { .name =3D "DUMMY", - .cp =3D 15, .crn =3D 0, .crm =3D 3, .opc1 =3D 0, .opc2 =3D C= P_ANY, - .access =3D PL1_R, .type =3D ARM_CP_CONST, .resetvalue =3D 0= }, - { .name =3D "DUMMY", - .cp =3D 15, .crn =3D 0, .crm =3D 4, .opc1 =3D 0, .opc2 =3D C= P_ANY, - .access =3D PL1_R, .type =3D ARM_CP_CONST, .resetvalue =3D 0= }, - { .name =3D "DUMMY", - .cp =3D 15, .crn =3D 0, .crm =3D 5, .opc1 =3D 0, .opc2 =3D C= P_ANY, - .access =3D PL1_R, .type =3D ARM_CP_CONST, .resetvalue =3D 0= }, - { .name =3D "DUMMY", - .cp =3D 15, .crn =3D 0, .crm =3D 6, .opc1 =3D 0, .opc2 =3D C= P_ANY, - .access =3D PL1_R, .type =3D ARM_CP_CONST, .resetvalue =3D 0= }, - { .name =3D "DUMMY", - .cp =3D 15, .crn =3D 0, .crm =3D 7, .opc1 =3D 0, .opc2 =3D C= P_ANY, - .access =3D PL1_R, .type =3D ARM_CP_CONST, .resetvalue =3D 0= }, - }; - ARMCPRegInfo id_v8_midr_cp_reginfo[] =3D { - { .name =3D "MIDR_EL1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 0, .opc2 =3D = 0, - .access =3D PL1_R, .type =3D ARM_CP_NO_RAW, .resetvalue =3D = cpu->midr, - .fieldoffset =3D offsetof(CPUARMState, cp15.c0_cpuid), - .readfn =3D midr_read }, - /* crn =3D 0 op1 =3D 0 crm =3D 0 op2 =3D 7 : AArch32 aliases o= f MIDR */ - { .name =3D "MIDR", .type =3D ARM_CP_ALIAS | ARM_CP_CONST, - .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 7, - .access =3D PL1_R, .resetvalue =3D cpu->midr }, - { .name =3D "REVIDR_EL1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 0, .crm =3D 0, .opc2 =3D = 6, - .access =3D PL1_R, - .accessfn =3D access_aa64_tid1, - .type =3D ARM_CP_CONST, .resetvalue =3D cpu->revidr }, - }; - ARMCPRegInfo id_v8_midr_alias_cp_reginfo =3D { - .name =3D "MIDR", .type =3D ARM_CP_ALIAS | ARM_CP_CONST, - .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 4, - .access =3D PL1_R, .resetvalue =3D cpu->midr - }; - ARMCPRegInfo id_cp_reginfo[] =3D { - /* These are common to v8 and pre-v8 */ - { .name =3D "CTR", - .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 1, - .access =3D PL1_R, .accessfn =3D ctr_el0_access, - .type =3D ARM_CP_CONST, .resetvalue =3D cpu->ctr }, - { .name =3D "CTR_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 3, .opc2 =3D 1, .crn =3D 0, .crm =3D = 0, - .access =3D PL0_R, .accessfn =3D ctr_el0_access, - .type =3D ARM_CP_CONST, .resetvalue =3D cpu->ctr }, - /* TCMTR and TLBTR exist in v8 but have no 64-bit versions */ - { .name =3D "TCMTR", - .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 2, - .access =3D PL1_R, - .accessfn =3D access_aa32_tid1, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - }; - /* TLBTR is specific to VMSA */ - ARMCPRegInfo id_tlbtr_reginfo =3D { - .name =3D "TLBTR", - .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 3, - .access =3D PL1_R, - .accessfn =3D access_aa32_tid1, - .type =3D ARM_CP_CONST, .resetvalue =3D 0, - }; - /* MPUIR is specific to PMSA V6+ */ - ARMCPRegInfo id_mpuir_reginfo =3D { - .name =3D "MPUIR", - .cp =3D 15, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D 4, - .access =3D PL1_R, .type =3D ARM_CP_CONST, - .resetvalue =3D cpu->pmsav7_dregion << 8 - }; - /* HMPUIR is specific to PMSA V8 */ - ARMCPRegInfo id_hmpuir_reginfo =3D { - .name =3D "HMPUIR", - .cp =3D 15, .opc1 =3D 4, .crn =3D 0, .crm =3D 0, .opc2 =3D 4, - .access =3D PL2_R, .type =3D ARM_CP_CONST, - .resetvalue =3D cpu->pmsav8r_hdregion - }; - static const ARMCPRegInfo crn0_wi_reginfo =3D { - .name =3D "CRN0_WI", .cp =3D 15, .crn =3D 0, .crm =3D CP_ANY, - .opc1 =3D CP_ANY, .opc2 =3D CP_ANY, .access =3D PL1_W, - .type =3D ARM_CP_NOP | ARM_CP_OVERRIDE - }; -#ifdef CONFIG_USER_ONLY - static const ARMCPRegUserSpaceInfo id_v8_user_midr_cp_reginfo[] = =3D { - { .name =3D "MIDR_EL1", - .exported_bits =3D R_MIDR_EL1_REVISION_MASK | - R_MIDR_EL1_PARTNUM_MASK | - R_MIDR_EL1_ARCHITECTURE_MASK | - R_MIDR_EL1_VARIANT_MASK | - R_MIDR_EL1_IMPLEMENTER_MASK }, - { .name =3D "REVIDR_EL1" }, - }; - modify_arm_cp_regs(id_v8_midr_cp_reginfo, id_v8_user_midr_cp_regin= fo); -#endif - if (arm_feature(env, ARM_FEATURE_OMAPCP) || - arm_feature(env, ARM_FEATURE_STRONGARM)) { - size_t i; - /* - * Register the blanket "writes ignored" value first to cover = the - * whole space. Then update the specific ID registers to allow= write - * access, so that they ignore writes rather than causing them= to - * UNDEF. - */ - define_one_arm_cp_reg(cpu, &crn0_wi_reginfo); - for (i =3D 0; i < ARRAY_SIZE(id_pre_v8_midr_cp_reginfo); ++i) { - id_pre_v8_midr_cp_reginfo[i].access =3D PL1_RW; - } - for (i =3D 0; i < ARRAY_SIZE(id_cp_reginfo); ++i) { - id_cp_reginfo[i].access =3D PL1_RW; - } - id_mpuir_reginfo.access =3D PL1_RW; - id_tlbtr_reginfo.access =3D PL1_RW; - } - if (arm_feature(env, ARM_FEATURE_V8)) { - define_arm_cp_regs(cpu, id_v8_midr_cp_reginfo); - if (!arm_feature(env, ARM_FEATURE_PMSA)) { - define_one_arm_cp_reg(cpu, &id_v8_midr_alias_cp_reginfo); - } - } else { - define_arm_cp_regs(cpu, id_pre_v8_midr_cp_reginfo); - } - define_arm_cp_regs(cpu, id_cp_reginfo); - if (!arm_feature(env, ARM_FEATURE_PMSA)) { - define_one_arm_cp_reg(cpu, &id_tlbtr_reginfo); - } else if (arm_feature(env, ARM_FEATURE_PMSA) && - arm_feature(env, ARM_FEATURE_V8)) { - uint32_t i =3D 0; - char *tmp_string; - - define_one_arm_cp_reg(cpu, &id_mpuir_reginfo); - define_one_arm_cp_reg(cpu, &id_hmpuir_reginfo); - define_arm_cp_regs(cpu, pmsav8r_cp_reginfo); - - /* Register alias is only valid for first 32 indexes */ - for (i =3D 0; i < MIN(cpu->pmsav7_dregion, 32); ++i) { - uint8_t crm =3D 0b1000 | extract32(i, 1, 3); - uint8_t opc1 =3D extract32(i, 4, 1); - uint8_t opc2 =3D extract32(i, 0, 1) << 2; - - tmp_string =3D g_strdup_printf("PRBAR%u", i); - ARMCPRegInfo tmp_prbarn_reginfo =3D { - .name =3D tmp_string, .type =3D ARM_CP_ALIAS | ARM_CP_= NO_RAW, - .cp =3D 15, .opc1 =3D opc1, .crn =3D 6, .crm =3D crm, = .opc2 =3D opc2, - .access =3D PL1_RW, .resetvalue =3D 0, - .accessfn =3D access_tvm_trvm, - .writefn =3D pmsav8r_regn_write, .readfn =3D pmsav8r_r= egn_read - }; - define_one_arm_cp_reg(cpu, &tmp_prbarn_reginfo); - g_free(tmp_string); - - opc2 =3D extract32(i, 0, 1) << 2 | 0x1; - tmp_string =3D g_strdup_printf("PRLAR%u", i); - ARMCPRegInfo tmp_prlarn_reginfo =3D { - .name =3D tmp_string, .type =3D ARM_CP_ALIAS | ARM_CP_= NO_RAW, - .cp =3D 15, .opc1 =3D opc1, .crn =3D 6, .crm =3D crm, = .opc2 =3D opc2, - .access =3D PL1_RW, .resetvalue =3D 0, - .accessfn =3D access_tvm_trvm, - .writefn =3D pmsav8r_regn_write, .readfn =3D pmsav8r_r= egn_read - }; - define_one_arm_cp_reg(cpu, &tmp_prlarn_reginfo); - g_free(tmp_string); - } - - /* Register alias is only valid for first 32 indexes */ - for (i =3D 0; i < MIN(cpu->pmsav8r_hdregion, 32); ++i) { - uint8_t crm =3D 0b1000 | extract32(i, 1, 3); - uint8_t opc1 =3D 0b100 | extract32(i, 4, 1); - uint8_t opc2 =3D extract32(i, 0, 1) << 2; - - tmp_string =3D g_strdup_printf("HPRBAR%u", i); - ARMCPRegInfo tmp_hprbarn_reginfo =3D { - .name =3D tmp_string, - .type =3D ARM_CP_NO_RAW, - .cp =3D 15, .opc1 =3D opc1, .crn =3D 6, .crm =3D crm, = .opc2 =3D opc2, - .access =3D PL2_RW, .resetvalue =3D 0, - .writefn =3D pmsav8r_regn_write, .readfn =3D pmsav8r_r= egn_read - }; - define_one_arm_cp_reg(cpu, &tmp_hprbarn_reginfo); - g_free(tmp_string); - - opc2 =3D extract32(i, 0, 1) << 2 | 0x1; - tmp_string =3D g_strdup_printf("HPRLAR%u", i); - ARMCPRegInfo tmp_hprlarn_reginfo =3D { - .name =3D tmp_string, - .type =3D ARM_CP_NO_RAW, - .cp =3D 15, .opc1 =3D opc1, .crn =3D 6, .crm =3D crm, = .opc2 =3D opc2, - .access =3D PL2_RW, .resetvalue =3D 0, - .writefn =3D pmsav8r_regn_write, .readfn =3D pmsav8r_r= egn_read - }; - define_one_arm_cp_reg(cpu, &tmp_hprlarn_reginfo); - g_free(tmp_string); - } - } else if (arm_feature(env, ARM_FEATURE_V7)) { - define_one_arm_cp_reg(cpu, &id_mpuir_reginfo); - } - } - - if (arm_feature(env, ARM_FEATURE_MPIDR)) { - ARMCPRegInfo mpidr_cp_reginfo[] =3D { - { .name =3D "MPIDR_EL1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .crn =3D 0, .crm =3D 0, .opc1 =3D 0, .opc2 =3D = 5, - .access =3D PL1_R, .readfn =3D mpidr_read, .type =3D ARM_CP_= NO_RAW }, - }; -#ifdef CONFIG_USER_ONLY - static const ARMCPRegUserSpaceInfo mpidr_user_cp_reginfo[] =3D { - { .name =3D "MPIDR_EL1", - .fixed_bits =3D 0x0000000080000000 }, - }; - modify_arm_cp_regs(mpidr_cp_reginfo, mpidr_user_cp_reginfo); -#endif - define_arm_cp_regs(cpu, mpidr_cp_reginfo); - } - - if (arm_feature(env, ARM_FEATURE_AUXCR)) { - ARMCPRegInfo auxcr_reginfo[] =3D { - { .name =3D "ACTLR_EL1", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 1, .crm =3D 0, .opc2 =3D = 1, - .access =3D PL1_RW, .accessfn =3D access_tacr, - .type =3D ARM_CP_CONST, .resetvalue =3D cpu->reset_auxcr }, - { .name =3D "ACTLR_EL2", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 4, .crn =3D 1, .crm =3D 0, .opc2 =3D = 1, - .access =3D PL2_RW, .type =3D ARM_CP_CONST, - .resetvalue =3D 0 }, - { .name =3D "ACTLR_EL3", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 3, .opc1 =3D 6, .crn =3D 1, .crm =3D 0, .opc2 =3D = 1, - .access =3D PL3_RW, .type =3D ARM_CP_CONST, - .resetvalue =3D 0 }, - }; - define_arm_cp_regs(cpu, auxcr_reginfo); - if (cpu_isar_feature(aa32_ac2, cpu)) { - define_arm_cp_regs(cpu, actlr2_hactlr2_reginfo); - } - } - - if (arm_feature(env, ARM_FEATURE_CBAR)) { - /* - * CBAR is IMPDEF, but common on Arm Cortex-A implementations. - * There are two flavours: - * (1) older 32-bit only cores have a simple 32-bit CBAR - * (2) 64-bit cores have a 64-bit CBAR visible to AArch64, plus a - * 32-bit register visible to AArch32 at a different encoding - * to the "flavour 1" register and with the bits rearranged to - * be able to squash a 64-bit address into the 32-bit view. - * We distinguish the two via the ARM_FEATURE_AARCH64 flag, but - * in future if we support AArch32-only configs of some of the - * AArch64 cores we might need to add a specific feature flag - * to indicate cores with "flavour 2" CBAR. - */ - if (arm_feature(env, ARM_FEATURE_AARCH64)) { - /* 32 bit view is [31:18] 0...0 [43:32]. */ - uint32_t cbar32 =3D (extract64(cpu->reset_cbar, 18, 14) << 18) - | extract64(cpu->reset_cbar, 32, 12); - ARMCPRegInfo cbar_reginfo[] =3D { - { .name =3D "CBAR", - .type =3D ARM_CP_CONST, - .cp =3D 15, .crn =3D 15, .crm =3D 3, .opc1 =3D 1, .opc2 = =3D 0, - .access =3D PL1_R, .resetvalue =3D cbar32 }, - { .name =3D "CBAR_EL1", .state =3D ARM_CP_STATE_AA64, - .type =3D ARM_CP_CONST, - .opc0 =3D 3, .opc1 =3D 1, .crn =3D 15, .crm =3D 3, .opc2= =3D 0, - .access =3D PL1_R, .resetvalue =3D cpu->reset_cbar }, - }; - /* We don't implement a r/w 64 bit CBAR currently */ - assert(arm_feature(env, ARM_FEATURE_CBAR_RO)); - define_arm_cp_regs(cpu, cbar_reginfo); - } else { - ARMCPRegInfo cbar =3D { - .name =3D "CBAR", - .cp =3D 15, .crn =3D 15, .crm =3D 0, .opc1 =3D 4, .opc2 = =3D 0, - .access =3D PL1_R | PL3_W, .resetvalue =3D cpu->reset_cbar, - .fieldoffset =3D offsetof(CPUARMState, - cp15.c15_config_base_address) - }; - if (arm_feature(env, ARM_FEATURE_CBAR_RO)) { - cbar.access =3D PL1_R; - cbar.fieldoffset =3D 0; - cbar.type =3D ARM_CP_CONST; - } - define_one_arm_cp_reg(cpu, &cbar); - } - } - - if (arm_feature(env, ARM_FEATURE_VBAR)) { - static const ARMCPRegInfo vbar_cp_reginfo[] =3D { - { .name =3D "VBAR", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .crn =3D 12, .crm =3D 0, .opc1 =3D 0, .opc2 =3D= 0, - .access =3D PL1_RW, .writefn =3D vbar_write, - .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.vbar_s), - offsetof(CPUARMState, cp15.vbar_ns) }, - .resetvalue =3D 0 }, - }; - define_arm_cp_regs(cpu, vbar_cp_reginfo); - } - - /* Generic registers whose values depend on the implementation */ - { - ARMCPRegInfo sctlr =3D { - .name =3D "SCTLR", .state =3D ARM_CP_STATE_BOTH, - .opc0 =3D 3, .opc1 =3D 0, .crn =3D 1, .crm =3D 0, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_tvm_trvm, - .bank_fieldoffsets =3D { offsetof(CPUARMState, cp15.sctlr_s), - offsetof(CPUARMState, cp15.sctlr_ns) }, - .writefn =3D sctlr_write, .resetvalue =3D cpu->reset_sctlr, - .raw_writefn =3D raw_write, - }; - if (arm_feature(env, ARM_FEATURE_XSCALE)) { - /* - * Normally we would always end the TB on an SCTLR write, but = Linux - * arch/arm/mach-pxa/sleep.S expects two instructions following - * an MMU enable to execute from cache. Imitate this behaviou= r. - */ - sctlr.type |=3D ARM_CP_SUPPRESS_TB_END; - } - define_one_arm_cp_reg(cpu, &sctlr); - - if (arm_feature(env, ARM_FEATURE_PMSA) && - arm_feature(env, ARM_FEATURE_V8)) { - ARMCPRegInfo vsctlr =3D { - .name =3D "VSCTLR", .state =3D ARM_CP_STATE_AA32, - .cp =3D 15, .opc1 =3D 4, .crn =3D 2, .crm =3D 0, .opc2 =3D= 0, - .access =3D PL2_RW, .resetvalue =3D 0x0, - .fieldoffset =3D offsetoflow32(CPUARMState, cp15.vsctlr), - }; - define_one_arm_cp_reg(cpu, &vsctlr); - } - } - - if (cpu_isar_feature(aa64_lor, cpu)) { - define_arm_cp_regs(cpu, lor_reginfo); - } - if (cpu_isar_feature(aa64_pan, cpu)) { - define_one_arm_cp_reg(cpu, &pan_reginfo); - } -#ifndef CONFIG_USER_ONLY - if (cpu_isar_feature(aa64_ats1e1, cpu)) { - define_arm_cp_regs(cpu, ats1e1_reginfo); - } - if (cpu_isar_feature(aa32_ats1e1, cpu)) { - define_arm_cp_regs(cpu, ats1cp_reginfo); - } -#endif - if (cpu_isar_feature(aa64_uao, cpu)) { - define_one_arm_cp_reg(cpu, &uao_reginfo); - } - - if (cpu_isar_feature(aa64_dit, cpu)) { - define_one_arm_cp_reg(cpu, &dit_reginfo); - } - if (cpu_isar_feature(aa64_ssbs, cpu)) { - define_one_arm_cp_reg(cpu, &ssbs_reginfo); - } - if (cpu_isar_feature(any_ras, cpu)) { - define_arm_cp_regs(cpu, minimal_ras_reginfo); - } - - if (cpu_isar_feature(aa64_vh, cpu) || - cpu_isar_feature(aa64_debugv8p2, cpu)) { - define_one_arm_cp_reg(cpu, &contextidr_el2); - } - if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu= )) { - define_arm_cp_regs(cpu, vhe_reginfo); - } - - if (cpu_isar_feature(aa64_sve, cpu)) { - define_arm_cp_regs(cpu, zcr_reginfo); - } - - if (cpu_isar_feature(aa64_hcx, cpu)) { - define_one_arm_cp_reg(cpu, &hcrx_el2_reginfo); - } - -#ifdef TARGET_AARCH64 - if (cpu_isar_feature(aa64_sme, cpu)) { - define_arm_cp_regs(cpu, sme_reginfo); - } - if (cpu_isar_feature(aa64_pauth, cpu)) { - define_arm_cp_regs(cpu, pauth_reginfo); - } - if (cpu_isar_feature(aa64_rndr, cpu)) { - define_arm_cp_regs(cpu, rndr_reginfo); - } - if (cpu_isar_feature(aa64_tlbirange, cpu)) { - define_arm_cp_regs(cpu, tlbirange_reginfo); - } - if (cpu_isar_feature(aa64_tlbios, cpu)) { - define_arm_cp_regs(cpu, tlbios_reginfo); - } -#ifndef CONFIG_USER_ONLY - /* Data Cache clean instructions up to PoP */ - if (cpu_isar_feature(aa64_dcpop, cpu)) { - define_one_arm_cp_reg(cpu, dcpop_reg); - - if (cpu_isar_feature(aa64_dcpodp, cpu)) { - define_one_arm_cp_reg(cpu, dcpodp_reg); - } - } -#endif /*CONFIG_USER_ONLY*/ - - /* - * If full MTE is enabled, add all of the system registers. - * If only "instructions available at EL0" are enabled, - * then define only a RAZ/WI version of PSTATE.TCO. - */ - if (cpu_isar_feature(aa64_mte, cpu)) { - define_arm_cp_regs(cpu, mte_reginfo); - define_arm_cp_regs(cpu, mte_el0_cacheop_reginfo); - } else if (cpu_isar_feature(aa64_mte_insn_reg, cpu)) { - define_arm_cp_regs(cpu, mte_tco_ro_reginfo); - define_arm_cp_regs(cpu, mte_el0_cacheop_reginfo); - } - - if (cpu_isar_feature(aa64_scxtnum, cpu)) { - define_arm_cp_regs(cpu, scxtnum_reginfo); - } -#endif - - if (cpu_isar_feature(any_predinv, cpu)) { - define_arm_cp_regs(cpu, predinv_reginfo); - } - - if (cpu_isar_feature(any_ccidx, cpu)) { - define_arm_cp_regs(cpu, ccsidr2_reginfo); - } - -#ifndef CONFIG_USER_ONLY - /* - * Register redirections and aliases must be done last, - * after the registers from the other extensions have been defined. - */ - if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu= )) { - define_arm_vh_e2h_redirects_aliases(cpu); - } -#endif -} - /* Sort alphabetically by type name, except for "any". */ static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b) { @@ -8991,461 +379,6 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Err= or **errp) return cpu_list; } =20 -/* - * Private utility function for define_one_arm_cp_reg_with_opaque(): - * add a single reginfo struct to the hash table. - */ -static void add_cpreg_to_hashtable(ARMCPU *cpu, const ARMCPRegInfo *r, - void *opaque, CPState state, - CPSecureState secstate, - int crm, int opc1, int opc2, - const char *name) -{ - CPUARMState *env =3D &cpu->env; - uint32_t key; - ARMCPRegInfo *r2; - bool is64 =3D r->type & ARM_CP_64BIT; - bool ns =3D secstate & ARM_CP_SECSTATE_NS; - int cp =3D r->cp; - size_t name_len; - bool make_const; - - switch (state) { - case ARM_CP_STATE_AA32: - /* We assume it is a cp15 register if the .cp field is left unset.= */ - if (cp =3D=3D 0 && r->state =3D=3D ARM_CP_STATE_BOTH) { - cp =3D 15; - } - key =3D ENCODE_CP_REG(cp, is64, ns, r->crn, crm, opc1, opc2); - break; - case ARM_CP_STATE_AA64: - /* - * To allow abbreviation of ARMCPRegInfo definitions, we treat - * cp =3D=3D 0 as equivalent to the value for "standard guest-visi= ble - * sysreg". STATE_BOTH definitions are also always "standard sysr= eg" - * in their AArch64 view (the .cp value may be non-zero for the - * benefit of the AArch32 view). - */ - if (cp =3D=3D 0 || r->state =3D=3D ARM_CP_STATE_BOTH) { - cp =3D CP_REG_ARM64_SYSREG_CP; - } - key =3D ENCODE_AA64_CP_REG(cp, r->crn, crm, r->opc0, opc1, opc2); - break; - default: - g_assert_not_reached(); - } - - /* Overriding of an existing definition must be explicitly requested. = */ - if (!(r->type & ARM_CP_OVERRIDE)) { - const ARMCPRegInfo *oldreg =3D get_arm_cp_reginfo(cpu->cp_regs, ke= y); - if (oldreg) { - assert(oldreg->type & ARM_CP_OVERRIDE); - } - } - - /* - * Eliminate registers that are not present because the EL is missing. - * Doing this here makes it easier to put all registers for a given - * feature into the same ARMCPRegInfo array and define them all at onc= e. - */ - make_const =3D false; - if (arm_feature(env, ARM_FEATURE_EL3)) { - /* - * An EL2 register without EL2 but with EL3 is (usually) RES0. - * See rule RJFFP in section D1.1.3 of DDI0487H.a. - */ - int min_el =3D ctz32(r->access) / 2; - if (min_el =3D=3D 2 && !arm_feature(env, ARM_FEATURE_EL2)) { - if (r->type & ARM_CP_EL3_NO_EL2_UNDEF) { - return; - } - make_const =3D !(r->type & ARM_CP_EL3_NO_EL2_KEEP); - } - } else { - CPAccessRights max_el =3D (arm_feature(env, ARM_FEATURE_EL2) - ? PL2_RW : PL1_RW); - if ((r->access & max_el) =3D=3D 0) { - return; - } - } - - /* Combine cpreg and name into one allocation. */ - name_len =3D strlen(name) + 1; - r2 =3D g_malloc(sizeof(*r2) + name_len); - *r2 =3D *r; - r2->name =3D memcpy(r2 + 1, name, name_len); - - /* - * Update fields to match the instantiation, overwiting wildcards - * such as CP_ANY, ARM_CP_STATE_BOTH, or ARM_CP_SECSTATE_BOTH. - */ - r2->cp =3D cp; - r2->crm =3D crm; - r2->opc1 =3D opc1; - r2->opc2 =3D opc2; - r2->state =3D state; - r2->secure =3D secstate; - if (opaque) { - r2->opaque =3D opaque; - } - - if (make_const) { - /* This should not have been a very special register to begin. */ - int old_special =3D r2->type & ARM_CP_SPECIAL_MASK; - assert(old_special =3D=3D 0 || old_special =3D=3D ARM_CP_NOP); - /* - * Set the special function to CONST, retaining the other flags. - * This is important for e.g. ARM_CP_SVE so that we still - * take the SVE trap if CPTR_EL3.EZ =3D=3D 0. - */ - r2->type =3D (r2->type & ~ARM_CP_SPECIAL_MASK) | ARM_CP_CONST; - /* - * Usually, these registers become RES0, but there are a few - * special cases like VPIDR_EL2 which have a constant non-zero - * value with writes ignored. - */ - if (!(r->type & ARM_CP_EL3_NO_EL2_C_NZ)) { - r2->resetvalue =3D 0; - } - /* - * ARM_CP_CONST has precedence, so removing the callbacks and - * offsets are not strictly necessary, but it is potentially - * less confusing to debug later. - */ - r2->readfn =3D NULL; - r2->writefn =3D NULL; - r2->raw_readfn =3D NULL; - r2->raw_writefn =3D NULL; - r2->resetfn =3D NULL; - r2->fieldoffset =3D 0; - r2->bank_fieldoffsets[0] =3D 0; - r2->bank_fieldoffsets[1] =3D 0; - } else { - bool isbanked =3D r->bank_fieldoffsets[0] && r->bank_fieldoffsets[= 1]; - - if (isbanked) { - /* - * Register is banked (using both entries in array). - * Overwriting fieldoffset as the array is only used to define - * banked registers but later only fieldoffset is used. - */ - r2->fieldoffset =3D r->bank_fieldoffsets[ns]; - } - if (state =3D=3D ARM_CP_STATE_AA32) { - if (isbanked) { - /* - * If the register is banked then we don't need to migrate= or - * reset the 32-bit instance in certain cases: - * - * 1) If the register has both 32-bit and 64-bit instances - * then we can count on the 64-bit instance taking care - * of the non-secure bank. - * 2) If ARMv8 is enabled then we can count on a 64-bit - * version taking care of the secure bank. This requir= es - * that separate 32 and 64-bit definitions are provided. - */ - if ((r->state =3D=3D ARM_CP_STATE_BOTH && ns) || - (arm_feature(env, ARM_FEATURE_V8) && !ns)) { - r2->type |=3D ARM_CP_ALIAS; - } - } else if ((secstate !=3D r->secure) && !ns) { - /* - * The register is not banked so we only want to allow - * migration of the non-secure instance. - */ - r2->type |=3D ARM_CP_ALIAS; - } - - if (HOST_BIG_ENDIAN && - r->state =3D=3D ARM_CP_STATE_BOTH && r2->fieldoffset) { - r2->fieldoffset +=3D sizeof(uint32_t); - } - } - } - - /* - * By convention, for wildcarded registers only the first - * entry is used for migration; the others are marked as - * ALIAS so we don't try to transfer the register - * multiple times. Special registers (ie NOP/WFI) are - * never migratable and not even raw-accessible. - */ - if (r2->type & ARM_CP_SPECIAL_MASK) { - r2->type |=3D ARM_CP_NO_RAW; - } - if (((r->crm =3D=3D CP_ANY) && crm !=3D 0) || - ((r->opc1 =3D=3D CP_ANY) && opc1 !=3D 0) || - ((r->opc2 =3D=3D CP_ANY) && opc2 !=3D 0)) { - r2->type |=3D ARM_CP_ALIAS | ARM_CP_NO_GDB; - } - - /* - * Check that raw accesses are either forbidden or handled. Note that - * we can't assert this earlier because the setup of fieldoffset for - * banked registers has to be done first. - */ - if (!(r2->type & ARM_CP_NO_RAW)) { - assert(!raw_accessors_invalid(r2)); - } - - g_hash_table_insert(cpu->cp_regs, (gpointer)(uintptr_t)key, r2); -} - - -void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu, - const ARMCPRegInfo *r, void *opaque) -{ - /* - * Define implementations of coprocessor registers. - * We store these in a hashtable because typically - * there are less than 150 registers in a space which - * is 16*16*16*8*8 =3D 262144 in size. - * Wildcarding is supported for the crm, opc1 and opc2 fields. - * If a register is defined twice then the second definition is - * used, so this can be used to define some generic registers and - * then override them with implementation specific variations. - * At least one of the original and the second definition should - * include ARM_CP_OVERRIDE in its type bits -- this is just a guard - * against accidental use. - * - * The state field defines whether the register is to be - * visible in the AArch32 or AArch64 execution state. If the - * state is set to ARM_CP_STATE_BOTH then we synthesise a - * reginfo structure for the AArch32 view, which sees the lower - * 32 bits of the 64 bit register. - * - * Only registers visible in AArch64 may set r->opc0; opc0 cannot - * be wildcarded. AArch64 registers are always considered to be 64 - * bits; the ARM_CP_64BIT* flag applies only to the AArch32 view of - * the register, if any. - */ - int crm, opc1, opc2; - int crmmin =3D (r->crm =3D=3D CP_ANY) ? 0 : r->crm; - int crmmax =3D (r->crm =3D=3D CP_ANY) ? 15 : r->crm; - int opc1min =3D (r->opc1 =3D=3D CP_ANY) ? 0 : r->opc1; - int opc1max =3D (r->opc1 =3D=3D CP_ANY) ? 7 : r->opc1; - int opc2min =3D (r->opc2 =3D=3D CP_ANY) ? 0 : r->opc2; - int opc2max =3D (r->opc2 =3D=3D CP_ANY) ? 7 : r->opc2; - CPState state; - - /* 64 bit registers have only CRm and Opc1 fields */ - assert(!((r->type & ARM_CP_64BIT) && (r->opc2 || r->crn))); - /* op0 only exists in the AArch64 encodings */ - assert((r->state !=3D ARM_CP_STATE_AA32) || (r->opc0 =3D=3D 0)); - /* AArch64 regs are all 64 bit so ARM_CP_64BIT is meaningless */ - assert((r->state !=3D ARM_CP_STATE_AA64) || !(r->type & ARM_CP_64BIT)); - /* - * This API is only for Arm's system coprocessors (14 and 15) or - * (M-profile or v7A-and-earlier only) for implementation defined - * coprocessors in the range 0..7. Our decode assumes this, since - * 8..13 can be used for other insns including VFP and Neon. See - * valid_cp() in translate.c. Assert here that we haven't tried - * to use an invalid coprocessor number. - */ - switch (r->state) { - case ARM_CP_STATE_BOTH: - /* 0 has a special meaning, but otherwise the same rules as AA32. = */ - if (r->cp =3D=3D 0) { - break; - } - /* fall through */ - case ARM_CP_STATE_AA32: - if (arm_feature(&cpu->env, ARM_FEATURE_V8) && - !arm_feature(&cpu->env, ARM_FEATURE_M)) { - assert(r->cp >=3D 14 && r->cp <=3D 15); - } else { - assert(r->cp < 8 || (r->cp >=3D 14 && r->cp <=3D 15)); - } - break; - case ARM_CP_STATE_AA64: - assert(r->cp =3D=3D 0 || r->cp =3D=3D CP_REG_ARM64_SYSREG_CP); - break; - default: - g_assert_not_reached(); - } - /* - * The AArch64 pseudocode CheckSystemAccess() specifies that op1 - * encodes a minimum access level for the register. We roll this - * runtime check into our general permission check code, so check - * here that the reginfo's specified permissions are strict enough - * to encompass the generic architectural permission check. - */ - if (r->state !=3D ARM_CP_STATE_AA32) { - CPAccessRights mask; - switch (r->opc1) { - case 0: - /* min_EL EL1, but some accessible to EL0 via kernel ABI */ - mask =3D PL0U_R | PL1_RW; - break; - case 1: case 2: - /* min_EL EL1 */ - mask =3D PL1_RW; - break; - case 3: - /* min_EL EL0 */ - mask =3D PL0_RW; - break; - case 4: - case 5: - /* min_EL EL2 */ - mask =3D PL2_RW; - break; - case 6: - /* min_EL EL3 */ - mask =3D PL3_RW; - break; - case 7: - /* min_EL EL1, secure mode only (we don't check the latter) */ - mask =3D PL1_RW; - break; - default: - /* broken reginfo with out-of-range opc1 */ - g_assert_not_reached(); - } - /* assert our permissions are not too lax (stricter is fine) */ - assert((r->access & ~mask) =3D=3D 0); - } - - /* - * Check that the register definition has enough info to handle - * reads and writes if they are permitted. - */ - if (!(r->type & (ARM_CP_SPECIAL_MASK | ARM_CP_CONST))) { - if (r->access & PL3_R) { - assert((r->fieldoffset || - (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) || - r->readfn); - } - if (r->access & PL3_W) { - assert((r->fieldoffset || - (r->bank_fieldoffsets[0] && r->bank_fieldoffsets[1])) || - r->writefn); - } - } - - for (crm =3D crmmin; crm <=3D crmmax; crm++) { - for (opc1 =3D opc1min; opc1 <=3D opc1max; opc1++) { - for (opc2 =3D opc2min; opc2 <=3D opc2max; opc2++) { - for (state =3D ARM_CP_STATE_AA32; - state <=3D ARM_CP_STATE_AA64; state++) { - if (r->state !=3D state && r->state !=3D ARM_CP_STATE_= BOTH) { - continue; - } - if (state =3D=3D ARM_CP_STATE_AA32) { - /* - * Under AArch32 CP registers can be common - * (same for secure and non-secure world) or banke= d. - */ - char *name; - - switch (r->secure) { - case ARM_CP_SECSTATE_S: - case ARM_CP_SECSTATE_NS: - add_cpreg_to_hashtable(cpu, r, opaque, state, - r->secure, crm, opc1, o= pc2, - r->name); - break; - case ARM_CP_SECSTATE_BOTH: - name =3D g_strdup_printf("%s_S", r->name); - add_cpreg_to_hashtable(cpu, r, opaque, state, - ARM_CP_SECSTATE_S, - crm, opc1, opc2, name); - g_free(name); - add_cpreg_to_hashtable(cpu, r, opaque, state, - ARM_CP_SECSTATE_NS, - crm, opc1, opc2, r->nam= e); - break; - default: - g_assert_not_reached(); - } - } else { - /* - * AArch64 registers get mapped to non-secure inst= ance - * of AArch32 - */ - add_cpreg_to_hashtable(cpu, r, opaque, state, - ARM_CP_SECSTATE_NS, - crm, opc1, opc2, r->name); - } - } - } - } - } -} - -/* Define a whole list of registers */ -void define_arm_cp_regs_with_opaque_len(ARMCPU *cpu, const ARMCPRegInfo *r= egs, - void *opaque, size_t len) -{ - size_t i; - for (i =3D 0; i < len; ++i) { - define_one_arm_cp_reg_with_opaque(cpu, regs + i, opaque); - } -} - -/* - * Modify ARMCPRegInfo for access from userspace. - * - * This is a data driven modification directed by - * ARMCPRegUserSpaceInfo. All registers become ARM_CP_CONST as - * user-space cannot alter any values and dynamic values pertaining to - * execution state are hidden from user space view anyway. - */ -void modify_arm_cp_regs_with_len(ARMCPRegInfo *regs, size_t regs_len, - const ARMCPRegUserSpaceInfo *mods, - size_t mods_len) -{ - for (size_t mi =3D 0; mi < mods_len; ++mi) { - const ARMCPRegUserSpaceInfo *m =3D mods + mi; - GPatternSpec *pat =3D NULL; - - if (m->is_glob) { - pat =3D g_pattern_spec_new(m->name); - } - for (size_t ri =3D 0; ri < regs_len; ++ri) { - ARMCPRegInfo *r =3D regs + ri; - - if (pat && g_pattern_match_string(pat, r->name)) { - r->type =3D ARM_CP_CONST; - r->access =3D PL0U_R; - r->resetvalue =3D 0; - /* continue */ - } else if (strcmp(r->name, m->name) =3D=3D 0) { - r->type =3D ARM_CP_CONST; - r->access =3D PL0U_R; - r->resetvalue &=3D m->exported_bits; - r->resetvalue |=3D m->fixed_bits; - break; - } - } - if (pat) { - g_pattern_spec_free(pat); - } - } -} - -const ARMCPRegInfo *get_arm_cp_reginfo(GHashTable *cpregs, uint32_t encode= d_cp) -{ - return g_hash_table_lookup(cpregs, (gpointer)(uintptr_t)encoded_cp); -} - -void arm_cp_write_ignore(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* Helper coprocessor write function for write-ignore registers */ -} - -uint64_t arm_cp_read_zero(CPUARMState *env, const ARMCPRegInfo *ri) -{ - /* Helper coprocessor write function for read-as-zero registers */ - return 0; -} - -void arm_cp_reset_ignore(CPUARMState *env, const ARMCPRegInfo *opaque) -{ - /* Helper coprocessor reset function for do-nothing-on-reset registers= */ -} - static int bad_mode_switch(CPUARMState *env, int mode, CPSRWriteType write= _type) { /* diff --git a/target/arm/machine.c b/target/arm/machine.c index b4c3850570..d5dd6825b9 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -5,6 +5,7 @@ #include "kvm_arm.h" #include "internals.h" #include "migration/cpu.h" +#include "cpregs.h" =20 static bool vfp_needed(void *opaque) { diff --git a/target/arm/meson.build b/target/arm/meson.build index 87e911b27f..aa5aae9888 100644 --- a/target/arm/meson.build +++ b/target/arm/meson.build @@ -18,6 +18,7 @@ gen =3D [ arm_ss =3D ss.source_set() arm_ss.add(gen) arm_ss.add(files( + 'cpregs.c', 'cpu.c', 'crypto_helper.c', 'debug_helper.c', diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index 70672bcd9f..8f027f64db 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu/main-loop.h" #include "cpu.h" +#include "cpregs.h" #include "exec/helper-proto.h" #include "internals.h" #include "exec/exec-all.h" diff --git a/target/arm/trace-events b/target/arm/trace-events index 2a0ba7bffc..04a480443e 100644 --- a/target/arm/trace-events +++ b/target/arm/trace-events @@ -1,6 +1,6 @@ # See docs/devel/tracing.rst for syntax documentation. =20 -# helper.c +# cpregs.c arm_gt_recalc(int timer, int irqstate, uint64_t nexttick) "gt recalc: time= r %d irqstate %d next tick 0x%" PRIx64 arm_gt_recalc_disabled(int timer) "gt recalc: timer %d irqstate 0 timer di= sabled" arm_gt_cval_write(int timer, uint64_t value) "gt_cval_write: timer %d valu= e 0x%" PRIx64 diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 2ee171f249..5c7ef25995 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" =20 #include "cpu.h" +#include "cpregs.h" #include "exec/exec-all.h" #include "tcg/tcg-op.h" #include "tcg/tcg-op-gvec.h" diff --git a/target/arm/translate.c b/target/arm/translate.c index 1dcaefb8e7..0bee6b0595 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -22,6 +22,7 @@ =20 #include "cpu.h" #include "internals.h" +#include "cpregs.h" #include "disas/disas.h" #include "exec/exec-all.h" #include "tcg/tcg-op.h" --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304326; cv=none; d=zohomail.com; s=zohoarc; b=mC6MIaPfGFHw0/LDRvNXF1IosvxK0Qn2gvU21GqSABCj0iq4m7wmACClcn9pFylTDkFDL6zvIUR+lDT/oVOMq8MyJ3BMWT1CX8wsScWI/ocHL9CS0cezvqPuQAN5CZ0vK+hla67XituymIRWST8xvw/NlfD2dIP/txavj/yKp4o= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304326; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=1HXOsnzP2Srqui3XDrDervO1BIRKgPR9CM+PyhvAr60=; b=ChjKxs3+6R1zdSHVPeu9U7IloAImCKna57Ca/KQU2dbI1zD7K9YpECjSB22KHReRPXSuZUGEOhATLFPhobL7lWE6GuvEFsz+AkRTaRkhwYWYB1Zy1swO/m0XHrVUx+3Q9wACORRGKTLwQFHCWzOdw2zwTScl2UaVViYl2//6oJA= 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 1673304326575123.12796661824689; Mon, 9 Jan 2023 14:45:26 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0r9-000482-PS; Mon, 09 Jan 2023 17:43:03 -0500 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 1pF0r7-00046S-G0; Mon, 09 Jan 2023 17:43:01 -0500 Received: from smtp-out2.suse.de ([2001:67c:2178:6::1d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0r4-000404-3s; Mon, 09 Jan 2023 17:43:01 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 8A1825CDD9; Mon, 9 Jan 2023 22:42:56 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id ED9F413583; Mon, 9 Jan 2023 22:42:53 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id QAQvLW2YvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:42:53 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304176; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1HXOsnzP2Srqui3XDrDervO1BIRKgPR9CM+PyhvAr60=; b=U2VXMQLDVYKormHm+lYPn+wysGHroPYxOsKEPtj3OSR9DgX4hQGOvXPOZFn+kQ2dxTa7kD jDGTaqfoG++p0EhzsxiXHN2+++PuOZAjHzUq1yJMgOJCADDLqO9cYX6Rv0PVUSJERCj7/J 6wlngBfz7V/HNvn/YVPGy+fBlXHL5nc= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304176; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1HXOsnzP2Srqui3XDrDervO1BIRKgPR9CM+PyhvAr60=; b=EAH4M/iG6ED2aqb0UuG6M5XDjGtHMcG3ck45qG6SESAgMZRijWOFIZdefoZZUfpwwV/pF7 My8d7lNm4U3tCbCg== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf Subject: [RFC PATCH v2 06/19] target/arm: Move define_debug_regs() to cpregs.c Date: Mon, 9 Jan 2023 19:42:19 -0300 Message-Id: <20230109224232.11661-7-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=2001:67c:2178:6::1d; envelope-from=farosas@suse.de; helo=smtp-out2.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304328740100007 Content-Type: text/plain; charset="utf-8" The debug_helper.c file will move into a tcg-specific directory, so take the cpregs code out of it. That code needs to be present in KVM builds as well. Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson --- target/arm/cpregs.c | 383 ++++++++++++++++++++++++++++++++++++++ target/arm/cpu.c | 7 +- target/arm/debug_helper.c | 367 ------------------------------------ target/arm/internals.h | 9 - target/arm/machine.c | 6 +- 5 files changed, 392 insertions(+), 380 deletions(-) diff --git a/target/arm/cpregs.c b/target/arm/cpregs.c index 9f15337b68..88d71dbe70 100644 --- a/target/arm/cpregs.c +++ b/target/arm/cpregs.c @@ -287,6 +287,74 @@ static CPAccessResult access_trap_aa32s_el1(CPUARMStat= e *env, return CP_ACCESS_TRAP_UNCATEGORIZED; } =20 +static uint64_t arm_mdcr_el2_eff(CPUARMState *env) +{ + return arm_is_el2_enabled(env) ? env->cp15.mdcr_el2 : 0; +} + +/* + * Check for traps to "powerdown debug" registers, which are controlled + * by MDCR.TDOSA + */ +static CPAccessResult access_tdosa(CPUARMState *env, const ARMCPRegInfo *r= i, + bool isread) +{ + int el =3D arm_current_el(env); + uint64_t mdcr_el2 =3D arm_mdcr_el2_eff(env); + bool mdcr_el2_tdosa =3D (mdcr_el2 & MDCR_TDOSA) || (mdcr_el2 & MDCR_TD= E) || + (arm_hcr_el2_eff(env) & HCR_TGE); + + if (el < 2 && mdcr_el2_tdosa) { + return CP_ACCESS_TRAP_EL2; + } + if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDOSA)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + +/* + * Check for traps to "debug ROM" registers, which are controlled + * by MDCR_EL2.TDRA for EL2 but by the more general MDCR_EL3.TDA for EL3. + */ +static CPAccessResult access_tdra(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + int el =3D arm_current_el(env); + uint64_t mdcr_el2 =3D arm_mdcr_el2_eff(env); + bool mdcr_el2_tdra =3D (mdcr_el2 & MDCR_TDRA) || (mdcr_el2 & MDCR_TDE)= || + (arm_hcr_el2_eff(env) & HCR_TGE); + + if (el < 2 && mdcr_el2_tdra) { + return CP_ACCESS_TRAP_EL2; + } + if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + +/* + * Check for traps to general debug registers, which are controlled + * by MDCR_EL2.TDA for EL2 and MDCR_EL3.TDA for EL3. + */ +static CPAccessResult access_tda(CPUARMState *env, const ARMCPRegInfo *ri, + bool isread) +{ + int el =3D arm_current_el(env); + uint64_t mdcr_el2 =3D arm_mdcr_el2_eff(env); + bool mdcr_el2_tda =3D (mdcr_el2 & MDCR_TDA) || (mdcr_el2 & MDCR_TDE) || + (arm_hcr_el2_eff(env) & HCR_TGE); + + if (el < 2 && mdcr_el2_tda) { + return CP_ACCESS_TRAP_EL2; + } + if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) { + return CP_ACCESS_TRAP_EL3; + } + return CP_ACCESS_OK; +} + /* * Check for traps to performance monitor registers, which are controlled * by MDCR_EL2.TPM for EL2 and MDCR_EL3.TPM for EL3. @@ -6286,6 +6354,132 @@ static CPAccessResult ctr_el0_access(CPUARMState *e= nv, const ARMCPRegInfo *ri, return CP_ACCESS_OK; } =20 +static void oslar_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * Writes to OSLAR_EL1 may update the OS lock status, which can be + * read via a bit in OSLSR_EL1. + */ + int oslock; + + if (ri->state =3D=3D ARM_CP_STATE_AA32) { + oslock =3D (value =3D=3D 0xC5ACCE55); + } else { + oslock =3D value & 1; + } + + env->cp15.oslsr_el1 =3D deposit32(env->cp15.oslsr_el1, 1, 1, oslock); +} + +static void osdlr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + /* + * Only defined bit is bit 0 (DLK); if Feat_DoubleLock is not + * implemented this is RAZ/WI. + */ + if (arm_feature(env, ARM_FEATURE_AARCH64) + ? cpu_isar_feature(aa64_doublelock, cpu) + : cpu_isar_feature(aa32_doublelock, cpu)) { + env->cp15.osdlr_el1 =3D value & 1; + } +} + +static const ARMCPRegInfo debug_cp_reginfo[] =3D { + /* + * DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped + * debug components. The AArch64 version of DBGDRAR is named MDRAR_EL1; + * unlike DBGDRAR it is never accessible from EL0. + * DBGDSAR is deprecated and must RAZ from v8 anyway, so it has no AAr= ch64 + * accessor. + */ + { .name =3D "DBGDRAR", .cp =3D 14, .crn =3D 1, .crm =3D 0, .opc1 =3D 0= , .opc2 =3D 0, + .access =3D PL0_R, .accessfn =3D access_tdra, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + { .name =3D "MDRAR_EL1", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 2, .opc1 =3D 0, .crn =3D 1, .crm =3D 0, .opc2 =3D 0, + .access =3D PL1_R, .accessfn =3D access_tdra, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + { .name =3D "DBGDSAR", .cp =3D 14, .crn =3D 2, .crm =3D 0, .opc1 =3D 0= , .opc2 =3D 0, + .access =3D PL0_R, .accessfn =3D access_tdra, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + /* Monitor debug system control register; the 32-bit alias is DBGDSCRe= xt. */ + { .name =3D "MDSCR_EL1", .state =3D ARM_CP_STATE_BOTH, + .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 = =3D 2, + .access =3D PL1_RW, .accessfn =3D access_tda, + .fieldoffset =3D offsetof(CPUARMState, cp15.mdscr_el1), + .resetvalue =3D 0 }, + /* + * MDCCSR_EL0[30:29] map to EDSCR[30:29]. Simply RAZ as the external + * Debug Communication Channel is not implemented. + */ + { .name =3D "MDCCSR_EL0", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 2, .opc1 =3D 3, .crn =3D 0, .crm =3D 1, .opc2 =3D 0, + .access =3D PL0_R, .accessfn =3D access_tda, + .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, + /* + * DBGDSCRint[15,12,5:2] map to MDSCR_EL1[15,12,5:2]. Map all bits as + * it is unlikely a guest will care. + * We don't implement the configurable EL0 access. + */ + { .name =3D "DBGDSCRint", .state =3D ARM_CP_STATE_AA32, + .cp =3D 14, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D 0, + .type =3D ARM_CP_ALIAS, + .access =3D PL1_R, .accessfn =3D access_tda, + .fieldoffset =3D offsetof(CPUARMState, cp15.mdscr_el1), }, + { .name =3D "OSLAR_EL1", .state =3D ARM_CP_STATE_BOTH, + .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 1, .crm =3D 0, .opc2 = =3D 4, + .access =3D PL1_W, .type =3D ARM_CP_NO_RAW, + .accessfn =3D access_tdosa, + .writefn =3D oslar_write }, + { .name =3D "OSLSR_EL1", .state =3D ARM_CP_STATE_BOTH, + .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 1, .crm =3D 1, .opc2 = =3D 4, + .access =3D PL1_R, .resetvalue =3D 10, + .accessfn =3D access_tdosa, + .fieldoffset =3D offsetof(CPUARMState, cp15.oslsr_el1) }, + /* Dummy OSDLR_EL1: 32-bit Linux will read this */ + { .name =3D "OSDLR_EL1", .state =3D ARM_CP_STATE_BOTH, + .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 1, .crm =3D 3, .opc2 = =3D 4, + .access =3D PL1_RW, .accessfn =3D access_tdosa, + .writefn =3D osdlr_write, + .fieldoffset =3D offsetof(CPUARMState, cp15.osdlr_el1) }, + /* + * Dummy DBGVCR: Linux wants to clear this on startup, but we don't + * implement vector catch debug events yet. + */ + { .name =3D "DBGVCR", + .cp =3D 14, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D 0, + .access =3D PL1_RW, .accessfn =3D access_tda, + .type =3D ARM_CP_NOP }, + /* + * Dummy DBGVCR32_EL2 (which is only for a 64-bit hypervisor + * to save and restore a 32-bit guest's DBGVCR) + */ + { .name =3D "DBGVCR32_EL2", .state =3D ARM_CP_STATE_AA64, + .opc0 =3D 2, .opc1 =3D 4, .crn =3D 0, .crm =3D 7, .opc2 =3D 0, + .access =3D PL2_RW, .accessfn =3D access_tda, + .type =3D ARM_CP_NOP | ARM_CP_EL3_NO_EL2_KEEP }, + /* + * Dummy MDCCINT_EL1, since we don't implement the Debug Communications + * Channel but Linux may try to access this register. The 32-bit + * alias is DBGDCCINT. + */ + { .name =3D "MDCCINT_EL1", .state =3D ARM_CP_STATE_BOTH, + .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 = =3D 0, + .access =3D PL1_RW, .accessfn =3D access_tda, + .type =3D ARM_CP_NOP }, +}; + +static const ARMCPRegInfo debug_lpae_cp_reginfo[] =3D { + /* 64 bit access versions of the (dummy) debug registers */ + { .name =3D "DBGDRAR", .cp =3D 14, .crm =3D 1, .opc1 =3D 0, + .access =3D PL0_R, .type =3D ARM_CP_CONST | ARM_CP_64BIT, .resetvalu= e =3D 0 }, + { .name =3D "DBGDSAR", .cp =3D 14, .crm =3D 2, .opc1 =3D 0, + .access =3D PL0_R, .type =3D ARM_CP_CONST | ARM_CP_64BIT, .resetvalu= e =3D 0 }, +}; + /* * Check for traps to RAS registers, which are controlled * by HCR_EL2.TERR and SCR_EL3.TERR. @@ -6520,6 +6714,195 @@ static const ARMCPRegInfo sme_reginfo[] =3D { }; #endif /* TARGET_AARCH64 */ =20 +static void dbgwvr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + int i =3D ri->crm; + + /* + * Bits [1:0] are RES0. + * + * It is IMPLEMENTATION DEFINED whether [63:49] ([63:53] with FEAT_LVA) + * are hardwired to the value of bit [48] ([52] with FEAT_LVA), or if + * they contain the value written. It is CONSTRAINED UNPREDICTABLE + * whether the RESS bits are ignored when comparing an address. + * + * Therefore we are allowed to compare the entire register, which lets + * us avoid considering whether or not FEAT_LVA is actually enabled. + */ + value &=3D ~3ULL; + + raw_write(env, ri, value); + + if (tcg_enabled()) { + hw_watchpoint_update(cpu, i); + } +} + +static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + int i =3D ri->crm; + + raw_write(env, ri, value); + + if (tcg_enabled()) { + hw_watchpoint_update(cpu, i); + } +} + +static void dbgbvr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + int i =3D ri->crm; + + raw_write(env, ri, value); + + if (tcg_enabled()) { + hw_breakpoint_update(cpu, i); + } +} + +static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + ARMCPU *cpu =3D env_archcpu(env); + int i =3D ri->crm; + + /* + * BAS[3] is a read-only copy of BAS[2], and BAS[1] a read-only + * copy of BAS[0]. + */ + value =3D deposit64(value, 6, 1, extract64(value, 5, 1)); + value =3D deposit64(value, 8, 1, extract64(value, 7, 1)); + + raw_write(env, ri, value); + + if (tcg_enabled()) { + hw_breakpoint_update(cpu, i); + } +} + +static void define_debug_regs(ARMCPU *cpu) +{ + /* + * Define v7 and v8 architectural debug registers. + * These are just dummy implementations for now. + */ + int i; + int wrps, brps, ctx_cmps; + + /* + * The Arm ARM says DBGDIDR is optional and deprecated if EL1 cannot + * use AArch32. Given that bit 15 is RES1, if the value is 0 then + * the register must not exist for this cpu. + */ + if (cpu->isar.dbgdidr !=3D 0) { + ARMCPRegInfo dbgdidr =3D { + .name =3D "DBGDIDR", .cp =3D 14, .crn =3D 0, .crm =3D 0, + .opc1 =3D 0, .opc2 =3D 0, + .access =3D PL0_R, .accessfn =3D access_tda, + .type =3D ARM_CP_CONST, .resetvalue =3D cpu->isar.dbgdidr, + }; + define_one_arm_cp_reg(cpu, &dbgdidr); + } + + /* + * DBGDEVID is present in the v7 debug architecture if + * DBGDIDR.DEVID_imp is 1 (bit 15); from v7.1 and on it is + * mandatory (and bit 15 is RES1). DBGDEVID1 and DBGDEVID2 exist + * from v7.1 of the debug architecture. Because no fields have yet + * been defined in DBGDEVID2 (and quite possibly none will ever + * be) we don't define an ARMISARegisters field for it. + * These registers exist only if EL1 can use AArch32, but that + * happens naturally because they are only PL1 accessible anyway. + */ + if (extract32(cpu->isar.dbgdidr, 15, 1)) { + ARMCPRegInfo dbgdevid =3D { + .name =3D "DBGDEVID", + .cp =3D 14, .opc1 =3D 0, .crn =3D 7, .opc2 =3D 2, .crn =3D 7, + .access =3D PL1_R, .accessfn =3D access_tda, + .type =3D ARM_CP_CONST, .resetvalue =3D cpu->isar.dbgdevid, + }; + define_one_arm_cp_reg(cpu, &dbgdevid); + } + if (cpu_isar_feature(aa32_debugv7p1, cpu)) { + ARMCPRegInfo dbgdevid12[] =3D { + { + .name =3D "DBGDEVID1", + .cp =3D 14, .opc1 =3D 0, .crn =3D 7, .opc2 =3D 1, .crn =3D= 7, + .access =3D PL1_R, .accessfn =3D access_tda, + .type =3D ARM_CP_CONST, .resetvalue =3D cpu->isar.dbgdevid= 1, + }, { + .name =3D "DBGDEVID2", + .cp =3D 14, .opc1 =3D 0, .crn =3D 7, .opc2 =3D 0, .crn =3D= 7, + .access =3D PL1_R, .accessfn =3D access_tda, + .type =3D ARM_CP_CONST, .resetvalue =3D 0, + }, + }; + define_arm_cp_regs(cpu, dbgdevid12); + } + + brps =3D arm_num_brps(cpu); + wrps =3D arm_num_wrps(cpu); + ctx_cmps =3D arm_num_ctx_cmps(cpu); + + assert(ctx_cmps <=3D brps); + + define_arm_cp_regs(cpu, debug_cp_reginfo); + + if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) { + define_arm_cp_regs(cpu, debug_lpae_cp_reginfo); + } + + for (i =3D 0; i < brps; i++) { + char *dbgbvr_el1_name =3D g_strdup_printf("DBGBVR%d_EL1", i); + char *dbgbcr_el1_name =3D g_strdup_printf("DBGBCR%d_EL1", i); + ARMCPRegInfo dbgregs[] =3D { + { .name =3D dbgbvr_el1_name, .state =3D ARM_CP_STATE_BOTH, + .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 0, .crm =3D i= , .opc2 =3D 4, + .access =3D PL1_RW, .accessfn =3D access_tda, + .fieldoffset =3D offsetof(CPUARMState, cp15.dbgbvr[i]), + .writefn =3D dbgbvr_write, .raw_writefn =3D raw_write + }, + { .name =3D dbgbcr_el1_name, .state =3D ARM_CP_STATE_BOTH, + .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 0, .crm =3D i= , .opc2 =3D 5, + .access =3D PL1_RW, .accessfn =3D access_tda, + .fieldoffset =3D offsetof(CPUARMState, cp15.dbgbcr[i]), + .writefn =3D dbgbcr_write, .raw_writefn =3D raw_write + }, + }; + define_arm_cp_regs(cpu, dbgregs); + g_free(dbgbvr_el1_name); + g_free(dbgbcr_el1_name); + } + + for (i =3D 0; i < wrps; i++) { + char *dbgwvr_el1_name =3D g_strdup_printf("DBGWVR%d_EL1", i); + char *dbgwcr_el1_name =3D g_strdup_printf("DBGWCR%d_EL1", i); + ARMCPRegInfo dbgregs[] =3D { + { .name =3D dbgwvr_el1_name, .state =3D ARM_CP_STATE_BOTH, + .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 0, .crm =3D i= , .opc2 =3D 6, + .access =3D PL1_RW, .accessfn =3D access_tda, + .fieldoffset =3D offsetof(CPUARMState, cp15.dbgwvr[i]), + .writefn =3D dbgwvr_write, .raw_writefn =3D raw_write + }, + { .name =3D dbgwcr_el1_name, .state =3D ARM_CP_STATE_BOTH, + .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 0, .crm =3D i= , .opc2 =3D 7, + .access =3D PL1_RW, .accessfn =3D access_tda, + .fieldoffset =3D offsetof(CPUARMState, cp15.dbgwcr[i]), + .writefn =3D dbgwcr_write, .raw_writefn =3D raw_write + }, + }; + define_arm_cp_regs(cpu, dbgregs); + g_free(dbgwvr_el1_name); + g_free(dbgwcr_el1_name); + } +} + static void define_pmu_regs(ARMCPU *cpu) { /* diff --git a/target/arm/cpu.c b/target/arm/cpu.c index fd337e1788..4cb524a102 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -537,8 +537,11 @@ static void arm_cpu_reset_hold(Object *obj) } #endif =20 - hw_breakpoint_update_all(cpu); - hw_watchpoint_update_all(cpu); + if (tcg_enabled()) { + hw_breakpoint_update_all(cpu); + hw_watchpoint_update_all(cpu); + } + arm_rebuild_hflags(env); } =20 diff --git a/target/arm/debug_helper.c b/target/arm/debug_helper.c index 2f6ddc0da5..eaee9f7731 100644 --- a/target/arm/debug_helper.c +++ b/target/arm/debug_helper.c @@ -9,7 +9,6 @@ #include "qemu/log.h" #include "cpu.h" #include "internals.h" -#include "cpregs.h" #include "exec/exec-all.h" #include "exec/helper-proto.h" =20 @@ -536,195 +535,6 @@ void HELPER(exception_swstep)(CPUARMState *env, uint3= 2_t syndrome) raise_exception_debug(env, EXCP_UDEF, syndrome); } =20 -/* - * Check for traps to "powerdown debug" registers, which are controlled - * by MDCR.TDOSA - */ -static CPAccessResult access_tdosa(CPUARMState *env, const ARMCPRegInfo *r= i, - bool isread) -{ - int el =3D arm_current_el(env); - uint64_t mdcr_el2 =3D arm_mdcr_el2_eff(env); - bool mdcr_el2_tdosa =3D (mdcr_el2 & MDCR_TDOSA) || (mdcr_el2 & MDCR_TD= E) || - (arm_hcr_el2_eff(env) & HCR_TGE); - - if (el < 2 && mdcr_el2_tdosa) { - return CP_ACCESS_TRAP_EL2; - } - if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDOSA)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -/* - * Check for traps to "debug ROM" registers, which are controlled - * by MDCR_EL2.TDRA for EL2 but by the more general MDCR_EL3.TDA for EL3. - */ -static CPAccessResult access_tdra(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - int el =3D arm_current_el(env); - uint64_t mdcr_el2 =3D arm_mdcr_el2_eff(env); - bool mdcr_el2_tdra =3D (mdcr_el2 & MDCR_TDRA) || (mdcr_el2 & MDCR_TDE)= || - (arm_hcr_el2_eff(env) & HCR_TGE); - - if (el < 2 && mdcr_el2_tdra) { - return CP_ACCESS_TRAP_EL2; - } - if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -/* - * Check for traps to general debug registers, which are controlled - * by MDCR_EL2.TDA for EL2 and MDCR_EL3.TDA for EL3. - */ -static CPAccessResult access_tda(CPUARMState *env, const ARMCPRegInfo *ri, - bool isread) -{ - int el =3D arm_current_el(env); - uint64_t mdcr_el2 =3D arm_mdcr_el2_eff(env); - bool mdcr_el2_tda =3D (mdcr_el2 & MDCR_TDA) || (mdcr_el2 & MDCR_TDE) || - (arm_hcr_el2_eff(env) & HCR_TGE); - - if (el < 2 && mdcr_el2_tda) { - return CP_ACCESS_TRAP_EL2; - } - if (el < 3 && (env->cp15.mdcr_el3 & MDCR_TDA)) { - return CP_ACCESS_TRAP_EL3; - } - return CP_ACCESS_OK; -} - -static void oslar_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - /* - * Writes to OSLAR_EL1 may update the OS lock status, which can be - * read via a bit in OSLSR_EL1. - */ - int oslock; - - if (ri->state =3D=3D ARM_CP_STATE_AA32) { - oslock =3D (value =3D=3D 0xC5ACCE55); - } else { - oslock =3D value & 1; - } - - env->cp15.oslsr_el1 =3D deposit32(env->cp15.oslsr_el1, 1, 1, oslock); -} - -static void osdlr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - /* - * Only defined bit is bit 0 (DLK); if Feat_DoubleLock is not - * implemented this is RAZ/WI. - */ - if(arm_feature(env, ARM_FEATURE_AARCH64) - ? cpu_isar_feature(aa64_doublelock, cpu) - : cpu_isar_feature(aa32_doublelock, cpu)) { - env->cp15.osdlr_el1 =3D value & 1; - } -} - -static const ARMCPRegInfo debug_cp_reginfo[] =3D { - /* - * DBGDRAR, DBGDSAR: always RAZ since we don't implement memory mapped - * debug components. The AArch64 version of DBGDRAR is named MDRAR_EL1; - * unlike DBGDRAR it is never accessible from EL0. - * DBGDSAR is deprecated and must RAZ from v8 anyway, so it has no AAr= ch64 - * accessor. - */ - { .name =3D "DBGDRAR", .cp =3D 14, .crn =3D 1, .crm =3D 0, .opc1 =3D 0= , .opc2 =3D 0, - .access =3D PL0_R, .accessfn =3D access_tdra, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - { .name =3D "MDRAR_EL1", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 2, .opc1 =3D 0, .crn =3D 1, .crm =3D 0, .opc2 =3D 0, - .access =3D PL1_R, .accessfn =3D access_tdra, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - { .name =3D "DBGDSAR", .cp =3D 14, .crn =3D 2, .crm =3D 0, .opc1 =3D 0= , .opc2 =3D 0, - .access =3D PL0_R, .accessfn =3D access_tdra, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - /* Monitor debug system control register; the 32-bit alias is DBGDSCRe= xt. */ - { .name =3D "MDSCR_EL1", .state =3D ARM_CP_STATE_BOTH, - .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 = =3D 2, - .access =3D PL1_RW, .accessfn =3D access_tda, - .fieldoffset =3D offsetof(CPUARMState, cp15.mdscr_el1), - .resetvalue =3D 0 }, - /* - * MDCCSR_EL0[30:29] map to EDSCR[30:29]. Simply RAZ as the external - * Debug Communication Channel is not implemented. - */ - { .name =3D "MDCCSR_EL0", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 2, .opc1 =3D 3, .crn =3D 0, .crm =3D 1, .opc2 =3D 0, - .access =3D PL0_R, .accessfn =3D access_tda, - .type =3D ARM_CP_CONST, .resetvalue =3D 0 }, - /* - * DBGDSCRint[15,12,5:2] map to MDSCR_EL1[15,12,5:2]. Map all bits as - * it is unlikely a guest will care. - * We don't implement the configurable EL0 access. - */ - { .name =3D "DBGDSCRint", .state =3D ARM_CP_STATE_AA32, - .cp =3D 14, .opc1 =3D 0, .crn =3D 0, .crm =3D 1, .opc2 =3D 0, - .type =3D ARM_CP_ALIAS, - .access =3D PL1_R, .accessfn =3D access_tda, - .fieldoffset =3D offsetof(CPUARMState, cp15.mdscr_el1), }, - { .name =3D "OSLAR_EL1", .state =3D ARM_CP_STATE_BOTH, - .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 1, .crm =3D 0, .opc2 = =3D 4, - .access =3D PL1_W, .type =3D ARM_CP_NO_RAW, - .accessfn =3D access_tdosa, - .writefn =3D oslar_write }, - { .name =3D "OSLSR_EL1", .state =3D ARM_CP_STATE_BOTH, - .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 1, .crm =3D 1, .opc2 = =3D 4, - .access =3D PL1_R, .resetvalue =3D 10, - .accessfn =3D access_tdosa, - .fieldoffset =3D offsetof(CPUARMState, cp15.oslsr_el1) }, - /* Dummy OSDLR_EL1: 32-bit Linux will read this */ - { .name =3D "OSDLR_EL1", .state =3D ARM_CP_STATE_BOTH, - .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 1, .crm =3D 3, .opc2 = =3D 4, - .access =3D PL1_RW, .accessfn =3D access_tdosa, - .writefn =3D osdlr_write, - .fieldoffset =3D offsetof(CPUARMState, cp15.osdlr_el1) }, - /* - * Dummy DBGVCR: Linux wants to clear this on startup, but we don't - * implement vector catch debug events yet. - */ - { .name =3D "DBGVCR", - .cp =3D 14, .opc1 =3D 0, .crn =3D 0, .crm =3D 7, .opc2 =3D 0, - .access =3D PL1_RW, .accessfn =3D access_tda, - .type =3D ARM_CP_NOP }, - /* - * Dummy DBGVCR32_EL2 (which is only for a 64-bit hypervisor - * to save and restore a 32-bit guest's DBGVCR) - */ - { .name =3D "DBGVCR32_EL2", .state =3D ARM_CP_STATE_AA64, - .opc0 =3D 2, .opc1 =3D 4, .crn =3D 0, .crm =3D 7, .opc2 =3D 0, - .access =3D PL2_RW, .accessfn =3D access_tda, - .type =3D ARM_CP_NOP | ARM_CP_EL3_NO_EL2_KEEP }, - /* - * Dummy MDCCINT_EL1, since we don't implement the Debug Communications - * Channel but Linux may try to access this register. The 32-bit - * alias is DBGDCCINT. - */ - { .name =3D "MDCCINT_EL1", .state =3D ARM_CP_STATE_BOTH, - .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 0, .crm =3D 2, .opc2 = =3D 0, - .access =3D PL1_RW, .accessfn =3D access_tda, - .type =3D ARM_CP_NOP }, -}; - -static const ARMCPRegInfo debug_lpae_cp_reginfo[] =3D { - /* 64 bit access versions of the (dummy) debug registers */ - { .name =3D "DBGDRAR", .cp =3D 14, .crm =3D 1, .opc1 =3D 0, - .access =3D PL0_R, .type =3D ARM_CP_CONST | ARM_CP_64BIT, .resetvalu= e =3D 0 }, - { .name =3D "DBGDSAR", .cp =3D 14, .crm =3D 2, .opc1 =3D 0, - .access =3D PL0_R, .type =3D ARM_CP_CONST | ARM_CP_64BIT, .resetvalu= e =3D 0 }, -}; - void hw_watchpoint_update(ARMCPU *cpu, int n) { CPUARMState *env =3D &cpu->env; @@ -831,39 +641,6 @@ void hw_watchpoint_update_all(ARMCPU *cpu) } } =20 -static void dbgwvr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - int i =3D ri->crm; - - /* - * Bits [1:0] are RES0. - * - * It is IMPLEMENTATION DEFINED whether [63:49] ([63:53] with FEAT_LVA) - * are hardwired to the value of bit [48] ([52] with FEAT_LVA), or if - * they contain the value written. It is CONSTRAINED UNPREDICTABLE - * whether the RESS bits are ignored when comparing an address. - * - * Therefore we are allowed to compare the entire register, which lets - * us avoid considering whether or not FEAT_LVA is actually enabled. - */ - value &=3D ~3ULL; - - raw_write(env, ri, value); - hw_watchpoint_update(cpu, i); -} - -static void dbgwcr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - int i =3D ri->crm; - - raw_write(env, ri, value); - hw_watchpoint_update(cpu, i); -} - void hw_breakpoint_update(ARMCPU *cpu, int n) { CPUARMState *env =3D &cpu->env; @@ -967,150 +744,6 @@ void hw_breakpoint_update_all(ARMCPU *cpu) } } =20 -static void dbgbvr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - int i =3D ri->crm; - - raw_write(env, ri, value); - hw_breakpoint_update(cpu, i); -} - -static void dbgbcr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) -{ - ARMCPU *cpu =3D env_archcpu(env); - int i =3D ri->crm; - - /* - * BAS[3] is a read-only copy of BAS[2], and BAS[1] a read-only - * copy of BAS[0]. - */ - value =3D deposit64(value, 6, 1, extract64(value, 5, 1)); - value =3D deposit64(value, 8, 1, extract64(value, 7, 1)); - - raw_write(env, ri, value); - hw_breakpoint_update(cpu, i); -} - -void define_debug_regs(ARMCPU *cpu) -{ - /* - * Define v7 and v8 architectural debug registers. - * These are just dummy implementations for now. - */ - int i; - int wrps, brps, ctx_cmps; - - /* - * The Arm ARM says DBGDIDR is optional and deprecated if EL1 cannot - * use AArch32. Given that bit 15 is RES1, if the value is 0 then - * the register must not exist for this cpu. - */ - if (cpu->isar.dbgdidr !=3D 0) { - ARMCPRegInfo dbgdidr =3D { - .name =3D "DBGDIDR", .cp =3D 14, .crn =3D 0, .crm =3D 0, - .opc1 =3D 0, .opc2 =3D 0, - .access =3D PL0_R, .accessfn =3D access_tda, - .type =3D ARM_CP_CONST, .resetvalue =3D cpu->isar.dbgdidr, - }; - define_one_arm_cp_reg(cpu, &dbgdidr); - } - - /* - * DBGDEVID is present in the v7 debug architecture if - * DBGDIDR.DEVID_imp is 1 (bit 15); from v7.1 and on it is - * mandatory (and bit 15 is RES1). DBGDEVID1 and DBGDEVID2 exist - * from v7.1 of the debug architecture. Because no fields have yet - * been defined in DBGDEVID2 (and quite possibly none will ever - * be) we don't define an ARMISARegisters field for it. - * These registers exist only if EL1 can use AArch32, but that - * happens naturally because they are only PL1 accessible anyway. - */ - if (extract32(cpu->isar.dbgdidr, 15, 1)) { - ARMCPRegInfo dbgdevid =3D { - .name =3D "DBGDEVID", - .cp =3D 14, .opc1 =3D 0, .crn =3D 7, .opc2 =3D 2, .crn =3D 7, - .access =3D PL1_R, .accessfn =3D access_tda, - .type =3D ARM_CP_CONST, .resetvalue =3D cpu->isar.dbgdevid, - }; - define_one_arm_cp_reg(cpu, &dbgdevid); - } - if (cpu_isar_feature(aa32_debugv7p1, cpu)) { - ARMCPRegInfo dbgdevid12[] =3D { - { - .name =3D "DBGDEVID1", - .cp =3D 14, .opc1 =3D 0, .crn =3D 7, .opc2 =3D 1, .crn =3D= 7, - .access =3D PL1_R, .accessfn =3D access_tda, - .type =3D ARM_CP_CONST, .resetvalue =3D cpu->isar.dbgdevid= 1, - }, { - .name =3D "DBGDEVID2", - .cp =3D 14, .opc1 =3D 0, .crn =3D 7, .opc2 =3D 0, .crn =3D= 7, - .access =3D PL1_R, .accessfn =3D access_tda, - .type =3D ARM_CP_CONST, .resetvalue =3D 0, - }, - }; - define_arm_cp_regs(cpu, dbgdevid12); - } - - brps =3D arm_num_brps(cpu); - wrps =3D arm_num_wrps(cpu); - ctx_cmps =3D arm_num_ctx_cmps(cpu); - - assert(ctx_cmps <=3D brps); - - define_arm_cp_regs(cpu, debug_cp_reginfo); - - if (arm_feature(&cpu->env, ARM_FEATURE_LPAE)) { - define_arm_cp_regs(cpu, debug_lpae_cp_reginfo); - } - - for (i =3D 0; i < brps; i++) { - char *dbgbvr_el1_name =3D g_strdup_printf("DBGBVR%d_EL1", i); - char *dbgbcr_el1_name =3D g_strdup_printf("DBGBCR%d_EL1", i); - ARMCPRegInfo dbgregs[] =3D { - { .name =3D dbgbvr_el1_name, .state =3D ARM_CP_STATE_BOTH, - .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 0, .crm =3D i= , .opc2 =3D 4, - .access =3D PL1_RW, .accessfn =3D access_tda, - .fieldoffset =3D offsetof(CPUARMState, cp15.dbgbvr[i]), - .writefn =3D dbgbvr_write, .raw_writefn =3D raw_write - }, - { .name =3D dbgbcr_el1_name, .state =3D ARM_CP_STATE_BOTH, - .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 0, .crm =3D i= , .opc2 =3D 5, - .access =3D PL1_RW, .accessfn =3D access_tda, - .fieldoffset =3D offsetof(CPUARMState, cp15.dbgbcr[i]), - .writefn =3D dbgbcr_write, .raw_writefn =3D raw_write - }, - }; - define_arm_cp_regs(cpu, dbgregs); - g_free(dbgbvr_el1_name); - g_free(dbgbcr_el1_name); - } - - for (i =3D 0; i < wrps; i++) { - char *dbgwvr_el1_name =3D g_strdup_printf("DBGWVR%d_EL1", i); - char *dbgwcr_el1_name =3D g_strdup_printf("DBGWCR%d_EL1", i); - ARMCPRegInfo dbgregs[] =3D { - { .name =3D dbgwvr_el1_name, .state =3D ARM_CP_STATE_BOTH, - .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 0, .crm =3D i= , .opc2 =3D 6, - .access =3D PL1_RW, .accessfn =3D access_tda, - .fieldoffset =3D offsetof(CPUARMState, cp15.dbgwvr[i]), - .writefn =3D dbgwvr_write, .raw_writefn =3D raw_write - }, - { .name =3D dbgwcr_el1_name, .state =3D ARM_CP_STATE_BOTH, - .cp =3D 14, .opc0 =3D 2, .opc1 =3D 0, .crn =3D 0, .crm =3D i= , .opc2 =3D 7, - .access =3D PL1_RW, .accessfn =3D access_tda, - .fieldoffset =3D offsetof(CPUARMState, cp15.dbgwcr[i]), - .writefn =3D dbgwcr_write, .raw_writefn =3D raw_write - }, - }; - define_arm_cp_regs(cpu, dbgregs); - g_free(dbgwvr_el1_name); - g_free(dbgwcr_el1_name); - } -} - #if !defined(CONFIG_USER_ONLY) =20 vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len) diff --git a/target/arm/internals.h b/target/arm/internals.h index d9555309df..0983e65300 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1363,15 +1363,6 @@ int exception_target_el(CPUARMState *env); bool arm_singlestep_active(CPUARMState *env); bool arm_generate_debug_exceptions(CPUARMState *env); =20 -/* Add the cpreg definitions for debug related system registers */ -void define_debug_regs(ARMCPU *cpu); - -/* Effective value of MDCR_EL2 */ -static inline uint64_t arm_mdcr_el2_eff(CPUARMState *env) -{ - return arm_is_el2_enabled(env) ? env->cp15.mdcr_el2 : 0; -} - /* Powers of 2 for sve_vq_map et al. */ #define SVE_VQ_POW2_MAP \ ((1 << (1 - 1)) | (1 << (2 - 1)) | \ diff --git a/target/arm/machine.c b/target/arm/machine.c index d5dd6825b9..b83b073da4 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -849,8 +849,10 @@ static int cpu_post_load(void *opaque, int version_id) return -1; } =20 - hw_breakpoint_update_all(cpu); - hw_watchpoint_update_all(cpu); + if (tcg_enabled()) { + hw_breakpoint_update_all(cpu); + hw_watchpoint_update_all(cpu); + } =20 /* * TCG gen_update_fp_context() relies on the invariant that --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304411; cv=none; d=zohomail.com; s=zohoarc; b=HTYDqXQlzRE26FzJTXC8qeCrizlOLdF3PWoGqZNNj6+QMycwuRTWYpqN0Ijd4sAAlInmgcVTiecJW2Zs24/ywohghwqAT5cbdxUHh+EO5wAKWX5GE9I3CbtWp8a1eKEuF9fI1thytv3+41pEddbMLgR/vYZ2k4AU4sibAyxtmYY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304411; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=zmK4Ea/HaIadAjuTHVjNYSm3Ct4FOeHVNr26BCQ9nXw=; b=KP60N333rCZKhXa9JSQNaZlzH1xpUzy6S+MWv2vyZjRHCgKItQNp9k5+xTfOAaHiSLSi+e+gAQByYaqIwsRLEMZUkgLtLA+jDYdKVC89oGVJbfqmXFALibthlgTV1x8/bZcZT1mNt5EbwSYKjg8PqA6dbRHu2dNxSrxv9T8JOUE= 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 1673304411783739.3444220272784; Mon, 9 Jan 2023 14:46:51 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0r9-00047f-Hs; Mon, 09 Jan 2023 17:43:03 -0500 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 1pF0r8-00046g-JB; Mon, 09 Jan 2023 17:43:02 -0500 Received: from smtp-out1.suse.de ([195.135.220.28]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0r6-00041c-Su; Mon, 09 Jan 2023 17:43:02 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 8C3704D368; Mon, 9 Jan 2023 22:42:59 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id EEC0A13583; Mon, 9 Jan 2023 22:42:56 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id oJaRLXCYvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:42:56 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304179; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=zmK4Ea/HaIadAjuTHVjNYSm3Ct4FOeHVNr26BCQ9nXw=; b=yIVIDKnxNTIQkV0AOn9T8AB7ycAHjHE0rb4fOWA0r0YuGZwnF89Izk4JJ1RI1JO0alNLv5 du3vA6XVteNb4FT+cRrvFY6iX0ANjxe0vFPfqFaqQSvQM7UkCD47sMZVXjN4AaDsesQcbD 08rK6PVthgncRejhk8fjyYFH40iLnc8= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304179; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=zmK4Ea/HaIadAjuTHVjNYSm3Ct4FOeHVNr26BCQ9nXw=; b=MgHR6q0geCCn0qxHOwnhQFsLgP9tWECxDJ4J4BmfWjTsp3Mat7uGplVxQa34dL86qmLsyX zxuJDc3yRuzgoZCg== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf Subject: [RFC PATCH v2 07/19] target/arm: Move helper_set_pstate_* into cpregs.c Date: Mon, 9 Jan 2023 19:42:20 -0300 Message-Id: <20230109224232.11661-8-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=195.135.220.28; envelope-from=farosas@suse.de; helo=smtp-out1.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304413217100001 Content-Type: text/plain; charset="utf-8" We want to move sme_helper into the tcg directory, but the cpregs accessor functions cannot go along, otherwise they would be separate from the respective ARMCPRegInfo definition which needs to be compiled with CONFIG_TCG=3Dn as well. Signed-off-by: Fabiano Rosas --- target/arm/cpregs.c | 29 +++++++++++++++++++++++++++++ target/arm/sme_helper.c | 29 ----------------------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/target/arm/cpregs.c b/target/arm/cpregs.c index 88d71dbe70..a6deae9926 100644 --- a/target/arm/cpregs.c +++ b/target/arm/cpregs.c @@ -6633,6 +6633,35 @@ static CPAccessResult access_esm(CPUARMState *env, c= onst ARMCPRegInfo *ri, return CP_ACCESS_OK; } =20 +void helper_set_pstate_sm(CPUARMState *env, uint32_t i) +{ + if (i =3D=3D FIELD_EX64(env->svcr, SVCR, SM)) { + return; + } + env->svcr ^=3D R_SVCR_SM_MASK; + arm_reset_sve_state(env); +} + +void helper_set_pstate_za(CPUARMState *env, uint32_t i) +{ + if (i =3D=3D FIELD_EX64(env->svcr, SVCR, ZA)) { + return; + } + env->svcr ^=3D R_SVCR_ZA_MASK; + + /* + * ResetSMEState. + * + * SetPSTATE_ZA zeros on enable and disable. We can zero this only + * on enable: while disabled, the storage is inaccessible and the + * value does not matter. We're not saving the storage in vmstate + * when disabled either. + */ + if (i) { + memset(env->zarray, 0, sizeof(env->zarray)); + } +} + static void svcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { diff --git a/target/arm/sme_helper.c b/target/arm/sme_helper.c index f891306bb9..ed04daf5d4 100644 --- a/target/arm/sme_helper.c +++ b/target/arm/sme_helper.c @@ -38,35 +38,6 @@ void arm_reset_sve_state(CPUARMState *env) vfp_set_fpcr(env, 0x0800009f); } =20 -void helper_set_pstate_sm(CPUARMState *env, uint32_t i) -{ - if (i =3D=3D FIELD_EX64(env->svcr, SVCR, SM)) { - return; - } - env->svcr ^=3D R_SVCR_SM_MASK; - arm_reset_sve_state(env); -} - -void helper_set_pstate_za(CPUARMState *env, uint32_t i) -{ - if (i =3D=3D FIELD_EX64(env->svcr, SVCR, ZA)) { - return; - } - env->svcr ^=3D R_SVCR_ZA_MASK; - - /* - * ResetSMEState. - * - * SetPSTATE_ZA zeros on enable and disable. We can zero this only - * on enable: while disabled, the storage is inaccessible and the - * value does not matter. We're not saving the storage in vmstate - * when disabled either. - */ - if (i) { - memset(env->zarray, 0, sizeof(env->zarray)); - } -} - void helper_sme_zero(CPUARMState *env, uint32_t imm, uint32_t svl) { uint32_t i; --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304393; cv=none; d=zohomail.com; s=zohoarc; b=Tpao3pLhpVDYIhWFnM+hoi4kr6/OL+Nsi6N+ZRpsqwoQHqsjEyWy43bMmNi3ecXgG327UkNK/o4OqbXDl5q6dEnhkQRiSh+HmvTMbG2vTcuu7DZ0//H0KqJrDmTQ5bjbnfK92RdGyfVb0nH+xUkGOkgv3HlqXXzn8NwjWe9KN6Y= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304393; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=sG/6HUvkCgEta+b0aAU3bFfLkmRWUJOwE35xCvrY564=; b=Zl4wDdTgZDEOyEn0zVtHagajRQK9RXmXL9UIAoNv95YWh97Wk467qwru0hpoFrp0ZzDY8+5wgnToedQcySTYfXuUJcHRKsgs32Yr4ijqYWC82lBW9jQUodgourmVSQNjcwaDhpP/vOEvel/+2iPLwIY/A2q9N/WI0yw6TIDNKBQ= 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 1673304393317844.9493127885876; Mon, 9 Jan 2023 14:46:33 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0rE-0004Cq-Ts; Mon, 09 Jan 2023 17:43:08 -0500 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 1pF0rC-00048s-BB; Mon, 09 Jan 2023 17:43:06 -0500 Received: from smtp-out1.suse.de ([2001:67c:2178:6::1c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0rA-000425-2C; Mon, 09 Jan 2023 17:43:06 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 906DE3F9BF; Mon, 9 Jan 2023 22:43:02 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id F11F313583; Mon, 9 Jan 2023 22:42:59 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id MOQSLnOYvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:42:59 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304182; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sG/6HUvkCgEta+b0aAU3bFfLkmRWUJOwE35xCvrY564=; b=wnc8vp4UwwVWcAWWrISs0rKC6frLTptKRKcSpMhxu9RztKy4G4A1PDjTEcDIpL22QXWqZR DXdYBXjHkC9/G5Rc5+zZuyB6InrxdKsKHWmCHK4NvQacrRzuWkiCKnJIEPiVFoowLHvd/q f+XMPInfDah06hAiOpkvfAWSwX9qOEQ= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304182; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sG/6HUvkCgEta+b0aAU3bFfLkmRWUJOwE35xCvrY564=; b=adybg3gWytn6Wn9DakOIeM5b7JIKYqLXwwT3MUlRM3jnikiy9jcxAG/ioGBEwTX3yEyxcU fh8zhhP+mSms7yAQ== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf Subject: [RFC PATCH v2 08/19] target/arm: move translate modules to tcg/ Date: Mon, 9 Jan 2023 19:42:21 -0300 Message-Id: <20230109224232.11661-9-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=2001:67c:2178:6::1c; envelope-from=farosas@suse.de; helo=smtp-out1.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304395170100003 Introduce the target/arm/tcg directory. Its purpose is to hold the TCG code that is selected by CONFIG_TCG. Signed-off-by: Claudio Fontana Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson Reviewed-by: Alex Benn=C3=A9e Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- I also moved translate-{m-nocp,mve,neon,vfp,sme}.c Originally from: https://lore.kernel.org/r/20210416162824.25131-2-cfontana@suse.de [RFC v14 01/80] target/arm: move translate modules to tcg/ --- MAINTAINERS | 1 + target/arm/meson.build | 30 ++++------------------- target/arm/{ =3D> tcg}/a32-uncond.decode | 0 target/arm/{ =3D> tcg}/a32.decode | 0 target/arm/{ =3D> tcg}/m-nocp.decode | 0 target/arm/tcg/meson.build | 32 +++++++++++++++++++++++++ target/arm/{ =3D> tcg}/mve.decode | 0 target/arm/{ =3D> tcg}/neon-dp.decode | 0 target/arm/{ =3D> tcg}/neon-ls.decode | 0 target/arm/{ =3D> tcg}/neon-shared.decode | 0 target/arm/{ =3D> tcg}/sme-fa64.decode | 0 target/arm/{ =3D> tcg}/sme.decode | 0 target/arm/{ =3D> tcg}/sve.decode | 0 target/arm/{ =3D> tcg}/t16.decode | 0 target/arm/{ =3D> tcg}/t32.decode | 0 target/arm/{ =3D> tcg}/translate-a64.c | 0 target/arm/{ =3D> tcg}/translate-a64.h | 0 target/arm/{ =3D> tcg}/translate-m-nocp.c | 0 target/arm/{ =3D> tcg}/translate-mve.c | 0 target/arm/{ =3D> tcg}/translate-neon.c | 0 target/arm/{ =3D> tcg}/translate-sme.c | 0 target/arm/{ =3D> tcg}/translate-sve.c | 0 target/arm/{ =3D> tcg}/translate-vfp.c | 0 target/arm/{ =3D> tcg}/translate.c | 0 target/arm/{ =3D> tcg}/translate.h | 0 target/arm/{ =3D> tcg}/vfp-uncond.decode | 0 target/arm/{ =3D> tcg}/vfp.decode | 0 27 files changed, 37 insertions(+), 26 deletions(-) rename target/arm/{ =3D> tcg}/a32-uncond.decode (100%) rename target/arm/{ =3D> tcg}/a32.decode (100%) rename target/arm/{ =3D> tcg}/m-nocp.decode (100%) create mode 100644 target/arm/tcg/meson.build rename target/arm/{ =3D> tcg}/mve.decode (100%) rename target/arm/{ =3D> tcg}/neon-dp.decode (100%) rename target/arm/{ =3D> tcg}/neon-ls.decode (100%) rename target/arm/{ =3D> tcg}/neon-shared.decode (100%) rename target/arm/{ =3D> tcg}/sme-fa64.decode (100%) rename target/arm/{ =3D> tcg}/sme.decode (100%) rename target/arm/{ =3D> tcg}/sve.decode (100%) rename target/arm/{ =3D> tcg}/t16.decode (100%) rename target/arm/{ =3D> tcg}/t32.decode (100%) rename target/arm/{ =3D> tcg}/translate-a64.c (100%) rename target/arm/{ =3D> tcg}/translate-a64.h (100%) rename target/arm/{ =3D> tcg}/translate-m-nocp.c (100%) rename target/arm/{ =3D> tcg}/translate-mve.c (100%) rename target/arm/{ =3D> tcg}/translate-neon.c (100%) rename target/arm/{ =3D> tcg}/translate-sme.c (100%) rename target/arm/{ =3D> tcg}/translate-sve.c (100%) rename target/arm/{ =3D> tcg}/translate-vfp.c (100%) rename target/arm/{ =3D> tcg}/translate.c (100%) rename target/arm/{ =3D> tcg}/translate.h (100%) rename target/arm/{ =3D> tcg}/vfp-uncond.decode (100%) rename target/arm/{ =3D> tcg}/vfp.decode (100%) diff --git a/MAINTAINERS b/MAINTAINERS index 7a40d4d865..50ccb74593 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -159,6 +159,7 @@ M: Peter Maydell L: qemu-arm@nongnu.org S: Maintained F: target/arm/ +F: target/arm/tcg/ F: tests/tcg/arm/ F: tests/tcg/aarch64/ F: tests/qtest/arm-cpu-features.c diff --git a/target/arm/meson.build b/target/arm/meson.build index aa5aae9888..6dc7b800e6 100644 --- a/target/arm/meson.build +++ b/target/arm/meson.build @@ -1,22 +1,4 @@ -gen =3D [ - decodetree.process('sve.decode', extra_args: '--decode=3Ddisas_sve'), - decodetree.process('sme.decode', extra_args: '--decode=3Ddisas_sme'), - decodetree.process('sme-fa64.decode', extra_args: '--static-decode=3Ddis= as_sme_fa64'), - decodetree.process('neon-shared.decode', extra_args: '--decode=3Ddisas_n= eon_shared'), - decodetree.process('neon-dp.decode', extra_args: '--decode=3Ddisas_neon_= dp'), - decodetree.process('neon-ls.decode', extra_args: '--decode=3Ddisas_neon_= ls'), - decodetree.process('vfp.decode', extra_args: '--decode=3Ddisas_vfp'), - decodetree.process('vfp-uncond.decode', extra_args: '--decode=3Ddisas_vf= p_uncond'), - decodetree.process('m-nocp.decode', extra_args: '--decode=3Ddisas_m_nocp= '), - decodetree.process('mve.decode', extra_args: '--decode=3Ddisas_mve'), - decodetree.process('a32.decode', extra_args: '--static-decode=3Ddisas_a3= 2'), - decodetree.process('a32-uncond.decode', extra_args: '--static-decode=3Dd= isas_a32_uncond'), - decodetree.process('t32.decode', extra_args: '--static-decode=3Ddisas_t3= 2'), - decodetree.process('t16.decode', extra_args: ['-w', '16', '--static-deco= de=3Ddisas_t16']), -] - arm_ss =3D ss.source_set() -arm_ss.add(gen) arm_ss.add(files( 'cpregs.c', 'cpu.c', @@ -30,11 +12,6 @@ arm_ss.add(files( 'neon_helper.c', 'op_helper.c', 'tlb_helper.c', - 'translate.c', - 'translate-m-nocp.c', - 'translate-mve.c', - 'translate-neon.c', - 'translate-vfp.c', 'vec_helper.c', 'vfp_helper.c', 'cpu_tcg.c', @@ -51,9 +28,6 @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files( 'pauth_helper.c', 'sve_helper.c', 'sme_helper.c', - 'translate-a64.c', - 'translate-sve.c', - 'translate-sme.c', )) =20 arm_softmmu_ss =3D ss.source_set() @@ -68,5 +42,9 @@ arm_softmmu_ss.add(files( =20 subdir('hvf') =20 +if 'CONFIG_TCG' in config_all + subdir('tcg') +endif + target_arch +=3D {'arm': arm_ss} target_softmmu_arch +=3D {'arm': arm_softmmu_ss} diff --git a/target/arm/a32-uncond.decode b/target/arm/tcg/a32-uncond.decode similarity index 100% rename from target/arm/a32-uncond.decode rename to target/arm/tcg/a32-uncond.decode diff --git a/target/arm/a32.decode b/target/arm/tcg/a32.decode similarity index 100% rename from target/arm/a32.decode rename to target/arm/tcg/a32.decode diff --git a/target/arm/m-nocp.decode b/target/arm/tcg/m-nocp.decode similarity index 100% rename from target/arm/m-nocp.decode rename to target/arm/tcg/m-nocp.decode diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build new file mode 100644 index 0000000000..044561bd4d --- /dev/null +++ b/target/arm/tcg/meson.build @@ -0,0 +1,32 @@ +gen =3D [ + decodetree.process('sve.decode', extra_args: '--decode=3Ddisas_sve'), + decodetree.process('sme.decode', extra_args: '--decode=3Ddisas_sme'), + decodetree.process('sme-fa64.decode', extra_args: '--static-decode=3Ddis= as_sme_fa64'), + decodetree.process('neon-shared.decode', extra_args: '--decode=3Ddisas_n= eon_shared'), + decodetree.process('neon-dp.decode', extra_args: '--decode=3Ddisas_neon_= dp'), + decodetree.process('neon-ls.decode', extra_args: '--decode=3Ddisas_neon_= ls'), + decodetree.process('vfp.decode', extra_args: '--decode=3Ddisas_vfp'), + decodetree.process('vfp-uncond.decode', extra_args: '--decode=3Ddisas_vf= p_uncond'), + decodetree.process('m-nocp.decode', extra_args: '--decode=3Ddisas_m_nocp= '), + decodetree.process('mve.decode', extra_args: '--decode=3Ddisas_mve'), + decodetree.process('a32.decode', extra_args: '--static-decode=3Ddisas_a3= 2'), + decodetree.process('a32-uncond.decode', extra_args: '--static-decode=3Dd= isas_a32_uncond'), + decodetree.process('t32.decode', extra_args: '--static-decode=3Ddisas_t3= 2'), + decodetree.process('t16.decode', extra_args: ['-w', '16', '--static-deco= de=3Ddisas_t16']), +] + +arm_ss.add(gen) + +arm_ss.add(files( + 'translate.c', + 'translate-m-nocp.c', + 'translate-mve.c', + 'translate-neon.c', + 'translate-vfp.c', +)) + +arm_ss.add(when: 'TARGET_AARCH64', if_true: files( + 'translate-a64.c', + 'translate-sve.c', + 'translate-sme.c', +)) diff --git a/target/arm/mve.decode b/target/arm/tcg/mve.decode similarity index 100% rename from target/arm/mve.decode rename to target/arm/tcg/mve.decode diff --git a/target/arm/neon-dp.decode b/target/arm/tcg/neon-dp.decode similarity index 100% rename from target/arm/neon-dp.decode rename to target/arm/tcg/neon-dp.decode diff --git a/target/arm/neon-ls.decode b/target/arm/tcg/neon-ls.decode similarity index 100% rename from target/arm/neon-ls.decode rename to target/arm/tcg/neon-ls.decode diff --git a/target/arm/neon-shared.decode b/target/arm/tcg/neon-shared.dec= ode similarity index 100% rename from target/arm/neon-shared.decode rename to target/arm/tcg/neon-shared.decode diff --git a/target/arm/sme-fa64.decode b/target/arm/tcg/sme-fa64.decode similarity index 100% rename from target/arm/sme-fa64.decode rename to target/arm/tcg/sme-fa64.decode diff --git a/target/arm/sme.decode b/target/arm/tcg/sme.decode similarity index 100% rename from target/arm/sme.decode rename to target/arm/tcg/sme.decode diff --git a/target/arm/sve.decode b/target/arm/tcg/sve.decode similarity index 100% rename from target/arm/sve.decode rename to target/arm/tcg/sve.decode diff --git a/target/arm/t16.decode b/target/arm/tcg/t16.decode similarity index 100% rename from target/arm/t16.decode rename to target/arm/tcg/t16.decode diff --git a/target/arm/t32.decode b/target/arm/tcg/t32.decode similarity index 100% rename from target/arm/t32.decode rename to target/arm/tcg/t32.decode diff --git a/target/arm/translate-a64.c b/target/arm/tcg/translate-a64.c similarity index 100% rename from target/arm/translate-a64.c rename to target/arm/tcg/translate-a64.c diff --git a/target/arm/translate-a64.h b/target/arm/tcg/translate-a64.h similarity index 100% rename from target/arm/translate-a64.h rename to target/arm/tcg/translate-a64.h diff --git a/target/arm/translate-m-nocp.c b/target/arm/tcg/translate-m-noc= p.c similarity index 100% rename from target/arm/translate-m-nocp.c rename to target/arm/tcg/translate-m-nocp.c diff --git a/target/arm/translate-mve.c b/target/arm/tcg/translate-mve.c similarity index 100% rename from target/arm/translate-mve.c rename to target/arm/tcg/translate-mve.c diff --git a/target/arm/translate-neon.c b/target/arm/tcg/translate-neon.c similarity index 100% rename from target/arm/translate-neon.c rename to target/arm/tcg/translate-neon.c diff --git a/target/arm/translate-sme.c b/target/arm/tcg/translate-sme.c similarity index 100% rename from target/arm/translate-sme.c rename to target/arm/tcg/translate-sme.c diff --git a/target/arm/translate-sve.c b/target/arm/tcg/translate-sve.c similarity index 100% rename from target/arm/translate-sve.c rename to target/arm/tcg/translate-sve.c diff --git a/target/arm/translate-vfp.c b/target/arm/tcg/translate-vfp.c similarity index 100% rename from target/arm/translate-vfp.c rename to target/arm/tcg/translate-vfp.c diff --git a/target/arm/translate.c b/target/arm/tcg/translate.c similarity index 100% rename from target/arm/translate.c rename to target/arm/tcg/translate.c diff --git a/target/arm/translate.h b/target/arm/tcg/translate.h similarity index 100% rename from target/arm/translate.h rename to target/arm/tcg/translate.h diff --git a/target/arm/vfp-uncond.decode b/target/arm/tcg/vfp-uncond.decode similarity index 100% rename from target/arm/vfp-uncond.decode rename to target/arm/tcg/vfp-uncond.decode diff --git a/target/arm/vfp.decode b/target/arm/tcg/vfp.decode similarity index 100% rename from target/arm/vfp.decode rename to target/arm/tcg/vfp.decode --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304800; cv=none; d=zohomail.com; s=zohoarc; b=e4IXoh5vnwOVVM6SdQfLZqIl0ERjM+VbGDKc/X382l4VlZ3km3p0rQCAZ5s7jKN4VxNkfc3SAYmb6FbMhs82qj7GQ4+Lwtdu2Kk9acn0GtP2m09+DHrQ0KlGHe924joV/SgGqy3i+kZEPk8zrJYZbZ/LvDFZlc8BIwv8wppGHdw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304800; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=pKLwvhRPuXtRlcYY51nLSTjafk4HZRRTFDg9CQyhWCo=; b=AZ/M1/MqH9mMB28r1jMofMXdqN+DzB/xAodmnSvOe+x+KmdpuY5C4As6IUt4rLbBcwpLEBULS4JuyHsCh7MR8TMlhjnE8N/k9P5WyhEhd6EUNw7K/BigJnyrWplLmufVyjs0s6/T37Q6kzJNKfG32xwFSMfqBNe/lJX2v1Td9VE= 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 1673304800462959.2553548253093; Mon, 9 Jan 2023 14:53:20 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0rH-0004K1-J4; Mon, 09 Jan 2023 17:43:11 -0500 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 1pF0rF-0004EP-Jm; Mon, 09 Jan 2023 17:43:09 -0500 Received: from smtp-out1.suse.de ([2001:67c:2178:6::1c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0rD-00042O-El; Mon, 09 Jan 2023 17:43:09 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 96ECF3F8AB; Mon, 9 Jan 2023 22:43:05 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 0243413583; Mon, 9 Jan 2023 22:43:02 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id wMQ3L3aYvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:43:02 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304185; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pKLwvhRPuXtRlcYY51nLSTjafk4HZRRTFDg9CQyhWCo=; b=yCqqrgUVS5fQkv4+fNWnyo9bd6AlfusXPXtYvl5TC1784PgGoVmfSgFIUgAKy8ZaIF5rb6 0CJ1L838/a61AXmtI01LJ7PjtUVeXbIXU+EABLR7nAXUejFoCIYaL1xzCFvxYAzUU+bQLm /QY1usNrX0yEsi1YxzOFGwRayo06RNU= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304185; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pKLwvhRPuXtRlcYY51nLSTjafk4HZRRTFDg9CQyhWCo=; b=9/psVeLXlOwZq3WD7gjlCikITPpYtN6SuBzh9ZeRNvbt7gRc9mQWR+Rc2uQuIdRnPLfydI Sd6crDUiSzsS+TCg== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf Subject: [RFC PATCH v2 09/19] target/arm: move helpers to tcg/ Date: Mon, 9 Jan 2023 19:42:22 -0300 Message-Id: <20230109224232.11661-10-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=2001:67c:2178:6::1c; envelope-from=farosas@suse.de; helo=smtp-out1.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304801717100007 Content-Type: text/plain; charset="utf-8" From: Claudio Fontana Signed-off-by: Claudio Fontana Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson --- Included {sme,mve}_helper.c and left a couple of files behind that still have non-tcg code to be removed from them: helper.c (and op_helper.h as a dep) vfp_helper.c Originally from: https://lore.kernel.org/r/20210416162824.25131-3-cfontana@suse.de [RFC v14 02/80] target/arm: move helpers to tcg/ --- target/arm/meson.build | 16 ++-------------- target/arm/tcg-stubs.c | 28 ++++++++++++++++++++++++++++ target/arm/{ =3D> tcg}/crypto_helper.c | 0 target/arm/{ =3D> tcg}/debug_helper.c | 0 target/arm/{ =3D> tcg}/helper-a64.c | 0 target/arm/{ =3D> tcg}/iwmmxt_helper.c | 0 target/arm/{ =3D> tcg}/m_helper.c | 0 target/arm/tcg/meson.build | 14 ++++++++++++++ target/arm/{ =3D> tcg}/mte_helper.c | 0 target/arm/{ =3D> tcg}/mve_helper.c | 0 target/arm/{ =3D> tcg}/neon_helper.c | 0 target/arm/{ =3D> tcg}/op_helper.c | 0 target/arm/{ =3D> tcg}/pauth_helper.c | 0 target/arm/{ =3D> tcg}/sme_helper.c | 0 target/arm/{ =3D> tcg}/sve_helper.c | 0 target/arm/{ =3D> tcg}/tlb_helper.c | 0 target/arm/{ =3D> tcg}/vec_helper.c | 0 target/arm/{ =3D> tcg}/vec_internal.h | 0 18 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 target/arm/tcg-stubs.c rename target/arm/{ =3D> tcg}/crypto_helper.c (100%) rename target/arm/{ =3D> tcg}/debug_helper.c (100%) rename target/arm/{ =3D> tcg}/helper-a64.c (100%) rename target/arm/{ =3D> tcg}/iwmmxt_helper.c (100%) rename target/arm/{ =3D> tcg}/m_helper.c (100%) rename target/arm/{ =3D> tcg}/mte_helper.c (100%) rename target/arm/{ =3D> tcg}/mve_helper.c (100%) rename target/arm/{ =3D> tcg}/neon_helper.c (100%) rename target/arm/{ =3D> tcg}/op_helper.c (100%) rename target/arm/{ =3D> tcg}/pauth_helper.c (100%) rename target/arm/{ =3D> tcg}/sme_helper.c (100%) rename target/arm/{ =3D> tcg}/sve_helper.c (100%) rename target/arm/{ =3D> tcg}/tlb_helper.c (100%) rename target/arm/{ =3D> tcg}/vec_helper.c (100%) rename target/arm/{ =3D> tcg}/vec_internal.h (100%) diff --git a/target/arm/meson.build b/target/arm/meson.build index 6dc7b800e6..01143a805c 100644 --- a/target/arm/meson.build +++ b/target/arm/meson.build @@ -2,17 +2,8 @@ arm_ss =3D ss.source_set() arm_ss.add(files( 'cpregs.c', 'cpu.c', - 'crypto_helper.c', - 'debug_helper.c', 'gdbstub.c', 'helper.c', - 'iwmmxt_helper.c', - 'm_helper.c', - 'mve_helper.c', - 'neon_helper.c', - 'op_helper.c', - 'tlb_helper.c', - 'vec_helper.c', 'vfp_helper.c', 'cpu_tcg.c', )) @@ -23,11 +14,6 @@ arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', '= kvm64.c'), if_false: fil arm_ss.add(when: 'TARGET_AARCH64', if_true: files( 'cpu64.c', 'gdbstub64.c', - 'helper-a64.c', - 'mte_helper.c', - 'pauth_helper.c', - 'sve_helper.c', - 'sme_helper.c', )) =20 arm_softmmu_ss =3D ss.source_set() @@ -44,6 +30,8 @@ subdir('hvf') =20 if 'CONFIG_TCG' in config_all subdir('tcg') +else + arm_ss.add(files('tcg-stubs.c')) endif =20 target_arch +=3D {'arm': arm_ss} diff --git a/target/arm/tcg-stubs.c b/target/arm/tcg-stubs.c new file mode 100644 index 0000000000..021489cf38 --- /dev/null +++ b/target/arm/tcg-stubs.c @@ -0,0 +1,28 @@ +/* + * QEMU ARM stubs for some TCG helper functions + * + * Copyright 2021 SUSE LLC + * + * This work is licensed under the terms of the GNU GPL, version 2 or late= r. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "internals.h" + +void write_v7m_exception(CPUARMState *env, uint32_t new_exc) +{ + g_assert_not_reached(); +} + +void raise_exception_ra(CPUARMState *env, uint32_t excp, uint32_t syndrome, + uint32_t target_el, uintptr_t ra) +{ + g_assert_not_reached(); +} + +void arm_reset_sve_state(CPUARMState *env) +{ + g_assert_not_reached(); +} diff --git a/target/arm/crypto_helper.c b/target/arm/tcg/crypto_helper.c similarity index 100% rename from target/arm/crypto_helper.c rename to target/arm/tcg/crypto_helper.c diff --git a/target/arm/debug_helper.c b/target/arm/tcg/debug_helper.c similarity index 100% rename from target/arm/debug_helper.c rename to target/arm/tcg/debug_helper.c diff --git a/target/arm/helper-a64.c b/target/arm/tcg/helper-a64.c similarity index 100% rename from target/arm/helper-a64.c rename to target/arm/tcg/helper-a64.c diff --git a/target/arm/iwmmxt_helper.c b/target/arm/tcg/iwmmxt_helper.c similarity index 100% rename from target/arm/iwmmxt_helper.c rename to target/arm/tcg/iwmmxt_helper.c diff --git a/target/arm/m_helper.c b/target/arm/tcg/m_helper.c similarity index 100% rename from target/arm/m_helper.c rename to target/arm/tcg/m_helper.c diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build index 044561bd4d..c27ac2939c 100644 --- a/target/arm/tcg/meson.build +++ b/target/arm/tcg/meson.build @@ -23,10 +23,24 @@ arm_ss.add(files( 'translate-mve.c', 'translate-neon.c', 'translate-vfp.c', + 'crypto_helper.c', + 'debug_helper.c', + 'iwmmxt_helper.c', + 'm_helper.c', + 'mve_helper.c', + 'neon_helper.c', + 'op_helper.c', + 'tlb_helper.c', + 'vec_helper.c', )) =20 arm_ss.add(when: 'TARGET_AARCH64', if_true: files( 'translate-a64.c', 'translate-sve.c', 'translate-sme.c', + 'helper-a64.c', + 'mte_helper.c', + 'pauth_helper.c', + 'sme_helper.c', + 'sve_helper.c', )) diff --git a/target/arm/mte_helper.c b/target/arm/tcg/mte_helper.c similarity index 100% rename from target/arm/mte_helper.c rename to target/arm/tcg/mte_helper.c diff --git a/target/arm/mve_helper.c b/target/arm/tcg/mve_helper.c similarity index 100% rename from target/arm/mve_helper.c rename to target/arm/tcg/mve_helper.c diff --git a/target/arm/neon_helper.c b/target/arm/tcg/neon_helper.c similarity index 100% rename from target/arm/neon_helper.c rename to target/arm/tcg/neon_helper.c diff --git a/target/arm/op_helper.c b/target/arm/tcg/op_helper.c similarity index 100% rename from target/arm/op_helper.c rename to target/arm/tcg/op_helper.c diff --git a/target/arm/pauth_helper.c b/target/arm/tcg/pauth_helper.c similarity index 100% rename from target/arm/pauth_helper.c rename to target/arm/tcg/pauth_helper.c diff --git a/target/arm/sme_helper.c b/target/arm/tcg/sme_helper.c similarity index 100% rename from target/arm/sme_helper.c rename to target/arm/tcg/sme_helper.c diff --git a/target/arm/sve_helper.c b/target/arm/tcg/sve_helper.c similarity index 100% rename from target/arm/sve_helper.c rename to target/arm/tcg/sve_helper.c diff --git a/target/arm/tlb_helper.c b/target/arm/tcg/tlb_helper.c similarity index 100% rename from target/arm/tlb_helper.c rename to target/arm/tcg/tlb_helper.c diff --git a/target/arm/vec_helper.c b/target/arm/tcg/vec_helper.c similarity index 100% rename from target/arm/vec_helper.c rename to target/arm/tcg/vec_helper.c diff --git a/target/arm/vec_internal.h b/target/arm/tcg/vec_internal.h similarity index 100% rename from target/arm/vec_internal.h rename to target/arm/tcg/vec_internal.h --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304822; cv=none; d=zohomail.com; s=zohoarc; b=MWkhPRgk8sqnReWJU9ct0SPiiN4GJOnPSxsVGXyDOsqh1ZmEXcMetDBvrIYdZUm/nMtgio28I5syeyuPciEBXcJtgqkVi+MOGhJ4AH4KvVIBSjEMYBrWO76Nbr7TOnbWMMBJ2r8OkXH7gPJpOnmGde/WtR7PS+gXoTWWy1bXtFc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304822; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=s2fBiDJmUaPyNIfgWPRbS/aVGtxHXhf27DnSmH1JgYU=; b=alqy/ddOlp8DKeL+193BwyUIM4ct8KuR2QgpndN6D96TkkTdSxC76huvdmenteJVAytyZvvNkHIdUHCy3NleRUOkAnDbqUQCQ3cdGhsur3UCn4upbK2Z3K2lxcgR1vMp3wXVJDogtata3uCKj2C7CUqQFjWsfKOIisJMS7sTcxQ= 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 1673304822439191.83111475586065; Mon, 9 Jan 2023 14:53:42 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0rM-0004SJ-3C; Mon, 09 Jan 2023 17:43:16 -0500 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 1pF0rJ-0004Oc-T0; Mon, 09 Jan 2023 17:43:13 -0500 Received: from smtp-out2.suse.de ([195.135.220.29]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0rI-000436-BV; Mon, 09 Jan 2023 17:43:13 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 97F995CDD9; Mon, 9 Jan 2023 22:43:08 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 06D7913583; Mon, 9 Jan 2023 22:43:05 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id MG2CMHmYvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:43:05 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304188; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=s2fBiDJmUaPyNIfgWPRbS/aVGtxHXhf27DnSmH1JgYU=; b=QtXXJ72fizud//BFJRx6lmqoxQYii5s9eQkzrBZXS0o1+H0sx2Sf/CNHCx5DNmNhLDdV7y SZf7Rh8hjva45WAgsoEpTdyAmTuwmRGxRJreV1DSCFYuMEpkqcRkpyHFiD36q20Jyg7nnn oyotXMyRteQqp8m9psva22r3rCcP43Q= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304188; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=s2fBiDJmUaPyNIfgWPRbS/aVGtxHXhf27DnSmH1JgYU=; b=QMHGZL8e3LrXWO4JFs/JFOpGM9mdkQEnkXdg8GVze7AMDIV7lji0BxqY3Z9XP5olgJ+E9Z Sv8Vjdqcb0ETSFBA== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf Subject: [RFC PATCH v2 10/19] target/arm: Move psci.c into the tcg directory Date: Mon, 9 Jan 2023 19:42:23 -0300 Message-Id: <20230109224232.11661-11-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=195.135.220.29; envelope-from=farosas@suse.de; helo=smtp-out2.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304823794100003 From: Claudio Fontana Signed-off-by: Claudio Fontana Reviewed-by: Richard Henderson Reviewed-by: Alex Benn=C3=A9e Signed-off-by: Fabiano Rosas --- target/arm/meson.build | 1 - target/arm/tcg/meson.build | 4 ++++ target/arm/{ =3D> tcg}/psci.c | 0 3 files changed, 4 insertions(+), 1 deletion(-) rename target/arm/{ =3D> tcg}/psci.c (100%) diff --git a/target/arm/meson.build b/target/arm/meson.build index 01143a805c..595d22a099 100644 --- a/target/arm/meson.build +++ b/target/arm/meson.build @@ -22,7 +22,6 @@ arm_softmmu_ss.add(files( 'arm-powerctl.c', 'machine.c', 'monitor.c', - 'psci.c', 'ptw.c', )) =20 diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build index c27ac2939c..47006f903c 100644 --- a/target/arm/tcg/meson.build +++ b/target/arm/tcg/meson.build @@ -44,3 +44,7 @@ arm_ss.add(when: 'TARGET_AARCH64', if_true: files( 'sme_helper.c', 'sve_helper.c', )) + +arm_softmmu_ss.add(files( + 'psci.c', +)) diff --git a/target/arm/psci.c b/target/arm/tcg/psci.c similarity index 100% rename from target/arm/psci.c rename to target/arm/tcg/psci.c --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304325; cv=none; d=zohomail.com; s=zohoarc; b=CxbH8KKmzPzrT3VS2QShnhUQY1xf8+/J5wdFgPKVZS9khUISruqiKrC44QoM7wgWxuL74lvEZ8XvauM73dp8JWYJZW2VVYFdi6zGqLpWkdR8VGBrRJ3jqNT/rKD8SXahTFmIkRmh8Jj9WmR5btOh4PHff6YG4fWxoOuRXTQpCNU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304325; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=Em5sFCFrBn9k7p4ReWFU7L6za46reGU1ENIoYYxEJMs=; b=J8ICwBOWtzHdUSV4oV9iZeg9FPfoXvCzXDCEMUANc2EDIpkFgyweVtrT25VYNT8Z7lj2xcL932DrghPbVq21lgfqIa8AUk9JU5Y7OCxMJ9xYTzTLKBtyxWz92Cpd+9WWoalU4iDETM3qZtQzLHELmDxdf40DgODVUGY9lSsMkMs= 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 1673304325841470.1478463510466; Mon, 9 Jan 2023 14:45:25 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0rP-0004UD-TX; Mon, 09 Jan 2023 17:43:19 -0500 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 1pF0rL-0004Rd-KY; Mon, 09 Jan 2023 17:43:15 -0500 Received: from smtp-out1.suse.de ([2001:67c:2178:6::1c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0rJ-00043R-OB; Mon, 09 Jan 2023 17:43:15 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 9ED153F8AB; Mon, 9 Jan 2023 22:43:11 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 07C7513583; Mon, 9 Jan 2023 22:43:08 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id IMDBMHyYvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:43:08 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304191; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Em5sFCFrBn9k7p4ReWFU7L6za46reGU1ENIoYYxEJMs=; b=DSzwPSzv+zZGnP2/Z1OXdR9GX16znS23qfgncgzcTK5B8Oy8ZnroF/bsKpU6//NNFsL6j/ MXI3HfMEJhNTEvVKtwxWuPKUGGIeYh5gFRt/PDgbf7tB/tEnva4LQf3GQ2ObjZIhezRCpp N1PW7uAXVRpaAZNRclv9V/IwxTRtwWI= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304191; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Em5sFCFrBn9k7p4ReWFU7L6za46reGU1ENIoYYxEJMs=; b=2rqqNYXB+wNBpZR0sfQOhFvgSWBRh74URcg1n63SmXOD26bJs5dPcQN813u/SLOgbpw9ON ah+al3DMU9mXUsDQ== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf Subject: [RFC PATCH v2 11/19] target/arm: Wrap arm_rebuild_hflags calls with tcg_enabled Date: Mon, 9 Jan 2023 19:42:24 -0300 Message-Id: <20230109224232.11661-12-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=2001:67c:2178:6::1c; envelope-from=farosas@suse.de; helo=smtp-out1.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304326719100001 Content-Type: text/plain; charset="utf-8" This is in preparation to moving the hflags code into its own file under the tcg/ directory. Signed-off-by: Fabiano Rosas --- I extracted these into a separate patch so we can discuss. If I move the tcg_enabled check to a header that would add overhead for all the calls where we know for sure that the code is running with TCG. And I don't think we want a new arm_rebuild_hflags_foo to be used for common code. --- hw/arm/boot.c | 6 +++++- hw/intc/armv7m_nvic.c | 20 +++++++++++++------- target/arm/arm-powerctl.c | 7 +++++-- target/arm/cpregs.c | 8 ++++++-- target/arm/cpu.c | 4 ++-- target/arm/helper.c | 12 +++++++++--- target/arm/machine.c | 6 +++++- 7 files changed, 45 insertions(+), 18 deletions(-) diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 3d7d11f782..1e021c4a34 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -15,6 +15,7 @@ #include "hw/arm/boot.h" #include "hw/arm/linux-boot-if.h" #include "sysemu/kvm.h" +#include "sysemu/tcg.h" #include "sysemu/sysemu.h" #include "sysemu/numa.h" #include "hw/boards.h" @@ -827,7 +828,10 @@ static void do_cpu_reset(void *opaque) info->secondary_cpu_reset_hook(cpu, info); } } - arm_rebuild_hflags(env); + + if (tcg_enabled()) { + arm_rebuild_hflags(env); + } } } =20 diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 1f7763964c..74ac8f610c 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -18,6 +18,7 @@ #include "hw/intc/armv7m_nvic.h" #include "hw/irq.h" #include "hw/qdev-properties.h" +#include "sysemu/tcg.h" #include "sysemu/runstate.h" #include "target/arm/cpu.h" #include "exec/exec-all.h" @@ -2466,8 +2467,10 @@ static MemTxResult nvic_sysreg_write(void *opaque, h= waddr addr, /* This is UNPREDICTABLE; treat as RAZ/WI */ =20 exit_ok: - /* Ensure any changes made are reflected in the cached hflags. */ - arm_rebuild_hflags(&s->cpu->env); + if (tcg_enabled()) { + /* Ensure any changes made are reflected in the cached hflags. */ + arm_rebuild_hflags(&s->cpu->env); + } return MEMTX_OK; } =20 @@ -2648,11 +2651,14 @@ static void armv7m_nvic_reset(DeviceState *dev) } } =20 - /* - * We updated state that affects the CPU's MMUidx and thus its hflags; - * and we can't guarantee that we run before the CPU reset function. - */ - arm_rebuild_hflags(&s->cpu->env); + if (tcg_enabled()) { + /* + * We updated state that affects the CPU's MMUidx and thus its + * hflags; and we can't guarantee that we run before the CPU + * reset function. + */ + arm_rebuild_hflags(&s->cpu->env); + } } =20 static void nvic_systick_trigger(void *opaque, int n, int level) diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c index b75f813b40..326a03153d 100644 --- a/target/arm/arm-powerctl.c +++ b/target/arm/arm-powerctl.c @@ -15,6 +15,7 @@ #include "arm-powerctl.h" #include "qemu/log.h" #include "qemu/main-loop.h" +#include "sysemu/tcg.h" =20 #ifndef DEBUG_ARM_POWERCTL #define DEBUG_ARM_POWERCTL 0 @@ -127,8 +128,10 @@ static void arm_set_cpu_on_async_work(CPUState *target= _cpu_state, target_cpu->env.regs[0] =3D info->context_id; } =20 - /* CP15 update requires rebuilding hflags */ - arm_rebuild_hflags(&target_cpu->env); + if (tcg_enabled()) { + /* CP15 update requires rebuilding hflags */ + arm_rebuild_hflags(&target_cpu->env); + } =20 /* Start the new CPU at the requested address */ cpu_set_pc(target_cpu_state, info->entry); diff --git a/target/arm/cpregs.c b/target/arm/cpregs.c index a6deae9926..3b0458e188 100644 --- a/target/arm/cpregs.c +++ b/target/arm/cpregs.c @@ -16,6 +16,7 @@ #include "exec/exec-all.h" #include "hw/irq.h" #include "sysemu/cpu-timers.h" +#include "sysemu/tcg.h" #include "qapi/error.h" #include "qemu/guest-random.h" #include "cpregs.h" @@ -5178,7 +5179,7 @@ static void sctlr_write(CPUARMState *env, const ARMCP= RegInfo *ri, /* This may enable/disable the MMU, so do a TLB flush. */ tlb_flush(CPU(cpu)); =20 - if (ri->type & ARM_CP_SUPPRESS_TB_END) { + if (tcg_enabled() && ri->type & ARM_CP_SUPPRESS_TB_END) { /* * Normally we would always end the TB on an SCTLR write; see the * comment in ARMCPRegInfo sctlr initialization below for why Xsca= le @@ -6667,7 +6668,10 @@ static void svcr_write(CPUARMState *env, const ARMCP= RegInfo *ri, { helper_set_pstate_sm(env, FIELD_EX64(value, SVCR, SM)); helper_set_pstate_za(env, FIELD_EX64(value, SVCR, ZA)); - arm_rebuild_hflags(env); + + if (tcg_enabled()) { + arm_rebuild_hflags(env); + } } =20 static void smcr_write(CPUARMState *env, const ARMCPRegInfo *ri, diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 4cb524a102..1d5f97a055 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -540,9 +540,9 @@ static void arm_cpu_reset_hold(Object *obj) if (tcg_enabled()) { hw_breakpoint_update_all(cpu); hw_watchpoint_update_all(cpu); - } =20 - arm_rebuild_hflags(env); + arm_rebuild_hflags(env); + } } =20 #if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) diff --git a/target/arm/helper.c b/target/arm/helper.c index 1809df829b..acefd4b69f 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -570,7 +570,7 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_= t mask, } mask &=3D ~CACHED_CPSR_BITS; env->uncached_cpsr =3D (env->uncached_cpsr & ~mask) | (val & mask); - if (rebuild_hflags) { + if (tcg_enabled() && rebuild_hflags) { arm_rebuild_hflags(env); } } @@ -1129,7 +1129,10 @@ static void take_aarch32_exception(CPUARMState *env,= int new_mode, env->regs[14] =3D env->regs[15] + offset; } env->regs[15] =3D newpc; - arm_rebuild_hflags(env); + + if (tcg_enabled()) { + arm_rebuild_hflags(env); + } } =20 static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs) @@ -1685,7 +1688,10 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *c= s) pstate_write(env, PSTATE_DAIF | new_mode); env->aarch64 =3D true; aarch64_restore_sp(env, new_el); - helper_rebuild_hflags_a64(env, new_el); + + if (tcg_enabled()) { + helper_rebuild_hflags_a64(env, new_el); + } =20 env->pc =3D addr; =20 diff --git a/target/arm/machine.c b/target/arm/machine.c index b83b073da4..fd5be7a558 100644 --- a/target/arm/machine.c +++ b/target/arm/machine.c @@ -2,6 +2,7 @@ #include "cpu.h" #include "qemu/error-report.h" #include "sysemu/kvm.h" +#include "sysemu/tcg.h" #include "kvm_arm.h" #include "internals.h" #include "migration/cpu.h" @@ -871,7 +872,10 @@ static int cpu_post_load(void *opaque, int version_id) if (!kvm_enabled()) { pmu_op_finish(&cpu->env); } - arm_rebuild_hflags(&cpu->env); + + if (tcg_enabled()) { + arm_rebuild_hflags(&cpu->env); + } =20 return 0; } --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304606; cv=none; d=zohomail.com; s=zohoarc; b=lNA5Q1Zec/Fl5d4yxyk0XUHHh5XXkPNO7WnLOo7CXl3gliPQe2Utbhxt/EVnAhBbLvr6RFi8fpTW+eUEXE+Kh+c2HBrM+/Be13KlSLeWI9EP3znhiKCrPCuQWqyDuZgjzwGAWKuLbIuB/iouAD88xNA84Q3F4/jWmBwCCGHp3tU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304606; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=2/yjNEHJNaEULeciYQUGHgrHQEQ93O3h/mzH44EwR50=; b=Am9iIGXBW2LMf58sfkQmJ0KwSC84ZnkElCTrNi4ijimOjZAv9aSUOs63ekbA+XUbXtHhyDNgmG4Rh/t4QH4AxQrbUZ1LP3lOlEpHIyCKif5Ns/zMYYwvOBzY8afyYX8GQCOdom0nABF2BglGZWogL3HEDW1fkKpn0OEapFslgX8= 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 1673304606479206.9094655496599; Mon, 9 Jan 2023 14:50:06 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0rR-0004YE-O5; Mon, 09 Jan 2023 17:43:21 -0500 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 1pF0rQ-0004Um-0G; Mon, 09 Jan 2023 17:43:20 -0500 Received: from smtp-out2.suse.de ([2001:67c:2178:6::1d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0rM-00043q-K4; Mon, 09 Jan 2023 17:43:19 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 92F035CDE0; Mon, 9 Jan 2023 22:43:14 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 03EDF13583; Mon, 9 Jan 2023 22:43:11 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id UJj2L3+YvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:43:11 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304194; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=2/yjNEHJNaEULeciYQUGHgrHQEQ93O3h/mzH44EwR50=; b=FDMQLFVnv3uN8uJsV7NB/K+0GIT+eRVSbSygg2tAh1APyI7eWMtgrycELW/ZdEFeCZiXki OK0EmW7siMmr2J5/2u+CPBAMLxvj4wGBcr46HOsO709FiIZ990Rem1twyVCEuel6/Gfff+ PuKQeZk2z31JQZyQotL3P8GhPHuKIx4= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304194; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=2/yjNEHJNaEULeciYQUGHgrHQEQ93O3h/mzH44EwR50=; b=oKN0hUxsRKBxCdQP9Cq7i3SrBkIunqbUE323IgDJPUo8GGTC6bOu+Dnd35iMGDBnpANuTW ZNQl7k1/gCQ5qFBw== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf Subject: [RFC PATCH v2 12/19] target/arm: Move hflags code into the tcg directory Date: Mon, 9 Jan 2023 19:42:25 -0300 Message-Id: <20230109224232.11661-13-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=2001:67c:2178:6::1d; envelope-from=farosas@suse.de; helo=smtp-out2.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304608191100003 Content-Type: text/plain; charset="utf-8" The hflags are used only for TCG code, so introduce a new file hflags.c to keep that code. Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson --- target/arm/helper.c | 361 +----------------------------------- target/arm/internals.h | 2 + target/arm/tcg-stubs.c | 5 + target/arm/tcg/hflags.c | 370 +++++++++++++++++++++++++++++++++++++ target/arm/tcg/meson.build | 1 + 5 files changed, 379 insertions(+), 360 deletions(-) create mode 100644 target/arm/tcg/hflags.c diff --git a/target/arm/helper.c b/target/arm/helper.c index acefd4b69f..d6aa59fecc 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -239,32 +239,6 @@ int sme_exception_el(CPUARMState *env, int el) return 0; } =20 -/* This corresponds to the ARM pseudocode function IsFullA64Enabled(). */ -static bool sme_fa64(CPUARMState *env, int el) -{ - if (!cpu_isar_feature(aa64_sme_fa64, env_archcpu(env))) { - return false; - } - - if (el <=3D 1 && !el_is_in_host(env, el)) { - if (!FIELD_EX64(env->vfp.smcr_el[1], SMCR, FA64)) { - return false; - } - } - if (el <=3D 2 && arm_is_el2_enabled(env)) { - if (!FIELD_EX64(env->vfp.smcr_el[2], SMCR, FA64)) { - return false; - } - } - if (arm_feature(env, ARM_FEATURE_EL3)) { - if (!FIELD_EX64(env->vfp.smcr_el[3], SMCR, FA64)) { - return false; - } - } - - return true; -} - /* * Given that SVE is enabled, return the vector length for EL. */ @@ -1832,7 +1806,7 @@ int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mm= u_idx) } } =20 -static int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx) +int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx) { if (regime_has_2_ranges(mmu_idx)) { return extract64(tcr, 57, 2); @@ -2543,339 +2517,6 @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env) return arm_mmu_idx_el(env, arm_current_el(env)); } =20 -static CPUARMTBFlags rebuild_hflags_common(CPUARMState *env, int fp_el, - ARMMMUIdx mmu_idx, - CPUARMTBFlags flags) -{ - DP_TBFLAG_ANY(flags, FPEXC_EL, fp_el); - DP_TBFLAG_ANY(flags, MMUIDX, arm_to_core_mmu_idx(mmu_idx)); - - if (arm_singlestep_active(env)) { - DP_TBFLAG_ANY(flags, SS_ACTIVE, 1); - } - return flags; -} - -static CPUARMTBFlags rebuild_hflags_common_32(CPUARMState *env, int fp_el, - ARMMMUIdx mmu_idx, - CPUARMTBFlags flags) -{ - bool sctlr_b =3D arm_sctlr_b(env); - - if (sctlr_b) { - DP_TBFLAG_A32(flags, SCTLR__B, 1); - } - if (arm_cpu_data_is_big_endian_a32(env, sctlr_b)) { - DP_TBFLAG_ANY(flags, BE_DATA, 1); - } - DP_TBFLAG_A32(flags, NS, !access_secure_reg(env)); - - return rebuild_hflags_common(env, fp_el, mmu_idx, flags); -} - -static CPUARMTBFlags rebuild_hflags_m32(CPUARMState *env, int fp_el, - ARMMMUIdx mmu_idx) -{ - CPUARMTBFlags flags =3D {}; - uint32_t ccr =3D env->v7m.ccr[env->v7m.secure]; - - /* Without HaveMainExt, CCR.UNALIGN_TRP is RES1. */ - if (ccr & R_V7M_CCR_UNALIGN_TRP_MASK) { - DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); - } - - if (arm_v7m_is_handler_mode(env)) { - DP_TBFLAG_M32(flags, HANDLER, 1); - } - - /* - * v8M always applies stack limit checks unless CCR.STKOFHFNMIGN - * is suppressing them because the requested execution priority - * is less than 0. - */ - if (arm_feature(env, ARM_FEATURE_V8) && - !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) && - (ccr & R_V7M_CCR_STKOFHFNMIGN_MASK))) { - DP_TBFLAG_M32(flags, STACKCHECK, 1); - } - - if (arm_feature(env, ARM_FEATURE_M_SECURITY) && env->v7m.secure) { - DP_TBFLAG_M32(flags, SECURE, 1); - } - - return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); -} - -static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el, - ARMMMUIdx mmu_idx) -{ - CPUARMTBFlags flags =3D {}; - int el =3D arm_current_el(env); - - if (arm_sctlr(env, el) & SCTLR_A) { - DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); - } - - if (arm_el_is_aa64(env, 1)) { - DP_TBFLAG_A32(flags, VFPEN, 1); - } - - if (el < 2 && env->cp15.hstr_el2 && - (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) !=3D (HCR_E2H | HCR_T= GE)) { - DP_TBFLAG_A32(flags, HSTR_ACTIVE, 1); - } - - if (env->uncached_cpsr & CPSR_IL) { - DP_TBFLAG_ANY(flags, PSTATE__IL, 1); - } - - /* - * The SME exception we are testing for is raised via - * AArch64.CheckFPAdvSIMDEnabled(), as called from - * AArch32.CheckAdvSIMDOrFPEnabled(). - */ - if (el =3D=3D 0 - && FIELD_EX64(env->svcr, SVCR, SM) - && (!arm_is_el2_enabled(env) - || (arm_el_is_aa64(env, 2) && !(env->cp15.hcr_el2 & HCR_TGE))) - && arm_el_is_aa64(env, 1) - && !sme_fa64(env, el)) { - DP_TBFLAG_A32(flags, SME_TRAP_NONSTREAMING, 1); - } - - return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); -} - -static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_e= l, - ARMMMUIdx mmu_idx) -{ - CPUARMTBFlags flags =3D {}; - ARMMMUIdx stage1 =3D stage_1_mmu_idx(mmu_idx); - uint64_t tcr =3D regime_tcr(env, mmu_idx); - uint64_t sctlr; - int tbii, tbid; - - DP_TBFLAG_ANY(flags, AARCH64_STATE, 1); - - /* Get control bits for tagged addresses. */ - tbid =3D aa64_va_parameter_tbi(tcr, mmu_idx); - tbii =3D tbid & ~aa64_va_parameter_tbid(tcr, mmu_idx); - - DP_TBFLAG_A64(flags, TBII, tbii); - DP_TBFLAG_A64(flags, TBID, tbid); - - if (cpu_isar_feature(aa64_sve, env_archcpu(env))) { - int sve_el =3D sve_exception_el(env, el); - - /* - * If either FP or SVE are disabled, translator does not need len. - * If SVE EL > FP EL, FP exception has precedence, and translator - * does not need SVE EL. Save potential re-translations by forcing - * the unneeded data to zero. - */ - if (fp_el !=3D 0) { - if (sve_el > fp_el) { - sve_el =3D 0; - } - } else if (sve_el =3D=3D 0) { - DP_TBFLAG_A64(flags, VL, sve_vqm1_for_el(env, el)); - } - DP_TBFLAG_A64(flags, SVEEXC_EL, sve_el); - } - if (cpu_isar_feature(aa64_sme, env_archcpu(env))) { - int sme_el =3D sme_exception_el(env, el); - bool sm =3D FIELD_EX64(env->svcr, SVCR, SM); - - DP_TBFLAG_A64(flags, SMEEXC_EL, sme_el); - if (sme_el =3D=3D 0) { - /* Similarly, do not compute SVL if SME is disabled. */ - int svl =3D sve_vqm1_for_el_sm(env, el, true); - DP_TBFLAG_A64(flags, SVL, svl); - if (sm) { - /* If SVE is disabled, we will not have set VL above. */ - DP_TBFLAG_A64(flags, VL, svl); - } - } - if (sm) { - DP_TBFLAG_A64(flags, PSTATE_SM, 1); - DP_TBFLAG_A64(flags, SME_TRAP_NONSTREAMING, !sme_fa64(env, el)= ); - } - DP_TBFLAG_A64(flags, PSTATE_ZA, FIELD_EX64(env->svcr, SVCR, ZA)); - } - - sctlr =3D regime_sctlr(env, stage1); - - if (sctlr & SCTLR_A) { - DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); - } - - if (arm_cpu_data_is_big_endian_a64(el, sctlr)) { - DP_TBFLAG_ANY(flags, BE_DATA, 1); - } - - if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) { - /* - * In order to save space in flags, we record only whether - * pauth is "inactive", meaning all insns are implemented as - * a nop, or "active" when some action must be performed. - * The decision of which action to take is left to a helper. - */ - if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) { - DP_TBFLAG_A64(flags, PAUTH_ACTIVE, 1); - } - } - - if (cpu_isar_feature(aa64_bti, env_archcpu(env))) { - /* Note that SCTLR_EL[23].BT =3D=3D SCTLR_BT1. */ - if (sctlr & (el =3D=3D 0 ? SCTLR_BT0 : SCTLR_BT1)) { - DP_TBFLAG_A64(flags, BT, 1); - } - } - - /* Compute the condition for using AccType_UNPRIV for LDTR et al. */ - if (!(env->pstate & PSTATE_UAO)) { - switch (mmu_idx) { - case ARMMMUIdx_E10_1: - case ARMMMUIdx_E10_1_PAN: - /* TODO: ARMv8.3-NV */ - DP_TBFLAG_A64(flags, UNPRIV, 1); - break; - case ARMMMUIdx_E20_2: - case ARMMMUIdx_E20_2_PAN: - /* - * Note that EL20_2 is gated by HCR_EL2.E2H =3D=3D 1, but EL20= _0 is - * gated by HCR_EL2. =3D=3D '11', and so is LDTR. - */ - if (env->cp15.hcr_el2 & HCR_TGE) { - DP_TBFLAG_A64(flags, UNPRIV, 1); - } - break; - default: - break; - } - } - - if (env->pstate & PSTATE_IL) { - DP_TBFLAG_ANY(flags, PSTATE__IL, 1); - } - - if (cpu_isar_feature(aa64_mte, env_archcpu(env))) { - /* - * Set MTE_ACTIVE if any access may be Checked, and leave clear - * if all accesses must be Unchecked: - * 1) If no TBI, then there are no tags in the address to check, - * 2) If Tag Check Override, then all accesses are Unchecked, - * 3) If Tag Check Fail =3D=3D 0, then Checked access have no effe= ct, - * 4) If no Allocation Tag Access, then all accesses are Unchecked. - */ - if (allocation_tag_access_enabled(env, el, sctlr)) { - DP_TBFLAG_A64(flags, ATA, 1); - if (tbid - && !(env->pstate & PSTATE_TCO) - && (sctlr & (el =3D=3D 0 ? SCTLR_TCF0 : SCTLR_TCF))) { - DP_TBFLAG_A64(flags, MTE_ACTIVE, 1); - } - } - /* And again for unprivileged accesses, if required. */ - if (EX_TBFLAG_A64(flags, UNPRIV) - && tbid - && !(env->pstate & PSTATE_TCO) - && (sctlr & SCTLR_TCF0) - && allocation_tag_access_enabled(env, 0, sctlr)) { - DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1); - } - /* Cache TCMA as well as TBI. */ - DP_TBFLAG_A64(flags, TCMA, aa64_va_parameter_tcma(tcr, mmu_idx)); - } - - return rebuild_hflags_common(env, fp_el, mmu_idx, flags); -} - -static CPUARMTBFlags rebuild_hflags_internal(CPUARMState *env) -{ - int el =3D arm_current_el(env); - int fp_el =3D fp_exception_el(env, el); - ARMMMUIdx mmu_idx =3D arm_mmu_idx_el(env, el); - - if (is_a64(env)) { - return rebuild_hflags_a64(env, el, fp_el, mmu_idx); - } else if (arm_feature(env, ARM_FEATURE_M)) { - return rebuild_hflags_m32(env, fp_el, mmu_idx); - } else { - return rebuild_hflags_a32(env, fp_el, mmu_idx); - } -} - -void arm_rebuild_hflags(CPUARMState *env) -{ - env->hflags =3D rebuild_hflags_internal(env); -} - -/* - * If we have triggered a EL state change we can't rely on the - * translator having passed it to us, we need to recompute. - */ -void HELPER(rebuild_hflags_m32_newel)(CPUARMState *env) -{ - int el =3D arm_current_el(env); - int fp_el =3D fp_exception_el(env, el); - ARMMMUIdx mmu_idx =3D arm_mmu_idx_el(env, el); - - env->hflags =3D rebuild_hflags_m32(env, fp_el, mmu_idx); -} - -void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el) -{ - int fp_el =3D fp_exception_el(env, el); - ARMMMUIdx mmu_idx =3D arm_mmu_idx_el(env, el); - - env->hflags =3D rebuild_hflags_m32(env, fp_el, mmu_idx); -} - -/* - * If we have triggered a EL state change we can't rely on the - * translator having passed it to us, we need to recompute. - */ -void HELPER(rebuild_hflags_a32_newel)(CPUARMState *env) -{ - int el =3D arm_current_el(env); - int fp_el =3D fp_exception_el(env, el); - ARMMMUIdx mmu_idx =3D arm_mmu_idx_el(env, el); - env->hflags =3D rebuild_hflags_a32(env, fp_el, mmu_idx); -} - -void HELPER(rebuild_hflags_a32)(CPUARMState *env, int el) -{ - int fp_el =3D fp_exception_el(env, el); - ARMMMUIdx mmu_idx =3D arm_mmu_idx_el(env, el); - - env->hflags =3D rebuild_hflags_a32(env, fp_el, mmu_idx); -} - -void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el) -{ - int fp_el =3D fp_exception_el(env, el); - ARMMMUIdx mmu_idx =3D arm_mmu_idx_el(env, el); - - env->hflags =3D rebuild_hflags_a64(env, el, fp_el, mmu_idx); -} - -static inline void assert_hflags_rebuild_correctly(CPUARMState *env) -{ -#ifdef CONFIG_DEBUG_TCG - CPUARMTBFlags c =3D env->hflags; - CPUARMTBFlags r =3D rebuild_hflags_internal(env); - - if (unlikely(c.flags !=3D r.flags || c.flags2 !=3D r.flags2)) { - fprintf(stderr, "TCG hflags mismatch " - "(current:(0x%08x,0x" TARGET_FMT_lx ")" - " rebuilt:(0x%08x,0x" TARGET_FMT_lx ")\n", - c.flags, c.flags2, r.flags, r.flags2); - abort(); - } -#endif -} - static bool mve_no_pred(CPUARMState *env) { /* diff --git a/target/arm/internals.h b/target/arm/internals.h index 0983e65300..865b9e8104 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1087,6 +1087,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, = uint64_t va, =20 int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx); int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx); +int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx); =20 /* Determine if allocation tags are available. */ static inline bool allocation_tag_access_enabled(CPUARMState *env, int el, @@ -1368,4 +1369,5 @@ bool arm_generate_debug_exceptions(CPUARMState *env); ((1 << (1 - 1)) | (1 << (2 - 1)) | \ (1 << (4 - 1)) | (1 << (8 - 1)) | (1 << (16 - 1))) =20 +void assert_hflags_rebuild_correctly(CPUARMState *env); #endif diff --git a/target/arm/tcg-stubs.c b/target/arm/tcg-stubs.c index 021489cf38..b6bc09504c 100644 --- a/target/arm/tcg-stubs.c +++ b/target/arm/tcg-stubs.c @@ -26,3 +26,8 @@ void arm_reset_sve_state(CPUARMState *env) { g_assert_not_reached(); } + +/* Temporarily while cpu_get_tb_cpu_state() is still in common code */ +void assert_hflags_rebuild_correctly(CPUARMState *env) +{ +} diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c new file mode 100644 index 0000000000..746b1c0d70 --- /dev/null +++ b/target/arm/tcg/hflags.c @@ -0,0 +1,370 @@ +/* + * ARM hflags + * + * This code is licensed under the GNU GPL v2 or later. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include "qemu/osdep.h" +#include "cpu.h" +#include "internals.h" +#include "exec/helper-proto.h" + +static CPUARMTBFlags rebuild_hflags_common(CPUARMState *env, int fp_el, + ARMMMUIdx mmu_idx, + CPUARMTBFlags flags) +{ + DP_TBFLAG_ANY(flags, FPEXC_EL, fp_el); + DP_TBFLAG_ANY(flags, MMUIDX, arm_to_core_mmu_idx(mmu_idx)); + + if (arm_singlestep_active(env)) { + DP_TBFLAG_ANY(flags, SS_ACTIVE, 1); + } + return flags; +} + +static CPUARMTBFlags rebuild_hflags_common_32(CPUARMState *env, int fp_el, + ARMMMUIdx mmu_idx, + CPUARMTBFlags flags) +{ + bool sctlr_b =3D arm_sctlr_b(env); + + if (sctlr_b) { + DP_TBFLAG_A32(flags, SCTLR__B, 1); + } + if (arm_cpu_data_is_big_endian_a32(env, sctlr_b)) { + DP_TBFLAG_ANY(flags, BE_DATA, 1); + } + DP_TBFLAG_A32(flags, NS, !access_secure_reg(env)); + + return rebuild_hflags_common(env, fp_el, mmu_idx, flags); +} + +static CPUARMTBFlags rebuild_hflags_m32(CPUARMState *env, int fp_el, + ARMMMUIdx mmu_idx) +{ + CPUARMTBFlags flags =3D {}; + uint32_t ccr =3D env->v7m.ccr[env->v7m.secure]; + + /* Without HaveMainExt, CCR.UNALIGN_TRP is RES1. */ + if (ccr & R_V7M_CCR_UNALIGN_TRP_MASK) { + DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); + } + + if (arm_v7m_is_handler_mode(env)) { + DP_TBFLAG_M32(flags, HANDLER, 1); + } + + /* + * v8M always applies stack limit checks unless CCR.STKOFHFNMIGN + * is suppressing them because the requested execution priority + * is less than 0. + */ + if (arm_feature(env, ARM_FEATURE_V8) && + !((mmu_idx & ARM_MMU_IDX_M_NEGPRI) && + (ccr & R_V7M_CCR_STKOFHFNMIGN_MASK))) { + DP_TBFLAG_M32(flags, STACKCHECK, 1); + } + + if (arm_feature(env, ARM_FEATURE_M_SECURITY) && env->v7m.secure) { + DP_TBFLAG_M32(flags, SECURE, 1); + } + + return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); +} + +/* This corresponds to the ARM pseudocode function IsFullA64Enabled(). */ +static bool sme_fa64(CPUARMState *env, int el) +{ + if (!cpu_isar_feature(aa64_sme_fa64, env_archcpu(env))) { + return false; + } + + if (el <=3D 1 && !el_is_in_host(env, el)) { + if (!FIELD_EX64(env->vfp.smcr_el[1], SMCR, FA64)) { + return false; + } + } + if (el <=3D 2 && arm_is_el2_enabled(env)) { + if (!FIELD_EX64(env->vfp.smcr_el[2], SMCR, FA64)) { + return false; + } + } + if (arm_feature(env, ARM_FEATURE_EL3)) { + if (!FIELD_EX64(env->vfp.smcr_el[3], SMCR, FA64)) { + return false; + } + } + + return true; +} + +static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el, + ARMMMUIdx mmu_idx) +{ + CPUARMTBFlags flags =3D {}; + int el =3D arm_current_el(env); + + if (arm_sctlr(env, el) & SCTLR_A) { + DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); + } + + if (arm_el_is_aa64(env, 1)) { + DP_TBFLAG_A32(flags, VFPEN, 1); + } + + if (el < 2 && env->cp15.hstr_el2 && + (arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE)) !=3D (HCR_E2H | HCR_T= GE)) { + DP_TBFLAG_A32(flags, HSTR_ACTIVE, 1); + } + + if (env->uncached_cpsr & CPSR_IL) { + DP_TBFLAG_ANY(flags, PSTATE__IL, 1); + } + + /* + * The SME exception we are testing for is raised via + * AArch64.CheckFPAdvSIMDEnabled(), as called from + * AArch32.CheckAdvSIMDOrFPEnabled(). + */ + if (el =3D=3D 0 + && FIELD_EX64(env->svcr, SVCR, SM) + && (!arm_is_el2_enabled(env) + || (arm_el_is_aa64(env, 2) && !(env->cp15.hcr_el2 & HCR_TGE))) + && arm_el_is_aa64(env, 1) + && !sme_fa64(env, el)) { + DP_TBFLAG_A32(flags, SME_TRAP_NONSTREAMING, 1); + } + + return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); +} + +static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_e= l, + ARMMMUIdx mmu_idx) +{ + CPUARMTBFlags flags =3D {}; + ARMMMUIdx stage1 =3D stage_1_mmu_idx(mmu_idx); + uint64_t tcr =3D regime_tcr(env, mmu_idx); + uint64_t sctlr; + int tbii, tbid; + + DP_TBFLAG_ANY(flags, AARCH64_STATE, 1); + + /* Get control bits for tagged addresses. */ + tbid =3D aa64_va_parameter_tbi(tcr, mmu_idx); + tbii =3D tbid & ~aa64_va_parameter_tbid(tcr, mmu_idx); + + DP_TBFLAG_A64(flags, TBII, tbii); + DP_TBFLAG_A64(flags, TBID, tbid); + + if (cpu_isar_feature(aa64_sve, env_archcpu(env))) { + int sve_el =3D sve_exception_el(env, el); + + /* + * If either FP or SVE are disabled, translator does not need len. + * If SVE EL > FP EL, FP exception has precedence, and translator + * does not need SVE EL. Save potential re-translations by forcing + * the unneeded data to zero. + */ + if (fp_el !=3D 0) { + if (sve_el > fp_el) { + sve_el =3D 0; + } + } else if (sve_el =3D=3D 0) { + DP_TBFLAG_A64(flags, VL, sve_vqm1_for_el(env, el)); + } + DP_TBFLAG_A64(flags, SVEEXC_EL, sve_el); + } + if (cpu_isar_feature(aa64_sme, env_archcpu(env))) { + int sme_el =3D sme_exception_el(env, el); + bool sm =3D FIELD_EX64(env->svcr, SVCR, SM); + + DP_TBFLAG_A64(flags, SMEEXC_EL, sme_el); + if (sme_el =3D=3D 0) { + /* Similarly, do not compute SVL if SME is disabled. */ + int svl =3D sve_vqm1_for_el_sm(env, el, true); + DP_TBFLAG_A64(flags, SVL, svl); + if (sm) { + /* If SVE is disabled, we will not have set VL above. */ + DP_TBFLAG_A64(flags, VL, svl); + } + } + if (sm) { + DP_TBFLAG_A64(flags, PSTATE_SM, 1); + DP_TBFLAG_A64(flags, SME_TRAP_NONSTREAMING, !sme_fa64(env, el)= ); + } + DP_TBFLAG_A64(flags, PSTATE_ZA, FIELD_EX64(env->svcr, SVCR, ZA)); + } + + sctlr =3D regime_sctlr(env, stage1); + + if (sctlr & SCTLR_A) { + DP_TBFLAG_ANY(flags, ALIGN_MEM, 1); + } + + if (arm_cpu_data_is_big_endian_a64(el, sctlr)) { + DP_TBFLAG_ANY(flags, BE_DATA, 1); + } + + if (cpu_isar_feature(aa64_pauth, env_archcpu(env))) { + /* + * In order to save space in flags, we record only whether + * pauth is "inactive", meaning all insns are implemented as + * a nop, or "active" when some action must be performed. + * The decision of which action to take is left to a helper. + */ + if (sctlr & (SCTLR_EnIA | SCTLR_EnIB | SCTLR_EnDA | SCTLR_EnDB)) { + DP_TBFLAG_A64(flags, PAUTH_ACTIVE, 1); + } + } + + if (cpu_isar_feature(aa64_bti, env_archcpu(env))) { + /* Note that SCTLR_EL[23].BT =3D=3D SCTLR_BT1. */ + if (sctlr & (el =3D=3D 0 ? SCTLR_BT0 : SCTLR_BT1)) { + DP_TBFLAG_A64(flags, BT, 1); + } + } + + /* Compute the condition for using AccType_UNPRIV for LDTR et al. */ + if (!(env->pstate & PSTATE_UAO)) { + switch (mmu_idx) { + case ARMMMUIdx_E10_1: + case ARMMMUIdx_E10_1_PAN: + /* TODO: ARMv8.3-NV */ + DP_TBFLAG_A64(flags, UNPRIV, 1); + break; + case ARMMMUIdx_E20_2: + case ARMMMUIdx_E20_2_PAN: + /* + * Note that EL20_2 is gated by HCR_EL2.E2H =3D=3D 1, but EL20= _0 is + * gated by HCR_EL2. =3D=3D '11', and so is LDTR. + */ + if (env->cp15.hcr_el2 & HCR_TGE) { + DP_TBFLAG_A64(flags, UNPRIV, 1); + } + break; + default: + break; + } + } + + if (env->pstate & PSTATE_IL) { + DP_TBFLAG_ANY(flags, PSTATE__IL, 1); + } + + if (cpu_isar_feature(aa64_mte, env_archcpu(env))) { + /* + * Set MTE_ACTIVE if any access may be Checked, and leave clear + * if all accesses must be Unchecked: + * 1) If no TBI, then there are no tags in the address to check, + * 2) If Tag Check Override, then all accesses are Unchecked, + * 3) If Tag Check Fail =3D=3D 0, then Checked access have no effe= ct, + * 4) If no Allocation Tag Access, then all accesses are Unchecked. + */ + if (allocation_tag_access_enabled(env, el, sctlr)) { + DP_TBFLAG_A64(flags, ATA, 1); + if (tbid + && !(env->pstate & PSTATE_TCO) + && (sctlr & (el =3D=3D 0 ? SCTLR_TCF0 : SCTLR_TCF))) { + DP_TBFLAG_A64(flags, MTE_ACTIVE, 1); + } + } + /* And again for unprivileged accesses, if required. */ + if (EX_TBFLAG_A64(flags, UNPRIV) + && tbid + && !(env->pstate & PSTATE_TCO) + && (sctlr & SCTLR_TCF0) + && allocation_tag_access_enabled(env, 0, sctlr)) { + DP_TBFLAG_A64(flags, MTE0_ACTIVE, 1); + } + /* Cache TCMA as well as TBI. */ + DP_TBFLAG_A64(flags, TCMA, aa64_va_parameter_tcma(tcr, mmu_idx)); + } + + return rebuild_hflags_common(env, fp_el, mmu_idx, flags); +} + +static CPUARMTBFlags rebuild_hflags_internal(CPUARMState *env) +{ + int el =3D arm_current_el(env); + int fp_el =3D fp_exception_el(env, el); + ARMMMUIdx mmu_idx =3D arm_mmu_idx_el(env, el); + + if (is_a64(env)) { + return rebuild_hflags_a64(env, el, fp_el, mmu_idx); + } else if (arm_feature(env, ARM_FEATURE_M)) { + return rebuild_hflags_m32(env, fp_el, mmu_idx); + } else { + return rebuild_hflags_a32(env, fp_el, mmu_idx); + } +} + +void arm_rebuild_hflags(CPUARMState *env) +{ + env->hflags =3D rebuild_hflags_internal(env); +} + +/* + * If we have triggered a EL state change we can't rely on the + * translator having passed it to us, we need to recompute. + */ +void HELPER(rebuild_hflags_m32_newel)(CPUARMState *env) +{ + int el =3D arm_current_el(env); + int fp_el =3D fp_exception_el(env, el); + ARMMMUIdx mmu_idx =3D arm_mmu_idx_el(env, el); + + env->hflags =3D rebuild_hflags_m32(env, fp_el, mmu_idx); +} + +void HELPER(rebuild_hflags_m32)(CPUARMState *env, int el) +{ + int fp_el =3D fp_exception_el(env, el); + ARMMMUIdx mmu_idx =3D arm_mmu_idx_el(env, el); + + env->hflags =3D rebuild_hflags_m32(env, fp_el, mmu_idx); +} + +/* + * If we have triggered a EL state change we can't rely on the + * translator having passed it to us, we need to recompute. + */ +void HELPER(rebuild_hflags_a32_newel)(CPUARMState *env) +{ + int el =3D arm_current_el(env); + int fp_el =3D fp_exception_el(env, el); + ARMMMUIdx mmu_idx =3D arm_mmu_idx_el(env, el); + env->hflags =3D rebuild_hflags_a32(env, fp_el, mmu_idx); +} + +void HELPER(rebuild_hflags_a32)(CPUARMState *env, int el) +{ + int fp_el =3D fp_exception_el(env, el); + ARMMMUIdx mmu_idx =3D arm_mmu_idx_el(env, el); + + env->hflags =3D rebuild_hflags_a32(env, fp_el, mmu_idx); +} + +void HELPER(rebuild_hflags_a64)(CPUARMState *env, int el) +{ + int fp_el =3D fp_exception_el(env, el); + ARMMMUIdx mmu_idx =3D arm_mmu_idx_el(env, el); + + env->hflags =3D rebuild_hflags_a64(env, el, fp_el, mmu_idx); +} + +inline void assert_hflags_rebuild_correctly(CPUARMState *env) +{ +#ifdef CONFIG_DEBUG_TCG + CPUARMTBFlags c =3D env->hflags; + CPUARMTBFlags r =3D rebuild_hflags_internal(env); + + if (unlikely(c.flags !=3D r.flags || c.flags2 !=3D r.flags2)) { + fprintf(stderr, "TCG hflags mismatch " + "(current:(0x%08x,0x" TARGET_FMT_lx ")" + " rebuilt:(0x%08x,0x" TARGET_FMT_lx ")\n", + c.flags, c.flags2, r.flags, r.flags2); + abort(); + } +#endif +} diff --git a/target/arm/tcg/meson.build b/target/arm/tcg/meson.build index 47006f903c..25bc98999e 100644 --- a/target/arm/tcg/meson.build +++ b/target/arm/tcg/meson.build @@ -25,6 +25,7 @@ arm_ss.add(files( 'translate-vfp.c', 'crypto_helper.c', 'debug_helper.c', + 'hflags.c', 'iwmmxt_helper.c', 'm_helper.c', 'mve_helper.c', --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304521; cv=none; d=zohomail.com; s=zohoarc; b=QYdVHZ1yjcWEBT2aQpnwsX839O82AnkvrlZRtEoKsfopVkzoAx9H8ZC/kSZ8lahf/Y4G53fddyhHL4CRWE1HnvEmEhOywynnsAbZmbCyIDHTC52R5ByEmXkBBJCRslPzPF8tiJUNvTi7WQ3vcfHTfujXyuxQgZLjafcOZGWdxf4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304521; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=1TOeNshkMsKn2Y3CsqOHq9PQkcZYQvOcN/VHQdwTADc=; b=Xy3cbNbrO93f2UzCOpO0H9uwpKCOOBJWyBkpBmjDoI6XsciUd+gP8SoSKJ9u2wT4+M/D6JdfaKhtJunbeXaTTJFiAxaONEgXHlHyRvahtBNzroxKwknkm1vNoYK+1ONP3VyRwSYYz276VIvoy7gMKdkvB0IadBjdZ9DLwkpXHfk= 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 167330452167244.90496418041903; Mon, 9 Jan 2023 14:48:41 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0rT-0004bs-QJ; Mon, 09 Jan 2023 17:43:23 -0500 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 1pF0rR-0004Y9-JN; Mon, 09 Jan 2023 17:43:21 -0500 Received: from smtp-out1.suse.de ([2001:67c:2178:6::1c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0rQ-00044R-3G; Mon, 09 Jan 2023 17:43:21 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 459053F8AB; Mon, 9 Jan 2023 22:43:18 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 05C9F13583; Mon, 9 Jan 2023 22:43:14 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id 4Gs4MIKYvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:43:14 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304198; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1TOeNshkMsKn2Y3CsqOHq9PQkcZYQvOcN/VHQdwTADc=; b=Y5mJLlJU7jn+plUG6zJNlfKJxcqtf+AauJMcOcvYiqKWOtAllU1C/pBlh1R5TB1iBJ+K71 Rw54NziHeG/qXubVsGHpjYJU+amU7LTTxHyfA2fOA4WC4RWvI6wGOe9mZphh1p0loZkigQ 5/AcAcPLhoen364OsiF157lvChfI+Ok= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304198; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1TOeNshkMsKn2Y3CsqOHq9PQkcZYQvOcN/VHQdwTADc=; b=ZEr9t76sBPGskZ9LDMLm5p269z52td372NzYsVh7HOyiZXUtyFhIEhE2JYhUzpAPxz5oJm 1sMjkr5XMemRENBQ== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf , Thomas Huth , Laurent Vivier , "Dr. David Alan Gilbert" Subject: [RFC PATCH v2 13/19] tests: do not run test-hmp on all machines for ARM KVM-only Date: Mon, 9 Jan 2023 19:42:26 -0300 Message-Id: <20230109224232.11661-14-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=2001:67c:2178:6::1c; envelope-from=farosas@suse.de; helo=smtp-out1.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304523935100003 Content-Type: text/plain; charset="utf-8" From: Claudio Fontana on ARM we currently list and build all machines, even when building KVM-only, without TCG. Until we fix this (and we only list and build machines that are compatible with KVM), only test specifically using the "virt" machine in this case. Signed-off-by: Claudio Fontana Signed-off-by: Fabiano Rosas Cc: Thomas Huth cc: Laurent Vivier Cc: "Dr. David Alan Gilbert" --- tests/qtest/test-hmp.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/qtest/test-hmp.c b/tests/qtest/test-hmp.c index f8b22abe4c..daa1e76a06 100644 --- a/tests/qtest/test-hmp.c +++ b/tests/qtest/test-hmp.c @@ -157,8 +157,29 @@ int main(int argc, char **argv) =20 g_test_init(&argc, &argv, NULL); =20 + /* + * XXX currently we build also boards for ARM that are + * incompatible with KVM. We therefore need to check this + * explicitly, and only test virt for kvm-only arm builds. After + * we do the work of Kconfig etc to ensure that only + * KVM-compatible boards are built for the kvm-only build, we + * could remove this. + */ +#ifndef CONFIG_TCG + { + const char *arch =3D qtest_get_arch(); + + if (strcmp(arch, "arm") =3D=3D 0 || strcmp(arch, "aarch64") =3D=3D= 0) { + add_machine_test_case("virt"); + goto add_machine_test_done; + } + } +#endif /* !CONFIG_TCG */ + qtest_cb_for_every_machine(add_machine_test_case, g_test_quick()); + goto add_machine_test_done; =20 + add_machine_test_done: /* as none machine has no memory by default, add a test case with memo= ry */ qtest_add_data_func("hmp/none+2MB", g_strdup("none -m 2"), test_machin= e); =20 --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304615; cv=none; d=zohomail.com; s=zohoarc; b=G20OFKUXVit7EMEg4fGXjHcs8whSrTAaC3Y+0vl25t0HMBLzGD6RZWsFMe7uGar4W65wKm1n4gQ1Z8IJIdPxQcHfuOhqzYBidznJU68IrJJYGCzqbHzYUZGWBumajleIZ4zzJQVV7h89a/rTPJNE1l6GpEONhSp8rTlRJoMGtbU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304615; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=dDe5vfmZ31EwcRxKz3+oipci4tDkatYe8l7lx/XZLg4=; b=LtobFsK9IyoEyix/Ml9sd2cAKK2vOjNkg4As5rSdiPWWsjGbK5GiF1PJQvyvzUjDdJQWcPk73PdKweVoNokxyjbe37i8LltrpKFcgIOZZuBTRG3X64I//Qyp9C0OWs8Vi7IRlZ9CTJef3LkBdYsNM+kf1OnJITA/mmTMHBzpE00= 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 1673304615007459.91529727828345; Mon, 9 Jan 2023 14:50:15 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0rX-0004h4-0w; Mon, 09 Jan 2023 17:43:27 -0500 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 1pF0rU-0004cy-SW; Mon, 09 Jan 2023 17:43:24 -0500 Received: from smtp-out1.suse.de ([2001:67c:2178:6::1c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0rT-000451-A5; Mon, 09 Jan 2023 17:43:24 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id BA06A4D34C; Mon, 9 Jan 2023 22:43:21 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id AA41813583; Mon, 9 Jan 2023 22:43:18 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id wHy1HIaYvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:43:18 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304201; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=dDe5vfmZ31EwcRxKz3+oipci4tDkatYe8l7lx/XZLg4=; b=fMv+tufBZX1rjQwENHKv7D/dAmX8tqAaoJlOekWyDO3AgSjFssSCKOEzhamRFPvFsjKb2d TN4AGC+DDBe12yW6nvCJYseN57hcBMnPlZ4NMHPkIDahfTvg1SOFsUVsQytx2uzv3OCHyu xZDIR9ZAQ1kczkjSVxTB8WOKI+0kNYw= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304201; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=dDe5vfmZ31EwcRxKz3+oipci4tDkatYe8l7lx/XZLg4=; b=6vqqybGYt70MaIQ3oxk5MsqA4QU02cW6nQc5qAnZNc+lW68dbd4Pwk/T99zrpy/go2rZRO roctYdqXC642hzAQ== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf , Thomas Huth , Laurent Vivier Subject: [RFC PATCH v2 14/19] tests: do not run qom-test on all machines for ARM KVM-only Date: Mon, 9 Jan 2023 19:42:27 -0300 Message-Id: <20230109224232.11661-15-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=2001:67c:2178:6::1c; envelope-from=farosas@suse.de; helo=smtp-out1.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304616176100001 Content-Type: text/plain; charset="utf-8" From: Claudio Fontana on ARM we currently list and build all machines, even when building KVM-only, without TCG. Until we fix this (and we only list and build machines that are compatible with KVM), only test specifically using the "virt" machine in this case. Signed-off-by: Claudio Fontana Signed-off-by: Fabiano Rosas Cc: Thomas Huth Cc: Laurent Vivier --- tests/qtest/qom-test.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/qtest/qom-test.c b/tests/qtest/qom-test.c index 13510bc349..aea969ef60 100644 --- a/tests/qtest/qom-test.c +++ b/tests/qtest/qom-test.c @@ -105,7 +105,28 @@ int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); =20 + /* + * XXX currently we build also boards for ARM that are + * incompatible with KVM. We therefore need to check this + * explicitly, and only test virt for kvm-only arm builds. After + * we do the work of Kconfig etc to ensure that only + * KVM-compatible boards are built for the kvm-only build, we + * could remove this. + */ +#ifndef CONFIG_TCG + { + const char *arch =3D qtest_get_arch(); + + if (strcmp(arch, "arm") =3D=3D 0 || strcmp(arch, "aarch64") =3D=3D= 0) { + add_machine_test_case("virt"); + goto add_machine_test_done; + } + } +#endif /* !CONFIG_TCG */ + qtest_cb_for_every_machine(add_machine_test_case, g_test_quick()); + goto add_machine_test_done; =20 + add_machine_test_done: return g_test_run(); } --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304383; cv=none; d=zohomail.com; s=zohoarc; b=NNmlGVc9lQFzerh2BFypv6ZruBB9St/+ChaeXUgLjZQZBEA9Z3x8pZa4PQ6f3g+Poqi4WWM4BXbn0/YVIwQpQApZmBM26sTgxKHWLC9zyi3T/GQGkYQURinhBXthuUFooj/bh43Vt+85x0Qa42tYGrfHIuCULQInyOrGRNkQbqg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304383; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=Z0zsUVLNnlB8or8gHrZOqCwKbl6RppYxTr0hODbbSNU=; b=Wzdkc029EXXBfRNdP1veixSRQQzL0bGcYTChHwULZATXh56/byLwMeUX5eRNjpH5KB3VPzv1jA1WNUGhS+0LYZEqA/VfIQtjWzuaQbVrPRd1xPSxfhy0VV4Y/CXDSfrT2yOph8t/cGaSI7mx9+pDdQJb7Re/scuugpICNeFKdKY= 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 1673304383608621.7360503305323; Mon, 9 Jan 2023 14:46:23 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0ra-0004i0-1h; Mon, 09 Jan 2023 17:43:30 -0500 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 1pF0rY-0004hX-ED; Mon, 09 Jan 2023 17:43:28 -0500 Received: from smtp-out1.suse.de ([2001:67c:2178:6::1c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0rW-00045T-PK; Mon, 09 Jan 2023 17:43:28 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 337A84D34C; Mon, 9 Jan 2023 22:43:25 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 2AE8513583; Mon, 9 Jan 2023 22:43:21 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id 0OdPOYmYvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:43:21 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304205; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Z0zsUVLNnlB8or8gHrZOqCwKbl6RppYxTr0hODbbSNU=; b=QN11WXbehq8DvzbITK6TE43f10xs0AaqUwKIgQtV4/Wf4TXJoHJYIvJMO3f/644st/ilG0 af/JHdlhuC2zhZEuMLcP7HGfH9zZsn22lVgX1M+Yq93fD00+m6du+PtFWOsTcyhx9TEpTv WGBQ9jmKn+tF+Hb6GjHJE3wXQuB2OpM= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304205; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Z0zsUVLNnlB8or8gHrZOqCwKbl6RppYxTr0hODbbSNU=; b=i4yiXorHjL+9WdfuVS78ueF6TGVDIlbVmQzGRgKUpjrWv6RU7xMPs7pDa+nXeCeTtTu17n hxrIbCTuI1zPmYCA== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf , Thomas Huth , Laurent Vivier Subject: [RFC PATCH v2 15/19] tests: device-introspect-test: cope with ARM TCG-only devices Date: Mon, 9 Jan 2023 19:42:28 -0300 Message-Id: <20230109224232.11661-16-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=2001:67c:2178:6::1c; envelope-from=farosas@suse.de; helo=smtp-out1.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304385114100003 From: Claudio Fontana Skip the test_device_intro_concrete for now for ARM KVM-only build, as on ARM we currently build devices for ARM that are not compatible with a KVM-only build. We can remove this workaround when we fix this in KConfig etc, and we only list and build machines that are compatible with KVM for KVM-only builds. Alternative implementation provided by Alex. Suggested-by: Alex Benn=C3=A9e Signed-off-by: Claudio Fontana Signed-off-by: Fabiano Rosas Cc: Thomas Huth Cc: Laurent Vivier --- tests/qtest/device-introspect-test.c | 32 +++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/tests/qtest/device-introspect-test.c b/tests/qtest/device-intr= ospect-test.c index 5b0ffe43f5..f89df87f74 100644 --- a/tests/qtest/device-introspect-test.c +++ b/tests/qtest/device-introspect-test.c @@ -304,6 +304,24 @@ static void test_abstract_interfaces(void) qtest_quit(qts); } =20 +/* + * XXX currently we build also boards for ARM that are incompatible with K= VM. + * We therefore need to check this explicitly, and only test virt for kvm-= only + * arm builds. + * After we do the work of Kconfig etc to ensure that only KVM-compatible = boards + * are built for the kvm-only build, we could remove this. + */ +static bool skip_machine_tests(void) +{ +#ifndef CONFIG_TCG + const char *arch =3D qtest_get_arch(); + if (strcmp(arch, "arm") =3D=3D 0 || strcmp(arch, "aarch64") =3D=3D 0) { + return true; + } +#endif /* !CONFIG_TCG */ + return false; +} + static void add_machine_test_case(const char *mname) { char *path, *args; @@ -328,11 +346,15 @@ int main(int argc, char **argv) qtest_add_func("device/introspect/none", test_device_intro_none); qtest_add_func("device/introspect/abstract", test_device_intro_abstrac= t); qtest_add_func("device/introspect/abstract-interfaces", test_abstract_= interfaces); - if (g_test_quick()) { - qtest_add_data_func("device/introspect/concrete/defaults/none", - g_strdup(common_args), test_device_intro_concr= ete); - } else { - qtest_cb_for_every_machine(add_machine_test_case, true); + + if (!skip_machine_tests()) { + if (g_test_quick()) { + qtest_add_data_func("device/introspect/concrete/defaults/none", + g_strdup(common_args), + test_device_intro_concrete); + } else { + qtest_cb_for_every_machine(add_machine_test_case, true); + } } =20 return g_test_run(); --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304618; cv=none; d=zohomail.com; s=zohoarc; b=bDAQJGbBoLF3CE1BidCxixxAyT8NaErS59r2i4rj6Vp00z6iG6CUf67Yhsz10QQ2c0NepYuBjje88kRE8um+iim9TWFBd1o/D5epUOuW+MY0LFOfIfD9ZlGNJlOUkIGfcPjrwZLePooJH4AzLuRL9n048fEoEj4NlKUE9ppa7VQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304618; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=HGJ4/+qQUdyPODxPG2cP+HJYVboRrZ3kGN9lq/KT9Qo=; b=WXPoq0QwUbA2D1hqwy8hxyQvqllaz6uNMKSKl1EkGgfZk/qUlzuSwY0ktaha73uysIVQAqOKaUP14PpLZ7mELPemF9f8P4aJRvBnvoqQqGiKpERGI/jeVG6oPkjp1xCY95N7OPzbCHGtM8rIPt/RMabrglWj5KzYpqq2b2ksHbI= 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 1673304618316841.930431443465; Mon, 9 Jan 2023 14:50:18 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0rd-0004nc-T5; Mon, 09 Jan 2023 17:43:34 -0500 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 1pF0rb-0004iP-QE; Mon, 09 Jan 2023 17:43:31 -0500 Received: from smtp-out2.suse.de ([195.135.220.29]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0ra-00045n-A0; Mon, 09 Jan 2023 17:43:31 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 6D1375CDE2; Mon, 9 Jan 2023 22:43:28 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 988D613583; Mon, 9 Jan 2023 22:43:25 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id UHV3GI2YvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:43:25 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304208; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HGJ4/+qQUdyPODxPG2cP+HJYVboRrZ3kGN9lq/KT9Qo=; b=S7nXKTaFaN3znEDGqEPHwKAb/JqzLtAVrypyG0xrUNmzB+CIrovmqFV1ByLZw4s9oWaUni JxSYxK9vmhCcFcKGjtce8NR73F2LWoYOn1GXWfrT4Zl5yX/WROppysdMzqfUpwPVdMfsjS 1yu5KVhT1jdgWJf0P15LLd5eZPjSpJ4= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304208; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=HGJ4/+qQUdyPODxPG2cP+HJYVboRrZ3kGN9lq/KT9Qo=; b=d4/BtsdUbOVzEXmAn5WN/t3joprzEv2y6kRHIFFA/l43/wZ5HWODxT2hxKdMp2J3sjnnJ8 +FjaWOqiRvbj1lCg== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf , Thomas Huth Subject: [RFC PATCH v2 16/19] tests/tcg: Do not build/run TCG tests if TCG is disabled Date: Mon, 9 Jan 2023 19:42:29 -0300 Message-Id: <20230109224232.11661-17-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=195.135.220.29; envelope-from=farosas@suse.de; helo=smtp-out2.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304620207100003 Content-Type: text/plain; charset="utf-8" The tests under tests/tcg depend on the TCG accelerator. Do not build them if --disable-tcg was given in the configure line. Test against CONFIG_TCG=3D'' instead of CONFIG_TCG=3Dy to account for CONFIG_TCG=3Dm. sample output: $ make check-tcg GIT ui/keycodemapdb meson dtc SKIPPED x86_64-softmmu guest-tests because TCG is disabled in this build Signed-off-by: Fabiano Rosas Cc: Thomas Huth Cc: Paolo Bonzini --- configure | 4 ++++ tests/Makefile.include | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/configure b/configure index 2281892657..ad25a3b5f5 100755 --- a/configure +++ b/configure @@ -2351,6 +2351,10 @@ if test "$plugins" =3D "yes" ; then echo "CONFIG_PLUGIN=3Dy" >> $config_host_mak fi =20 +if test "$tcg" =3D "enabled" ; then + echo "CONFIG_TCG=3Dy" >> $config_host_mak +fi + if test -n "$gdb_bin"; then gdb_version=3D$($gdb_bin --version | head -n 1) if version_ge ${gdb_version##* } 9.1; then diff --git a/tests/Makefile.include b/tests/Makefile.include index 9422ddaece..aa0e610cf2 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -45,6 +45,7 @@ RUN_TCG_TARGET_RULES=3D$(patsubst %,run-tcg-tests-%, $(TC= G_TESTS_TARGETS)) $(foreach TARGET,$(TCG_TESTS_TARGETS), \ $(eval $(BUILD_DIR)/tests/tcg/config-$(TARGET).mak: config-host.ma= k)) =20 +ifneq ($(CONFIG_TCG),) .PHONY: $(TCG_TESTS_TARGETS:%=3Dbuild-tcg-tests-%) $(TCG_TESTS_TARGETS:%=3Dbuild-tcg-tests-%): build-tcg-tests-%: $(BUILD_DIR= )/tests/tcg/config-%.mak $(call quiet-command, \ @@ -56,6 +57,15 @@ $(TCG_TESTS_TARGETS:%=3Drun-tcg-tests-%): run-tcg-tests-= %: build-tcg-tests-% $(call quiet-command, \ $(MAKE) -C tests/tcg/$* $(SUBDIR_MAKEFLAGS) SPEED=3D$(SPEED) ru= n, \ "RUN", "$* guest-tests") +else +.PHONY: $(TCG_TESTS_TARGETS:%=3Dbuild-tcg-tests-%) +$(TCG_TESTS_TARGETS:%=3Dbuild-tcg-tests-%): + @echo " SKIPPED $(subst build-tcg-tests-,,$@) guest-tests because TCG is= disabled in this build" + +.PHONY: $(TCG_TESTS_TARGETS:%=3Drun-tcg-tests-%) +$(TCG_TESTS_TARGETS:%=3Drun-tcg-tests-%): + @echo " SKIPPED $(subst run-tcg-tests-,,$@) guest-tests because TCG is d= isabled in this build" +endif =20 .PHONY: $(TCG_TESTS_TARGETS:%=3Dclean-tcg-tests-%) $(TCG_TESTS_TARGETS:%=3Dclean-tcg-tests-%): clean-tcg-tests-%: --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304254; cv=none; d=zohomail.com; s=zohoarc; b=AsG40xd5QGZd3g/dLgzKWgPSSlAumZ/eFiME+Zs++y19/Rhhsk8SmSVftxwT6Pbtf0bH0zLjh+5VTjUU+PcM2ndgrHXIjnA3zC4jpjeoA08kyX4MxVcQXXBXVR7BKbQ96C1kJcKQvhCwzCfE87i6QfHqthAFGasay2+CiyFsizE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304254; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=/8HcNTklXSC35TOyNK0U8zsTJeBdHzQ/ZioX1yIWwcE=; b=hZnxUtW3yq4UM1m7DEUACJs8WHTghFpahFqBUcSM/HStPXw7uZweXULhSifjuY41fMnGYP9C92e8BAdxsYikO9yFr49M4kMF0G3a0n2BzNJK4vAkiyFVY+c6wIHFmvsfwI/kU3+zbbwZ0LAnlDppOLVd330t7ONqu1bdMoJjiGY= 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 16733042539905.972277866760351; Mon, 9 Jan 2023 14:44:13 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0rh-0004wf-Vk; Mon, 09 Jan 2023 17:43:38 -0500 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 1pF0re-0004sS-O8; Mon, 09 Jan 2023 17:43:35 -0500 Received: from smtp-out1.suse.de ([195.135.220.28]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0rd-000461-1W; Mon, 09 Jan 2023 17:43:34 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 7197F3FF55; Mon, 9 Jan 2023 22:43:31 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id D1B9013583; Mon, 9 Jan 2023 22:43:28 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id GFowJpCYvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:43:28 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304211; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/8HcNTklXSC35TOyNK0U8zsTJeBdHzQ/ZioX1yIWwcE=; b=OknEBO+JdjYSu5/aHnatsN3rfHuKJvvmOuTPmZVBOOUTNj26UJ3uoIr8Cb59r6xH1dxCFy QwX+GnPL62uAYo/79UMFg7+LnrKCTdE7+68uRuzDxXBSWaAy24OGd019z7UmuxhMDWqS6E 8n0j6+AnCLRaG9zmWe8eoYeAwOtmjB0= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304211; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=/8HcNTklXSC35TOyNK0U8zsTJeBdHzQ/ZioX1yIWwcE=; b=o2S5ur1A4aYsI4OqTvVcwMKTxn01p/jWdzqga0w+DcZhiRnwm74WS3mtqnN62YdBYZGWsr Er/GIoyLvxsMtACA== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf Subject: [RFC PATCH v2 17/19] target/arm: Move regime_using_lpae_format into internal.h Date: Mon, 9 Jan 2023 19:42:30 -0300 Message-Id: <20230109224232.11661-18-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=195.135.220.28; envelope-from=farosas@suse.de; helo=smtp-out1.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304254236100001 Content-Type: text/plain; charset="utf-8" This function is needed by common code (ptw.c), so move it along with the other regime_* functions in internal.h. When we enable the build without TCG, the tlb_helper.c file will not be present. Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson --- Richard: this cannot into ptw.c because that file is softmmu only --- target/arm/internals.h | 21 ++++++++++++++++++--- target/arm/tcg/tlb_helper.c | 18 ------------------ 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index 865b9e8104..b1fccf13a3 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -614,9 +614,6 @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMS= tate *env, /* Return the MMU index for a v7M CPU in the specified security state */ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate); =20 -/* Return true if the translation regime is using LPAE format page tables = */ -bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx); - /* * Return true if the stage 1 translation regime is using LPAE * format page tables @@ -781,6 +778,24 @@ static inline uint64_t regime_tcr(CPUARMState *env, AR= MMMUIdx mmu_idx) return env->cp15.tcr_el[regime_el(env, mmu_idx)]; } =20 +/* Return true if the translation regime is using LPAE format page tables = */ +static inline bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mm= u_idx) +{ + int el =3D regime_el(env, mmu_idx); + if (el =3D=3D 2 || arm_el_is_aa64(env, el)) { + return true; + } + if (arm_feature(env, ARM_FEATURE_PMSA) && + arm_feature(env, ARM_FEATURE_V8)) { + return true; + } + if (arm_feature(env, ARM_FEATURE_LPAE) + && (regime_tcr(env, mmu_idx) & TTBCR_EAE)) { + return true; + } + return false; +} + /** * arm_num_brps: Return number of implemented breakpoints. * Note that the ID register BRPS field is "number of bps - 1", diff --git a/target/arm/tcg/tlb_helper.c b/target/arm/tcg/tlb_helper.c index 60abcbebe6..31eb77f7df 100644 --- a/target/arm/tcg/tlb_helper.c +++ b/target/arm/tcg/tlb_helper.c @@ -12,24 +12,6 @@ #include "exec/helper-proto.h" =20 =20 -/* Return true if the translation regime is using LPAE format page tables = */ -bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx) -{ - int el =3D regime_el(env, mmu_idx); - if (el =3D=3D 2 || arm_el_is_aa64(env, el)) { - return true; - } - if (arm_feature(env, ARM_FEATURE_PMSA) && - arm_feature(env, ARM_FEATURE_V8)) { - return true; - } - if (arm_feature(env, ARM_FEATURE_LPAE) - && (regime_tcr(env, mmu_idx) & TTBCR_EAE)) { - return true; - } - return false; -} - /* * Returns true if the stage 1 translation regime is using LPAE format page * tables. Used when raising alignment exceptions, whose FSR changes depen= ding --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304851; cv=none; d=zohomail.com; s=zohoarc; b=iD4WO4i9wnQp+VCDcVqsrj5yYJSHG7ZWcfcbtwnAva8dS+vyaK8usin1tbEAFX3aOYNLL8Jg+NzwXdclRBbg6gaGSDbBktcHSM7GCOM3J92c7Kt4vJc2QjlE5Ek6cF5uTXdA657v22QDsSmq+9zYmVBUwSw8S5CfwkfJXtoSO5A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304851; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=UcPvJ2TkX8BmU0xYGg1vpayMTRS1XI7tg4m7dSlXwDU=; b=oL7hYxE2eKG3V5KLHm5LynFNAS5L3MM8TewCmLaOuzmG570yeGroibSiRvJPAuZ9C+snUszQHDso2DAU0qFX9WKRoWSK5NW4yo+11N/yAXqwAabjR/pQGtC3Lw/kMOGYee7n3o0qSKMPns0Fd7JnqYp6TceaQyklb4xCBdnb6I0= 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 1673304851630704.4311526436624; Mon, 9 Jan 2023 14:54:11 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0rs-00059U-AJ; Mon, 09 Jan 2023 17:43:48 -0500 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 1pF0rh-0004wL-O9; Mon, 09 Jan 2023 17:43:37 -0500 Received: from smtp-out2.suse.de ([2001:67c:2178:6::1d]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0rg-00046F-8i; Mon, 09 Jan 2023 17:43:37 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 724FB5CDDF; Mon, 9 Jan 2023 22:43:34 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id D62CB13583; Mon, 9 Jan 2023 22:43:31 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id 0Bp1J5OYvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:43:31 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304214; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UcPvJ2TkX8BmU0xYGg1vpayMTRS1XI7tg4m7dSlXwDU=; b=1q/S1jlgKvGsJxOItlLNN7nJvVmPUIJk6RwWsG7iCcndL6hXg8SWxuq4xrU8PAKTMF2hUS 607JHLI4V5X4NSxftcRQX3iYYFe+v21h18QnidIMABm9EC+UhMSdcO3N9DOyVo2leshRza quNCkPksybxSLp5EWXXZlxt+pGhl6Yg= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304214; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UcPvJ2TkX8BmU0xYGg1vpayMTRS1XI7tg4m7dSlXwDU=; b=sEkkpLQUHcvJtHvwJaKBbtA7qMjeNgbRGn4fM63RuH+Pr6SjrcDZWSX7s90axsx13flqds QjarXhbG2iNW28Dg== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf Subject: [RFC PATCH v2 18/19] cpu-defs.h: Expose CPUTLBEntryFull to non-TCG code Date: Mon, 9 Jan 2023 19:42:31 -0300 Message-Id: <20230109224232.11661-19-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=2001:67c:2178:6::1d; envelope-from=farosas@suse.de; helo=smtp-out2.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304852024100001 Content-Type: text/plain; charset="utf-8" This struct has no dependencies on TCG code and it is being used in target/arm/ptw.c to simplify the passing around of page table walk results. Those routines can be reached by KVM code via the gdbstub breakpoint code, so take the structure out of CONFIG_TCG to make it visible when building with --disable-tcg. Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson --- include/exec/cpu-defs.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index 21309cf567..d5a4f30717 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -135,6 +135,10 @@ typedef struct CPUTLBEntry { =20 QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) !=3D (1 << CPU_TLB_ENTRY_BITS)); =20 + +#endif /* !CONFIG_USER_ONLY && CONFIG_TCG */ + +#if !defined(CONFIG_USER_ONLY) /* * The full TLB entry, which is not accessed by generated TCG code, * so the layout is not as critical as that of CPUTLBEntry. This is @@ -176,7 +180,9 @@ typedef struct CPUTLBEntryFull { TARGET_PAGE_ENTRY_EXTRA #endif } CPUTLBEntryFull; +#endif /* !CONFIG_USER_ONLY */ =20 +#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG) /* * Data elements that are per MMU mode, minus the bits accessed by * the TCG fast path. --=20 2.35.3 From nobody Sun May 19 12:26:33 2024 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=suse.de ARC-Seal: i=1; a=rsa-sha256; t=1673304299; cv=none; d=zohomail.com; s=zohoarc; b=XPteuG1GG7WCtcjcP+ov7tZ51D5SLqP2wUNEpkdYMSeFAVLmvydTAdaekafbWs3VihlmsDxgfOLtZPXnCOOz3arAgkQ5YT3DJbcOubE+vwVNgysKFX/ofa6xkxM/ex/XmMcMAIBveKqd8mkvNWCeKsX0aFMg/cBkhVyEtNvrzqo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1673304299; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=GJJaQ6RX18AB1IgIirPBH7v9XndR2ZG0D9lUt6BsoB8=; b=YHrg6W7WwrKHGsSJiy5j+OnZ+gwVml6/EO5GM6haT+f3W7vjZGSZNJ/ubwG3FdNtlCYBgmt3iTH6SDKH155PsG96LHmIQv6xWiPaoC2JaNLrh8DHQFoyazmWu1T9haoasJy7Xf5z6pvby0dP+mEqJgTjZ+NC+xqJHPKz+pB0mQQ= 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 1673304299075962.7650813720068; Mon, 9 Jan 2023 14:44:59 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pF0ru-0005B0-11; Mon, 09 Jan 2023 17:43:50 -0500 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 1pF0ro-00058v-NA; Mon, 09 Jan 2023 17:43:46 -0500 Received: from smtp-out1.suse.de ([195.135.220.28]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1pF0rj-00046q-G6; Mon, 09 Jan 2023 17:43:40 -0500 Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 6E93C4D34C; Mon, 9 Jan 2023 22:43:37 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id D65FF13583; Mon, 9 Jan 2023 22:43:34 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id IKaoJ5aYvGMdIQAAMHmgww (envelope-from ); Mon, 09 Jan 2023 22:43:34 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1673304217; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GJJaQ6RX18AB1IgIirPBH7v9XndR2ZG0D9lUt6BsoB8=; b=zHhLLfRvhjUr7LV5rAIfzHgU2/WZFTBhz7ImM+U1AzkyQJRtixaVnPm4J5iFVa4myOEzmF zDNVVy4Ja5wAHX3XFMcgC3DbuYeI5lhdEBmXzQXqcoy8UtRbN5r5ERAinmVA5QaaD9RPXn XKki7LYPbgQEgS3N5PEXkoHm8mRCM90= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1673304217; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=GJJaQ6RX18AB1IgIirPBH7v9XndR2ZG0D9lUt6BsoB8=; b=h2shsNdXIdCsBnrxdBpNaV/a8dKdocNaO4NE8Z/zu5RUmNnOIcrvepiJ4ZODoiFZ8Hg07t dfnNVk+QzLYoqTAg== From: Fabiano Rosas To: qemu-devel@nongnu.org Cc: qemu-arm@nongnu.org, Peter Maydell , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Paolo Bonzini , Claudio Fontana , Eduardo Habkost , Alexander Graf Subject: [RFC PATCH v2 19/19] target/arm: don't access TCG code when debugging with KVM Date: Mon, 9 Jan 2023 19:42:32 -0300 Message-Id: <20230109224232.11661-20-farosas@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230109224232.11661-1-farosas@suse.de> References: <20230109224232.11661-1-farosas@suse.de> 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=195.135.220.28; envelope-from=farosas@suse.de; helo=smtp-out1.suse.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 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, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @suse.de) X-ZM-MESSAGEID: 1673304300479100003 Content-Type: text/plain; charset="utf-8" When TCG is disabled this part of the code should not be reachable, so wrap it with an ifdef for now. This allows us to start using CONFIG_TCG=3Dn (--disable-tcg in the configure line). Signed-off-by: Fabiano Rosas Reviewed-by: Richard Henderson --- target/arm/ptw.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 4bda0590c7..2af75d0904 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -254,6 +254,7 @@ static bool S1_ptw_translate(CPUARMState *env, S1Transl= ate *ptw, ptw->out_host =3D NULL; ptw->out_rw =3D false; } else { +#ifdef CONFIG_TCG CPUTLBEntryFull *full; int flags; =20 @@ -270,6 +271,9 @@ static bool S1_ptw_translate(CPUARMState *env, S1Transl= ate *ptw, ptw->out_rw =3D full->prot & PAGE_WRITE; pte_attrs =3D full->pte_attrs; pte_secure =3D full->attrs.secure; +#else + g_assert_not_reached(); +#endif } =20 if (regime_is_stage2(s2_mmu_idx)) { --=20 2.35.3