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 /drivers/kvm/x86.c | |
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>
Diffstat (limited to 'drivers/kvm/x86.c')
-rw-r--r-- | drivers/kvm/x86.c | 25 |
1 files changed, 25 insertions, 0 deletions
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"); |