qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: Igor Mammedov <imammedo@redhat.com>, Peter Xu <peterx@redhat.com>
Subject: [PULL 26/28] hpet: make main counter read lock-less
Date: Fri, 29 Aug 2025 14:59:33 +0200	[thread overview]
Message-ID: <20250829125935.1526984-27-pbonzini@redhat.com> (raw)
In-Reply-To: <20250829125935.1526984-1-pbonzini@redhat.com>

From: Igor Mammedov <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>
Reviewed-by: Peter Xu <peterx@redhat.com>
Link: https://lore.kernel.org/r/20250814160600.2327672-6-imammedo@redhat.com
Signed-off-by: Paolo Bonzini <pbonzini@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 c776afc0f2d..789a31d0a08 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.51.0



  parent reply	other threads:[~2025-08-30 16:36 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-29 12:59 [PULL 00/28] i386, accel, memory patches for 2025-08-29 Paolo Bonzini
2025-08-29 12:59 ` [PULL 01/28] hw/i386/pc_piix.c: restrict isapc machine to 32-bit CPUs Paolo Bonzini
2025-08-29 12:59 ` [PULL 02/28] hw/i386/pc_piix.c: restrict isapc machine to 3.5G memory Paolo Bonzini
2025-08-29 12:59 ` [PULL 03/28] hw/i386/pc_piix.c: remove include for loader.h Paolo Bonzini
2025-08-29 12:59 ` [PULL 04/28] hw/i386/pc_piix.c: inline pc_xen_hvm_init_pci() into pc_xen_hvm_init() Paolo Bonzini
2025-08-29 12:59 ` [PULL 05/28] hw/i386/pc_piix.c: duplicate pc_init1() into pc_isa_init() Paolo Bonzini
2025-08-29 12:59 ` [PULL 06/28] hw/i386/pc_piix.c: remove pcmc->pci_enabled dependent initialisation from pc_init_isa() Paolo Bonzini
2025-08-29 12:59 ` [PULL 07/28] hw/i386/pc_piix.c: remove igvm " Paolo Bonzini
2025-08-29 12:59 ` [PULL 08/28] hw/i386/pc_piix.c: remove SMI and piix4_pm " Paolo Bonzini
2025-08-29 12:59 ` [PULL 09/28] hw/i386/pc_piix.c: remove SGX " Paolo Bonzini
2025-08-29 12:59 ` [PULL 10/28] hw/i386/pc_piix.c: remove nvdimm " Paolo Bonzini
2025-08-29 12:59 ` [PULL 11/28] hw/i386/pc_piix.c: simplify RAM size logic in pc_init_isa() Paolo Bonzini
2025-08-29 12:59 ` [PULL 12/28] hw/i386/pc_piix.c: hardcode hole64_size to 0 " Paolo Bonzini
2025-08-29 12:59 ` [PULL 13/28] hw/i386/pc_piix.c: remove pc_system_flash_cleanup_unused() from pc_init_isa() Paolo Bonzini
2025-08-29 12:59 ` [PULL 14/28] hw/i386/pc_piix.c: always initialise ISA IDE drives in pc_init_isa() Paolo Bonzini
2025-08-29 12:59 ` [PULL 15/28] hw/i386/pc_piix.c: assume pcmc->pci_enabled is always true in pc_init1() Paolo Bonzini
2025-09-01 10:43   ` Peter Maydell
2025-09-01 13:27     ` Mark Cave-Ayland
2025-08-29 12:59 ` [PULL 16/28] hw/i386: move isapc machine to separate isapc.c file Paolo Bonzini
2025-08-29 12:59 ` [PULL 17/28] hw/i386/pc_piix.c: remove unused headers after isapc machine split Paolo Bonzini
2025-08-29 12:59 ` [PULL 18/28] hw/i386/pc_piix.c: replace rom_memory with pci_memory Paolo Bonzini
2025-08-29 12:59 ` [PULL 19/28] hw/i386/isapc.c: replace rom_memory with system_memory Paolo Bonzini
2025-08-29 12:59 ` [PULL 20/28] user-exec: ensure interrupt_request is not used Paolo Bonzini
2025-08-29 12:59 ` [PULL 21/28] add cpu_test_interrupt()/cpu_set_interrupt() helpers and use them tree wide Paolo Bonzini
2025-10-27 14:38   ` Thomas Huth
2025-10-30 17:03     ` Igor Mammedov
2025-08-29 12:59 ` [PULL 22/28] memory: reintroduce BQL-free fine-grained PIO/MMIO Paolo Bonzini
2025-08-29 12:59 ` [PULL 23/28] acpi: mark PMTIMER as unlocked Paolo Bonzini
2025-08-29 12:59 ` [PULL 24/28] hpet: switch to fine-grained device locking Paolo Bonzini
2025-09-08 14:30   ` Daniel P. Berrangé
2025-09-10 11:16     ` Igor Mammedov
2025-09-10 11:23       ` Paolo Bonzini
2025-09-10 12:56         ` Igor Mammedov
2025-09-15 13:26           ` Peter Maydell
2025-09-10 14:25     ` [PATCH] hpet: guard IRQ handling with BQL Igor Mammedov
2025-09-11 13:40       ` Paolo Bonzini
2025-08-29 12:59 ` [PULL 25/28] hpet: move out main counter read into a separate block Paolo Bonzini
2025-08-29 12:59 ` Paolo Bonzini [this message]
2025-08-29 12:59 ` [PULL 27/28] kvm: i386: irqchip: take BQL only if there is an interrupt Paolo Bonzini
2025-08-29 12:59 ` [PULL 28/28] tcg: move interrupt caching and single step masking closer to user Paolo Bonzini
2025-08-31  7:28 ` [PULL 00/28] i386, accel, memory patches for 2025-08-29 Richard Henderson

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=20250829125935.1526984-27-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=imammedo@redhat.com \
    --cc=peterx@redhat.com \
    --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).