3333#include "cpuid.h"
3434#include "trace.h"
3535
36- #define GHCB_VERSION_MAX 1ULL
36+ #define GHCB_VERSION_MAX 2ULL
37+ #define GHCB_VERSION_DEFAULT 2ULL
3738#define GHCB_VERSION_MIN 1ULL
3839
40+ #define GHCB_HV_FT_SUPPORTED GHCB_HV_FT_SNP
41+
3942/* enable/disable SEV support */
4043static bool sev_enabled = true;
4144module_param_named (sev , sev_enabled , bool , 0444 );
@@ -49,6 +52,10 @@ static bool sev_es_debug_swap_enabled = true;
4952module_param_named (debug_swap , sev_es_debug_swap_enabled , bool , 0444 );
5053static u64 sev_supported_vmsa_features ;
5154
55+ #define AP_RESET_HOLD_NONE 0
56+ #define AP_RESET_HOLD_NAE_EVENT 1
57+ #define AP_RESET_HOLD_MSR_PROTO 2
58+
5259static u8 sev_enc_bit ;
5360static DECLARE_RWSEM (sev_deactivate_lock );
5461static DEFINE_MUTEX (sev_bitmap_lock );
@@ -262,12 +269,24 @@ static int __sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp,
262269 if (data -> vmsa_features & ~valid_vmsa_features )
263270 return - EINVAL ;
264271
272+ if (data -> ghcb_version > GHCB_VERSION_MAX || (!es_active && data -> ghcb_version ))
273+ return - EINVAL ;
274+
265275 if (unlikely (sev -> active ))
266276 return - EINVAL ;
267277
268278 sev -> active = true;
269279 sev -> es_active = es_active ;
270280 sev -> vmsa_features = data -> vmsa_features ;
281+ sev -> ghcb_version = data -> ghcb_version ;
282+
283+ /*
284+ * Currently KVM supports the full range of mandatory features defined
285+ * by version 2 of the GHCB protocol, so default to that for SEV-ES
286+ * guests created via KVM_SEV_INIT2.
287+ */
288+ if (sev -> es_active && !sev -> ghcb_version )
289+ sev -> ghcb_version = GHCB_VERSION_DEFAULT ;
271290
272291 ret = sev_asid_new (sev );
273292 if (ret )
@@ -301,13 +320,22 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
301320{
302321 struct kvm_sev_init data = {
303322 .vmsa_features = 0 ,
323+ .ghcb_version = 0 ,
304324 };
305325 unsigned long vm_type ;
306326
307327 if (kvm -> arch .vm_type != KVM_X86_DEFAULT_VM )
308328 return - EINVAL ;
309329
310330 vm_type = (argp -> id == KVM_SEV_INIT ? KVM_X86_SEV_VM : KVM_X86_SEV_ES_VM );
331+
332+ /*
333+ * KVM_SEV_ES_INIT has been deprecated by KVM_SEV_INIT2, so it will
334+ * continue to only ever support the minimal GHCB protocol version.
335+ */
336+ if (vm_type == KVM_X86_SEV_ES_VM )
337+ data .ghcb_version = GHCB_VERSION_MIN ;
338+
311339 return __sev_guest_init (kvm , argp , & data , vm_type );
312340}
313341
@@ -2697,6 +2725,8 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
26972725 case SVM_VMGEXIT_AP_HLT_LOOP :
26982726 case SVM_VMGEXIT_AP_JUMP_TABLE :
26992727 case SVM_VMGEXIT_UNSUPPORTED_EVENT :
2728+ case SVM_VMGEXIT_HV_FEATURES :
2729+ case SVM_VMGEXIT_TERM_REQUEST :
27002730 break ;
27012731 default :
27022732 reason = GHCB_ERR_INVALID_EVENT ;
@@ -2727,6 +2757,9 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm)
27272757
27282758void sev_es_unmap_ghcb (struct vcpu_svm * svm )
27292759{
2760+ /* Clear any indication that the vCPU is in a type of AP Reset Hold */
2761+ svm -> sev_es .ap_reset_hold_type = AP_RESET_HOLD_NONE ;
2762+
27302763 if (!svm -> sev_es .ghcb )
27312764 return ;
27322765
@@ -2886,6 +2919,7 @@ static int sev_handle_vmgexit_msr_protocol(struct vcpu_svm *svm)
28862919{
28872920 struct vmcb_control_area * control = & svm -> vmcb -> control ;
28882921 struct kvm_vcpu * vcpu = & svm -> vcpu ;
2922+ struct kvm_sev_info * sev = & to_kvm_svm (vcpu -> kvm )-> sev_info ;
28892923 u64 ghcb_info ;
28902924 int ret = 1 ;
28912925
@@ -2896,7 +2930,7 @@ static int sev_handle_vmgexit_msr_protocol(struct vcpu_svm *svm)
28962930
28972931 switch (ghcb_info ) {
28982932 case GHCB_MSR_SEV_INFO_REQ :
2899- set_ghcb_msr (svm , GHCB_MSR_SEV_INFO (GHCB_VERSION_MAX ,
2933+ set_ghcb_msr (svm , GHCB_MSR_SEV_INFO (( __u64 ) sev -> ghcb_version ,
29002934 GHCB_VERSION_MIN ,
29012935 sev_enc_bit ));
29022936 break ;
@@ -2938,6 +2972,28 @@ static int sev_handle_vmgexit_msr_protocol(struct vcpu_svm *svm)
29382972 GHCB_MSR_INFO_POS );
29392973 break ;
29402974 }
2975+ case GHCB_MSR_AP_RESET_HOLD_REQ :
2976+ svm -> sev_es .ap_reset_hold_type = AP_RESET_HOLD_MSR_PROTO ;
2977+ ret = kvm_emulate_ap_reset_hold (& svm -> vcpu );
2978+
2979+ /*
2980+ * Preset the result to a non-SIPI return and then only set
2981+ * the result to non-zero when delivering a SIPI.
2982+ */
2983+ set_ghcb_msr_bits (svm , 0 ,
2984+ GHCB_MSR_AP_RESET_HOLD_RESULT_MASK ,
2985+ GHCB_MSR_AP_RESET_HOLD_RESULT_POS );
2986+
2987+ set_ghcb_msr_bits (svm , GHCB_MSR_AP_RESET_HOLD_RESP ,
2988+ GHCB_MSR_INFO_MASK ,
2989+ GHCB_MSR_INFO_POS );
2990+ break ;
2991+ case GHCB_MSR_HV_FT_REQ :
2992+ set_ghcb_msr_bits (svm , GHCB_HV_FT_SUPPORTED ,
2993+ GHCB_MSR_HV_FT_MASK , GHCB_MSR_HV_FT_POS );
2994+ set_ghcb_msr_bits (svm , GHCB_MSR_HV_FT_RESP ,
2995+ GHCB_MSR_INFO_MASK , GHCB_MSR_INFO_POS );
2996+ break ;
29412997 case GHCB_MSR_TERM_REQ : {
29422998 u64 reason_set , reason_code ;
29432999
@@ -3037,6 +3093,7 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
30373093 ret = 1 ;
30383094 break ;
30393095 case SVM_VMGEXIT_AP_HLT_LOOP :
3096+ svm -> sev_es .ap_reset_hold_type = AP_RESET_HOLD_NAE_EVENT ;
30403097 ret = kvm_emulate_ap_reset_hold (vcpu );
30413098 break ;
30423099 case SVM_VMGEXIT_AP_JUMP_TABLE : {
@@ -3061,6 +3118,19 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
30613118 ret = 1 ;
30623119 break ;
30633120 }
3121+ case SVM_VMGEXIT_HV_FEATURES :
3122+ ghcb_set_sw_exit_info_2 (svm -> sev_es .ghcb , GHCB_HV_FT_SUPPORTED );
3123+
3124+ ret = 1 ;
3125+ break ;
3126+ case SVM_VMGEXIT_TERM_REQUEST :
3127+ pr_info ("SEV-ES guest requested termination: reason %#llx info %#llx\n" ,
3128+ control -> exit_info_1 , control -> exit_info_2 );
3129+ vcpu -> run -> exit_reason = KVM_EXIT_SYSTEM_EVENT ;
3130+ vcpu -> run -> system_event .type = KVM_SYSTEM_EVENT_SEV_TERM ;
3131+ vcpu -> run -> system_event .ndata = 1 ;
3132+ vcpu -> run -> system_event .data [0 ] = control -> ghcb_gpa ;
3133+ break ;
30643134 case SVM_VMGEXIT_UNSUPPORTED_EVENT :
30653135 vcpu_unimpl (vcpu ,
30663136 "vmgexit: unsupported event - exit_info_1=%#llx, exit_info_2=%#llx\n" ,
@@ -3221,11 +3291,14 @@ void sev_init_vmcb(struct vcpu_svm *svm)
32213291
32223292void sev_es_vcpu_reset (struct vcpu_svm * svm )
32233293{
3294+ struct kvm_vcpu * vcpu = & svm -> vcpu ;
3295+ struct kvm_sev_info * sev = & to_kvm_svm (vcpu -> kvm )-> sev_info ;
3296+
32243297 /*
32253298 * Set the GHCB MSR value as per the GHCB specification when emulating
32263299 * vCPU RESET for an SEV-ES guest.
32273300 */
3228- set_ghcb_msr (svm , GHCB_MSR_SEV_INFO (GHCB_VERSION_MAX ,
3301+ set_ghcb_msr (svm , GHCB_MSR_SEV_INFO (( __u64 ) sev -> ghcb_version ,
32293302 GHCB_VERSION_MIN ,
32303303 sev_enc_bit ));
32313304}
@@ -3280,15 +3353,31 @@ void sev_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector)
32803353 return ;
32813354 }
32823355
3283- /*
3284- * Subsequent SIPI: Return from an AP Reset Hold VMGEXIT, where
3285- * the guest will set the CS and RIP. Set SW_EXIT_INFO_2 to a
3286- * non-zero value.
3287- */
3288- if (!svm -> sev_es .ghcb )
3289- return ;
3356+ /* Subsequent SIPI */
3357+ switch (svm -> sev_es .ap_reset_hold_type ) {
3358+ case AP_RESET_HOLD_NAE_EVENT :
3359+ /*
3360+ * Return from an AP Reset Hold VMGEXIT, where the guest will
3361+ * set the CS and RIP. Set SW_EXIT_INFO_2 to a non-zero value.
3362+ */
3363+ ghcb_set_sw_exit_info_2 (svm -> sev_es .ghcb , 1 );
3364+ break ;
3365+ case AP_RESET_HOLD_MSR_PROTO :
3366+ /*
3367+ * Return from an AP Reset Hold VMGEXIT, where the guest will
3368+ * set the CS and RIP. Set GHCB data field to a non-zero value.
3369+ */
3370+ set_ghcb_msr_bits (svm , 1 ,
3371+ GHCB_MSR_AP_RESET_HOLD_RESULT_MASK ,
3372+ GHCB_MSR_AP_RESET_HOLD_RESULT_POS );
32903373
3291- ghcb_set_sw_exit_info_2 (svm -> sev_es .ghcb , 1 );
3374+ set_ghcb_msr_bits (svm , GHCB_MSR_AP_RESET_HOLD_RESP ,
3375+ GHCB_MSR_INFO_MASK ,
3376+ GHCB_MSR_INFO_POS );
3377+ break ;
3378+ default :
3379+ break ;
3380+ }
32923381}
32933382
32943383struct page * snp_safe_alloc_page (struct kvm_vcpu * vcpu )
0 commit comments