From patchwork Sat Mar 15 09:14:19 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Michael Tokarev X-Patchwork-Id: 873872 Delivered-To: patch@linaro.org Received: by 2002:a5d:4308:0:b0:38f:210b:807b with SMTP id h8csp1105362wrq; Sat, 15 Mar 2025 02:19:22 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCUvhXOo92O1LroVWPIzfIkXpiHDzWqglhmlhE2UGnB3rmhzWLe5ZrNtiHCfocO3DIexDWtZnA==@linaro.org X-Google-Smtp-Source: AGHT+IFXkrzNkpHYaPujtpjAtm6J9o3OUY8B/2jk6rLhmDwrSKFQjyx36xiORNyjVf3L8aurhxF+ X-Received: by 2002:a05:620a:408a:b0:7c5:4c6d:7fa5 with SMTP id af79cd13be357-7c57c9192e2mr847855985a.48.1742030362077; Sat, 15 Mar 2025 02:19:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1742030362; cv=none; d=google.com; s=arc-20240605; b=aoz1YBUghq2x4uiynwfFFdppwIA1uApbbFrkv6RL/4/V0FJRtAO04PGO6HBNZtOY2d uB21L2acWYZXxGxyAuw2pdf284ZPKhvlHBjHDEwRGowkAFSUb5Xx0BxL6tSsej+sYHkO xaQ9JCldokomKoSrJhVP8FhILR+62ffV9+k6fHQ4FWfi3LHsF39f0CUEAFMNkijn3Q8z Y9H32YHNABv3os24EaRLylG4eAzcJOmTcmBu/eRBPWs1uKXJv+H2o01m/xPAzymd3PSY oUqSytN5DBUwMZdz+4Xl9EpGqWJZbDsJYENyCVdrgtqIcSDYKH8/BNiP3p3Nk8afDK9h UKyA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from; bh=cqIY/ECi5/Z4ptbhU4OyGEFfgUrJ/qPGOULcj3wNQRw=; fh=upfN+4mcRAuX+bX9oPqMwq1TP+fTfKlWZBqspF+lG6I=; b=dc8ViMP/0JD4oVRZZ6Dlv4+Jn2UM0xXrU//v6TnEn1pHX4vFCIjQXpvQYkFujeMVQp GwaA3g+EDe7vkdWVf/H2BlyQUtK+s5Ns8bvNYzYg9VsPwnq/lpisU4m0gbYCDLNa88ul S3EGyak9uApcJKVeF2KDb9YVjJ6oeg0Lkj6TcCwwEUqxz+UQCSZs434D71U2Pp3Qggp0 oVepIcgPjplD46MA/KvqDEuTtRYcecxSExPCYa9pxysTH/+E7THUmKPgY2DdjP5HfnVk FHxFm4gBG7Hv7OjCk/QJDS8rKJmqZjkEg33BsN+DKdo8HAyuWwcVLhcxDjgEw2MicJ36 yA+Q==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org" Return-Path: Received: from lists.gnu.org (lists.gnu.org. [209.51.188.17]) by mx.google.com with ESMTPS id af79cd13be357-7c573b75442si542402285a.126.2025.03.15.02.19.21 for (version=TLS1_2 cipher=ECDHE-ECDSA-CHACHA20-POLY1305 bits=256/256); Sat, 15 Mar 2025 02:19:22 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; Authentication-Results: mx.google.com; spf=pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom="qemu-devel-bounces+patch=linaro.org@nongnu.org" Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ttNc8-0002vp-0B; Sat, 15 Mar 2025 05:15:28 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ttNbn-0002kl-4V; Sat, 15 Mar 2025 05:15:08 -0400 Received: from isrv.corpit.ru ([86.62.121.231]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ttNbl-0007ma-5s; Sat, 15 Mar 2025 05:15:06 -0400 Received: from tsrv.corpit.ru (tsrv.tls.msk.ru [192.168.177.2]) by isrv.corpit.ru (Postfix) with ESMTP id BE535FFBB9; Sat, 15 Mar 2025 12:13:45 +0300 (MSK) Received: from gandalf.tls.msk.ru (mjt.wg.tls.msk.ru [192.168.177.130]) by tsrv.corpit.ru (Postfix) with ESMTP id C6C631CAD52; Sat, 15 Mar 2025 12:14:39 +0300 (MSK) Received: by gandalf.tls.msk.ru (Postfix, from userid 1000) id A5A4955A3A; Sat, 15 Mar 2025 12:14:39 +0300 (MSK) From: Michael Tokarev To: qemu-devel@nongnu.org Cc: qemu-stable@nongnu.org, Peter Maydell , =?utf-8?q?Alex_Benn=C3=A9e?= , Richard Henderson , Michael Tokarev Subject: [Stable-7.2.17 08/27] target/arm: Make CP_ACCESS_TRAPs to AArch32 EL3 be Monitor traps Date: Sat, 15 Mar 2025 12:14:19 +0300 Message-Id: <20250315091439.657371-8-mjt@tls.msk.ru> X-Mailer: git-send-email 2.39.5 In-Reply-To: References: MIME-Version: 1.0 Received-SPF: pass client-ip=86.62.121.231; envelope-from=mjt@tls.msk.ru; helo=isrv.corpit.ru X-Spam_score_int: -68 X-Spam_score: -6.9 X-Spam_bar: ------ X-Spam_report: (-6.9 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_HI=-5, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, 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+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org From: Peter Maydell In system register access pseudocode the common pattern for AArch32 registers with access traps to EL3 is: at EL1 and EL2: if HaveEL(EL3) && !ELUsingAArch32(EL3) && (SCR_EL3.TERR == 1) then AArch64.AArch32SystemAccessTrap(EL3, 0x03); elsif HaveEL(EL3) && ELUsingAArch32(EL3) && (SCR.TERR == 1) then AArch32.TakeMonitorTrapException(); at EL3: if (PSTATE.M != M32_Monitor) && (SCR.TERR == 1) then AArch32.TakeMonitorTrapException(); (taking as an example the ERRIDR access pseudocode). This implements the behaviour of (in this case) SCR.TERR that "Accesses to the specified registers from modes other than Monitor mode generate a Monitor Trap exception" and of SCR_EL3.TERR that "Accesses of the specified Error Record registers at EL2 and EL1 are trapped to EL3, unless the instruction generates a higher priority exception". In QEMU we don't implement this pattern correctly in two ways: * in access_check_cp_reg() we turn the CP_ACCESS_TRAP_EL3 into an UNDEF, not a trap to Monitor mode * in the access functions, we check trap bits like SCR.TERR only when arm_current_el(env) < 3 -- this is correct for AArch64 EL3, but misses the "trap non-Monitor-mode execution at EL3 into Monitor mode" case for AArch32 EL3 In this commit we fix the first of these two issues, by making access_check_cp_reg() handle CP_ACCESS_TRAP_EL3 as a Monitor trap. This is a kind of exception that we haven't yet implemented(!), so we need a new EXCP_MON_TRAP for it. This diverges from the pseudocode approach, where every access check function explicitly checks for "if EL3 is AArch32" and takes a monitor trap; if we wanted to be closer to the pseudocode we could add a new CP_ACCESS_TRAP_MONITOR and make all the accessfns use it when appropriate. But because there are no non-standard cases in the pseudocode (i.e. where either it raises a Monitor trap that doesn't correspond to an AArch64 SystemAccessTrap or where it raises a SystemAccessTrap that doesn't correspond to a Monitor trap), handling this all in one place seems less likely to result in future bugs where we forgot again about this special case when writing an accessor. (The cc of stable here is because "hw/intc/arm_gicv3_cpuif: Don't downgrade monitor traps for AArch32 EL3" which is also cc:stable will implicitly use the new EXCP_MON_TRAP code path.) Cc: qemu-stable@nongnu.org Signed-off-by: Peter Maydell Reviewed-by: Alex Bennée Reviewed-by: Richard Henderson Message-id: 20250130182309.717346-6-peter.maydell@linaro.org (cherry picked from commit 4cf4948651615181c5bc3d0e4a9f5c46be576bb2) (Mjt: context fix due to missing v9.0.0-151-gb36a32ead159 "target/arm: Add support for Non-maskable Interrupt", v8.0.0-2011-g11b76fda0adc "target/arm: Implement GPC exceptions") Signed-off-by: Michael Tokarev diff --git a/target/arm/cpu.h b/target/arm/cpu.h index a9cd7178f8..32b0bf8e2d 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -57,6 +57,7 @@ #define EXCP_UNALIGNED 22 /* v7M UNALIGNED UsageFault */ #define EXCP_DIVBYZERO 23 /* v7M DIVBYZERO UsageFault */ #define EXCP_VSERR 24 +#define EXCP_MON_TRAP 29 /* AArch32 trap to Monitor mode */ /* NB: add new EXCP_ defines to the array in arm_log_exception() too */ #define ARMV7M_EXCP_RESET 1 diff --git a/target/arm/helper.c b/target/arm/helper.c index 24585d528b..6cffbcb276 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -9475,6 +9475,7 @@ void arm_log_exception(CPUState *cs) [EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault", [EXCP_DIVBYZERO] = "v7M DIVBYZERO UsageFault", [EXCP_VSERR] = "Virtual SERR", + [EXCP_MON_TRAP] = "Monitor Trap", }; if (idx >= 0 && idx < ARRAY_SIZE(excnames)) { @@ -10036,6 +10037,16 @@ static void arm_cpu_do_interrupt_aarch32(CPUState *cs) mask = CPSR_A | CPSR_I | CPSR_F; offset = 0; break; + case EXCP_MON_TRAP: + new_mode = ARM_CPU_MODE_MON; + addr = 0x04; + mask = CPSR_A | CPSR_I | CPSR_F; + if (env->thumb) { + offset = 2; + } else { + offset = 4; + } + break; default: cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index); return; /* Never happens. Keep compiler happy. */ diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c index 70672bcd9f..9b07c79392 100644 --- a/target/arm/op_helper.c +++ b/target/arm/op_helper.c @@ -631,6 +631,7 @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome, const ARMCPRegInfo *ri = rip; CPAccessResult res = CP_ACCESS_OK; int target_el; + uint32_t excp; if (arm_feature(env, ARM_FEATURE_XSCALE) && ri->cp < 14 && extract32(env->cp15.c15_cpar, ri->cp, 1) == 0) { @@ -667,8 +668,18 @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome, } fail: + excp = EXCP_UDEF; switch (res & ~CP_ACCESS_EL_MASK) { case CP_ACCESS_TRAP: + /* + * If EL3 is AArch32 then there's no syndrome register; the cases + * where we would raise a SystemAccessTrap to AArch64 EL3 all become + * raising a Monitor trap exception. (Because there's no visible + * syndrome it doesn't matter what we pass to raise_exception().) + */ + if ((res & CP_ACCESS_EL_MASK) == 3 && !arm_el_is_aa64(env, 3)) { + excp = EXCP_MON_TRAP; + } break; case CP_ACCESS_TRAP_UNCATEGORIZED: if (cpu_isar_feature(aa64_ids, cpu) && isread && @@ -702,7 +713,7 @@ void HELPER(access_check_cp_reg)(CPUARMState *env, void *rip, uint32_t syndrome, g_assert_not_reached(); } - raise_exception(env, EXCP_UDEF, syndrome, target_el); + raise_exception(env, excp, syndrome, target_el); } void HELPER(set_cp_reg)(CPUARMState *env, void *rip, uint32_t value)