qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Igor Mammedov <imammedo@redhat.com>
To: qemu-devel@nongnu.org
Cc: mst@redhat.com, pbonzini@redhat.com, peterx@redhat.com,
	david@redhat.com, philmd@linaro.org, mtosatti@redhat.com
Subject: [PATCH v3 05/10] hpet: make main counter read lock-less
Date: Fri,  8 Aug 2025 14:01:32 +0200	[thread overview]
Message-ID: <20250808120137.2208800-6-imammedo@redhat.com> (raw)
In-Reply-To: <20250808120137.2208800-1-imammedo@redhat.com>

Make access to main HPET counter lock-less.

In unlikely event of an update in progress, readers will busy wait
untill update is finished.

As result micro benchmark of concurrent reading of HPET counter
with large number of vCPU shows over 80% better (less) latency.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
v3:
  * make reader busy wait during update and reuse existing seqlock API
       Peter Xu <peterx@redhat.com>
---
 hw/timer/hpet.c | 26 ++++++++++++++++++++------
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index c776afc0f2..789a31d0a0 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -39,6 +39,7 @@
 #include "system/address-spaces.h"
 #include "qom/object.h"
 #include "qemu/lockable.h"
+#include "qemu/seqlock.h"
 #include "trace.h"
 
 struct hpet_fw_config hpet_fw_cfg = {.count = UINT8_MAX};
@@ -74,6 +75,7 @@ struct HPETState {
     MemoryRegion iomem;
     uint64_t hpet_offset;
     bool hpet_offset_saved;
+    QemuSeqLock state_version;
     qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
     uint32_t flags;
     uint8_t rtc_irq_level;
@@ -430,17 +432,25 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
     trace_hpet_ram_read(addr);
     addr &= ~4;
 
-    QEMU_LOCK_GUARD(&s->lock);
     if (addr == HPET_COUNTER) {
-        if (hpet_enabled(s)) {
-            cur_tick = hpet_get_ticks(s);
-        } else {
-            cur_tick = s->hpet_counter;
-        }
+        unsigned version;
+
+        /*
+         * Write update is rare, so busywait here is unlikely to happen
+         */
+        do {
+            version = seqlock_read_begin(&s->state_version);
+            if (unlikely(!hpet_enabled(s))) {
+                cur_tick = s->hpet_counter;
+            } else {
+                cur_tick = hpet_get_ticks(s);
+            }
+        } while (seqlock_read_retry(&s->state_version, version));
         trace_hpet_ram_read_reading_counter(addr & 4, cur_tick);
         return cur_tick >> shift;
     }
 
+    QEMU_LOCK_GUARD(&s->lock);
     /*address range of all global regs*/
     if (addr <= 0xff) {
         switch (addr) {
@@ -500,6 +510,7 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
             old_val = s->config;
             new_val = deposit64(old_val, shift, len, value);
             new_val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK);
+            seqlock_write_begin(&s->state_version);
             s->config = new_val;
             if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
                 /* Enable main counter and interrupt generation. */
@@ -518,6 +529,8 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
                     hpet_del_timer(&s->timer[i]);
                 }
             }
+            seqlock_write_end(&s->state_version);
+
             /* i8254 and RTC output pins are disabled
              * when HPET is in legacy mode */
             if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
@@ -686,6 +699,7 @@ static void hpet_init(Object *obj)
     HPETState *s = HPET(obj);
 
     qemu_mutex_init(&s->lock);
+    seqlock_init(&s->state_version);
     /* HPET Area */
     memory_region_init_io(&s->iomem, obj, &hpet_ram_ops, s, "hpet", HPET_LEN);
     memory_region_enable_lockless_io(&s->iomem);
-- 
2.47.1



  parent reply	other threads:[~2025-08-08 12:10 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-08 12:01 [PATCH v3 00/10] Reinvent BQL-free PIO/MMIO Igor Mammedov
2025-08-08 12:01 ` [PATCH v3 01/10] memory: reintroduce BQL-free fine-grained PIO/MMIO Igor Mammedov
2025-08-08 12:12   ` David Hildenbrand
2025-08-08 14:36     ` Igor Mammedov
2025-08-08 15:24       ` David Hildenbrand
2025-08-11 12:08         ` Igor Mammedov
2025-08-11 15:54   ` Peter Xu
2025-08-08 12:01 ` [PATCH v3 02/10] acpi: mark PMTIMER as unlocked Igor Mammedov
2025-08-11 15:55   ` Peter Xu
2025-08-08 12:01 ` [PATCH v3 03/10] hpet: switch to fain-grained device locking Igor Mammedov
2025-08-11 15:56   ` Peter Xu
2025-08-08 12:01 ` [PATCH v3 04/10] hpet: move out main counter read into a separate block Igor Mammedov
2025-08-11 15:56   ` Peter Xu
2025-08-08 12:01 ` Igor Mammedov [this message]
2025-08-11 15:58   ` [PATCH v3 05/10] hpet: make main counter read lock-less Peter Xu
2025-08-08 12:01 ` [PATCH v3 06/10] introduce cpu_test_interrupt() that will replace open coded checks Igor Mammedov
2025-08-11 16:31   ` Peter Xu
2025-08-12 15:00     ` Igor Mammedov
2025-08-12 16:10       ` Peter Xu
2025-08-08 12:01 ` [PATCH v3 07/10] x86: kvm: use cpu_test_interrupt() instead of oppen coding checks Igor Mammedov
2025-08-08 12:01 ` [PATCH v3 08/10] kvm: i386: irqchip: take BQL only if there is an interrupt Igor Mammedov
2025-08-11 16:22   ` Peter Xu
2025-08-08 12:01 ` [PATCH v3 09/10] use cpu_test_interrupt() instead of oppen coding checks tree wide Igor Mammedov
2025-08-08 12:01 ` [PATCH v3 10/10] tcg: move interrupt caching and single step masking closer to user Igor Mammedov
2025-08-11  5:36 ` [PATCH v3 00/10] Reinvent BQL-free PIO/MMIO Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250808120137.2208800-6-imammedo@redhat.com \
    --to=imammedo@redhat.com \
    --cc=david@redhat.com \
    --cc=mst@redhat.com \
    --cc=mtosatti@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peterx@redhat.com \
    --cc=philmd@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).