From nobody Fri Mar 20 21:46:49 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=linaro.org ARC-Seal: i=1; a=rsa-sha256; t=1771935120; cv=none; d=zohomail.com; s=zohoarc; b=RVA4oZtBq5cpgyFOZ5U8rF+zeSZHK/CHAH9HKlmaHvndh5ReNbtwE6qTkOvllEkyJGMO/+itS7BP80JvcQhk60WL6xvifv14dZiLSGDM2Kg1LTHglMLbfAUGaa5l1pVYntSwaViKXz8zDdm/R5yJo++abX0i3xmGcVE228h1axk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1771935120; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=hdm/FWJYafm9q16YplQfONC7aZ1Ud4UCye6jBHBX6zg=; b=B6+scI+sRUiSmNqEMlr8IGYspq/ik5FyOrJXGPT8zLcCzS1/H3oAM3HqssFzI33BiprC5GsdT280uOFfHbEK1sYPSacYGVrAebaYQptAOAxL74hLb4K2uxHzbhkognvR+J121z1ToyVQiiRRT2AQBw+yRjHkwIXtGdnbB/eN1Q0= 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 1771935120971455.0423304201522; Tue, 24 Feb 2026 04:12:00 -0800 (PST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1vurFk-0005h4-8S; Tue, 24 Feb 2026 07:11:00 -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 1vurFJ-0005aR-B9 for qemu-devel@nongnu.org; Tue, 24 Feb 2026 07:10:34 -0500 Received: from mail-ed1-x529.google.com ([2a00:1450:4864:20::529]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1vurFG-0005tH-Ju for qemu-devel@nongnu.org; Tue, 24 Feb 2026 07:10:32 -0500 Received: by mail-ed1-x529.google.com with SMTP id 4fb4d7f45d1cf-65a40f3f048so10057571a12.3 for ; Tue, 24 Feb 2026 04:10:22 -0800 (PST) Received: from draig.lan ([185.124.0.126]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-65eaba3f967sm3618611a12.31.2026.02.24.04.10.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Feb 2026 04:10:18 -0800 (PST) Received: from draig.lan (localhost [IPv6:::1]) by draig.lan (Postfix) with ESMTP id 0EE9D5F8D3; Tue, 24 Feb 2026 12:10:15 +0000 (GMT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1771935021; x=1772539821; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=hdm/FWJYafm9q16YplQfONC7aZ1Ud4UCye6jBHBX6zg=; b=FW6NUDS6QM0b0x1/xPGux5nI4/l7zolm44WoSHD6jHNEnpFMGNka1UcbLmW7SrG4ne 6pvzjyVVRRFMFo7fHzKDUJeHV0P7lXXho2kN9tqSYafFHxZhnqotBBQffCxzXVxQ4LhA TEnH2g1OPZ4GGd+29xsDrFxQl52VG+xcFmKS0kYetzQRwCVakU6PMLnYHXZ3oIem7nOp 8/h5FK3HtA6s31Euh4G03ASFTlcwpZXUg7VWJM1CIlZ8izbt4VaC56XWo1Bv71TIk/3s NRgWsvDZy3Gkcd1TfBfqaJEav1yLa1J5MmAfZOpgO0UrRUyPBq2SryTpAmnl0rWT2Q4y Pj2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1771935021; x=1772539821; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=hdm/FWJYafm9q16YplQfONC7aZ1Ud4UCye6jBHBX6zg=; b=rXkrjexXoZyngcv77WSCXSzNauKbxmNdSu9dC8F0O+BF2RntvcWnQxFDmp+4CWs1eq P8IsSb3n8sB6zScxa0odllI78wO6bgOuHcdl6ncF+evabd3IEML99NvVXWhx6VRQNtBs DwmaEWpcVl13Q9YW39mFZ8rjIYcPvDfrkbZRGwgLAhRNhOBhW9/E81/C95JqQwt2lSS+ fYFcWOUOaqggCbX8aGAGtDOb5kyqS6M8SrXbu6zbtGVL9fgNUtYmufcKRDV5DqjZXSTw 9h5GoUruqKT7VkZUyXON98MBloh2V20Y4hv0+EcO+FlXlfVmFhmwUFNf6jPKaBSaNwSF Ke6w== X-Gm-Message-State: AOJu0YwfJipkdH8DB6chVpwKnlOPY3o7vB5jbURidHKfyE9h3e608mrM TLrSD/eW3bnZe8j2fkuVBlRQMvpcakHeEkMAAQGBb1OeTGrqMDyqE4LDo1l3AKfU7rg= X-Gm-Gg: ATEYQzwkwqGnxe7YGyrKHOVWbIyY5R/5UieF1G5VxOl2kULXeOJWlU6zeoIqOXt4yYW rlrSmAhX1JRqSlyxk7fINQJp16nKvDUi1qtyAOeuYaJ3JbUScW+K1oH6+tpwe2aJlGCksqWP+h5 zDH4AIOTB5YEGPWs+czMlwE14TclfZji9m9qEolhSjmh29ucZNcwpbJ8XdLYqglEY1Ea5wLGMGL JRsmO7pZmP4clw7HelJ/WIlbKxfMHF/hYuOENLg2Wwe6By87fYS5juCbzO3aOulVOYS7moBuDR4 V4HJUStaJE1PlRlNOXzjMnhzYYUyPWS/arRzNQRtbWkFytMHlmyUeBhZ6e4gedb14rXC/X/4lr7 0pqOwgoe2/Zg/tQPIqMnU7zk4/Ei49z5USp2KE556MynJRbdb7UQxawlH/eogmyv5XmNHNZMJTc YNEGd7c9KZlTMJiR7C9QwnTScAal3TBKIQPA== X-Received: by 2002:a05:6402:399b:b0:65b:bd9d:731a with SMTP id 4fb4d7f45d1cf-65ea4ec7eebmr5431890a12.13.1771935021335; Tue, 24 Feb 2026 04:10:21 -0800 (PST) From: =?UTF-8?q?Alex=20Benn=C3=A9e?= To: qemu-devel@nongnu.org Cc: Peter Maydell , qemu-arm@nongnu.org, =?UTF-8?q?Alex=20Benn=C3=A9e?= , eca Subject: [PATCH 5/8] target/arm: extend WFX support for A-profile Date: Tue, 24 Feb 2026 12:10:11 +0000 Message-ID: <20260224121014.279248-6-alex.bennee@linaro.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260224121014.279248-1-alex.bennee@linaro.org> References: <20260224121014.279248-1-alex.bennee@linaro.org> 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=2a00:1450:4864:20::529; envelope-from=alex.bennee@linaro.org; helo=mail-ed1-x529.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @linaro.org) X-ZM-MESSAGEID: 1771935122502158500 This commit extends support for WFI, WFE, WFIT, and WFET instructions for A-profile ARM CPUs, ensuring proper architectural semantics and full ISS (Instruction Specific Syndrome) field support for traps. Key changes: - Update `syn_wfx` in `target/arm/syndrome.h` to include `RN` (register number) and `RV` (register valid) fields using `registerfields.h` macros. - Refactor `HELPER(wfi)` and `HELPER(wfit)` to use correct AArch64 syndrome values (CV=3D0, COND=3D0xf). - Implement `HELPER(wfet)` and update `trans_WFET` to support the new Wait For Event with Timeout instruction. - Update `HELPER(wfe)` to implement proper A-profile semantics, including trap checks and event register handling. - Extend `event_register` handling to all ARM CPUs (not just M-profile) by updating `HELPER(sev)` and `arm_cpu_has_work`. - Declare WFxT helpers as `TCG_CALL_NO_WG` as they can raise exceptions. =F0=9F=A4=96 Generated with [eca](https://eca.dev) Co-Authored-By: eca --- ajb - this commit is a bit big, it didn't follow the instructions to keep the commits small - I had to add DEF_HELPER_FLAGS_3 to the helpers as it didn't realise we need to ensure rd is potentially rectified. --- target/arm/syndrome.h | 24 ++++++-- target/arm/tcg/helper-defs.h | 3 +- target/arm/cpu.c | 6 +- target/arm/tcg/op_helper.c | 101 +++++++++++++++++++++++---------- target/arm/tcg/translate-a64.c | 17 +++--- 5 files changed, 104 insertions(+), 47 deletions(-) diff --git a/target/arm/syndrome.h b/target/arm/syndrome.h index bff61f052cc..49861758262 100644 --- a/target/arm/syndrome.h +++ b/target/arm/syndrome.h @@ -26,6 +26,7 @@ #define TARGET_ARM_SYNDROME_H =20 #include "qemu/bitops.h" +#include "hw/core/registerfields.h" =20 /* Valid Syndrome Register EC field values */ enum arm_exception_class { @@ -352,11 +353,26 @@ static inline uint32_t syn_breakpoint(int same_el) | ARM_EL_IL | 0x22; } =20 -static inline uint32_t syn_wfx(int cv, int cond, int ti, bool is_16bit) +FIELD(WFX_ISS, TI, 0, 2) +FIELD(WFX_ISS, RV, 14, 1) +FIELD(WFX_ISS, RN, 15, 5) +FIELD(WFX_ISS, COND, 20, 4) +FIELD(WFX_ISS, CV, 24, 1) + +static inline uint32_t syn_wfx(int cv, int cond, int rd, int rv, int ti, b= ool is_16bit) { - return (EC_WFX_TRAP << ARM_EL_EC_SHIFT) | - (is_16bit ? 0 : (1 << ARM_EL_IL_SHIFT)) | - (cv << 24) | (cond << 20) | ti; + uint32_t res =3D (EC_WFX_TRAP << ARM_EL_EC_SHIFT); + + res =3D FIELD_DP32(res, WFX_ISS, CV, cv); + res =3D FIELD_DP32(res, WFX_ISS, COND, cond); + res =3D FIELD_DP32(res, WFX_ISS, RN, rd); + res =3D FIELD_DP32(res, WFX_ISS, RV, rv); + res =3D FIELD_DP32(res, WFX_ISS, TI, ti); + + if (!is_16bit) { + res |=3D ARM_EL_IL; + } + return res; } =20 static inline uint32_t syn_illegalstate(void) diff --git a/target/arm/tcg/helper-defs.h b/target/arm/tcg/helper-defs.h index 5a10a9fba3b..d54eb63eef6 100644 --- a/target/arm/tcg/helper-defs.h +++ b/target/arm/tcg/helper-defs.h @@ -55,7 +55,8 @@ DEF_HELPER_2(exception_pc_alignment, noreturn, env, vaddr) DEF_HELPER_1(setend, void, env) DEF_HELPER_2(wfi, void, env, i32) DEF_HELPER_1(wfe, void, env) -DEF_HELPER_2(wfit, void, env, i64) +DEF_HELPER_FLAGS_3(wfit, TCG_CALL_NO_WG, void, env, i64, i32) +DEF_HELPER_FLAGS_3(wfet, TCG_CALL_NO_WG, void, env, i64, i32) DEF_HELPER_1(yield, void, env) DEF_HELPER_1(pre_hvc, void, env) DEF_HELPER_2(pre_smc, void, env, i32) diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 10f8280eef2..bc789515af9 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -144,10 +144,8 @@ static bool arm_cpu_has_work(CPUState *cs) { ARMCPU *cpu =3D ARM_CPU(cs); =20 - if (arm_feature(&cpu->env, ARM_FEATURE_M)) { - if (cpu->env.event_register) { - return true; - } + if (cpu->env.event_register) { + return true; } =20 return (cpu->power_state !=3D PSCI_OFF) diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c index aa14f15eb62..37538daea74 100644 --- a/target/arm/tcg/op_helper.c +++ b/target/arm/tcg/op_helper.c @@ -393,13 +393,17 @@ void HELPER(wfi)(CPUARMState *env, uint32_t insn_len) } =20 if (target_el) { - if (env->aarch64) { + int cv =3D 1, cond =3D 0xe; + + if (is_a64(env)) { env->pc -=3D insn_len; + cv =3D 0; + cond =3D 0xf; } else { env->regs[15] -=3D insn_len; } =20 - raise_exception(env, excp, syn_wfx(1, 0xe, 0, insn_len =3D=3D 2), + raise_exception(env, excp, syn_wfx(cv, cond, 0, 0, 0, insn_len =3D= =3D 2), target_el); } =20 @@ -409,7 +413,7 @@ void HELPER(wfi)(CPUARMState *env, uint32_t insn_len) #endif } =20 -void HELPER(wfit)(CPUARMState *env, uint64_t timeout) +void HELPER(wfit)(CPUARMState *env, uint64_t timeout, uint32_t rd) { #ifdef CONFIG_USER_ONLY /* @@ -448,7 +452,7 @@ void HELPER(wfit)(CPUARMState *env, uint64_t timeout) =20 if (target_el) { env->pc -=3D 4; - raise_exception(env, excp, syn_wfx(1, 0xe, 2, false), target_el); + raise_exception(env, excp, syn_wfx(0, 0xf, rd, 1, 2, false), targe= t_el); } =20 if (uadd64_overflow(timeout, offset, &nexttick)) { @@ -469,14 +473,50 @@ void HELPER(wfit)(CPUARMState *env, uint64_t timeout) #endif } =20 +void HELPER(wfet)(CPUARMState *env, uint64_t timeout, uint32_t rd) +{ +#ifdef CONFIG_USER_ONLY + return; +#else + ARMCPU *cpu =3D env_archcpu(env); + CPUState *cs =3D env_cpu(env); + uint32_t excp; + int target_el =3D check_wfx_trap(env, true, &excp); + uint64_t cntval =3D gt_get_countervalue(env); + uint64_t offset =3D gt_direct_access_timer_offset(env, GTIMER_VIRT); + uint64_t cntvct =3D cntval - offset; + uint64_t nexttick; + + if (env->event_register || cpu_has_work(cs) || cntvct >=3D timeout) { + env->event_register =3D false; + return; + } + + if (target_el) { + env->pc -=3D 4; + raise_exception(env, excp, syn_wfx(0, 0xf, rd, 1, 3, false), targe= t_el); + } + + if (uadd64_overflow(timeout, offset, &nexttick)) { + nexttick =3D UINT64_MAX; + } + if (nexttick > INT64_MAX / gt_cntfrq_period_ns(cpu)) { + timer_mod_ns(cpu->wfxt_timer, INT64_MAX); + } else { + timer_mod(cpu->wfxt_timer, nexttick); + } + cs->exception_index =3D EXCP_HLT; + cs->halted =3D 1; + cpu_loop_exit(cs); +#endif +} + void HELPER(sev)(CPUARMState *env) { CPUState *cs =3D env_cpu(env); CPU_FOREACH(cs) { ARMCPU *target_cpu =3D ARM_CPU(cs); - if (arm_feature(&target_cpu->env, ARM_FEATURE_M)) { - target_cpu->env.event_register =3D true; - } + target_cpu->env.event_register =3D true; if (!qemu_cpu_is_self(cs)) { qemu_cpu_kick(cs); } @@ -493,33 +533,34 @@ void HELPER(wfe)(CPUARMState *env) */ return; #else - /* - * WFE (Wait For Event) is a hint instruction. - * For Cortex-M (M-profile), we implement the strict architectural beh= avior: - * 1. Check the Event Register (set by SEV or SEVONPEND). - * 2. If set, clear it and continue (consume the event). - */ - if (arm_feature(env, ARM_FEATURE_M)) { - CPUState *cs =3D env_cpu(env); + CPUState *cs =3D env_cpu(env); + uint32_t excp; + int target_el =3D check_wfx_trap(env, true, &excp); =20 - if (env->event_register) { - env->event_register =3D false; - return; + if (env->event_register) { + env->event_register =3D false; + return; + } + + if (target_el) { + bool is_16bit =3D false; + if (is_a64(env)) { + env->pc -=3D 4; + } else { + is_16bit =3D env->thumb; + env->regs[15] -=3D (is_16bit ? 2 : 4); } =20 - cs->exception_index =3D EXCP_HLT; - cs->halted =3D 1; - cpu_loop_exit(cs); - } else { - /* - * For A-profile and others, we rely on the existing "yield" behav= ior. - * Don't actually halt the CPU, just yield back to top - * level loop. This is not going into a "low power state" - * (ie halting until some event occurs), so we never take - * a configurable trap to a different exception level - */ - HELPER(yield)(env); + raise_exception(env, excp, + syn_wfx(is_a64(env) ? 0 : 1, + is_a64(env) ? 0xf : 0xe, + 0, 0, 1, is_16bit), + target_el); } + + cs->exception_index =3D EXCP_HLT; + cs->halted =3D 1; + cpu_loop_exit(cs); #endif } =20 diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c index 5d261a5e32b..f76a00d1329 100644 --- a/target/arm/tcg/translate-a64.c +++ b/target/arm/tcg/translate-a64.c @@ -2064,7 +2064,7 @@ static bool trans_WFIT(DisasContext *s, arg_WFIT *a) } =20 gen_a64_update_pc(s, 4); - gen_helper_wfit(tcg_env, cpu_reg(s, a->rd)); + gen_helper_wfit(tcg_env, cpu_reg(s, a->rd), tcg_constant_i32(a->rd)); /* Go back to the main loop to check for interrupts */ s->base.is_jmp =3D DISAS_EXIT; return true; @@ -2076,14 +2076,15 @@ static bool trans_WFET(DisasContext *s, arg_WFET *a) return false; } =20 - /* - * We rely here on our WFE implementation being a NOP, so we - * don't need to do anything different to handle the WFET timeout - * from what trans_WFE does. - */ - if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) { - s->base.is_jmp =3D DISAS_WFE; + if (s->ss_active) { + /* Act like a NOP under architectural singlestep */ + return true; } + + gen_a64_update_pc(s, 4); + gen_helper_wfet(tcg_env, cpu_reg(s, a->rd), tcg_constant_i32(a->rd)); + /* Go back to the main loop to check for interrupts */ + s->base.is_jmp =3D DISAS_EXIT; return true; } =20 --=20 2.47.3