diff options
author | Avi Kivity <avi@redhat.com> | 2010-06-06 07:31:27 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-08-01 23:40:17 -0400 |
commit | be38d276b0189fa86231fc311428622a1981ad62 (patch) | |
tree | 4706819e23ade99c43bb676830071da9bd2d0abd /arch/x86/kvm/paging_tmpl.h | |
parent | dd180b3e90253cb4ca95d603a8c17413f8daec69 (diff) |
KVM: MMU: Introduce drop_spte()
When we call rmap_remove(), we (almost) always immediately follow it by
an __set_spte() to a nonpresent pte. Since we need to perform the two
operations atomically, to avoid losing the dirty and accessed bits, introduce
a helper drop_spte() and convert all call sites.
The operation is still nonatomic at this point.
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/paging_tmpl.h')
-rw-r--r-- | arch/x86/kvm/paging_tmpl.h | 13 |
1 files changed, 6 insertions, 7 deletions
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 59e750c1a269..796a325c7e59 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h | |||
@@ -353,8 +353,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, | |||
353 | } | 353 | } |
354 | 354 | ||
355 | if (is_large_pte(*sptep)) { | 355 | if (is_large_pte(*sptep)) { |
356 | rmap_remove(vcpu->kvm, sptep); | 356 | drop_spte(vcpu->kvm, sptep, shadow_trap_nonpresent_pte); |
357 | __set_spte(sptep, shadow_trap_nonpresent_pte); | ||
358 | kvm_flush_remote_tlbs(vcpu->kvm); | 357 | kvm_flush_remote_tlbs(vcpu->kvm); |
359 | } | 358 | } |
360 | 359 | ||
@@ -516,12 +515,13 @@ static void FNAME(invlpg)(struct kvm_vcpu *vcpu, gva_t gva) | |||
516 | pte_gpa += (sptep - sp->spt) * sizeof(pt_element_t); | 515 | pte_gpa += (sptep - sp->spt) * sizeof(pt_element_t); |
517 | 516 | ||
518 | if (is_shadow_present_pte(*sptep)) { | 517 | if (is_shadow_present_pte(*sptep)) { |
519 | rmap_remove(vcpu->kvm, sptep); | ||
520 | if (is_large_pte(*sptep)) | 518 | if (is_large_pte(*sptep)) |
521 | --vcpu->kvm->stat.lpages; | 519 | --vcpu->kvm->stat.lpages; |
520 | drop_spte(vcpu->kvm, sptep, | ||
521 | shadow_trap_nonpresent_pte); | ||
522 | need_flush = 1; | 522 | need_flush = 1; |
523 | } | 523 | } else |
524 | __set_spte(sptep, shadow_trap_nonpresent_pte); | 524 | __set_spte(sptep, shadow_trap_nonpresent_pte); |
525 | break; | 525 | break; |
526 | } | 526 | } |
527 | 527 | ||
@@ -637,12 +637,11 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp, | |||
637 | !is_present_gpte(gpte) || !(gpte & PT_ACCESSED_MASK)) { | 637 | !is_present_gpte(gpte) || !(gpte & PT_ACCESSED_MASK)) { |
638 | u64 nonpresent; | 638 | u64 nonpresent; |
639 | 639 | ||
640 | rmap_remove(vcpu->kvm, &sp->spt[i]); | ||
641 | if (is_present_gpte(gpte) || !clear_unsync) | 640 | if (is_present_gpte(gpte) || !clear_unsync) |
642 | nonpresent = shadow_trap_nonpresent_pte; | 641 | nonpresent = shadow_trap_nonpresent_pte; |
643 | else | 642 | else |
644 | nonpresent = shadow_notrap_nonpresent_pte; | 643 | nonpresent = shadow_notrap_nonpresent_pte; |
645 | __set_spte(&sp->spt[i], nonpresent); | 644 | drop_spte(vcpu->kvm, &sp->spt[i], nonpresent); |
646 | continue; | 645 | continue; |
647 | } | 646 | } |
648 | 647 | ||