From nobody Sat May 30 17:33:08 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=1779880769; cv=none; d=zohomail.com; s=zohoarc; b=muOKK4K7JsHsCghAF9ebApvtgQvV2I/PubcC+aOAWJFS97hU9mPEZRQdfWDulLf7USuSuayFYnEmwKw1jrBReug1bIhav93R7WvdWM08izkPyjNNCTv9kM2T4NCo8yPuEQdEs0SpH4YG73qbZ5xreee/wMqiJigEdAgcmQ+fsWo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1779880769; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=0QGieyo5gKzeqh6AipqQcO1qteBU8LLbZeI6OWN5t84=; b=CrCGL5QZe8iRSwdsgsDpUJ/KAUkHqQT2+SvZUPS0PO/PskFCzq1e4IJUo9PRe9JTTQt/Qxzo37yu1lHlycTjyk5G2ki1yxX0GMg2RkeQ7dc+6meG12ayOPwzFUcuSCQBC5Ph87aHisJyU8KGj585FE6iuAjCWBaBqVzmG5Ys0d4= 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 lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1779880769173905.8086791493241; Wed, 27 May 2026 04:19:29 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1wSCHc-0007RA-PE; Wed, 27 May 2026 07:18:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1wSCHY-0007Qx-EL for qemu-devel@nongnu.org; Wed, 27 May 2026 07:18:42 -0400 Received: from mail-wr1-x436.google.com ([2a00:1450:4864:20::436]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1wSCHW-0000vC-Bj for qemu-devel@nongnu.org; Wed, 27 May 2026 07:18:40 -0400 Received: by mail-wr1-x436.google.com with SMTP id ffacd0b85a97d-44e5624c053so6919402f8f.2 for ; Wed, 27 May 2026 04:18:37 -0700 (PDT) Received: from draig.lan ([185.124.0.195]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-45edb5b28absm5398550f8f.27.2026.05.27.04.18.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 27 May 2026 04:18:35 -0700 (PDT) Received: from draig.lan (localhost [IPv6:::1]) by draig.lan (Postfix) with ESMTP id 9ECBF5F7F0; Wed, 27 May 2026 12:18:34 +0100 (BST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1779880716; x=1780485516; darn=nongnu.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=0QGieyo5gKzeqh6AipqQcO1qteBU8LLbZeI6OWN5t84=; b=zc1hjmvmhZPX/Hz3c9QdUl9I27GYTkuI9lSTt03eCIB2uT+E+nJTorVJKgJdNiLQWD BAuJ4ObHkuX0NOpeK0A0cQA6yJCn1JEcF48erB0tEKBaIbeaK8/0cRo1+6phCeHuEq/l fCtxHxDRuedQfs4LIVdJ1cLa5UqcgHxxTAWmglkKglK73H4IcziFnWoHJcEHHkt/vCwl B8hlsBslknldrVg60SYxiLWAV5uijwnZe6zO+LYTisQleOxH7RvKQtpuInJdpuCBtMTs wXnXKk29hD6IEhQhCQNZWqvyBRk160XeAy95n8mp2IKNBu+wQZF71+puO+XStp7KY3yr 8C8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779880716; x=1780485516; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=0QGieyo5gKzeqh6AipqQcO1qteBU8LLbZeI6OWN5t84=; b=AKGsVwRHf8zKsXXT2W3jBudboh7MvyK4qJn+cliZfDL5L/B8GVy8I4k6TFNNORhc1I zElxSCrfADTCk2JtFpnx6Ib6jYqm2Skhf5/tbP1ZSnx1rK7PEIKiHpYsWFUv+dR51nYS R24pMU61cvciDDIVquU1JZc9ymaVinedh7iNmUQY60hSiC+Tk2IY418R7plF+003FW87 pedv6zEuSAf2Gw6aDFdVOPwodbTeoG+4jv3CrNgc7j9sF56PeLXQv8agAbcJtd98Ts7r 0HhHLWMPJYQClH4+i4WF/VKyJbwnwUGVfbxYEJS00PpXnnRVuBVIKAu7RN2F8nuJ8lSW ayCw== X-Gm-Message-State: AOJu0Yw3x6eYzso7s29GlBQRNoCwVQg7z0CQnBnd5aSr2BM90XEjQbC3 mhtkXNQ7YDewrVFHOjQ0uK6aFHk58p4BQlrP9JW5lUIbgbaB3HFYCv2ZQ5c7A74LbxE= X-Gm-Gg: Acq92OEwem+y5VxDbF/DT2LeWDkwLhLp9wJjybhAw9IB6qJhzieQLzJD9mHQ6l8Rauv X6EnPIPB2MzhW2MGOn4zC2ZCMK0He4jvxu0wj5fA1IHFZPfNS8VPewFgsaSiYYpvQLAZAOjPw47 x92zZLZiggj/YedI1XiDd7JMshfqyU3Urm71Dy7+O/tws2W2+O3GXEJYWZFksAc56U4QiJyFRVV r2KqR1dNXRJ208od7EMPuquKDScofHUf7E4OlN0ul2bHpQjAn/yBxGUpkAGXxxCr6RmNQU9vQ7g GhAhdiThdpQdbaEH6IwR5LY9B/V6/8qOLcI/8ldx2WhaTkw+TefzdxbPba17AMQfJ+oPRX5kg1Y iYk0BJ4GEFjJ05hfuPg0bPAjELycEio5dNVrxMpylRXanXzbxYbF1W7yfOxWzo1yb7hZArYFuhj uQ0WvGZdvMK/9m37GmIqlC2D1ZN5GObaOr1Q== X-Received: by 2002:a05:6000:4606:b0:44a:b0a3:7c1a with SMTP id ffacd0b85a97d-45eb36b0126mr40044368f8f.24.1779880716257; Wed, 27 May 2026 04:18:36 -0700 (PDT) From: =?UTF-8?q?Alex=20Benn=C3=A9e?= To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Alex=20Benn=C3=A9e?= , Andrew Jones , Alexandru Elisei , Eric Auger , kvmarm@lists.linux.dev (open list:ARM), kvm@vger.kernel.org (open list:Default mailing list) Subject: [kvm-unit-tests PATCH v2] arm: add wfx test case Date: Wed, 27 May 2026 12:18:21 +0100 Message-ID: <20260527111822.1563679-1-alex.bennee@linaro.org> X-Mailer: git-send-email 2.47.3 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=lists1p.gnu.org; Received-SPF: pass client-ip=2a00:1450:4864:20::436; envelope-from=alex.bennee@linaro.org; helo=mail-wr1-x436.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: 1779880770987154100 This is based on a similar test case I wrote for QEMU's tcg tests although obviously able to take advantage of kvm-unit-tests additional plumbing for dealing with the GIC and IRQs. Signed-off-by: Alex Benn=C3=A9e Reviewed-by: Richard Henderson --- v2 - drop TIMEOUT in favour of computed 10ms timeout - add comments for each test - use sevl for local clearing - set gic irc depending on CurrentEL - EOI the GIC - display elapsed ns (no float to do ms ;-) - fix some style issues - make test TCG only --- arm/Makefile.arm64 | 1 + lib/arm64/asm/processor.h | 7 ++ lib/arm64/asm/sysreg.h | 3 + arm/wfx.c | 187 ++++++++++++++++++++++++++++++++++++++ arm/unittests.cfg | 7 ++ 5 files changed, 205 insertions(+) create mode 100644 arm/wfx.c diff --git a/arm/Makefile.arm64 b/arm/Makefile.arm64 index a40c830d..52b3f35d 100644 --- a/arm/Makefile.arm64 +++ b/arm/Makefile.arm64 @@ -64,6 +64,7 @@ tests +=3D $(TEST_DIR)/cache.$(exe) tests +=3D $(TEST_DIR)/debug.$(exe) tests +=3D $(TEST_DIR)/fpu.$(exe) tests +=3D $(TEST_DIR)/mte.$(exe) +tests +=3D $(TEST_DIR)/wfx.$(exe) =20 include $(SRCDIR)/$(TEST_DIR)/Makefile.common =20 diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h index 32ddc1b3..2104036d 100644 --- a/lib/arm64/asm/processor.h +++ b/lib/arm64/asm/processor.h @@ -173,5 +173,12 @@ static inline bool system_supports_rndr(void) return ((id_aa64isar0_el1 >> ID_AA64ISAR0_EL1_RNDR_SHIFT) & 0xf) !=3D 0; } =20 +static inline bool system_supports_wfxt(void) +{ + u64 id_aa64isar2_el1 =3D read_sysreg_s(ID_AA64ISAR2_EL1); + + return ((id_aa64isar2_el1 >> ID_AA64ISAR2_EL1_WFxT_SHIFT) & 0xf) !=3D 0; +} + #endif /* !__ASSEMBLER__ */ #endif /* _ASMARM64_PROCESSOR_H_ */ diff --git a/lib/arm64/asm/sysreg.h b/lib/arm64/asm/sysreg.h index f2d05018..cb96a649 100644 --- a/lib/arm64/asm/sysreg.h +++ b/lib/arm64/asm/sysreg.h @@ -77,6 +77,9 @@ asm( #define ID_AA64ISAR0_EL1_RNDR_SHIFT 60 #define ID_AA64PFR1_EL1_MTE_SHIFT 8 =20 +#define ID_AA64ISAR2_EL1 sys_reg(3, 0, 0, 6, 2) +#define ID_AA64ISAR2_EL1_WFxT_SHIFT 0 + #define ID_AA64MMFR0_EL1_FGT_SHIFT 56 #define ID_AA64MMFR0_EL1_FGT_FGT2 0x2 =20 diff --git a/arm/wfx.c b/arm/wfx.c new file mode 100644 index 00000000..0825c5cb --- /dev/null +++ b/arm/wfx.c @@ -0,0 +1,187 @@ +/* + * WFX Instructions Test (WFI, WFE, WFIT, WFET) + * + * Copyright (c) 2026 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#include +#include +#include +#include + +#define sev() asm volatile("sev" : : : "memory") +#define sevl() asm volatile("sevl" : : : "memory") +#define wfi() asm volatile("wfi" : : : "memory") +#define wfe() asm volatile("wfe" : : : "memory") + +#define wfit(reg) \ + asm volatile(".arch armv8.7-a\n\twfit %0" : : "r" (reg) : "memory") +#define wfet(reg) \ + asm volatile(".arch armv8.7-a\n\twfet %0" : : "r" (reg) : "memory") + +uint64_t time_hz; +uint64_t time_10ms; + +static void timer_handler(struct pt_regs *regs) +{ + u32 irqstat =3D gic_read_iar(); + u32 irqnr =3D gic_iar_irqnr(irqstat); + + /* Disable timer to stop IRQ from re-firing */ + if (irqnr =3D=3D TIMER_VTIMER_IRQ || irqnr =3D=3D TIMER_HVTIMER_IRQ) { + write_sysreg(0, cntv_ctl_el0); + isb(); + } else { + if (irqnr !=3D GICC_INT_SPURIOUS) + gic_write_eoir(irqstat); + report_info("Unexpected interrupt: %d\n", irqnr); + return; + } + + /* Also acknowledge EOI for the GIC */ + gic_write_eoir(irqstat); +} + +static bool check_elapsed(uint64_t start, uint64_t threshold, const char *= test, bool more) +{ + uint64_t end =3D read_sysreg(cntvct_el0); + uint64_t elapsed =3D end - start; + bool pass =3D more ? elapsed >=3D threshold : elapsed <=3D threshold; + + report(pass, "%s (%ld ticks / %ld ns)", + test, elapsed, elapsed / (time_hz / 1000000)); + + if (!pass) + report_info("%s %s", test, more ? "woke too early" : "slept despite SEV"= ); + + return pass; +} + +/* + * Test WFI with timer interrupt + * + * WFI should wake up when the interrupt is pending. We unmask + * interrupts here so they are taken and then check WFI actually + * did sleep rather than return straight away. + */ +static void test_wfi(void) +{ + uint64_t start; + + report_info("Testing WFI..."); + + start =3D read_sysreg(cntvct_el0); + write_sysreg(time_10ms, cntv_tval_el0); + write_sysreg(1, cntv_ctl_el0); /* Enable timer, no mask */ + isb(); + + local_irq_enable(); + wfi(); + local_irq_disable(); + + check_elapsed(start, time_10ms, "WFI", true); +} + +/* + * Test WFE and SEV[L] + * + * There are two SEV instructions, the normal one is a broadcast + * from any PE on the system, the other is local only. + * Functionally they have the same effect (setting the event + * register) and should be immediately consumed by the WFE. + * + * As we want to detect an early exit the sense of the timeout + * check is reversed. + */ +static void test_wfe(void) +{ + uint64_t start; + + report_info("Testing WFE/SEV..."); + sev(); + start =3D read_sysreg(cntvct_el0); + wfe(); + check_elapsed(start, time_10ms, "WFE/SEV", false); + + report_info("Testing WFE/SEVL..."); + sevl(); + start =3D read_sysreg(cntvct_el0); + wfe(); + check_elapsed(start, time_10ms, "WFE/SEVL", false); +} + +/* + * Test WFIT + * + * With the timer disabled and no other IRQ sources firing the + * WFIT instruction should timeout. + */ +static void test_wfit(void) +{ + uint64_t start, timeout; + + report_info("Testing WFIT..."); + start =3D read_sysreg(cntvct_el0); + timeout =3D start + time_10ms; + wfit(timeout); + check_elapsed(start, time_10ms, "WFIT", true); +} + +/* + * Test WFET + * + * Much like WFIT there are no IRQs to wake us up. However the + * event_register is a latch so we must first consume the event + * register with a normal WFE before we do the timeout version. + */ +static void test_wfet(void) +{ + uint64_t start, timeout; + + report_info("Testing WFET..."); + /* Ensure no pending events */ + sevl(); + wfe(); + + start =3D read_sysreg(cntvct_el0); + timeout =3D start + time_10ms; + wfet(timeout); + check_elapsed(start, time_10ms, "WFET", true); +} + +int main(void) +{ + uint32_t irq =3D current_level() =3D=3D CurrentEL_EL1 ? TIMER_VTIMER_IRQ = : TIMER_HVTIMER_IRQ; + + if (gic_init() < 0) { + report_abort("GIC init failed"); + return 1; + } + + /* Install timer handler for WFI wake-up */ + install_irq_handler(EL1H_IRQ, timer_handler); + gic_enable_defaults(); + time_hz =3D read_sysreg(cntfrq_el0); + time_10ms =3D time_hz / 100; + + /* Enable Virtual Timer PPI */ + gic_irq_set_clr_enable(irq, true); + + report_prefix_push("WFx"); + test_wfi(); + test_wfe(); + report_prefix_pop(); + + if (system_supports_wfxt()) { + report_prefix_push("WFxT"); + test_wfit(); + test_wfet(); + } else { + report_skip("WFxT instructions not supported"); + } + + return report_summary(); +} diff --git a/arm/unittests.cfg b/arm/unittests.cfg index 12fc4468..ae8b5534 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -339,3 +339,10 @@ groups =3D mte test_args =3D asymm qemu_params =3D -machine mte=3Don arch =3D arm64 + +[wfx] +file =3D wfx.flat +groups =3D wfx +arch =3D arm64 +# This test exercise CPU emulation so limit to TCG to avoid confusion +accel =3D tcg --=20 2.47.3