[PULL 24/28] hpet: switch to fine-grained device locking

Paolo Bonzini posted 28 patches 1 month ago
Maintainers: Richard Henderson <richard.henderson@linaro.org>, Paolo Bonzini <pbonzini@redhat.com>, Riku Voipio <riku.voipio@iki.fi>, "Michael S. Tsirkin" <mst@redhat.com>, Igor Mammedov <imammedo@redhat.com>, Ani Sinha <anisinha@redhat.com>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, Eduardo Habkost <eduardo@habkost.net>, Thomas Huth <thuth@redhat.com>, Halil Pasic <pasic@linux.ibm.com>, Christian Borntraeger <borntraeger@linux.ibm.com>, David Hildenbrand <david@redhat.com>, Jason Herne <jjherne@linux.ibm.com>, Stafford Horne <shorne@gmail.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Yanan Wang <wangyanan55@huawei.com>, Zhao Liu <zhao1.liu@intel.com>, Peter Xu <peterx@redhat.com>, Peter Maydell <peter.maydell@linaro.org>, Alexander Graf <agraf@csgraf.de>, Mads Ynddal <mads@ynddal.dk>, Michael Rolnik <mrolnik@gmail.com>, Helge Deller <deller@gmx.de>, Cameron Esfahani <dirty@apple.com>, Roman Bolshakov <rbolshakov@ddn.com>, Phil Dennis-Jordan <phil@philjordan.eu>, Marcelo Tosatti <mtosatti@redhat.com>, Reinoud Zandijk <reinoud@netbsd.org>, Sunil Muthuswamy <sunilmut@microsoft.com>, Song Gao <gaosong@loongson.cn>, Laurent Vivier <laurent@vivier.eu>, "Edgar E. Iglesias" <edgar.iglesias@gmail.com>, Aurelien Jarno <aurelien@aurel32.net>, Jiaxun Yang <jiaxun.yang@flygoat.com>, Aleksandar Rikalo <arikalo@gmail.com>, Huacai Chen <chenhuacai@kernel.org>, Nicholas Piggin <npiggin@gmail.com>, Chinmay Rath <rathc@linux.ibm.com>, Harsh Prateek Bora <harshpb@linux.ibm.com>, Yoshinori Sato <yoshinori.sato@nifty.com>, Ilya Leoshkevich <iii@linux.ibm.com>, Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>, Artyom Tarasenko <atar4qemu@gmail.com>
[PULL 24/28] hpet: switch to fine-grained device locking
Posted by Paolo Bonzini 1 month ago
From: Igor Mammedov <imammedo@redhat.com>

as a step towards lock-less HPET counter read,
use per device locking instead of BQL.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Link: https://lore.kernel.org/r/20250814160600.2327672-4-imammedo@redhat.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 hw/timer/hpet.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index cb48cc151f1..ab5aa59ae4e 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -38,6 +38,7 @@
 #include "hw/timer/i8254.h"
 #include "system/address-spaces.h"
 #include "qom/object.h"
+#include "qemu/lockable.h"
 #include "trace.h"
 
 struct hpet_fw_config hpet_fw_cfg = {.count = UINT8_MAX};
