diff options
author | Avi Kivity <avi@qumranet.com> | 2007-11-20 19:57:59 -0500 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:53:10 -0500 |
commit | d835dfecd00fd770288dcd9a46c0e0966d526fdf (patch) | |
tree | 9e80c69f9024e45b39cf0d1eeda56ba4a57567a6 | |
parent | 79539cec0c3c38d35a1e3e5310d2c562ae6e82b8 (diff) |
KVM: Don't bother the mmu if cr3 load doesn't change cr3
If the guest requests just a tlb flush, don't take the vm lock and
drop the mmu context pointlessly.
Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r-- | drivers/kvm/mmu.c | 2 | ||||
-rw-r--r-- | drivers/kvm/x86.c | 25 | ||||
-rw-r--r-- | drivers/kvm/x86.h | 1 |
3 files changed, 27 insertions, 1 deletions
diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c index 281dd5f9310c..346aa65a08d5 100644 --- a/drivers/kvm/mmu.c +++ b/drivers/kvm/mmu.c | |||
@@ -1086,7 +1086,7 @@ static int nonpaging_init_context(struct kvm_vcpu *vcpu) | |||
1086 | return 0; | 1086 | return 0; |
1087 | } | 1087 | } |
1088 | 1088 | ||
1089 | static void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu) | 1089 | void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu) |
1090 | { | 1090 | { |
1091 | ++vcpu->stat.tlb_flush; | 1091 | ++vcpu->stat.tlb_flush; |
1092 | kvm_x86_ops->tlb_flush(vcpu); | 1092 | kvm_x86_ops->tlb_flush(vcpu); |
diff --git a/drivers/kvm/x86.c b/drivers/kvm/x86.c index ac09f381f47f..15e1203faef0 100644 --- a/drivers/kvm/x86.c +++ b/drivers/kvm/x86.c | |||
@@ -166,6 +166,26 @@ out: | |||
166 | return ret; | 166 | return ret; |
167 | } | 167 | } |
168 | 168 | ||
169 | static bool pdptrs_changed(struct kvm_vcpu *vcpu) | ||
170 | { | ||
171 | u64 pdpte[ARRAY_SIZE(vcpu->pdptrs)]; | ||
172 | bool changed = true; | ||
173 | int r; | ||
174 | |||
175 | if (is_long_mode(vcpu) || !is_pae(vcpu)) | ||
176 | return false; | ||
177 | |||
178 | mutex_lock(&vcpu->kvm->lock); | ||
179 | r = kvm_read_guest(vcpu->kvm, vcpu->cr3 & ~31u, pdpte, sizeof(pdpte)); | ||
180 | if (r < 0) | ||
181 | goto out; | ||
182 | changed = memcmp(pdpte, vcpu->pdptrs, sizeof(pdpte)) != 0; | ||
183 | out: | ||
184 | mutex_unlock(&vcpu->kvm->lock); | ||
185 | |||
186 | return changed; | ||
187 | } | ||
188 | |||
169 | void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) | 189 | void set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0) |
170 | { | 190 | { |
171 | if (cr0 & CR0_RESERVED_BITS) { | 191 | if (cr0 & CR0_RESERVED_BITS) { |
@@ -271,6 +291,11 @@ EXPORT_SYMBOL_GPL(set_cr4); | |||
271 | 291 | ||
272 | void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) | 292 | void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3) |
273 | { | 293 | { |
294 | if (cr3 == vcpu->cr3 && !pdptrs_changed(vcpu)) { | ||
295 | kvm_mmu_flush_tlb(vcpu); | ||
296 | return; | ||
297 | } | ||
298 | |||
274 | if (is_long_mode(vcpu)) { | 299 | if (is_long_mode(vcpu)) { |
275 | if (cr3 & CR3_L_MODE_RESERVED_BITS) { | 300 | if (cr3 & CR3_L_MODE_RESERVED_BITS) { |
276 | printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n"); | 301 | printk(KERN_DEBUG "set_cr3: #GP, reserved bits\n"); |
diff --git a/drivers/kvm/x86.h b/drivers/kvm/x86.h index 71f2477d03fd..b1528c9f566f 100644 --- a/drivers/kvm/x86.h +++ b/drivers/kvm/x86.h | |||
@@ -299,6 +299,7 @@ int emulator_write_emulated(unsigned long addr, | |||
299 | 299 | ||
300 | unsigned long segment_base(u16 selector); | 300 | unsigned long segment_base(u16 selector); |
301 | 301 | ||
302 | void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu); | ||
302 | void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, | 303 | void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, |
303 | const u8 *new, int bytes); | 304 | const u8 *new, int bytes); |
304 | int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva); | 305 | int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva); |