3838#include <linux/intel-iommu.h>
3939#include <linux/cpufreq.h>
4040#include <linux/user-return-notifier.h>
41+ #include <linux/srcu.h>
4142#include <trace/events/kvm.h>
4243#undef TRACE_INCLUDE_FILE
4344#define CREATE_TRACE_POINTS
@@ -2223,11 +2224,32 @@ static int kvm_vm_ioctl_get_nr_mmu_pages(struct kvm *kvm)
22232224 return kvm -> arch .n_alloc_mmu_pages ;
22242225}
22252226
2227+ gfn_t unalias_gfn_instantiation (struct kvm * kvm , gfn_t gfn )
2228+ {
2229+ int i ;
2230+ struct kvm_mem_alias * alias ;
2231+ struct kvm_mem_aliases * aliases ;
2232+
2233+ aliases = rcu_dereference (kvm -> arch .aliases );
2234+
2235+ for (i = 0 ; i < aliases -> naliases ; ++ i ) {
2236+ alias = & aliases -> aliases [i ];
2237+ if (alias -> flags & KVM_ALIAS_INVALID )
2238+ continue ;
2239+ if (gfn >= alias -> base_gfn
2240+ && gfn < alias -> base_gfn + alias -> npages )
2241+ return alias -> target_gfn + gfn - alias -> base_gfn ;
2242+ }
2243+ return gfn ;
2244+ }
2245+
22262246gfn_t unalias_gfn (struct kvm * kvm , gfn_t gfn )
22272247{
22282248 int i ;
22292249 struct kvm_mem_alias * alias ;
2230- struct kvm_mem_aliases * aliases = kvm -> arch .aliases ;
2250+ struct kvm_mem_aliases * aliases ;
2251+
2252+ aliases = rcu_dereference (kvm -> arch .aliases );
22312253
22322254 for (i = 0 ; i < aliases -> naliases ; ++ i ) {
22332255 alias = & aliases -> aliases [i ];
@@ -2248,7 +2270,7 @@ static int kvm_vm_ioctl_set_memory_alias(struct kvm *kvm,
22482270{
22492271 int r , n ;
22502272 struct kvm_mem_alias * p ;
2251- struct kvm_mem_aliases * aliases ;
2273+ struct kvm_mem_aliases * aliases , * old_aliases ;
22522274
22532275 r = - EINVAL ;
22542276 /* General sanity checks */
@@ -2265,28 +2287,48 @@ static int kvm_vm_ioctl_set_memory_alias(struct kvm *kvm,
22652287 < alias -> target_phys_addr )
22662288 goto out ;
22672289
2290+ r = - ENOMEM ;
2291+ aliases = kzalloc (sizeof (struct kvm_mem_aliases ), GFP_KERNEL );
2292+ if (!aliases )
2293+ goto out ;
2294+
22682295 down_write (& kvm -> slots_lock );
2269- spin_lock (& kvm -> mmu_lock );
22702296
2271- aliases = kvm -> arch .aliases ;
2297+ /* invalidate any gfn reference in case of deletion/shrinking */
2298+ memcpy (aliases , kvm -> arch .aliases , sizeof (struct kvm_mem_aliases ));
2299+ aliases -> aliases [alias -> slot ].flags |= KVM_ALIAS_INVALID ;
2300+ old_aliases = kvm -> arch .aliases ;
2301+ rcu_assign_pointer (kvm -> arch .aliases , aliases );
2302+ synchronize_srcu_expedited (& kvm -> srcu );
2303+ kvm_mmu_zap_all (kvm );
2304+ kfree (old_aliases );
2305+
2306+ r = - ENOMEM ;
2307+ aliases = kzalloc (sizeof (struct kvm_mem_aliases ), GFP_KERNEL );
2308+ if (!aliases )
2309+ goto out_unlock ;
2310+
2311+ memcpy (aliases , kvm -> arch .aliases , sizeof (struct kvm_mem_aliases ));
22722312
22732313 p = & aliases -> aliases [alias -> slot ];
22742314 p -> base_gfn = alias -> guest_phys_addr >> PAGE_SHIFT ;
22752315 p -> npages = alias -> memory_size >> PAGE_SHIFT ;
22762316 p -> target_gfn = alias -> target_phys_addr >> PAGE_SHIFT ;
2317+ p -> flags &= ~(KVM_ALIAS_INVALID );
22772318
22782319 for (n = KVM_ALIAS_SLOTS ; n > 0 ; -- n )
22792320 if (aliases -> aliases [n - 1 ].npages )
22802321 break ;
22812322 aliases -> naliases = n ;
22822323
2283- spin_unlock (& kvm -> mmu_lock );
2284- kvm_mmu_zap_all (kvm );
2324+ old_aliases = kvm -> arch .aliases ;
2325+ rcu_assign_pointer (kvm -> arch .aliases , aliases );
2326+ synchronize_srcu_expedited (& kvm -> srcu );
2327+ kfree (old_aliases );
2328+ r = 0 ;
22852329
2330+ out_unlock :
22862331 up_write (& kvm -> slots_lock );
2287-
2288- return 0 ;
2289-
22902332out :
22912333 return r ;
22922334}
0 commit comments