[This has been applied to the master branch as 
998b6db69e3ec58fd52ddc7a06ece6cf286f3c77]

On 9/21/26 10:44, Fuad Tabba wrote:
The WFIT and WFET helpers arm the wakeup timer at count == timeout +
offset, treating an overflow of that sum as "beyond the counter's
wrap" and arming at INT64_MAX. As in gt_recalc_timer(), that reading
is valid only when offset <= count: with a CNTVOFF_EL2 that puts the
virtual count ahead of the physical count, the sum overflows for
every timeout still in the future and the wrapped value was the
correct wakeup. The CPU then waits until an interrupt or event
instead of waking at its timeout. A Linux guest uses WFIT and WFET in
__delay() when FEAT_WFxT is present, which -cpu max advertises.

Arm cntval + (timeout - cntvct) instead, so only a physical count past
2^64 is "never", and add a tcg system test that issues WFIT and WFET
with such an offset, with a timer interrupt 1s out so a broken WFxT
still returns: before this change both wake at the interrupt, after
it at their timeout.

Fixes: a96edb687e76 ("target/arm: Implement FEAT WFxT and enable for '-cpu 
max'")
Fixes: da9b86c35fa8 ("target/arm: implement WFET")

Hi.

For stable-10.0.x LTS series, which does not support WFET (commit
da9b86c35fa8), I'm picking up just the first half of this patch,
and half of the test.

An alternative is to pick da9b86c35fa8 ("target/arm: implement WFET")
for 10.0.x, which does not actually look bad.  It will probably require
v11.0.0-332-g4575da5ecb7 "target/arm: report register in WFIT syndromes"
too.

What do you think?

Thanks,

/mjt

Cc: [email protected]
Signed-off-by: Fuad Tabba <[email protected]>
---
  target/arm/tcg/op_helper.c           |   6 +-
  tests/tcg/aarch64/system/meson.build |   7 ++
  tests/tcg/aarch64/system/wfxt.c      | 118 +++++++++++++++++++++++++++
  3 files changed, 129 insertions(+), 2 deletions(-)
  create mode 100644 tests/tcg/aarch64/system/wfxt.c

diff --git a/target/arm/tcg/op_helper.c b/target/arm/tcg/op_helper.c
index c2b09176cb..562f11f390 100644
--- a/target/arm/tcg/op_helper.c
+++ b/target/arm/tcg/op_helper.c
@@ -448,7 +448,8 @@ void HELPER(wfit)(CPUARMState *env, uint32_t rd)
          raise_exception(env, excp, syn_wfx(1, 0xe, rd, true, WFIT, false), 
target_el);
      }
- if (uadd64_overflow(timeout, offset, &nexttick)) {
+    /* Physical count at the timeout. Only an overflow of it is "never". */
+    if (uadd64_overflow(cntval, timeout - cntvct, &nexttick)) {
          nexttick = UINT64_MAX;
      }
      if (nexttick > INT64_MAX / gt_cntfrq_period_ns(cpu)) {
@@ -705,7 +706,8 @@ void HELPER(wfet)(CPUARMState *env, uint32_t rd)
       * The WFET should time out when CNTVCT_EL0 >= the specified value.
       */
      cpu = env_archcpu(env);
-    if (uadd64_overflow(timeout, offset, &nexttick)) {
+    /* Physical count at the timeout. Only an overflow of it is "never". */
+    if (uadd64_overflow(cntval, timeout - cntvct, &nexttick)) {
          nexttick = UINT64_MAX;
      }
      if (nexttick > INT64_MAX / gt_cntfrq_period_ns(cpu)) {


Reply via email to