Skip to content

Commit d011151

Browse files
committed
Merge branch 'kvm-x86-mmu-6.6' into HEAD
KVM x86 MMU changes for 6.6: - Rip out the ancient MMU_DEBUG crud and replace the useful bits with CONFIG_KVM_PROVE_MMU - Overhaul KVM's page-track APIs, and KVMGT's usage, to reduce the API surface that is needed by external users (currently only KVMGT), and fix a variety of issues in the process - Fix KVM's handling of !visible guest roots to avoid premature triple fault injection by loading a dummy root backed by the zero page
2 parents 6d5e3c3 + d10f378 commit d011151

20 files changed

+562
-578
lines changed

arch/x86/include/asm/kvm_host.h

+8-8
Original file line numberDiff line numberDiff line change
@@ -288,13 +288,13 @@ struct kvm_kernel_irq_routing_entry;
288288
* kvm_mmu_page_role tracks the properties of a shadow page (where shadow page
289289
* also includes TDP pages) to determine whether or not a page can be used in
290290
* the given MMU context. This is a subset of the overall kvm_cpu_role to
291-
* minimize the size of kvm_memory_slot.arch.gfn_track, i.e. allows allocating
292-
* 2 bytes per gfn instead of 4 bytes per gfn.
291+
* minimize the size of kvm_memory_slot.arch.gfn_write_track, i.e. allows
292+
* allocating 2 bytes per gfn instead of 4 bytes per gfn.
293293
*
294294
* Upper-level shadow pages having gptes are tracked for write-protection via
295-
* gfn_track. As above, gfn_track is a 16 bit counter, so KVM must not create
296-
* more than 2^16-1 upper-level shadow pages at a single gfn, otherwise
297-
* gfn_track will overflow and explosions will ensure.
295+
* gfn_write_track. As above, gfn_write_track is a 16 bit counter, so KVM must
296+
* not create more than 2^16-1 upper-level shadow pages at a single gfn,
297+
* otherwise gfn_write_track will overflow and explosions will ensue.
298298
*
299299
* A unique shadow page (SP) for a gfn is created if and only if an existing SP
300300
* cannot be reused. The ability to reuse a SP is tracked by its role, which
@@ -1023,7 +1023,7 @@ struct kvm_lpage_info {
10231023
struct kvm_arch_memory_slot {
10241024
struct kvm_rmap_head *rmap[KVM_NR_PAGE_SIZES];
10251025
struct kvm_lpage_info *lpage_info[KVM_NR_PAGE_SIZES - 1];
1026-
unsigned short *gfn_track[KVM_PAGE_TRACK_MAX];
1026+
unsigned short *gfn_write_track;
10271027
};
10281028

10291029
/*
@@ -1265,8 +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-
struct kvm_page_track_notifier_node mmu_sp_tracker;
1268+
#ifdef CONFIG_KVM_EXTERNAL_WRITE_TRACKING
12691269
struct kvm_page_track_notifier_head track_notifier_head;
1270+
#endif
12701271
/*
12711272
* Protects marking pages unsync during page faults, as TDP MMU page
12721273
* faults only take mmu_lock for read. For simplicity, the unsync
@@ -1853,7 +1854,6 @@ void kvm_mmu_zap_collapsible_sptes(struct kvm *kvm,
18531854
const struct kvm_memory_slot *memslot);
18541855
void kvm_mmu_slot_leaf_clear_dirty(struct kvm *kvm,
18551856
const struct kvm_memory_slot *memslot);
1856-
void kvm_mmu_zap_all(struct kvm *kvm);
18571857
void kvm_mmu_invalidate_mmio_sptes(struct kvm *kvm, u64 gen);
18581858
void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned long kvm_nr_mmu_pages);
18591859

arch/x86/include/asm/kvm_page_track.h

+25-42
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@
22
#ifndef _ASM_X86_KVM_PAGE_TRACK_H
33
#define _ASM_X86_KVM_PAGE_TRACK_H
44

5-
enum kvm_page_track_mode {
6-
KVM_PAGE_TRACK_WRITE,
7-
KVM_PAGE_TRACK_MAX,
8-
};
5+
#include <linux/kvm_types.h>
96

7+
#ifdef CONFIG_KVM_EXTERNAL_WRITE_TRACKING
108
/*
119
* The notifier represented by @kvm_page_track_notifier_node is linked into
1210
* the head which will be notified when guest is triggering the track event.
@@ -26,54 +24,39 @@ struct kvm_page_track_notifier_node {
2624
* It is called when guest is writing the write-tracked page
2725
* and write emulation is finished at that time.
2826
*
29-
* @vcpu: the vcpu where the write access happened.
3027
* @gpa: the physical address written by guest.
3128
* @new: the data was written to the address.
3229
* @bytes: the written length.
3330
* @node: this node
3431
*/
35-
void (*track_write)(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
36-
int bytes, struct kvm_page_track_notifier_node *node);
32+
void (*track_write)(gpa_t gpa, const u8 *new, int bytes,
33+
struct kvm_page_track_notifier_node *node);
34+
3735
/*
38-
* It is called when memory slot is being moved or removed
39-
* users can drop write-protection for the pages in that memory slot
36+
* Invoked when a memory region is removed from the guest. Or in KVM
37+
* terms, when a memslot is deleted.
4038
*
41-
* @kvm: the kvm where memory slot being moved or removed
42-
* @slot: the memory slot being moved or removed
43-
* @node: this node
39+
* @gfn: base gfn of the region being removed
40+
* @nr_pages: number of pages in the to-be-removed region
41+
* @node: this node
4442
*/
45-
void (*track_flush_slot)(struct kvm *kvm, struct kvm_memory_slot *slot,
46-
struct kvm_page_track_notifier_node *node);
43+
void (*track_remove_region)(gfn_t gfn, unsigned long nr_pages,
44+
struct kvm_page_track_notifier_node *node);
4745
};
4846

