diff options
author | Marcelo Tosatti <mtosatti@redhat.com> | 2010-10-25 09:58:22 -0400 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2010-11-05 12:42:26 -0400 |
commit | eb45fda45f915c7ca3e81e005e853cb770da2642 (patch) | |
tree | 9c10bbdb52a1a1752cac30343a3c6f4d79ef4a88 /arch/x86/kvm/mmu.c | |
parent | edde99ce05290e50ce0b3495d209e54e6349ab47 (diff) |
KVM: MMU: fix rmap_remove on non present sptes
drop_spte should not attempt to rmap_remove a non present shadow pte.
This fixes a BUG_ON seen on kvm-autotest.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Reported-by: Lucas Meneghel Rodrigues <lmr@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/mmu.c')
-rw-r--r-- | arch/x86/kvm/mmu.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 908ea5464a51..fb8b376bf28c 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c | |||
@@ -720,7 +720,7 @@ static void rmap_remove(struct kvm *kvm, u64 *spte) | |||
720 | } | 720 | } |
721 | } | 721 | } |
722 | 722 | ||
723 | static void set_spte_track_bits(u64 *sptep, u64 new_spte) | 723 | static int set_spte_track_bits(u64 *sptep, u64 new_spte) |
724 | { | 724 | { |
725 | pfn_t pfn; | 725 | pfn_t pfn; |
726 | u64 old_spte = *sptep; | 726 | u64 old_spte = *sptep; |
@@ -731,19 +731,20 @@ static void set_spte_track_bits(u64 *sptep, u64 new_spte) | |||
731 | old_spte = __xchg_spte(sptep, new_spte); | 731 | old_spte = __xchg_spte(sptep, new_spte); |
732 | 732 | ||
733 | if (!is_rmap_spte(old_spte)) | 733 | if (!is_rmap_spte(old_spte)) |
734 | return; | 734 | return 0; |
735 | 735 | ||
736 | pfn = spte_to_pfn(old_spte); | 736 | pfn = spte_to_pfn(old_spte); |
737 | if (!shadow_accessed_mask || old_spte & shadow_accessed_mask) | 737 | if (!shadow_accessed_mask || old_spte & shadow_accessed_mask) |
738 | kvm_set_pfn_accessed(pfn); | 738 | kvm_set_pfn_accessed(pfn); |
739 | if (!shadow_dirty_mask || (old_spte & shadow_dirty_mask)) | 739 | if (!shadow_dirty_mask || (old_spte & shadow_dirty_mask)) |
740 | kvm_set_pfn_dirty(pfn); | 740 | kvm_set_pfn_dirty(pfn); |
741 | return 1; | ||
741 | } | 742 | } |
742 | 743 | ||
743 | static void drop_spte(struct kvm *kvm, u64 *sptep, u64 new_spte) | 744 | static void drop_spte(struct kvm *kvm, u64 *sptep, u64 new_spte) |
744 | { | 745 | { |
745 | set_spte_track_bits(sptep, new_spte); | 746 | if (set_spte_track_bits(sptep, new_spte)) |
746 | rmap_remove(kvm, sptep); | 747 | rmap_remove(kvm, sptep); |
747 | } | 748 | } |
748 | 749 | ||
749 | static u64 *rmap_next(struct kvm *kvm, unsigned long *rmapp, u64 *spte) | 750 | static u64 *rmap_next(struct kvm *kvm, unsigned long *rmapp, u64 *spte) |