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 | |
| 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>
| -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) |