49-
int kvm_page_track_init(struct kvm *kvm);
50-
void kvm_page_track_cleanup(struct kvm *kvm);
47+
int kvm_page_track_register_notifier(struct kvm *kvm,
48+
struct kvm_page_track_notifier_node *n);
49+
void kvm_page_track_unregister_notifier(struct kvm *kvm,
50+
struct kvm_page_track_notifier_node *n);
5151

52-
bool kvm_page_track_write_tracking_enabled(struct kvm *kvm);
53-
int kvm_page_track_write_tracking_alloc(struct kvm_memory_slot *slot);
54-
55-
void kvm_page_track_free_memslot(struct kvm_memory_slot *slot);
56-
int kvm_page_track_create_memslot(struct kvm *kvm,
57-
struct kvm_memory_slot *slot,
58-
unsigned long npages);
59-
60-
void kvm_slot_page_track_add_page(struct kvm *kvm,
61-
struct kvm_memory_slot *slot, gfn_t gfn,
62-
enum kvm_page_track_mode mode);
63-
void kvm_slot_page_track_remove_page(struct kvm *kvm,
64-
struct kvm_memory_slot *slot, gfn_t gfn,
65-
enum kvm_page_track_mode mode);
66-
bool kvm_slot_page_track_is_active(struct kvm *kvm,
67-
const struct kvm_memory_slot *slot,
68-
gfn_t gfn, enum kvm_page_track_mode mode);
52+
int kvm_write_track_add_gfn(struct kvm *kvm, gfn_t gfn);
53+
int kvm_write_track_remove_gfn(struct kvm *kvm, gfn_t gfn);
54+
#else
55+
/*
56+
* Allow defining a node in a structure even if page tracking is disabled, e.g.
57+
* to play nice with testing headers via direct inclusion from the command line.
58+
*/
59+
struct kvm_page_track_notifier_node {};
60+
#endif /* CONFIG_KVM_EXTERNAL_WRITE_TRACKING */
6961

70-
void
71-
kvm_page_track_register_notifier(struct kvm *kvm,
72-
struct kvm_page_track_notifier_node *n);
73-
void
74-
kvm_page_track_unregister_notifier(struct kvm *kvm,
75-
struct kvm_page_track_notifier_node *n);
76-
void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
77-
int bytes);
78-
void kvm_page_track_flush_slot(struct kvm *kvm, struct kvm_memory_slot *slot);
7962
#endif

arch/x86/kvm/Kconfig

+13
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,19 @@ config KVM_XEN
138138

139139
If in doubt, say "N".
140140

141+
config KVM_PROVE_MMU
142+
bool "Prove KVM MMU correctness"
143+
depends on DEBUG_KERNEL
144+
depends on KVM
145+
depends on EXPERT
146+
help
147+
Enables runtime assertions in KVM's MMU that are too costly to enable
148+
in anything remotely resembling a production environment, e.g. this
149+
gates code that verifies a to-be-freed page table doesn't have any
150+
present SPTEs.
151+
152+
If in doubt, say "N".
153+
141154
config KVM_EXTERNAL_WRITE_TRACKING
142155
bool
143156

arch/x86/kvm/mmu.h

+2
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ void kvm_mmu_unload(struct kvm_vcpu *vcpu);
121121
void kvm_mmu_free_obsolete_roots(struct kvm_vcpu *vcpu);
122122
void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu);
123123
void kvm_mmu_sync_prev_roots(struct kvm_vcpu *vcpu);
124+
void kvm_mmu_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
125+
int bytes);
124126

125127
static inline int kvm_mmu_reload(struct kvm_vcpu *vcpu)
126128
{

0 commit comments

Comments
 (0)