memory: reintroduce BQL-free fine-grained PIO/MMIO

This patch brings back Jan's idea [1] of BQL-free IO access

This will let us make access to ACPI PM/HPET timers cheaper,
and prevent BQL contention in case of workload that heavily
uses the timers with a lot of vCPUs.

1) 196ea13104 (memory: Add global-locking property to memory regions)
   ... de7ea885c5 (kvm: Switch to unlocked MMIO)

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Link: https://lore.kernel.org/r/20250814160600.2327672-2-imammedo@redhat.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Igor Mammedov 2025-08-14 18:05:53 +02:00 committed by Paolo Bonzini
parent 87511341c3
commit 73c520b088
3 changed files with 28 additions and 1 deletions

View file

@ -833,6 +833,7 @@ struct MemoryRegion {
bool nonvolatile;
bool rom_device;
bool flush_coalesced_mmio;
bool lockless_io;
bool unmergeable;
uint8_t dirty_log_mask;
bool is_iommu;
@ -2341,6 +2342,17 @@ void memory_region_set_flush_coalesced(MemoryRegion *mr);
*/
void memory_region_clear_flush_coalesced(MemoryRegion *mr);
/**
* memory_region_enable_lockless_io: Enable lockless (BQL free) acceess.
*
* Enable BQL-free access for devices that are well prepared to handle
* locking during I/O themselves: either by doing fine grained locking or
* by providing lock-free I/O schemes.
*
* @mr: the memory region to be updated.
*/
void memory_region_enable_lockless_io(MemoryRegion *mr);
/**
* memory_region_add_eventfd: Request an eventfd to be triggered when a word
* is written to a location.

View file

@ -2546,6 +2546,21 @@ void memory_region_clear_flush_coalesced(MemoryRegion *mr)
}
}
void memory_region_enable_lockless_io(MemoryRegion *mr)
{
mr->lockless_io = true;
/*
* reentrancy_guard has per device scope, that when enabled
* will effectively prevent concurrent access to device's IO
* MemoryRegion(s) by not calling accessor callback.
*
* Turn it off for lock-less IO enabled devices, to allow
* concurrent IO.
* TODO: remove this when reentrancy_guard becomes per transaction.
*/
mr->disable_reentrancy_guard = true;
}
void memory_region_add_eventfd(MemoryRegion *mr,
hwaddr addr,
unsigned size,

View file

@ -2900,7 +2900,7 @@ bool prepare_mmio_access(MemoryRegion *mr)
{
bool release_lock = false;
if (!bql_locked()) {
if (!bql_locked() && !mr->lockless_io) {
bql_lock();
release_lock = true;
}