@@ -259,6 +259,45 @@ static void sev_decommission(unsigned int handle)
259259 sev_guest_decommission (& decommission , NULL );
260260}
261261
262+ /*
263+ * Certain page-states, such as Pre-Guest and Firmware pages (as documented
264+ * in Chapter 5 of the SEV-SNP Firmware ABI under "Page States") cannot be
265+ * directly transitioned back to normal/hypervisor-owned state via RMPUPDATE
266+ * unless they are reclaimed first.
267+ *
268+ * Until they are reclaimed and subsequently transitioned via RMPUPDATE, they
269+ * might not be usable by the host due to being set as immutable or still
270+ * being associated with a guest ASID.
271+ */
272+ static int snp_page_reclaim (u64 pfn )
273+ {
274+ struct sev_data_snp_page_reclaim data = {0 };
275+ int err , rc ;
276+
277+ data .paddr = __sme_set (pfn << PAGE_SHIFT );
278+ rc = sev_do_cmd (SEV_CMD_SNP_PAGE_RECLAIM , & data , & err );
279+ if (WARN_ONCE (rc , "Failed to reclaim PFN %llx" , pfn ))
280+ snp_leak_pages (pfn , 1 );
281+
282+ return rc ;
283+ }
284+
285+ /*
286+ * Transition a page to hypervisor-owned/shared state in the RMP table. This
287+ * should not fail under normal conditions, but leak the page should that
288+ * happen since it will no longer be usable by the host due to RMP protections.
289+ */
290+ static int host_rmp_make_shared (u64 pfn , enum pg_level level )
291+ {
292+ int rc ;
293+
294+ rc = rmp_make_shared (pfn , level );
295+ if (WARN_ON_ONCE (rc ))
296+ snp_leak_pages (pfn , page_level_size (level ) >> PAGE_SHIFT );
297+
298+ return rc ;
299+ }
300+
262301static void sev_unbind_asid (struct kvm * kvm , unsigned int handle )
263302{
264303 struct sev_data_deactivate deactivate ;
@@ -2121,6 +2160,194 @@ static int snp_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp)
21212160 return rc ;
21222161}
21232162
2163+ struct sev_gmem_populate_args {
2164+ __u8 type ;
2165+ int sev_fd ;
2166+ int fw_error ;
2167+ };
2168+
2169+ static int sev_gmem_post_populate (struct kvm * kvm , gfn_t gfn_start , kvm_pfn_t pfn ,
2170+ void __user * src , int order , void * opaque )
2171+ {
2172+ struct sev_gmem_populate_args * sev_populate_args = opaque ;
2173+ struct kvm_sev_info * sev = & to_kvm_svm (kvm )-> sev_info ;
2174+ int n_private = 0 , ret , i ;
2175+ int npages = (1 << order );
2176+ gfn_t gfn ;
2177+
2178+ if (WARN_ON_ONCE (sev_populate_args -> type != KVM_SEV_SNP_PAGE_TYPE_ZERO && !src ))
2179+ return - EINVAL ;
2180+
2181+ for (gfn = gfn_start , i = 0 ; gfn < gfn_start + npages ; gfn ++ , i ++ ) {
2182+ struct sev_data_snp_launch_update fw_args = {0 };
2183+ bool assigned ;
2184+ int level ;
2185+
2186+ if (!kvm_mem_is_private (kvm , gfn )) {
2187+ pr_debug ("%s: Failed to ensure GFN 0x%llx has private memory attribute set\n" ,
2188+ __func__ , gfn );
2189+ ret = - EINVAL ;
2190+ goto err ;
2191+ }
2192+
2193+ ret = snp_lookup_rmpentry ((u64 )pfn + i , & assigned , & level );
2194+ if (ret || assigned ) {
2195+ pr_debug ("%s: Failed to ensure GFN 0x%llx RMP entry is initial shared state, ret: %d assigned: %d\n" ,
2196+ __func__ , gfn , ret , assigned );
2197+ ret = - EINVAL ;
2198+ goto err ;
2199+ }
2200+
2201+ if (src ) {
2202+ void * vaddr = kmap_local_pfn (pfn + i );
2203+
2204+ ret = copy_from_user (vaddr , src + i * PAGE_SIZE , PAGE_SIZE );
2205+ if (ret )
2206+ goto err ;
2207+ kunmap_local (vaddr );
2208+ }
2209+
2210+ ret = rmp_make_private (pfn + i , gfn << PAGE_SHIFT , PG_LEVEL_4K ,
2211+ sev_get_asid (kvm ), true);
2212+ if (ret )
2213+ goto err ;
2214+
2215+ n_private ++ ;
2216+
2217+ fw_args .gctx_paddr = __psp_pa (sev -> snp_context );
2218+ fw_args .address = __sme_set (pfn_to_hpa (pfn + i ));
2219+ fw_args .page_size = PG_LEVEL_TO_RMP (PG_LEVEL_4K );
2220+ fw_args .page_type = sev_populate_args -> type ;
2221+
2222+ ret = __sev_issue_cmd (sev_populate_args -> sev_fd , SEV_CMD_SNP_LAUNCH_UPDATE ,
2223+ & fw_args , & sev_populate_args -> fw_error );
2224+ if (ret )
2225+ goto fw_err ;
2226+ }
2227+
2228+ return 0 ;
2229+
2230+ fw_err :
2231+ /*
2232+ * If the firmware command failed handle the reclaim and cleanup of that
2233+ * PFN specially vs. prior pages which can be cleaned up below without
2234+ * needing to reclaim in advance.
2235+ *
2236+ * Additionally, when invalid CPUID function entries are detected,
2237+ * firmware writes the expected values into the page and leaves it
2238+ * unencrypted so it can be used for debugging and error-reporting.
2239+ *
2240+ * Copy this page back into the source buffer so userspace can use this
2241+ * information to provide information on which CPUID leaves/fields
2242+ * failed CPUID validation.
2243+ */
2244+ if (!snp_page_reclaim (pfn + i ) && !host_rmp_make_shared (pfn + i , PG_LEVEL_4K ) &&
2245+ sev_populate_args -> type == KVM_SEV_SNP_PAGE_TYPE_CPUID &&
2246+ sev_populate_args -> fw_error == SEV_RET_INVALID_PARAM ) {
2247+ void * vaddr = kmap_local_pfn (pfn + i );
2248+
2249+ if (copy_to_user (src + i * PAGE_SIZE , vaddr , PAGE_SIZE ))
2250+ pr_debug ("Failed to write CPUID page back to userspace\n" );
2251+
2252+ kunmap_local (vaddr );
2253+ }
2254+
2255+ /* pfn + i is hypervisor-owned now, so skip below cleanup for it. */
2256+ n_private -- ;
2257+
2258+ err :
2259+ pr_debug ("%s: exiting with error ret %d (fw_error %d), restoring %d gmem PFNs to shared.\n" ,
2260+ __func__ , ret , sev_populate_args -> fw_error , n_private );
2261+ for (i = 0 ; i < n_private ; i ++ )
2262+ host_rmp_make_shared (pfn + i , PG_LEVEL_4K );
2263+
2264+ return ret ;
2265+ }
2266+
2267+ static int snp_launch_update (struct kvm * kvm , struct kvm_sev_cmd * argp )
2268+ {
2269+ struct kvm_sev_info * sev = & to_kvm_svm (kvm )-> sev_info ;
2270+ struct sev_gmem_populate_args sev_populate_args = {0 };
2271+ struct kvm_sev_snp_launch_update params ;
2272+ struct kvm_memory_slot * memslot ;
2273+ long npages , count ;
2274+ void __user * src ;
2275+ int ret = 0 ;
2276+
2277+ if (!sev_snp_guest (kvm ) || !sev -> snp_context )
2278+ return - EINVAL ;
2279+
2280+ if (copy_from_user (& params , u64_to_user_ptr (argp -> data ), sizeof (params )))
2281+ return - EFAULT ;
2282+
2283+ pr_debug ("%s: GFN start 0x%llx length 0x%llx type %d flags %d\n" , __func__ ,
2284+ params .gfn_start , params .len , params .type , params .flags );
2285+
2286+ if (!PAGE_ALIGNED (params .len ) || params .flags ||
2287+ (params .type != KVM_SEV_SNP_PAGE_TYPE_NORMAL &&
2288+ params .type != KVM_SEV_SNP_PAGE_TYPE_ZERO &&
2289+ params .type != KVM_SEV_SNP_PAGE_TYPE_UNMEASURED &&
2290+ params .type != KVM_SEV_SNP_PAGE_TYPE_SECRETS &&
2291+ params .type != KVM_SEV_SNP_PAGE_TYPE_CPUID ))
2292+ return - EINVAL ;
2293+
2294+ npages = params .len / PAGE_SIZE ;
2295+
2296+ /*
2297+ * For each GFN that's being prepared as part of the initial guest
2298+ * state, the following pre-conditions are verified:
2299+ *
2300+ * 1) The backing memslot is a valid private memslot.
2301+ * 2) The GFN has been set to private via KVM_SET_MEMORY_ATTRIBUTES
2302+ * beforehand.
2303+ * 3) The PFN of the guest_memfd has not already been set to private
2304+ * in the RMP table.
2305+ *
2306+ * The KVM MMU relies on kvm->mmu_invalidate_seq to retry nested page
2307+ * faults if there's a race between a fault and an attribute update via
2308+ * KVM_SET_MEMORY_ATTRIBUTES, and a similar approach could be utilized
2309+ * here. However, kvm->slots_lock guards against both this as well as
2310+ * concurrent memslot updates occurring while these checks are being
2311+ * performed, so use that here to make it easier to reason about the
2312+ * initial expected state and better guard against unexpected
2313+ * situations.
2314+ */
2315+ mutex_lock (& kvm -> slots_lock );
2316+
2317+ memslot = gfn_to_memslot (kvm , params .gfn_start );
2318+ if (!kvm_slot_can_be_private (memslot )) {
2319+ ret = - EINVAL ;
2320+ goto out ;
2321+ }
2322+
2323+ sev_populate_args .sev_fd = argp -> sev_fd ;
2324+ sev_populate_args .type = params .type ;
2325+ src = params .type == KVM_SEV_SNP_PAGE_TYPE_ZERO ? NULL : u64_to_user_ptr (params .uaddr );
2326+
2327+ count = kvm_gmem_populate (kvm , params .gfn_start , src , npages ,
2328+ sev_gmem_post_populate , & sev_populate_args );
2329+ if (count < 0 ) {
2330+ argp -> error = sev_populate_args .fw_error ;
2331+ pr_debug ("%s: kvm_gmem_populate failed, ret %ld (fw_error %d)\n" ,
2332+ __func__ , count , argp -> error );
2333+ ret = - EIO ;
2334+ } else {
2335+ params .gfn_start += count ;
2336+ params .len -= count * PAGE_SIZE ;
2337+ if (params .type != KVM_SEV_SNP_PAGE_TYPE_ZERO )
2338+ params .uaddr += count * PAGE_SIZE ;
2339+
2340+ ret = 0 ;
2341+ if (copy_to_user (u64_to_user_ptr (argp -> data ), & params , sizeof (params )))
2342+ ret = - EFAULT ;
2343+ }
2344+
2345+ out :
2346+ mutex_unlock (& kvm -> slots_lock );
2347+
2348+ return ret ;
2349+ }
2350+
21242351int sev_mem_enc_ioctl (struct kvm * kvm , void __user * argp )
21252352{
21262353 struct kvm_sev_cmd sev_cmd ;
@@ -2220,6 +2447,9 @@ int sev_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
22202447 case KVM_SEV_SNP_LAUNCH_START :
22212448 r = snp_launch_start (kvm , & sev_cmd );
22222449 break ;
2450+ case KVM_SEV_SNP_LAUNCH_UPDATE :
2451+ r = snp_launch_update (kvm , & sev_cmd );
2452+ break ;
22232453 default :
22242454 r = - EINVAL ;
22252455 goto out ;
0 commit comments