@@ -262,6 +262,21 @@ static void sev_decommission(unsigned int handle)
262
262
sev_guest_decommission (& decommission , NULL );
263
263
}
264
264
265
+ /*
266
+ * Transition a page to hypervisor-owned/shared state in the RMP table. This
267
+ * should not fail under normal conditions, but leak the page should that
268
+ * happen since it will no longer be usable by the host due to RMP protections.
269
+ */
270
+ static int kvm_rmp_make_shared (struct kvm * kvm , u64 pfn , enum pg_level level )
271
+ {
272
+ if (KVM_BUG_ON (rmp_make_shared (pfn , level ), kvm )) {
273
+ snp_leak_pages (pfn , page_level_size (level ) >> PAGE_SHIFT );
274
+ return - EIO ;
275
+ }
276
+
277
+ return 0 ;
278
+ }
279
+
265
280
/*
266
281
* Certain page-states, such as Pre-Guest and Firmware pages (as documented
267
282
* in Chapter 5 of the SEV-SNP Firmware ABI under "Page States") cannot be
@@ -271,32 +286,25 @@ static void sev_decommission(unsigned int handle)
271
286
* Until they are reclaimed and subsequently transitioned via RMPUPDATE, they
272
287
* might not be usable by the host due to being set as immutable or still
273
288
* being associated with a guest ASID.
289
+ *
290
+ * Bug the VM and leak the page if reclaim fails, or if the RMP entry can't be
291
+ * converted back to shared, as the page is no longer usable due to RMP
292
+ * protections, and it's infeasible for the guest to continue on.
274
293
*/
275
- static int snp_page_reclaim (u64 pfn )
294
+ static int snp_page_reclaim (struct kvm * kvm , u64 pfn )
276
295
{
277
296
struct sev_data_snp_page_reclaim data = {0 };
278
- int err , rc ;
297
+ int fw_err , rc ;
279
298
280
299
data .paddr = __sme_set (pfn << PAGE_SHIFT );
281
- rc = sev_do_cmd (SEV_CMD_SNP_PAGE_RECLAIM , & data , & err );
282
- if (WARN_ONCE (rc , "Failed to reclaim PFN %llx" , pfn ))
300
+ rc = sev_do_cmd (SEV_CMD_SNP_PAGE_RECLAIM , & data , & fw_err );
301
+ if (KVM_BUG (rc , kvm , "Failed to reclaim PFN %llx, rc %d fw_err %d " , pfn , rc , fw_err )) {
283
302
snp_leak_pages (pfn , 1 );
303
+ return - EIO ;
304
+ }
284
305
285
- return rc ;
286
- }
287
-
288
- /*
289
- * Transition a page to hypervisor-owned/shared state in the RMP table. This
290
- * should not fail under normal conditions, but leak the page should that
291
- * happen since it will no longer be usable by the host due to RMP protections.
292
- */
293
- static int host_rmp_make_shared (u64 pfn , enum pg_level level )
294
- {
295
- int rc ;
296
-
297
- rc = rmp_make_shared (pfn , level );
298
- if (WARN_ON_ONCE (rc ))
299
- snp_leak_pages (pfn , page_level_size (level ) >> PAGE_SHIFT );
306
+ if (kvm_rmp_make_shared (kvm , pfn , PG_LEVEL_4K ))
307
+ return - EIO ;
300
308
301
309
return rc ;
302
310
}
@@ -2244,7 +2252,7 @@ static int sev_gmem_post_populate(struct kvm *kvm, gfn_t gfn_start, kvm_pfn_t pf
2244
2252
* information to provide information on which CPUID leaves/fields
2245
2253
* failed CPUID validation.
2246
2254
*/
2247
- if (!snp_page_reclaim (pfn + i ) && ! host_rmp_make_shared ( pfn + i , PG_LEVEL_4K ) &&
2255
+ if (!snp_page_reclaim (kvm , pfn + i ) &&
2248
2256
sev_populate_args -> type == KVM_SEV_SNP_PAGE_TYPE_CPUID &&
2249
2257
sev_populate_args -> fw_error == SEV_RET_INVALID_PARAM ) {
2250
2258
void * vaddr = kmap_local_pfn (pfn + i );
@@ -2262,7 +2270,7 @@ static int sev_gmem_post_populate(struct kvm *kvm, gfn_t gfn_start, kvm_pfn_t pf
2262
2270
pr_debug ("%s: exiting with error ret %d (fw_error %d), restoring %d gmem PFNs to shared.\n" ,
2263
2271
__func__ , ret , sev_populate_args -> fw_error , n_private );
2264
2272
for (i = 0 ; i < n_private ; i ++ )
2265
- host_rmp_make_shared ( pfn + i , PG_LEVEL_4K );
2273
+ kvm_rmp_make_shared ( kvm , pfn + i , PG_LEVEL_4K );
2266
2274
2267
2275
return ret ;
2268
2276
}
@@ -2380,8 +2388,7 @@ static int snp_launch_update_vmsa(struct kvm *kvm, struct kvm_sev_cmd *argp)
2380
2388
ret = __sev_issue_cmd (argp -> sev_fd , SEV_CMD_SNP_LAUNCH_UPDATE ,
2381
2389
& data , & argp -> error );
2382
2390
if (ret ) {
2383
- if (!snp_page_reclaim (pfn ))
2384
- host_rmp_make_shared (pfn , PG_LEVEL_4K );
2391
+ snp_page_reclaim (kvm , pfn );
2385
2392
2386
2393
return ret ;
2387
2394
}
@@ -3069,7 +3076,7 @@ void sev_free_vcpu(struct kvm_vcpu *vcpu)
3069
3076
if (sev_snp_guest (vcpu -> kvm )) {
3070
3077
u64 pfn = __pa (svm -> sev_es .vmsa ) >> PAGE_SHIFT ;
3071
3078
3072
- if (host_rmp_make_shared ( pfn , PG_LEVEL_4K ))
3079
+ if (kvm_rmp_make_shared ( vcpu -> kvm , pfn , PG_LEVEL_4K ))
3073
3080
goto skip_vmsa_free ;
3074
3081
}
3075
3082
0 commit comments