diff options
author | Xiao Guangrong <xiaoguangrong@cn.fujitsu.com> | 2010-08-30 06:25:03 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-10-24 04:51:57 -0400 |
commit | 49edf87806f52a005152beaed9f4731862efc8fe (patch) | |
tree | 5644102bac68fdb28266d2961a2763f872443ee7 /arch | |
parent | 2f4f337248cd5660040b7e09b7287a7a0a861f3f (diff) |
KVM: MMU: improve active sp audit
Both audit_rmap() and audit_write_protection() need to walk all active sp, so
we can do these checking in a sp walking
Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/mmu_audit.c | 74 |
1 files changed, 38 insertions, 36 deletions
diff --git a/arch/x86/kvm/mmu_audit.c b/arch/x86/kvm/mmu_audit.c index fb8a461333c5..8becb86cd348 100644 --- a/arch/x86/kvm/mmu_audit.c +++ b/arch/x86/kvm/mmu_audit.c | |||
@@ -65,6 +65,16 @@ static void mmu_spte_walk(struct kvm_vcpu *vcpu, inspect_spte_fn fn) | |||
65 | return; | 65 | return; |
66 | } | 66 | } |
67 | 67 | ||
68 | typedef void (*sp_handler) (struct kvm *kvm, struct kvm_mmu_page *sp); | ||
69 | |||
70 | static void walk_all_active_sps(struct kvm *kvm, sp_handler fn) | ||
71 | { | ||
72 | struct kvm_mmu_page *sp; | ||
73 | |||
74 | list_for_each_entry(sp, &kvm->arch.active_mmu_pages, link) | ||
75 | fn(kvm, sp); | ||
76 | } | ||
77 | |||
68 | static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte, | 78 | static void audit_mappings_page(struct kvm_vcpu *vcpu, u64 page_pte, |
69 | gva_t va, int level) | 79 | gva_t va, int level) |
70 | { | 80 | { |
@@ -175,67 +185,59 @@ void audit_sptes_have_rmaps(struct kvm_vcpu *vcpu) | |||
175 | mmu_spte_walk(vcpu, inspect_spte_has_rmap); | 185 | mmu_spte_walk(vcpu, inspect_spte_has_rmap); |
176 | } | 186 | } |
177 | 187 | ||
178 | static void check_mappings_rmap(struct kvm_vcpu *vcpu) | 188 | static void check_mappings_rmap(struct kvm *kvm, struct kvm_mmu_page *sp) |
179 | { | 189 | { |
180 | struct kvm_mmu_page *sp; | ||
181 | int i; | 190 | int i; |
182 | 191 | ||
183 | list_for_each_entry(sp, &vcpu->kvm->arch.active_mmu_pages, link) { | 192 | if (sp->role.level != PT_PAGE_TABLE_LEVEL) |
184 | u64 *pt = sp->spt; | 193 | return; |
185 | 194 | ||
186 | if (sp->role.level != PT_PAGE_TABLE_LEVEL) | 195 | for (i = 0; i < PT64_ENT_PER_PAGE; ++i) { |
196 | if (!is_rmap_spte(sp->spt[i])) | ||
187 | continue; | 197 | continue; |
188 | 198 | ||
189 | for (i = 0; i < PT64_ENT_PER_PAGE; ++i) { | 199 | inspect_spte_has_rmap(kvm, sp->spt + i); |
190 | if (!is_rmap_spte(pt[i])) | ||
191 | continue; | ||
192 | |||
193 | inspect_spte_has_rmap(vcpu->kvm, &pt[i]); | ||
194 | } | ||
195 | } | 200 | } |
196 | return; | ||
197 | } | 201 | } |
198 | 202 | ||
199 | static void audit_rmap(struct kvm_vcpu *vcpu) | 203 | void audit_write_protection(struct kvm *kvm, struct kvm_mmu_page *sp) |
200 | { | 204 | { |
201 | check_mappings_rmap(vcpu); | ||
202 | } | ||
203 | |||
204 | static void audit_write_protection(struct kvm_vcpu *vcpu) | ||
205 | { | ||
206 | struct kvm_mmu_page *sp; | ||
207 | struct kvm_memory_slot *slot; | 205 | struct kvm_memory_slot *slot; |
208 | unsigned long *rmapp; | 206 | unsigned long *rmapp; |
209 | u64 *spte; | 207 | u64 *spte; |
210 | 208 | ||
211 | list_for_each_entry(sp, &vcpu->kvm->arch.active_mmu_pages, link) { | 209 | if (sp->role.direct || sp->unsync || sp->role.invalid) |
212 | if (sp->role.direct) | 210 | return; |
213 | continue; | ||
214 | if (sp->unsync) | ||
215 | continue; | ||
216 | if (sp->role.invalid) | ||
217 | continue; | ||
218 | 211 | ||
219 | slot = gfn_to_memslot(vcpu->kvm, sp->gfn); | 212 | slot = gfn_to_memslot(kvm, sp->gfn); |
220 | rmapp = &slot->rmap[sp->gfn - slot->base_gfn]; | 213 | rmapp = &slot->rmap[sp->gfn - slot->base_gfn]; |
221 | 214 | ||
222 | spte = rmap_next(vcpu->kvm, rmapp, NULL); | 215 | spte = rmap_next(kvm, rmapp, NULL); |
223 | while (spte) { | 216 | while (spte) { |
224 | if (is_writable_pte(*spte)) | 217 | if (is_writable_pte(*spte)) |
225 | printk(KERN_ERR "%s: (%s) shadow page has " | 218 | printk(KERN_ERR "%s: (%s) shadow page has " |
226 | "writable mappings: gfn %llx role %x\n", | 219 | "writable mappings: gfn %llx role %x\n", |
227 | __func__, audit_msg, sp->gfn, | 220 | __func__, audit_msg, sp->gfn, |
228 | sp->role.word); | 221 | sp->role.word); |
229 | spte = rmap_next(vcpu->kvm, rmapp, spte); | 222 | spte = rmap_next(kvm, rmapp, spte); |
230 | } | ||
231 | } | 223 | } |
232 | } | 224 | } |
233 | 225 | ||
226 | static void audit_sp(struct kvm *kvm, struct kvm_mmu_page *sp) | ||
227 | { | ||
228 | check_mappings_rmap(kvm, sp); | ||
229 | audit_write_protection(kvm, sp); | ||
230 | } | ||
231 | |||
232 | static void audit_all_active_sps(struct kvm *kvm) | ||
233 | { | ||
234 | walk_all_active_sps(kvm, audit_sp); | ||
235 | } | ||
236 | |||
234 | static void kvm_mmu_audit(void *ignore, struct kvm_vcpu *vcpu, int audit_point) | 237 | static void kvm_mmu_audit(void *ignore, struct kvm_vcpu *vcpu, int audit_point) |
235 | { | 238 | { |
236 | audit_msg = audit_point_name[audit_point]; | 239 | audit_msg = audit_point_name[audit_point]; |
237 | audit_rmap(vcpu); | 240 | audit_all_active_sps(vcpu->kvm); |
238 | audit_write_protection(vcpu); | ||
239 | if (strcmp("pre pte write", audit_msg) != 0) | 241 | if (strcmp("pre pte write", audit_msg) != 0) |
240 | audit_mappings(vcpu); | 242 | audit_mappings(vcpu); |
241 | audit_sptes_have_rmaps(vcpu); | 243 | audit_sptes_have_rmaps(vcpu); |