@@ -69,6 +70,7 @@ struct HPETState {
     SysBusDevice parent_obj;
     /*< public >*/
 
+    QemuMutex lock;
     MemoryRegion iomem;
     uint64_t hpet_offset;
     bool hpet_offset_saved;
@@ -428,6 +430,7 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
     trace_hpet_ram_read(addr);
     addr &= ~4;
 
+    QEMU_LOCK_GUARD(&s->lock);
     /*address range of all global regs*/
     if (addr <= 0xff) {
         switch (addr) {
@@ -482,6 +485,7 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
     int len = MIN(size * 8, 64 - shift);
     uint64_t old_val, new_val, cleared;
 
+    QEMU_LOCK_GUARD(&s->lock);
     trace_hpet_ram_write(addr, value);
     addr &= ~4;
 
@@ -679,8 +683,10 @@ static void hpet_init(Object *obj)
     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
     HPETState *s = HPET(obj);
 
+    qemu_mutex_init(&s->lock);
     /* HPET Area */
     memory_region_init_io(&s->iomem, obj, &hpet_ram_ops, s, "hpet", HPET_LEN);
+    memory_region_enable_lockless_io(&s->iomem);
     sysbus_init_mmio(sbd, &s->iomem);
 }
 
-- 
2.51.0
Re: [PULL 24/28] hpet: switch to fine-grained device locking
Posted by Daniel P. Berrangé 2 weeks, 6 days ago
Hi,

This patches causes a regression making QEMU  abort in the KVM Xen
functional test.

To reproduce please run 'make check-functional-x86_64', or more
specifically run this single test:

 QEMU_TEST_QEMU_BINARY=./build/qemu-system-x86_64 PYTHONPATH=./python:./tests/functional ./tests/functional/x86_64/test_kvm_xen.py

though I recommend you first add this series:

  https://lists.nongnu.org/archive/html/qemu-devel/2025-09/msg01540.html

as that fixes an infinite loop in the functional test console
code on QEMU abnormal premature exit.

In the test logs we see the following on the serial console:

  2025-09-08 15:26:32,286: Cannot get hvm parameter CONSOLE_EVTCHN (18): -22!

and then the following on stder:

  qemu-system-x86_64: ../hw/i386/kvm/xen_evtchn.c:1619: xen_evtchn_set_gsi: Assertion `bql_locked()' failed.

The QEMU command line was:

  2025-09-08 15:26:32,097 - DEBUG: VM launch command: './build/qemu-system-x86_64 -display none -vga none -chardev socket,id=mon,fd=5 -mon chardev=mon,mode=control -chardev socket,id=console,fd=10 -serial chardev:console -accel kvm,xen-version=0x4000a,kernel-irqchip=split -smp 2 -kernel /var/home/berrange/.cache/qemu/download/ec0ad7bb8c33c5982baee0a75505fe7dbf29d3ff5d44258204d6307c6fe0132a -append "printk.time=0 root=/dev/xvda console=ttyS0 quiet xen_emul_unplug=ide-disks" -drive file=/var/home/berrange/.cache/qemu/download/b11045d649006c649c184e93339aaa41a8fe20a1a86620af70323252eb29e40b,if=none,snapshot=on,format=raw,id=drv0 -device xen-disk,drive=drv0,vdev=xvda -device virtio-net-pci,netdev=unet -netdev user,id=unet,hostfwd=:127.0.0.1:0-:22'

On Fri, Aug 29, 2025 at 02:59:31PM +0200, Paolo Bonzini wrote:
> From: Igor Mammedov <imammedo@redhat.com>
> 
> as a step towards lock-less HPET counter read,
> use per device locking instead of BQL.
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> Reviewed-by: Peter Xu <peterx@redhat.com>
> Link: https://lore.kernel.org/r/20250814160600.2327672-4-imammedo@redhat.com
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  hw/timer/hpet.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
> index cb48cc151f1..ab5aa59ae4e 100644
> --- a/hw/timer/hpet.c
> +++ b/hw/timer/hpet.c
> @@ -38,6 +38,7 @@
>  #include "hw/timer/i8254.h"
>  #include "system/address-spaces.h"
>  #include "qom/object.h"
> +#include "qemu/lockable.h"
>  #include "trace.h"
>  
>  struct hpet_fw_config hpet_fw_cfg = {.count = UINT8_MAX};
> @@ -69,6 +70,7 @@ struct HPETState {
>      SysBusDevice parent_obj;
>      /*< public >*/
>  
> +    QemuMutex lock;
>      MemoryRegion iomem;
>      uint64_t hpet_offset;
>      bool hpet_offset_saved;
> @@ -428,6 +430,7 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
>      trace_hpet_ram_read(addr);
>      addr &= ~4;
>  
> +    QEMU_LOCK_GUARD(&s->lock);
>      /*address range of all global regs*/
>      if (addr <= 0xff) {
>          switch (addr) {
> @@ -482,6 +485,7 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
>      int len = MIN(size * 8, 64 - shift);
>      uint64_t old_val, new_val, cleared;
>  
> +    QEMU_LOCK_GUARD(&s->lock);
>      trace_hpet_ram_write(addr, value);
>      addr &= ~4;
>  
> @@ -679,8 +683,10 @@ static void hpet_init(Object *obj)
>      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
>      HPETState *s = HPET(obj);
>  
> +    qemu_mutex_init(&s->lock);
>      /* HPET Area */
>      memory_region_init_io(&s->iomem, obj, &hpet_ram_ops, s, "hpet", HPET_LEN);
> +    memory_region_enable_lockless_io(&s->iomem);
>      sysbus_init_mmio(sbd, &s->iomem);
>  }
>  
> -- 
> 2.51.0
> 
> 

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|
Re: [PULL 24/28] hpet: switch to fine-grained device locking
Posted by Igor Mammedov 2 weeks, 4 days ago
On Mon, 8 Sep 2025 15:30:19 +0100
Daniel P. Berrangé <berrange@redhat.com> wrote:

> Hi,
> 
> This patches causes a regression making QEMU  abort in the KVM Xen
> functional test.
> 
> To reproduce please run 'make check-functional-x86_64', or more
> specifically run this single test:
> 
>  QEMU_TEST_QEMU_BINARY=./build/qemu-system-x86_64 PYTHONPATH=./python:./tests/functional ./tests/functional/x86_64/test_kvm_xen.py
> 
> though I recommend you first add this series:
> 
>   https://lists.nongnu.org/archive/html/qemu-devel/2025-09/msg01540.html
> 
> as that fixes an infinite loop in the functional test console
> code on QEMU abnormal premature exit.

I'll try to reproduce and see where it goes wrong

> 
> In the test logs we see the following on the serial console:
> 
>   2025-09-08 15:26:32,286: Cannot get hvm parameter CONSOLE_EVTCHN (18): -22!
> 
> and then the following on stder:
> 
>   qemu-system-x86_64: ../hw/i386/kvm/xen_evtchn.c:1619: xen_evtchn_set_gsi: Assertion `bql_locked()' failed.
> 
> The QEMU command line was:
> 
>   2025-09-08 15:26:32,097 - DEBUG: VM launch command: './build/qemu-system-x86_64 -display none -vga none -chardev socket,id=mon,fd=5 -mon chardev=mon,mode=control -chardev socket,id=console,fd=10 -serial chardev:console -accel kvm,xen-version=0x4000a,kernel-irqchip=split -smp 2 -kernel /var/home/berrange/.cache/qemu/download/ec0ad7bb8c33c5982baee0a75505fe7dbf29d3ff5d44258204d6307c6fe0132a -append "printk.time=0 root=/dev/xvda console=ttyS0 quiet xen_emul_unplug=ide-disks" -drive file=/var/home/berrange/.cache/qemu/download/b11045d649006c649c184e93339aaa41a8fe20a1a86620af70323252eb29e40b,if=none,snapshot=on,format=raw,id=drv0 -device xen-disk,drive=drv0,vdev=xvda -device virtio-net-pci,netdev=unet -netdev user,id=unet,hostfwd=:127.0.0.1:0-:22'
> 
> On Fri, Aug 29, 2025 at 02:59:31PM +0200, Paolo Bonzini wrote:
> > From: Igor Mammedov <imammedo@redhat.com>
> > 
> > as a step towards lock-less HPET counter read,
> > use per device locking instead of BQL.
> > 
> > Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> > Reviewed-by: Peter Xu <peterx@redhat.com>
> > Link: https://lore.kernel.org/r/20250814160600.2327672-4-imammedo@redhat.com
> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> > ---
> >  hw/timer/hpet.c | 6 ++++++
> >  1 file changed, 6 insertions(+)
> > 
> > diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
> > index cb48cc151f1..ab5aa59ae4e 100644
> > --- a/hw/timer/hpet.c
> > +++ b/hw/timer/hpet.c
> > @@ -38,6 +38,7 @@
> >  #include "hw/timer/i8254.h"
> >  #include "system/address-spaces.h"
> >  #include "qom/object.h"
> > +#include "qemu/lockable.h"
> >  #include "trace.h"
> >  
> >  struct hpet_fw_config hpet_fw_cfg = {.count = UINT8_MAX};
> > @@ -69,6 +70,7 @@ struct HPETState {
> >      SysBusDevice parent_obj;
> >      /*< public >*/
> >  
> > +    QemuMutex lock;
> >      MemoryRegion iomem;
> >      uint64_t hpet_offset;
> >      bool hpet_offset_saved;
> > @@ -428,6 +430,7 @@ static uint64_t hpet_ram_read(void *opaque, hwaddr addr,
> >      trace_hpet_ram_read(addr);
> >      addr &= ~4;
> >  
> > +    QEMU_LOCK_GUARD(&s->lock);
> >      /*address range of all global regs*/
> >      if (addr <= 0xff) {
> >          switch (addr) {
> > @@ -482,6 +485,7 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
> >      int len = MIN(size * 8, 64 - shift);
> >      uint64_t old_val, new_val, cleared;
> >  
> > +    QEMU_LOCK_GUARD(&s->lock);
> >      trace_hpet_ram_write(addr, value);
> >      addr &= ~4;
> >  
> > @@ -679,8 +683,10 @@ static void hpet_init(Object *obj)
> >      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
> >      HPETState *s = HPET(obj);
> >  
> > +    qemu_mutex_init(&s->lock);
> >      /* HPET Area */
> >      memory_region_init_io(&s->iomem, obj, &hpet_ram_ops, s, "hpet", HPET_LEN);
> > +    memory_region_enable_lockless_io(&s->iomem);
> >      sysbus_init_mmio(sbd, &s->iomem);
> >  }
> >  
> > -- 
> > 2.51.0
> > 
> >   
> 
> With regards,
> Daniel
Re: [PULL 24/28] hpet: switch to fine-grained device locking
Posted by Paolo Bonzini 2 weeks, 4 days ago
On Wed, Sep 10, 2025 at 1:16 PM Igor Mammedov <imammedo@redhat.com> wrote:
>
> On Mon, 8 Sep 2025 15:30:19 +0100
> Daniel P. Berrangé <berrange@redhat.com> wrote:
>
> > Hi,
> >
> > This patches causes a regression making QEMU  abort in the KVM Xen
> > functional test.
> >
> > To reproduce please run 'make check-functional-x86_64', or more
> > specifically run this single test:
> >
> >  QEMU_TEST_QEMU_BINARY=./build/qemu-system-x86_64 PYTHONPATH=./python:./tests/functional ./tests/functional/x86_64/test_kvm_xen.py
> >
> > though I recommend you first add this series:
> >
> >   https://lists.nongnu.org/archive/html/qemu-devel/2025-09/msg01540.html
> >
> > as that fixes an infinite loop in the functional test console
> > code on QEMU abnormal premature exit.
>
> I'll try to reproduce and see where it goes wrong

I've only looked at it briefly, but it fails on the bql_locked()
assertion of xen_evtchn_set_gsi().

I think the assertion can be moved inside "if (gsi && gsi == s->callback_gsi)".

Paolo
Re: [PULL 24/28] hpet: switch to fine-grained device locking
Posted by Igor Mammedov 2 weeks, 4 days ago
On Wed, 10 Sep 2025 13:23:10 +0200
Paolo Bonzini <pbonzini@redhat.com> wrote:

> On Wed, Sep 10, 2025 at 1:16 PM Igor Mammedov <imammedo@redhat.com> wrote:
> >
> > On Mon, 8 Sep 2025 15:30:19 +0100
> > Daniel P. Berrangé <berrange@redhat.com> wrote:
> >  
> > > Hi,
> > >
> > > This patches causes a regression making QEMU  abort in the KVM Xen
> > > functional test.
> > >
> > > To reproduce please run 'make check-functional-x86_64', or more
> > > specifically run this single test:
> > >
> > >  QEMU_TEST_QEMU_BINARY=./build/qemu-system-x86_64 PYTHONPATH=./python:./tests/functional ./tests/functional/x86_64/test_kvm_xen.py
> > >
> > > though I recommend you first add this series:
> > >
> > >   https://lists.nongnu.org/archive/html/qemu-devel/2025-09/msg01540.html
> > >
> > > as that fixes an infinite loop in the functional test console
> > > code on QEMU abnormal premature exit.  
> >
> > I'll try to reproduce and see where it goes wrong  
> 
> I've only looked at it briefly, but it fails on the bql_locked()
> assertion of xen_evtchn_set_gsi().
> 
> I think the assertion can be moved inside "if (gsi && gsi == s->callback_gsi)".

given it's manipulating interrupts,
shouldn't we take BQL when doing so?

I see 2 options here
  1: guard qemu_irq_foo calls inside of hpet.c with BQL_LOCK_GUARD
  2: drop new hpet:lock and use BQL instead of it.

> 
> Paolo
> 
Re: [PULL 24/28] hpet: switch to fine-grained device locking
Posted by Peter Maydell 1 week, 6 days ago
On Wed, 10 Sept 2025 at 13:57, Igor Mammedov <imammedo@redhat.com> wrote:
>
> On Wed, 10 Sep 2025 13:23:10 +0200
> Paolo Bonzini <pbonzini@redhat.com> wrote:
> > I've only looked at it briefly, but it fails on the bql_locked()
> > assertion of xen_evtchn_set_gsi().
> >
> > I think the assertion can be moved inside "if (gsi && gsi == s->callback_gsi)".
>
> given it's manipulating interrupts,
> shouldn't we take BQL when doing so?

Yes, if you call qemu_irq_* then you must hold the BQL, because
you can't guarantee what's on the other end and it may be assuming
it has the BQL.

-- PMM
[PATCH] hpet: guard IRQ handling with BQL
Posted by Igor Mammedov 2 weeks, 4 days ago
Commit [1] made qemu fail with abort:
  xen_evtchn_set_gsi: Assertion `bql_locked()' failed.
when running ./tests/functional/x86_64/test_kvm_xen.py tests.

To fix it make sure that BQL is held when manipulating IRQs.

1)
Fixes: 7defb58baf (hpet: switch to fine-grained device locking)
Reported-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 hw/timer/hpet.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index 789a31d0a0..1acba4fa9d 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -40,6 +40,7 @@
 #include "qom/object.h"
 #include "qemu/lockable.h"
 #include "qemu/seqlock.h"
+#include "qemu/main-loop.h"
 #include "trace.h"
 
 struct hpet_fw_config hpet_fw_cfg = {.count = UINT8_MAX};
@@ -222,12 +223,15 @@ static void update_irq(struct HPETTimer *timer, int set)
                                  timer->fsb & 0xffffffff, MEMTXATTRS_UNSPECIFIED,
                                  NULL);
         } else if (timer->config & HPET_TN_TYPE_LEVEL) {
+            BQL_LOCK_GUARD();
             qemu_irq_raise(s->irqs[route]);
         } else {
+            BQL_LOCK_GUARD();
             qemu_irq_pulse(s->irqs[route]);
         }
     } else {
         if (!timer_fsb_route(timer)) {
+            BQL_LOCK_GUARD();
             qemu_irq_lower(s->irqs[route]);
         }
     }
@@ -534,10 +538,12 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
             /* i8254 and RTC output pins are disabled
              * when HPET is in legacy mode */
             if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
+                BQL_LOCK_GUARD();
                 qemu_set_irq(s->pit_enabled, 0);
                 qemu_irq_lower(s->irqs[0]);
                 qemu_irq_lower(s->irqs[RTC_ISA_IRQ]);
             } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
+                BQL_LOCK_GUARD();
                 qemu_irq_lower(s->irqs[0]);
                 qemu_set_irq(s->pit_enabled, 1);
                 qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level);
@@ -683,11 +689,13 @@ static void hpet_handle_legacy_irq(void *opaque, int n, int level)
 
     if (n == HPET_LEGACY_PIT_INT) {
         if (!hpet_in_legacy_mode(s)) {
+            BQL_LOCK_GUARD();
             qemu_set_irq(s->irqs[0], level);
         }
     } else {
         s->rtc_irq_level = level;
         if (!hpet_in_legacy_mode(s)) {
+            BQL_LOCK_GUARD();
             qemu_set_irq(s->irqs[RTC_ISA_IRQ], level);
         }
     }
-- 
2.47.3


Re: [PATCH] hpet: guard IRQ handling with BQL
Posted by Paolo Bonzini 2 weeks, 3 days ago
On 9/10/25 16:25, Igor Mammedov wrote:
> Commit [1] made qemu fail with abort:
>    xen_evtchn_set_gsi: Assertion `bql_locked()' failed.
> when running ./tests/functional/x86_64/test_kvm_xen.py tests.
> 
> To fix it make sure that BQL is held when manipulating IRQs.

Queued, but I think it's time to allow qemu_irq handlers to run outside 
the BQL.

The idea would be to add qemu_allocate_irq_unlocked and 
qemu_allocate_irqs_unlocked, and add a boolean to IRQState.  If the 
boolean is set (the default), qemu_set_irq would wrap the callback with 
bql_lock()/bql_unlock().

Together with the MMIO support that you introduced, this would allow 
making interrupt controllers BQL-free.

Easier thread-safety would also, but I digress, provide a good reason to 
write even the simple devices in Rust---that's in my opinion an even 
better reason than memory safety, for which we already have developed 
lots of abstractions in QEMU.

Paolo

> Fixes: 7defb58baf (hpet: switch to fine-grained device locking)
> Reported-by: Daniel P. Berrangé <berrange@redhat.com>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
>   hw/timer/hpet.c | 8 ++++++++
>   1 file changed, 8 insertions(+)
> 
> diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
> index 789a31d0a0..1acba4fa9d 100644
> --- a/hw/timer/hpet.c
> +++ b/hw/timer/hpet.c
> @@ -40,6 +40,7 @@
>   #include "qom/object.h"
>   #include "qemu/lockable.h"
>   #include "qemu/seqlock.h"
> +#include "qemu/main-loop.h"
>   #include "trace.h"
>   
>   struct hpet_fw_config hpet_fw_cfg = {.count = UINT8_MAX};
> @@ -222,12 +223,15 @@ static void update_irq(struct HPETTimer *timer, int set)
>                                    timer->fsb & 0xffffffff, MEMTXATTRS_UNSPECIFIED,
>                                    NULL);
>           } else if (timer->config & HPET_TN_TYPE_LEVEL) {
> +            BQL_LOCK_GUARD();
>               qemu_irq_raise(s->irqs[route]);
>           } else {
> +            BQL_LOCK_GUARD();
>               qemu_irq_pulse(s->irqs[route]);
>           }
>       } else {
>           if (!timer_fsb_route(timer)) {
> +            BQL_LOCK_GUARD();
>               qemu_irq_lower(s->irqs[route]);
>           }
>       }
> @@ -534,10 +538,12 @@ static void hpet_ram_write(void *opaque, hwaddr addr,
>               /* i8254 and RTC output pins are disabled
>                * when HPET is in legacy mode */
>               if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
> +                BQL_LOCK_GUARD();
>                   qemu_set_irq(s->pit_enabled, 0);
>                   qemu_irq_lower(s->irqs[0]);
>                   qemu_irq_lower(s->irqs[RTC_ISA_IRQ]);
>               } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
> +                BQL_LOCK_GUARD();
>                   qemu_irq_lower(s->irqs[0]);
>                   qemu_set_irq(s->pit_enabled, 1);
>                   qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level);
> @@ -683,11 +689,13 @@ static void hpet_handle_legacy_irq(void *opaque, int n, int level)
>   
>       if (n == HPET_LEGACY_PIT_INT) {
>           if (!hpet_in_legacy_mode(s)) {
> +            BQL_LOCK_GUARD();
>               qemu_set_irq(s->irqs[0], level);
>           }
>       } else {
>           s->rtc_irq_level = level;
>           if (!hpet_in_legacy_mode(s)) {
> +            BQL_LOCK_GUARD();
>               qemu_set_irq(s->irqs[RTC_ISA_IRQ], level);
>           }
>       }