Skip to content

Commit 250012d

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/dirty-log-ordered into kvmarm-master/next
* kvm-arm64/dirty-log-ordered: : . : Retrofit some ordering into the existing API dirty-ring by: : : - relying on acquire/release semantics which are the default on x86, : but need to be explicit on arm64 : : - adding a new capability that indicate which flavor is supported, either : with explicit ordering (arm64) or both implicit and explicit (x86), : as suggested by Paolo at KVM Forum : : - documenting the requirements for this new capability on weakly ordered : architectures : : - updating the selftests to do the right thing : . KVM: selftests: dirty-log: Use KVM_CAP_DIRTY_LOG_RING_ACQ_REL if available KVM: selftests: dirty-log: Upgrade flag accesses to acquire/release semantics KVM: Document weakly ordered architecture requirements for dirty ring KVM: x86: Select CONFIG_HAVE_KVM_DIRTY_RING_ACQ_REL KVM: Add KVM_CAP_DIRTY_LOG_RING_ACQ_REL capability and config option KVM: Use acquire/release semantics when accessing dirty ring GFN state Signed-off-by: Marc Zyngier <[email protected]>
2 parents bb0cca2 + 4b3402f commit 250012d

File tree

8 files changed

+51
-10
lines changed

8 files changed

+51
-10
lines changed

Documentation/virt/kvm/api.rst

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8019,8 +8019,8 @@ guest according to the bits in the KVM_CPUID_FEATURES CPUID leaf
80198019
(0x40000001). Otherwise, a guest may use the paravirtual features
80208020
regardless of what has actually been exposed through the CPUID leaf.
80218021

8022-
8.29 KVM_CAP_DIRTY_LOG_RING
8023-
---------------------------
8022+
8.29 KVM_CAP_DIRTY_LOG_RING/KVM_CAP_DIRTY_LOG_RING_ACQ_REL
8023+
----------------------------------------------------------
80248024

80258025
:Architectures: x86
80268026
:Parameters: args[0] - size of the dirty log ring
@@ -8078,6 +8078,11 @@ on to the next GFN. The userspace should continue to do this until the
80788078
flags of a GFN have the DIRTY bit cleared, meaning that it has harvested
80798079
all the dirty GFNs that were available.
80808080

8081+
Note that on weakly ordered architectures, userspace accesses to the
8082+
ring buffer (and more specifically the 'flags' field) must be ordered,
8083+
using load-acquire/store-release accessors when available, or any
8084+
other memory barrier that will ensure this ordering.
8085+
80818086
It's not necessary for userspace to harvest the all dirty GFNs at once.
80828087
However it must collect the dirty GFNs in sequence, i.e., the userspace
80838088
program cannot skip one dirty GFN to collect the one next to it.
@@ -8106,6 +8111,14 @@ KVM_CAP_DIRTY_LOG_RING with an acceptable dirty ring size, the virtual
81068111
machine will switch to ring-buffer dirty page tracking and further
81078112
KVM_GET_DIRTY_LOG or KVM_CLEAR_DIRTY_LOG ioctls will fail.
81088113

8114+
NOTE: KVM_CAP_DIRTY_LOG_RING_ACQ_REL is the only capability that
8115+
should be exposed by weakly ordered architecture, in order to indicate
8116+
the additional memory ordering requirements imposed on userspace when
8117+
reading the state of an entry and mutating it from DIRTY to HARVESTED.
8118+
Architecture with TSO-like ordering (such as x86) are allowed to
8119+
expose both KVM_CAP_DIRTY_LOG_RING and KVM_CAP_DIRTY_LOG_RING_ACQ_REL
8120+
to userspace.
8121+
81098122
8.30 KVM_CAP_XEN_HVM
81108123
--------------------
81118124

arch/x86/kvm/Kconfig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ config KVM
2828
select HAVE_KVM_IRQCHIP
2929
select HAVE_KVM_PFNCACHE
3030
select HAVE_KVM_IRQFD
31-
select HAVE_KVM_DIRTY_RING
31+
select HAVE_KVM_DIRTY_RING_TSO
32+
select HAVE_KVM_DIRTY_RING_ACQ_REL
3233
select IRQ_BYPASS_MANAGER
3334
select HAVE_KVM_IRQ_BYPASS
3435
select HAVE_KVM_IRQ_ROUTING

