Skip to content

Commit e998fb1

Browse files
sean-jcbonzini
authored andcommitted
KVM: x86/mmu: Use page-track notifiers iff there are external users
Disable the page-track notifier code at compile time if there are no external users, i.e. if CONFIG_KVM_EXTERNAL_WRITE_TRACKING=n. KVM itself now hooks emulated writes directly instead of relying on the page-track mechanism. Provide a stub for "struct kvm_page_track_notifier_node" so that including headers directly from the command line, e.g. for testing include guards, doesn't fail due to a struct having an incomplete type. Reviewed-by: Yan Zhao <yan.y.zhao@intel.com> Tested-by: Yongwei Ma <yongwei.ma@intel.com> Link: https://lore.kernel.org/r/20230729013535.1070024-23-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 58ea7cf commit e998fb1

File tree

4 files changed

+47
-16
lines changed

4 files changed

+47
-16
lines changed

arch/x86/include/asm/kvm_host.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,7 +1265,9 @@ struct kvm_arch {
12651265
* create an NX huge page (without hanging the guest).
12661266
*/
12671267
struct list_head possible_nx_huge_pages;
1268+
#ifdef CONFIG_KVM_EXTERNAL_WRITE_TRACKING
12681269
struct kvm_page_track_notifier_head track_notifier_head;
1270+
#endif
12691271
/*
12701272
* Protects marking pages unsync during page faults, as TDP MMU page
12711273
* faults only take mmu_lock for read. For simplicity, the unsync

arch/x86/include/asm/kvm_page_track.h

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ enum kvm_page_track_mode {
99
KVM_PAGE_TRACK_MAX,
1010
};
1111

12+
void kvm_slot_page_track_add_page(struct kvm *kvm,
13+
struct kvm_memory_slot *slot, gfn_t gfn,
14+
enum kvm_page_track_mode mode);
15+
void kvm_slot_page_track_remove_page(struct kvm *kvm,
16+
struct kvm_memory_slot *slot, gfn_t gfn,
17+
enum kvm_page_track_mode mode);
18+
19+
#ifdef CONFIG_KVM_EXTERNAL_WRITE_TRACKING
1220
/*
1321
* The notifier represented by @kvm_page_track_notifier_node is linked into
1422
* the head which will be notified when guest is triggering the track event.
@@ -48,18 +56,18 @@ struct kvm_page_track_notifier_node {
4856
struct kvm_page_track_notifier_node *node);
4957
};
5058

51-
void kvm_slot_page_track_add_page(struct kvm *kvm,
52-
struct kvm_memory_slot *slot, gfn_t gfn,
53-
enum kvm_page_track_mode mode);
54-
void kvm_slot_page_track_remove_page(struct kvm *kvm,
55-
struct kvm_memory_slot *slot, gfn_t gfn,
56-
enum kvm_page_track_mode mode);
57-
5859
void
5960
kvm_page_track_register_notifier(struct kvm *kvm,
6061
struct kvm_page_track_notifier_node *n);
6162
void
6263
kvm_page_track_unregister_notifier(struct kvm *kvm,
6364
struct kvm_page_track_notifier_node *n);
65+
#else
66+
/*
67+
* Allow defining a node in a structure even if page tracking is disabled, e.g.
68+
* to play nice with testing headers via direct inclusion from the command line.
69+
*/
70+
struct kvm_page_track_notifier_node {};
71+
#endif /* CONFIG_KVM_EXTERNAL_WRITE_TRACKING */
6472

6573
#endif

arch/x86/kvm/mmu/page_track.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ bool kvm_slot_page_track_is_active(struct kvm *kvm,
194194
return !!READ_ONCE(slot->arch.gfn_track[mode][index]);
195195
}
196196

197+
#ifdef CONFIG_KVM_EXTERNAL_WRITE_TRACKING
197198
void kvm_page_track_cleanup(struct kvm *kvm)
198199
{
199200
struct kvm_page_track_notifier_head *head;
@@ -255,14 +256,13 @@ EXPORT_SYMBOL_GPL(kvm_page_track_unregister_notifier);
255256
* The node should figure out if the written page is the one that node is
256257
* interested in by itself.
257258
*/
258-
void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
259-
int bytes)
259+
void __kvm_page_track_write(struct kvm *kvm, gpa_t gpa, const u8 *new, int bytes)
260260
{
261261
struct kvm_page_track_notifier_head *head;
262262
struct kvm_page_track_notifier_node *n;
263263
int idx;
264264

265-
head = &vcpu->kvm->arch.track_notifier_head;
265+
head = &kvm->arch.track_notifier_head;
266266

267267
if (hlist_empty(&head->track_notifier_list))
268268
return;
@@ -273,8 +273,6 @@ void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
273273
if (n->track_write)
274274
n->track_write(gpa, new, bytes, n);
275275
srcu_read_unlock(&head->track_srcu, idx);
276-
277-
kvm_mmu_track_write(vcpu, gpa, new, bytes);
278276
}
279277

280278
/*
@@ -299,3 +297,5 @@ void kvm_page_track_delete_slot(struct kvm *kvm, struct kvm_memory_slot *slot)
299297
n->track_remove_region(slot->base_gfn, slot->npages, n);
300298
srcu_read_unlock(&head->track_srcu, idx);
301299
}
300+
301+
#endif

arch/x86/kvm/mmu/page_track.h

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66

77
#include <asm/kvm_page_track.h>
88

9-
int kvm_page_track_init(struct kvm *kvm);
10-
void kvm_page_track_cleanup(struct kvm *kvm);
119

1210
bool kvm_page_track_write_tracking_enabled(struct kvm *kvm);
1311
int kvm_page_track_write_tracking_alloc(struct kvm_memory_slot *slot);
@@ -21,13 +19,36 @@ bool kvm_slot_page_track_is_active(struct kvm *kvm,
2119
const struct kvm_memory_slot *slot,
2220
gfn_t gfn, enum kvm_page_track_mode mode);
2321

24-
void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
25-
int bytes);
22+
#ifdef CONFIG_KVM_EXTERNAL_WRITE_TRACKING
23+
int kvm_page_track_init(struct kvm *kvm);
24+
void kvm_page_track_cleanup(struct kvm *kvm);
25+
26+
void __kvm_page_track_write(struct kvm *kvm, gpa_t gpa, const u8 *new, int bytes);
2627
void kvm_page_track_delete_slot(struct kvm *kvm, struct kvm_memory_slot *slot);
2728

2829
static inline bool kvm_page_track_has_external_user(struct kvm *kvm)
2930
{
3031
return !hlist_empty(&kvm->arch.track_notifier_head.track_notifier_list);
3132
}
33+
#else
34+
static inline int kvm_page_track_init(struct kvm *kvm) { return 0; }
35+
static inline void kvm_page_track_cleanup(struct kvm *kvm) { }
36+
37+
static inline void __kvm_page_track_write(struct kvm *kvm, gpa_t gpa,
38+
const u8 *new, int bytes) { }
39+
static inline void kvm_page_track_delete_slot(struct kvm *kvm,
40+
struct kvm_memory_slot *slot) { }
41+
42+
static inline bool kvm_page_track_has_external_user(struct kvm *kvm) { return false; }
43+
44+
#endif /* CONFIG_KVM_EXTERNAL_WRITE_TRACKING */
45+
46+
static inline void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa,
47+
const u8 *new, int bytes)
48+
{
49+
__kvm_page_track_write(vcpu->kvm, gpa, new, bytes);
50+
51+
kvm_mmu_track_write(vcpu, gpa, new, bytes);
52+
}
3253

3354
#endif /* __KVM_X86_PAGE_TRACK_H */

0 commit comments

Comments
 (0)