2525#include <asm/fpu/xcr.h>
2626#include <asm/fpu/xstate.h>
2727#include <asm/debugreg.h>
28+ #include <asm/sev.h>
2829
2930#include "mmu.h"
3031#include "x86.h"
@@ -59,6 +60,21 @@ static u64 sev_supported_vmsa_features;
5960#define AP_RESET_HOLD_NAE_EVENT 1
6061#define AP_RESET_HOLD_MSR_PROTO 2
6162
63+ /* As defined by SEV-SNP Firmware ABI, under "Guest Policy". */
64+ #define SNP_POLICY_MASK_API_MINOR GENMASK_ULL(7, 0)
65+ #define SNP_POLICY_MASK_API_MAJOR GENMASK_ULL(15, 8)
66+ #define SNP_POLICY_MASK_SMT BIT_ULL(16)
67+ #define SNP_POLICY_MASK_RSVD_MBO BIT_ULL(17)
68+ #define SNP_POLICY_MASK_DEBUG BIT_ULL(19)
69+ #define SNP_POLICY_MASK_SINGLE_SOCKET BIT_ULL(20)
70+
71+ #define SNP_POLICY_MASK_VALID (SNP_POLICY_MASK_API_MINOR | \
72+ SNP_POLICY_MASK_API_MAJOR | \
73+ SNP_POLICY_MASK_SMT | \
74+ SNP_POLICY_MASK_RSVD_MBO | \
75+ SNP_POLICY_MASK_DEBUG | \
76+ SNP_POLICY_MASK_SINGLE_SOCKET)
77+
6278static u8 sev_enc_bit ;
6379static DECLARE_RWSEM (sev_deactivate_lock );
6480static DEFINE_MUTEX (sev_bitmap_lock );
@@ -69,6 +85,8 @@ static unsigned int nr_asids;
6985static unsigned long * sev_asid_bitmap ;
7086static unsigned long * sev_reclaim_asid_bitmap ;
7187
88+ static int snp_decommission_context (struct kvm * kvm );
89+
7290struct enc_region {
7391 struct list_head list ;
7492 unsigned long npages ;
@@ -95,12 +113,17 @@ static int sev_flush_asids(unsigned int min_asid, unsigned int max_asid)
95113 down_write (& sev_deactivate_lock );
96114
97115 wbinvd_on_all_cpus ();
98- ret = sev_guest_df_flush (& error );
116+
117+ if (sev_snp_enabled )
118+ ret = sev_do_cmd (SEV_CMD_SNP_DF_FLUSH , NULL , & error );
119+ else
120+ ret = sev_guest_df_flush (& error );
99121
100122 up_write (& sev_deactivate_lock );
101123
102124 if (ret )
103- pr_err ("SEV: DF_FLUSH failed, ret=%d, error=%#x\n" , ret , error );
125+ pr_err ("SEV%s: DF_FLUSH failed, ret=%d, error=%#x\n" ,
126+ sev_snp_enabled ? "-SNP" : "" , ret , error );
104127
105128 return ret ;
106129}
@@ -1998,6 +2021,106 @@ int sev_dev_get_attr(u32 group, u64 attr, u64 *val)
19982021 }
19992022}
20002023
2024+ /*
2025+ * The guest context contains all the information, keys and metadata
2026+ * associated with the guest that the firmware tracks to implement SEV
2027+ * and SNP features. The firmware stores the guest context in hypervisor
2028+ * provide page via the SNP_GCTX_CREATE command.
2029+ */
2030+ static void * snp_context_create (struct kvm * kvm , struct kvm_sev_cmd * argp )
2031+ {
2032+ struct sev_data_snp_addr data = {};
2033+ void * context ;
2034+ int rc ;
2035+
2036+ /* Allocate memory for context page */
2037+ context = snp_alloc_firmware_page (GFP_KERNEL_ACCOUNT );
2038+ if (!context )
2039+ return NULL ;
2040+
2041+ data .address = __psp_pa (context );
2042+ rc = __sev_issue_cmd (argp -> sev_fd , SEV_CMD_SNP_GCTX_CREATE , & data , & argp -> error );
2043+ if (rc ) {
2044+ pr_warn ("Failed to create SEV-SNP context, rc %d fw_error %d" ,
2045+ rc , argp -> error );
2046+ snp_free_firmware_page (context );
2047+ return NULL ;
2048+ }
2049+
2050+ return context ;
2051+ }
2052+
2053+ static int snp_bind_asid (struct kvm * kvm , int * error )
2054+ {
2055+ struct kvm_sev_info * sev = & to_kvm_svm (kvm )-> sev_info ;
2056+ struct sev_data_snp_activate data = {0 };
2057+
2058+ data .gctx_paddr = __psp_pa (sev -> snp_context );
2059+ data .asid = sev_get_asid (kvm );
2060+ return sev_issue_cmd (kvm , SEV_CMD_SNP_ACTIVATE , & data , error );
2061+ }
2062+
2063+ static int snp_launch_start (struct kvm * kvm , struct kvm_sev_cmd * argp )
2064+ {
2065+ struct kvm_sev_info * sev = & to_kvm_svm (kvm )-> sev_info ;
2066+ struct sev_data_snp_launch_start start = {0 };
2067+ struct kvm_sev_snp_launch_start params ;
2068+ int rc ;
2069+
2070+ if (!sev_snp_guest (kvm ))
2071+ return - ENOTTY ;
2072+
2073+ if (copy_from_user (& params , u64_to_user_ptr (argp -> data ), sizeof (params )))
2074+ return - EFAULT ;
2075+
2076+ /* Don't allow userspace to allocate memory for more than 1 SNP context. */
2077+ if (sev -> snp_context )
2078+ return - EINVAL ;
2079+
2080+ sev -> snp_context = snp_context_create (kvm , argp );
2081+ if (!sev -> snp_context )
2082+ return - ENOTTY ;
2083+
2084+ if (params .flags )
2085+ return - EINVAL ;
2086+
2087+ if (params .policy & ~SNP_POLICY_MASK_VALID )
2088+ return - EINVAL ;
2089+
2090+ /* Check for policy bits that must be set */
2091+ if (!(params .policy & SNP_POLICY_MASK_RSVD_MBO ) ||
2092+ !(params .policy & SNP_POLICY_MASK_SMT ))
2093+ return - EINVAL ;
2094+
2095+ if (params .policy & SNP_POLICY_MASK_SINGLE_SOCKET )
2096+ return - EINVAL ;
2097+
2098+ start .gctx_paddr = __psp_pa (sev -> snp_context );
2099+ start .policy = params .policy ;
2100+ memcpy (start .gosvw , params .gosvw , sizeof (params .gosvw ));
2101+ rc = __sev_issue_cmd (argp -> sev_fd , SEV_CMD_SNP_LAUNCH_START , & start , & argp -> error );
2102+ if (rc ) {
2103+ pr_debug ("%s: SEV_CMD_SNP_LAUNCH_START firmware command failed, rc %d\n" ,
2104+ __func__ , rc );
2105+ goto e_free_context ;
2106+ }
2107+
2108+ sev -> fd = argp -> sev_fd ;
2109+ rc = snp_bind_asid (kvm , & argp -> error );
2110+ if (rc ) {
2111+ pr_debug ("%s: Failed to bind ASID to SEV-SNP context, rc %d\n" ,
2112+ __func__ , rc );
2113+ goto e_free_context ;
2114+ }
2115+
2116+ return 0 ;
2117+
2118+ e_free_context :
2119+ snp_decommission_context (kvm );
2120+
2121+ return rc ;
2122+ }
2123+
20012124int sev_mem_enc_ioctl (struct kvm * kvm , void __user * argp )
20022125{
20032126 struct kvm_sev_cmd sev_cmd ;
@@ -2021,6 +2144,15 @@ int sev_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
20212144 goto out ;
20222145 }
20232146
2147+ /*
2148+ * Once KVM_SEV_INIT2 initializes a KVM instance as an SNP guest, only
2149+ * allow the use of SNP-specific commands.
2150+ */
2151+ if (sev_snp_guest (kvm ) && sev_cmd .id < KVM_SEV_SNP_LAUNCH_START ) {
2152+ r = - EPERM ;
2153+ goto out ;
2154+ }
2155+
20242156 switch (sev_cmd .id ) {
20252157 case KVM_SEV_ES_INIT :
20262158 if (!sev_es_enabled ) {
@@ -2085,6 +2217,9 @@ int sev_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
20852217 case KVM_SEV_RECEIVE_FINISH :
20862218 r = sev_receive_finish (kvm , & sev_cmd );
20872219 break ;
2220+ case KVM_SEV_SNP_LAUNCH_START :
2221+ r = snp_launch_start (kvm , & sev_cmd );
2222+ break ;
20882223 default :
20892224 r = - EINVAL ;
20902225 goto out ;
@@ -2280,6 +2415,31 @@ int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
22802415 return ret ;
22812416}
22822417
2418+ static int snp_decommission_context (struct kvm * kvm )
2419+ {
2420+ struct kvm_sev_info * sev = & to_kvm_svm (kvm )-> sev_info ;
2421+ struct sev_data_snp_addr data = {};
2422+ int ret ;
2423+
2424+ /* If context is not created then do nothing */
2425+ if (!sev -> snp_context )
2426+ return 0 ;
2427+
2428+ /* Do the decommision, which will unbind the ASID from the SNP context */
2429+ data .address = __sme_pa (sev -> snp_context );
2430+ down_write (& sev_deactivate_lock );
2431+ ret = sev_do_cmd (SEV_CMD_SNP_DECOMMISSION , & data , NULL );
2432+ up_write (& sev_deactivate_lock );
2433+
2434+ if (WARN_ONCE (ret , "Failed to release guest context, ret %d" , ret ))
2435+ return ret ;
2436+
2437+ snp_free_firmware_page (sev -> snp_context );
2438+ sev -> snp_context = NULL ;
2439+
2440+ return 0 ;
2441+ }
2442+
22832443void sev_vm_destroy (struct kvm * kvm )
22842444{
22852445 struct kvm_sev_info * sev = & to_kvm_svm (kvm )-> sev_info ;
@@ -2321,7 +2481,17 @@ void sev_vm_destroy(struct kvm *kvm)
23212481 }
23222482 }
23232483
2324- sev_unbind_asid (kvm , sev -> handle );
2484+ if (sev_snp_guest (kvm )) {
2485+ /*
2486+ * Decomission handles unbinding of the ASID. If it fails for
2487+ * some unexpected reason, just leak the ASID.
2488+ */
2489+ if (snp_decommission_context (kvm ))
2490+ return ;
2491+ } else {
2492+ sev_unbind_asid (kvm , sev -> handle );
2493+ }
2494+
23252495 sev_asid_free (sev );
23262496}
23272497
0 commit comments