include/uapi/linux/kvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,6 +1177,7 @@ struct kvm_ppc_resize_hpt {
11771177
#define KVM_CAP_VM_DISABLE_NX_HUGE_PAGES 220
11781178
#define KVM_CAP_S390_ZPCI_OP 221
11791179
#define KVM_CAP_S390_CPU_TOPOLOGY 222
1180+
#define KVM_CAP_DIRTY_LOG_RING_ACQ_REL 223
11801181

11811182
#ifdef KVM_CAP_IRQ_ROUTING
11821183

tools/testing/selftests/kvm/dirty_log_test.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/bitmap.h>
1818
#include <linux/bitops.h>
1919
#include <linux/atomic.h>
20+
#include <asm/barrier.h>
2021

2122
#include "kvm_util.h"
2223
#include "test_util.h"
@@ -264,7 +265,8 @@ static void default_after_vcpu_run(struct kvm_vcpu *vcpu, int ret, int err)
264265

265266
static bool dirty_ring_supported(void)
266267
{
267-
return kvm_has_cap(KVM_CAP_DIRTY_LOG_RING);
268+
return (kvm_has_cap(KVM_CAP_DIRTY_LOG_RING) ||
269+
kvm_has_cap(KVM_CAP_DIRTY_LOG_RING_ACQ_REL));
268270
}
269271

270272
static void dirty_ring_create_vm_done(struct kvm_vm *vm)
@@ -279,12 +281,12 @@ static void dirty_ring_create_vm_done(struct kvm_vm *vm)
279281

280282
static inline bool dirty_gfn_is_dirtied(struct kvm_dirty_gfn *gfn)
281283
{
282-
return gfn->flags == KVM_DIRTY_GFN_F_DIRTY;
284+
return smp_load_acquire(&gfn->flags) == KVM_DIRTY_GFN_F_DIRTY;
283285
}
284286

285287
static inline void dirty_gfn_set_collected(struct kvm_dirty_gfn *gfn)
286288
{
287-
gfn->flags = KVM_DIRTY_GFN_F_RESET;
289+
smp_store_release(&gfn->flags, KVM_DIRTY_GFN_F_RESET);
288290
}
289291

290292
static uint32_t dirty_ring_collect_one(struct kvm_dirty_gfn *dirty_gfns,

tools/testing/selftests/kvm/lib/kvm_util.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ unsigned int kvm_check_cap(long cap)
8282

8383
void vm_enable_dirty_ring(struct kvm_vm *vm, uint32_t ring_size)
8484
{
85-
vm_enable_cap(vm, KVM_CAP_DIRTY_LOG_RING, ring_size);
85+
if (vm_check_cap(vm, KVM_CAP_DIRTY_LOG_RING_ACQ_REL))
86+
vm_enable_cap(vm, KVM_CAP_DIRTY_LOG_RING_ACQ_REL, ring_size);
87+
else
88+
vm_enable_cap(vm, KVM_CAP_DIRTY_LOG_RING, ring_size);
8689
vm->dirty_ring_size = ring_size;
8790
}
8891

virt/kvm/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@ config HAVE_KVM_IRQ_ROUTING
1919
config HAVE_KVM_DIRTY_RING
2020
bool
2121

22+
# Only strongly ordered architectures can select this, as it doesn't
23+
# put any explicit constraint on userspace ordering. They can also
24+
# select the _ACQ_REL version.
25+
config HAVE_KVM_DIRTY_RING_TSO
26+
bool
27+
select HAVE_KVM_DIRTY_RING
28+
depends on X86
29+
30+
# Weakly ordered architectures can only select this, advertising
31+
# to userspace the additional ordering requirements.
32+
config HAVE_KVM_DIRTY_RING_ACQ_REL
33+
bool
34+
select HAVE_KVM_DIRTY_RING
35+
2236
config HAVE_KVM_EVENTFD
2337
bool
2438
select EVENTFD

virt/kvm/dirty_ring.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ int kvm_dirty_ring_alloc(struct kvm_dirty_ring *ring, int index, u32 size)
7474

7575
static inline void kvm_dirty_gfn_set_invalid(struct kvm_dirty_gfn *gfn)
7676
{
77-
gfn->flags = 0;
77+
smp_store_release(&gfn->flags, 0);
7878
}
7979

8080
static inline void kvm_dirty_gfn_set_dirtied(struct kvm_dirty_gfn *gfn)
@@ -84,7 +84,7 @@ static inline void kvm_dirty_gfn_set_dirtied(struct kvm_dirty_gfn *gfn)
8484

8585
static inline bool kvm_dirty_gfn_harvested(struct kvm_dirty_gfn *gfn)
8686
{
87-
return gfn->flags & KVM_DIRTY_GFN_F_RESET;
87+
return smp_load_acquire(&gfn->flags) & KVM_DIRTY_GFN_F_RESET;
8888
}
8989

9090
int kvm_dirty_ring_reset(struct kvm *kvm, struct kvm_dirty_ring *ring)

virt/kvm/kvm_main.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4475,7 +4475,13 @@ static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
44754475
case KVM_CAP_NR_MEMSLOTS:
44764476
return KVM_USER_MEM_SLOTS;
44774477
case KVM_CAP_DIRTY_LOG_RING:
4478-
#ifdef CONFIG_HAVE_KVM_DIRTY_RING
4478+
#ifdef CONFIG_HAVE_KVM_DIRTY_RING_TSO
4479+
return KVM_DIRTY_RING_MAX_ENTRIES * sizeof(struct kvm_dirty_gfn);
4480+
#else
4481+
return 0;
4482+
#endif
4483+
case KVM_CAP_DIRTY_LOG_RING_ACQ_REL:
4484+
#ifdef CONFIG_HAVE_KVM_DIRTY_RING_ACQ_REL
44794485
return KVM_DIRTY_RING_MAX_ENTRIES * sizeof(struct kvm_dirty_gfn);
44804486
#else
44814487
return 0;
@@ -4580,6 +4586,7 @@ static int kvm_vm_ioctl_enable_cap_generic(struct kvm *kvm,
45804586
return 0;
45814587
}
45824588
case KVM_CAP_DIRTY_LOG_RING:
4589+
case KVM_CAP_DIRTY_LOG_RING_ACQ_REL:
45834590
return kvm_vm_ioctl_enable_dirty_log_ring(kvm, cap->args[0]);
45844591
default:
45854592
return kvm_vm_ioctl_enable_cap(kvm, cap);

0 commit comments

Comments
 (0)