@@ -2277,66 +2277,52 @@ struct sev_gmem_populate_args {
22772277 int fw_error ;
22782278};
22792279
2280- static int sev_gmem_post_populate (struct kvm * kvm , gfn_t gfn_start , kvm_pfn_t pfn ,
2281- void __user * src , int order , void * opaque )
2280+ static int sev_gmem_post_populate (struct kvm * kvm , gfn_t gfn , kvm_pfn_t pfn ,
2281+ struct page * src_page , void * opaque )
22822282{
22832283 struct sev_gmem_populate_args * sev_populate_args = opaque ;
2284+ struct sev_data_snp_launch_update fw_args = {0 };
22842285 struct kvm_sev_info * sev = to_kvm_sev_info (kvm );
2285- int n_private = 0 , ret , i ;
2286- int npages = ( 1 << order ) ;
2287- gfn_t gfn ;
2286+ bool assigned = false ;
2287+ int level ;
2288+ int ret ;
22882289
2289- if (WARN_ON_ONCE (sev_populate_args -> type != KVM_SEV_SNP_PAGE_TYPE_ZERO && !src ))
2290+ if (WARN_ON_ONCE (sev_populate_args -> type != KVM_SEV_SNP_PAGE_TYPE_ZERO && !src_page ))
22902291 return - EINVAL ;
22912292
2292- for (gfn = gfn_start , i = 0 ; gfn < gfn_start + npages ; gfn ++ , i ++ ) {
2293- struct sev_data_snp_launch_update fw_args = {0 };
2294- bool assigned = false;
2295- int level ;
2296-
2297- ret = snp_lookup_rmpentry ((u64 )pfn + i , & assigned , & level );
2298- if (ret || assigned ) {
2299- pr_debug ("%s: Failed to ensure GFN 0x%llx RMP entry is initial shared state, ret: %d assigned: %d\n" ,
2300- __func__ , gfn , ret , assigned );
2301- ret = ret ? - EINVAL : - EEXIST ;
2302- goto err ;
2303- }
2304-
2305- if (src ) {
2306- void * vaddr = kmap_local_pfn (pfn + i );
2307-
2308- if (copy_from_user (vaddr , src + i * PAGE_SIZE , PAGE_SIZE )) {
2309- ret = - EFAULT ;
2310- goto err ;
2311- }
2312- kunmap_local (vaddr );
2313- }
2314-
2315- ret = rmp_make_private (pfn + i , gfn << PAGE_SHIFT , PG_LEVEL_4K ,
2316- sev_get_asid (kvm ), true);
2317- if (ret )
2318- goto err ;
2293+ ret = snp_lookup_rmpentry ((u64 )pfn , & assigned , & level );
2294+ if (ret || assigned ) {
2295+ pr_debug ("%s: Failed to ensure GFN 0x%llx RMP entry is initial shared state, ret: %d assigned: %d\n" ,
2296+ __func__ , gfn , ret , assigned );
2297+ ret = ret ? - EINVAL : - EEXIST ;
2298+ goto out ;
2299+ }
23192300
2320- n_private ++ ;
2301+ if (src_page ) {
2302+ void * src_vaddr = kmap_local_page (src_page );
2303+ void * dst_vaddr = kmap_local_pfn (pfn );
23212304
2322- fw_args .gctx_paddr = __psp_pa (sev -> snp_context );
2323- fw_args .address = __sme_set (pfn_to_hpa (pfn + i ));
2324- fw_args .page_size = PG_LEVEL_TO_RMP (PG_LEVEL_4K );
2325- fw_args .page_type = sev_populate_args -> type ;
2305+ memcpy (dst_vaddr , src_vaddr , PAGE_SIZE );
23262306
2327- ret = __sev_issue_cmd (sev_populate_args -> sev_fd , SEV_CMD_SNP_LAUNCH_UPDATE ,
2328- & fw_args , & sev_populate_args -> fw_error );
2329- if (ret )
2330- goto fw_err ;
2307+ kunmap_local (src_vaddr );
2308+ kunmap_local (dst_vaddr );
23312309 }
23322310
2333- return 0 ;
2311+ ret = rmp_make_private (pfn , gfn << PAGE_SHIFT , PG_LEVEL_4K ,
2312+ sev_get_asid (kvm ), true);
2313+ if (ret )
2314+ goto out ;
23342315
2335- fw_err :
2316+ fw_args .gctx_paddr = __psp_pa (sev -> snp_context );
2317+ fw_args .address = __sme_set (pfn_to_hpa (pfn ));
2318+ fw_args .page_size = PG_LEVEL_TO_RMP (PG_LEVEL_4K );
2319+ fw_args .page_type = sev_populate_args -> type ;
2320+
2321+ ret = __sev_issue_cmd (sev_populate_args -> sev_fd , SEV_CMD_SNP_LAUNCH_UPDATE ,
2322+ & fw_args , & sev_populate_args -> fw_error );
23362323 /*
23372324 * If the firmware command failed handle the reclaim and cleanup of that
2338- * PFN specially vs. prior pages which can be cleaned up below without
2339- * needing to reclaim in advance.
2325+ * PFN before reporting an error.
23402326 *
23412327 * Additionally, when invalid CPUID function entries are detected,
23422328 * firmware writes the expected values into the page and leaves it
@@ -2346,26 +2332,22 @@ static int sev_gmem_post_populate(struct kvm *kvm, gfn_t gfn_start, kvm_pfn_t pf
23462332 * information to provide information on which CPUID leaves/fields
23472333 * failed CPUID validation.
23482334 */
2349- if (!snp_page_reclaim (kvm , pfn + i ) &&
2335+ if (ret && !snp_page_reclaim (kvm , pfn ) &&
23502336 sev_populate_args -> type == KVM_SEV_SNP_PAGE_TYPE_CPUID &&
23512337 sev_populate_args -> fw_error == SEV_RET_INVALID_PARAM ) {
2352- void * vaddr = kmap_local_pfn (pfn + i );
2338+ void * src_vaddr = kmap_local_page (src_page );
2339+ void * dst_vaddr = kmap_local_pfn (pfn );
23532340
2354- if (copy_to_user (src + i * PAGE_SIZE , vaddr , PAGE_SIZE ))
2355- pr_debug ("Failed to write CPUID page back to userspace\n" );
2341+ memcpy (src_vaddr , dst_vaddr , PAGE_SIZE );
23562342
2357- kunmap_local (vaddr );
2343+ kunmap_local (src_vaddr );
2344+ kunmap_local (dst_vaddr );
23582345 }
23592346
2360- /* pfn + i is hypervisor-owned now, so skip below cleanup for it. */
2361- n_private -- ;
2362-
2363- err :
2364- pr_debug ("%s: exiting with error ret %d (fw_error %d), restoring %d gmem PFNs to shared.\n" ,
2365- __func__ , ret , sev_populate_args -> fw_error , n_private );
2366- for (i = 0 ; i < n_private ; i ++ )
2367- kvm_rmp_make_shared (kvm , pfn + i , PG_LEVEL_4K );
2368-
2347+ out :
2348+ if (ret )
2349+ pr_debug ("%s: error updating GFN %llx, return code %d (fw_error %d)\n" ,
2350+ __func__ , gfn , ret , sev_populate_args -> fw_error );
23692351 return ret ;
23702352}
23712353
@@ -2396,6 +2378,11 @@ static int snp_launch_update(struct kvm *kvm, struct kvm_sev_cmd *argp)
23962378 params .type != KVM_SEV_SNP_PAGE_TYPE_CPUID ))
23972379 return - EINVAL ;
23982380
2381+ src = params .type == KVM_SEV_SNP_PAGE_TYPE_ZERO ? NULL : u64_to_user_ptr (params .uaddr );
2382+
2383+ if (!PAGE_ALIGNED (src ))
2384+ return - EINVAL ;
2385+
23992386 npages = params .len / PAGE_SIZE ;
24002387
24012388 /*
@@ -2427,7 +2414,6 @@ static int snp_launch_update(struct kvm *kvm, struct kvm_sev_cmd *argp)
24272414
24282415 sev_populate_args .sev_fd = argp -> sev_fd ;
24292416 sev_populate_args .type = params .type ;
2430- src = params .type == KVM_SEV_SNP_PAGE_TYPE_ZERO ? NULL : u64_to_user_ptr (params .uaddr );
24312417
24322418 count = kvm_gmem_populate (kvm , params .gfn_start , src , npages ,
24332419 sev_gmem_post_populate , & sev_populate_args );
0 commit comments