@@ -742,13 +742,53 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
742
742
return kvm_handle_hva_range (kvm , hva , hva + 1 , handler );
743
743
}
744
744
745
+ /* Must be called with both HPTE and rmap locked */
746
+ static void kvmppc_unmap_hpte (struct kvm * kvm , unsigned long i ,
747
+ unsigned long * rmapp , unsigned long gfn )
748
+ {
749
+ __be64 * hptep = (__be64 * ) (kvm -> arch .hpt .virt + (i << 4 ));
750
+ struct revmap_entry * rev = kvm -> arch .hpt .rev ;
751
+ unsigned long j , h ;
752
+ unsigned long ptel , psize , rcbits ;
753
+
754
+ j = rev [i ].forw ;
755
+ if (j == i ) {
756
+ /* chain is now empty */
757
+ * rmapp &= ~(KVMPPC_RMAP_PRESENT | KVMPPC_RMAP_INDEX );
758
+ } else {
759
+ /* remove i from chain */
760
+ h = rev [i ].back ;
761
+ rev [h ].forw = j ;
762
+ rev [j ].back = h ;
763
+ rev [i ].forw = rev [i ].back = i ;
764
+ * rmapp = (* rmapp & ~KVMPPC_RMAP_INDEX ) | j ;
765
+ }
766
+
767
+ /* Now check and modify the HPTE */
768
+ ptel = rev [i ].guest_rpte ;
769
+ psize = hpte_page_size (be64_to_cpu (hptep [0 ]), ptel );
770
+ if ((be64_to_cpu (hptep [0 ]) & HPTE_V_VALID ) &&
771
+ hpte_rpn (ptel , psize ) == gfn ) {
772
+ hptep [0 ] |= cpu_to_be64 (HPTE_V_ABSENT );
773
+ kvmppc_invalidate_hpte (kvm , hptep , i );
774
+ hptep [1 ] &= ~cpu_to_be64 (HPTE_R_KEY_HI | HPTE_R_KEY_LO );
775
+ /* Harvest R and C */
776
+ rcbits = be64_to_cpu (hptep [1 ]) & (HPTE_R_R | HPTE_R_C );
777
+ * rmapp |= rcbits << KVMPPC_RMAP_RC_SHIFT ;
778
+ if (rcbits & HPTE_R_C )
779
+ kvmppc_update_rmap_change (rmapp , psize );
780
+ if (rcbits & ~rev [i ].guest_rpte ) {
781
+ rev [i ].guest_rpte = ptel | rcbits ;
782
+ note_hpte_modification (kvm , & rev [i ]);
783
+ }
784
+ }
785
+ }
786
+
745
787
static int kvm_unmap_rmapp (struct kvm * kvm , struct kvm_memory_slot * memslot ,
746
788
unsigned long gfn )
747
789
{
748
- struct revmap_entry * rev = kvm -> arch .hpt .rev ;
749
- unsigned long h , i , j ;
790
+ unsigned long i ;
750
791
__be64 * hptep ;
751
- unsigned long ptel , psize , rcbits ;
752
792
unsigned long * rmapp ;
753
793
754
794
rmapp = & memslot -> arch .rmap [gfn - memslot -> base_gfn ];
@@ -773,37 +813,8 @@ static int kvm_unmap_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
773
813
cpu_relax ();
774
814
continue ;
775
815
}
776
- j = rev [i ].forw ;
777
- if (j == i ) {
778
- /* chain is now empty */
779
- * rmapp &= ~(KVMPPC_RMAP_PRESENT | KVMPPC_RMAP_INDEX );
780
- } else {
781
- /* remove i from chain */
782
- h = rev [i ].back ;
783
- rev [h ].forw = j ;
784
- rev [j ].back = h ;
785
- rev [i ].forw = rev [i ].back = i ;
786
- * rmapp = (* rmapp & ~KVMPPC_RMAP_INDEX ) | j ;
787
- }
788
816
789
- /* Now check and modify the HPTE */
790
- ptel = rev [i ].guest_rpte ;
791
- psize = hpte_page_size (be64_to_cpu (hptep [0 ]), ptel );
792
- if ((be64_to_cpu (hptep [0 ]) & HPTE_V_VALID ) &&
793
- hpte_rpn (ptel , psize ) == gfn ) {
794
- hptep [0 ] |= cpu_to_be64 (HPTE_V_ABSENT );
795
- kvmppc_invalidate_hpte (kvm , hptep , i );
796
- hptep [1 ] &= ~cpu_to_be64 (HPTE_R_KEY_HI | HPTE_R_KEY_LO );
797
- /* Harvest R and C */
798
- rcbits = be64_to_cpu (hptep [1 ]) & (HPTE_R_R | HPTE_R_C );
799
- * rmapp |= rcbits << KVMPPC_RMAP_RC_SHIFT ;
800
- if (rcbits & HPTE_R_C )
801
- kvmppc_update_rmap_change (rmapp , psize );
802
- if (rcbits & ~rev [i ].guest_rpte ) {
803
- rev [i ].guest_rpte = ptel | rcbits ;
804
- note_hpte_modification (kvm , & rev [i ]);
805
- }
806
- }
817
+ kvmppc_unmap_hpte (kvm , i , rmapp , gfn );
807
818
unlock_rmap (rmapp );
808
819
__unlock_hpte (hptep , be64_to_cpu (hptep [0 ]));
809
820
}
0 commit comments