{"id":2231089,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2231089/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20260430104434.1482407-8-alex.bennee@linaro.org/","project":{"id":14,"url":"http://patchwork.ozlabs.org/api/1.1/projects/14/?format=json","name":"QEMU Development","link_name":"qemu-devel","list_id":"qemu-devel.nongnu.org","list_email":"qemu-devel@nongnu.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20260430104434.1482407-8-alex.bennee@linaro.org>","date":"2026-04-30T10:44:34","name":"[v4,7/7] target/arm: implement WFET","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"8dceb2c63fbdceb068b675131536ee9c64df7940","submitter":{"id":39532,"url":"http://patchwork.ozlabs.org/api/1.1/people/39532/?format=json","name":"Alex Bennée","email":"alex.bennee@linaro.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20260430104434.1482407-8-alex.bennee@linaro.org/mbox/","series":[{"id":502271,"url":"http://patchwork.ozlabs.org/api/1.1/series/502271/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/list/?series=502271","date":"2026-04-30T10:44:31","name":"target/arm: fully model WFxT instructions for A-profile","version":4,"mbox":"http://patchwork.ozlabs.org/series/502271/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2231089/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2231089/checks/","tags":{},"headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256\n header.s=google header.b=uHsO6JMo;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g5rTC2GKVz1yJr\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 30 Apr 2026 20:46:55 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wIOt7-0008Mf-PQ; Thu, 30 Apr 2026 06:44:57 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <alex.bennee@linaro.org>)\n id 1wIOsz-0008Gp-35\n for qemu-devel@nongnu.org; Thu, 30 Apr 2026 06:44:49 -0400","from mail-wm1-x344.google.com ([2a00:1450:4864:20::344])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.90_1) (envelope-from <alex.bennee@linaro.org>)\n id 1wIOsu-0005LO-Fi\n for qemu-devel@nongnu.org; Thu, 30 Apr 2026 06:44:48 -0400","by mail-wm1-x344.google.com with SMTP id\n 5b1f17b1804b1-4891b0786beso5117015e9.1\n for <qemu-devel@nongnu.org>; Thu, 30 Apr 2026 03:44:43 -0700 (PDT)","from draig.lan ([185.124.0.195]) by smtp.gmail.com with ESMTPSA id\n ffacd0b85a97d-447b7217afesm12338368f8f.23.2026.04.30.03.44.37\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Thu, 30 Apr 2026 03:44:39 -0700 (PDT)","from draig.lan (localhost [IPv6:::1])\n by draig.lan (Postfix) with ESMTP id 7D1855F954;\n Thu, 30 Apr 2026 11:44:35 +0100 (BST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=linaro.org; s=google; t=1777545882; x=1778150682; darn=nongnu.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=5z/E+NEUk6p/y4Qsh2ZiVobxIRwHiu1lhqMJeWdQLKM=;\n b=uHsO6JMo6sVIpJLRApTlqkt024zQ+YnYE/Vu28o7qPGaFZfYyY84PYPyHY4GiBUQae\n BTQ9mv/r5/WgHQakUVNRgjGh2QS4MQnZUFfXHRAAY7IJ2HfBB6FzEdFMQ1UE0wX4C60Q\n UaqwXV2qNcZpwkPjj7derqRMNENeqPFVNNoqNnr0TxuD8v1XmuRuhmusj05zEX7IBscz\n /rIE5XEu8fQICXmUfGFvcwA5wAOx6mU3Vy3pAExtabexN/kNqMecVsh0+1i6rJ0rUWpL\n hlaTyP9tNd3NqzZ1t1H6RQ5vFQMgZwl6sBcbMCel+wX959hGaa23rh0G6XIxVwhoQ75h\n 73tA==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777545882; x=1778150682;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=5z/E+NEUk6p/y4Qsh2ZiVobxIRwHiu1lhqMJeWdQLKM=;\n b=mbVPxEzZkf4Xvh/JADvzIXuOcZU1U47AG2YAhyW+mWz0/qDtWWF8nKgCrPCZuHv0Y0\n fiqeCRE2KGBWWjKHU3nBm9wvsnGJKAfZqjJUmwq9E7woEir9lL+yBF7k80QtVJBOST+t\n YtcfdZvN14CS3zd1oWR7Ww8jNhqefDlwJG0W3joFBpRGAvyreOoBznkwW/OzVo9ARr0c\n V7KwDPYfLsUSBtlZE7Hv+Vg7LCNjRttl66s+MTYscRT/q+2QS8imMmXSFDp7q8rdzRWf\n rxkwdNU7H6qQIy3Ie+lcKqa0IYccRwjrLWZCJoBtV83S8kWaccUy00kGoP/bAdCB8Uk0\n s47A==","X-Gm-Message-State":"AOJu0YwuMjGZKlVHwQnvj99kyG6nmL38v1UFh1HjxywDSeHbyFMjoh8u\n NuqNdE5LUo4g++/7uUN65UXzsE9kgtW+IBrtLwjn4r+vJ/EzSRaYLQ0w35h5rIxFdEWuYj+XKbu\n jRgyXOR7LshUf","X-Gm-Gg":"AeBDietQxPNfgCmPfXQWV8JT2NbaOK+yFxeq6yc69CVYDpUD2lP8nXLHcPycA8KkuZk\n tTbU4b7OakCic6aiVrS04dIFDGn3DrOWTSaMDINuNG4cjzK8ujKmycToqC0KeWh13Z5GJ+qOMyQ\n 95ikvsnkicVc594KzUfWwdJcv00b3ZxS3OkxqQVfFPFpfq/rMVz+yRel20BNh+1nOx6Ggo3opNf\n dy7eiOW2jZqmaxkcpD/hfUoe02EG6tvCQSKngVESaSlEqMpNeBcsh5H+t1gE5UrqkHqmeU7SMmS\n cDe7IPyczwmPj0Ff9A9uNE/9HNs32GQo08coETxyqFIK8qYGc8noWpJTgddKxQxgLuWl9Cr9XK1\n 52Axw6FyAezQ7cNp0C1u+iSJfm0eq0jiYcJV+2qmO481g7xuSyjC9DLuvBOExR9vW76lBVxO+tZ\n Z90/hyav2GQRj2SYPGiFQBG+mZY5qYlq0V5g==","X-Received":"by 2002:a5d:5847:0:b0:43f:e791:a347 with SMTP id\n ffacd0b85a97d-4493e982935mr3711927f8f.26.1777545881915;\n Thu, 30 Apr 2026 03:44:41 -0700 (PDT)","From":"=?utf-8?q?Alex_Benn=C3=A9e?= <alex.bennee@linaro.org>","To":"qemu-devel@nongnu.org","Cc":"Mohamed Mediouni <mohamed@unpredictable.fr>, qemu-arm@nongnu.org,\n Pedro Barbuda <pbarbuda@microsoft.com>,\n Peter Maydell <peter.maydell@linaro.org>,\n Paolo Bonzini <pbonzini@redhat.com>, kvm@vger.kernel.org,\n Alexander Graf <agraf@csgraf.de>,\n =?utf-8?q?Alex_Benn=C3=A9e?= <alex.bennee@linaro.org>","Subject":"[PATCH v4 7/7] target/arm: implement WFET","Date":"Thu, 30 Apr 2026 11:44:34 +0100","Message-ID":"<20260430104434.1482407-8-alex.bennee@linaro.org>","X-Mailer":"git-send-email 2.47.3","In-Reply-To":"<20260430104434.1482407-1-alex.bennee@linaro.org>","References":"<20260430104434.1482407-1-alex.bennee@linaro.org>","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Received-SPF":"pass client-ip=2a00:1450:4864:20::344;\n envelope-from=alex.bennee@linaro.org; helo=mail-wm1-x344.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,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001,\n 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 <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"},"content":"Now we have the event stream and SEV/SEVL implemented we can finally\nenable WFET for Aarch64.\n\nTo avoid issues with QEMU's incomplete ldst exclusive handling causing\npotential deadlocks in common WFE enabled locking patterns we take\nadvantage of the architectures flexibility and treat being in the\nexclusive region as a reason to exit.\n\nSigned-off-by: Alex Bennée <alex.bennee@linaro.org>\n\n---\nv2\n  - fix exception syndrome by using enum value\n  - use env->halt_reason\nv3\n  - fix check_wfx_trap(s/false/true/) as it is a WFE\nv4\n  - defer expensive calculations until needed\n  - treat cs->exclusive_addr as a IMPDEF WFE exit\n  - update commit message\n---\n target/arm/tcg/helper-defs.h   |  1 +\n target/arm/tcg/op_helper.c     | 95 ++++++++++++++++++++++++++++++++++\n target/arm/tcg/translate-a64.c | 15 +++---\n 3 files changed, 104 insertions(+), 7 deletions(-)","diff":"diff --git a/target/arm/tcg/helper-defs.h b/target/arm/tcg/helper-defs.h\nindex ebdf09be38a..5e4d828dd55 100644\n--- a/target/arm/tcg/helper-defs.h\n+++ b/target/arm/tcg/helper-defs.h\n@@ -56,6 +56,7 @@ DEF_HELPER_1(setend, void, env)\n DEF_HELPER_2(wfi, void, env, i32)\n DEF_HELPER_2(wfe, void, env, i32)\n DEF_HELPER_2(wfit, void, env, i32)\n+DEF_HELPER_2(wfet, void, env, i32)\n DEF_HELPER_1(yield, void, env)\n DEF_HELPER_1(pre_hvc, void, env)\n DEF_HELPER_2(pre_smc, void, env, i32)\ndiff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c\nindex 77ac6161e93..8421c548303 100644\n--- a/target/arm/tcg/op_helper.c\n+++ b/target/arm/tcg/op_helper.c\n@@ -640,6 +640,101 @@ void HELPER(wfe)(CPUARMState *env, uint32_t insn_len)\n #endif\n }\n \n+void HELPER(wfet)(CPUARMState *env, uint32_t rd)\n+{\n+#ifdef CONFIG_USER_ONLY\n+    /*\n+     * As for WFIT make it NOP here, because trying to raise EXCP_HLT\n+     * would trigger an abort.\n+     */\n+    return;\n+#else\n+    CPUState *cs = env_cpu(env);\n+    uint32_t excp;\n+    int target_el;\n+    ARMCPU *cpu;\n+    uint64_t cntval, timeout, offset, cntvct, nexttick;\n+    int64_t next_event;\n+\n+    /*\n+     * As for WFE if the event register is already set we can consume\n+     * the event and return immediately.\n+     */\n+    if (env->event_register) {\n+        env->event_register = false;\n+        return;\n+    }\n+\n+    /*\n+     * Don't bother to go into our \"low power state\" if\n+     * we would just wake up immediately.\n+     *\n+     * We want the value that we would get if we read CNTVCT_EL0 from\n+     * the current exception level, so the direct_access offset, not\n+     * the indirect_access one. Compare the pseudocode LocalTimeoutEvent(),\n+     * which calls VirtualCounterTimer().\n+     */\n+    cntval = gt_get_countervalue(env);\n+    offset = gt_direct_access_timer_offset(env, GTIMER_VIRT);\n+    cntvct = cntval - offset;\n+    timeout = env->xregs[rd];\n+    if (cpu_has_work(cs) || cntvct >= timeout) {\n+        return;\n+    }\n+\n+    /* We might sleep, so now we check to see if we should trap */\n+    target_el = check_wfx_trap(env, true, &excp);\n+    if (target_el) {\n+        env->pc -= 4;\n+        raise_exception(env, excp, syn_wfx(1, 0xe, rd, true, WFET, false), target_el);\n+    }\n+\n+    /*\n+     * If the CPU has entered the exclusive region we could sleep\n+     * until the global monitor moves from Exclusive to Open Access.\n+     * However it would be expensive for QEMU to fully model the\n+     * global monitor and not doing so would potentially trigger\n+     * deadlocks in WFE enabled locking code. However as WFE is a hint\n+     * instruction the architecture allows for the PE to leave\n+     * low-power state for any reason. QEMU chooses to treat being in\n+     * an exclusive region as such and return directly.\n+     */\n+    if (env->exclusive_addr != -1) {\n+        return;\n+    }\n+\n+    /*\n+     * Finally work out if the timeout or event stream will kick in\n+     * earlier.\n+     *\n+     * The WFET should time out when CNTVCT_EL0 >= the specified value.\n+     */\n+    cpu = env_archcpu(env);\n+    if (uadd64_overflow(timeout, offset, &nexttick)) {\n+        nexttick = UINT64_MAX;\n+    }\n+    if (nexttick > INT64_MAX / gt_cntfrq_period_ns(cpu)) {\n+        nexttick = INT64_MAX;\n+    }\n+\n+    next_event = gt_calc_next_event_stream(env);\n+    if (next_event > 0 && next_event < nexttick) {\n+        timer_mod(cpu->wfxt_timer, next_event);\n+    } else {\n+        if (nexttick == INT64_MAX) {\n+            timer_mod_ns(cpu->wfxt_timer, INT64_MAX);\n+        } else {\n+            timer_mod(cpu->wfxt_timer, nexttick);\n+        }\n+    }\n+\n+    env->halt_reason = HALT_WFE;\n+    cs->exception_index = EXCP_HLT;\n+    cs->halted = 1;\n+    cpu_loop_exit(cs);\n+#endif\n+}\n+\n void HELPER(yield)(CPUARMState *env)\n {\n     CPUState *cs = env_cpu(env);\ndiff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c\nindex a6f392a28f8..ead2a7ff81f 100644\n--- a/target/arm/tcg/translate-a64.c\n+++ b/target/arm/tcg/translate-a64.c\n@@ -2086,14 +2086,15 @@ static bool trans_WFET(DisasContext *s, arg_WFET *a)\n         return false;\n     }\n \n-    /*\n-     * We rely here on our WFE implementation being a NOP, so we\n-     * don't need to do anything different to handle the WFET timeout\n-     * from what trans_WFE does.\n-     */\n-    if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {\n-        s->base.is_jmp = DISAS_WFE;\n+    if (s->ss_active) {\n+        /* Act like a NOP under architectural singlestep */\n+        return true;\n     }\n+\n+    gen_a64_update_pc(s, 4);\n+    gen_helper_wfet(tcg_env, tcg_constant_i32(a->rd));\n+    /* Go back to the main loop to check for interrupts */\n+    s->base.is_jmp = DISAS_EXIT;\n     return true;\n }\n \n","prefixes":["v4","7/7"]}