2323#include <asm/pkru.h>
2424#include <asm/trapnr.h>
2525#include <asm/fpu/xcr.h>
26+ #include <asm/debugreg.h>
2627
2728#include "mmu.h"
2829#include "x86.h"
@@ -54,9 +55,14 @@ module_param_named(sev, sev_enabled, bool, 0444);
5455/* enable/disable SEV-ES support */
5556static bool sev_es_enabled = true;
5657module_param_named (sev_es , sev_es_enabled , bool , 0444 );
58+
59+ /* enable/disable SEV-ES DebugSwap support */
60+ static bool sev_es_debug_swap_enabled = true;
61+ module_param_named (debug_swap , sev_es_debug_swap_enabled , bool , 0444 );
5762#else
5863#define sev_enabled false
5964#define sev_es_enabled false
65+ #define sev_es_debug_swap_enabled false
6066#endif /* CONFIG_KVM_AMD_SEV */
6167
6268static u8 sev_enc_bit ;
@@ -606,6 +612,9 @@ static int sev_es_sync_vmsa(struct vcpu_svm *svm)
606612 save -> xss = svm -> vcpu .arch .ia32_xss ;
607613 save -> dr6 = svm -> vcpu .arch .dr6 ;
608614
615+ if (sev_es_debug_swap_enabled )
616+ save -> sev_features |= SVM_SEV_FEAT_DEBUG_SWAP ;
617+
609618 pr_debug ("Virtual Machine Save Area (VMSA):\n" );
610619 print_hex_dump_debug ("" , DUMP_PREFIX_NONE , 16 , 1 , save , sizeof (* save ), false);
611620
@@ -619,6 +628,11 @@ static int __sev_launch_update_vmsa(struct kvm *kvm, struct kvm_vcpu *vcpu,
619628 struct vcpu_svm * svm = to_svm (vcpu );
620629 int ret ;
621630
631+ if (vcpu -> guest_debug ) {
632+ pr_warn_once ("KVM_SET_GUEST_DEBUG for SEV-ES guest is not supported" );
633+ return - EINVAL ;
634+ }
635+
622636 /* Perform some pre-encryption checks against the VMSA */
623637 ret = sev_es_sync_vmsa (svm );
624638 if (ret )
@@ -1725,7 +1739,7 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
17251739 * Note, the source is not required to have the same number of
17261740 * vCPUs as the destination when migrating a vanilla SEV VM.
17271741 */
1728- src_vcpu = kvm_get_vcpu (dst_kvm , i );
1742+ src_vcpu = kvm_get_vcpu (src_kvm , i );
17291743 src_svm = to_svm (src_vcpu );
17301744
17311745 /*
@@ -2171,7 +2185,7 @@ void __init sev_hardware_setup(void)
21712185 bool sev_es_supported = false;
21722186 bool sev_supported = false;
21732187
2174- if (!sev_enabled || !npt_enabled )
2188+ if (!sev_enabled || !npt_enabled || ! nrips )
21752189 goto out ;
21762190
21772191 /*
@@ -2256,6 +2270,9 @@ void __init sev_hardware_setup(void)
22562270
22572271 sev_enabled = sev_supported ;
22582272 sev_es_enabled = sev_es_supported ;
2273+ if (!sev_es_enabled || !cpu_feature_enabled (X86_FEATURE_DEBUG_SWAP ) ||
2274+ !cpu_feature_enabled (X86_FEATURE_NO_NESTED_DATA_BP ))
2275+ sev_es_debug_swap_enabled = false;
22592276#endif
22602277}
22612278
@@ -2881,7 +2898,10 @@ int sev_handle_vmgexit(struct kvm_vcpu *vcpu)
28812898 svm -> sev_es .ghcb_sa );
28822899 break ;
28832900 case SVM_VMGEXIT_NMI_COMPLETE :
2884- ret = svm_invoke_exit_handler (vcpu , SVM_EXIT_IRET );
2901+ ++ vcpu -> stat .nmi_window_exits ;
2902+ svm -> nmi_masked = false;
2903+ kvm_make_request (KVM_REQ_EVENT , vcpu );
2904+ ret = 1 ;
28852905 break ;
28862906 case SVM_VMGEXIT_AP_HLT_LOOP :
28872907 ret = kvm_emulate_ap_reset_hold (vcpu );
@@ -2944,6 +2964,7 @@ int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in)
29442964
29452965static void sev_es_init_vmcb (struct vcpu_svm * svm )
29462966{
2967+ struct vmcb * vmcb = svm -> vmcb01 .ptr ;
29472968 struct kvm_vcpu * vcpu = & svm -> vcpu ;
29482969
29492970 svm -> vmcb -> control .nested_ctl |= SVM_NESTED_CTL_SEV_ES_ENABLE ;
@@ -2952,9 +2973,12 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm)
29522973 /*
29532974 * An SEV-ES guest requires a VMSA area that is a separate from the
29542975 * VMCB page. Do not include the encryption mask on the VMSA physical
2955- * address since hardware will access it using the guest key.
2976+ * address since hardware will access it using the guest key. Note,
2977+ * the VMSA will be NULL if this vCPU is the destination for intrahost
2978+ * migration, and will be copied later.
29562979 */
2957- svm -> vmcb -> control .vmsa_pa = __pa (svm -> sev_es .vmsa );
2980+ if (svm -> sev_es .vmsa )
2981+ svm -> vmcb -> control .vmsa_pa = __pa (svm -> sev_es .vmsa );
29582982
29592983 /* Can't intercept CR register access, HV can't modify CR registers */
29602984 svm_clr_intercept (svm , INTERCEPT_CR0_READ );
@@ -2972,8 +2996,23 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm)
29722996 svm_set_intercept (svm , TRAP_CR4_WRITE );
29732997 svm_set_intercept (svm , TRAP_CR8_WRITE );
29742998
2975- /* No support for enable_vmware_backdoor */
2976- clr_exception_intercept (svm , GP_VECTOR );
2999+ vmcb -> control .intercepts [INTERCEPT_DR ] = 0 ;
3000+ if (!sev_es_debug_swap_enabled ) {
3001+ vmcb_set_intercept (& vmcb -> control , INTERCEPT_DR7_READ );
3002+ vmcb_set_intercept (& vmcb -> control , INTERCEPT_DR7_WRITE );
3003+ recalc_intercepts (svm );
3004+ } else {
3005+ /*
3006+ * Disable #DB intercept iff DebugSwap is enabled. KVM doesn't
3007+ * allow debugging SEV-ES guests, and enables DebugSwap iff
3008+ * NO_NESTED_DATA_BP is supported, so there's no reason to
3009+ * intercept #DB when DebugSwap is enabled. For simplicity
3010+ * with respect to guest debug, intercept #DB for other VMs
3011+ * even if NO_NESTED_DATA_BP is supported, i.e. even if the
3012+ * guest can't DoS the CPU with infinite #DB vectoring.
3013+ */
3014+ clr_exception_intercept (svm , DB_VECTOR );
3015+ }
29773016
29783017 /* Can't intercept XSETBV, HV can't modify XCR0 directly */
29793018 svm_clr_intercept (svm , INTERCEPT_XSETBV );
@@ -3000,6 +3039,12 @@ void sev_init_vmcb(struct vcpu_svm *svm)
30003039 svm -> vmcb -> control .nested_ctl |= SVM_NESTED_CTL_SEV_ENABLE ;
30013040 clr_exception_intercept (svm , UD_VECTOR );
30023041
3042+ /*
3043+ * Don't intercept #GP for SEV guests, e.g. for the VMware backdoor, as
3044+ * KVM can't decrypt guest memory to decode the faulting instruction.
3045+ */
3046+ clr_exception_intercept (svm , GP_VECTOR );
3047+
30033048 if (sev_es_guest (svm -> vcpu .kvm ))
30043049 sev_es_init_vmcb (svm );
30053050}
@@ -3018,20 +3063,41 @@ void sev_es_vcpu_reset(struct vcpu_svm *svm)
30183063void sev_es_prepare_switch_to_guest (struct sev_es_save_area * hostsa )
30193064{
30203065 /*
3021- * As an SEV-ES guest, hardware will restore the host state on VMEXIT,
3022- * of which one step is to perform a VMLOAD. KVM performs the
3023- * corresponding VMSAVE in svm_prepare_guest_switch for both
3024- * traditional and SEV-ES guests.
3066+ * All host state for SEV-ES guests is categorized into three swap types
3067+ * based on how it is handled by hardware during a world switch:
3068+ *
3069+ * A: VMRUN: Host state saved in host save area
3070+ * VMEXIT: Host state loaded from host save area
3071+ *
3072+ * B: VMRUN: Host state _NOT_ saved in host save area
3073+ * VMEXIT: Host state loaded from host save area
3074+ *
3075+ * C: VMRUN: Host state _NOT_ saved in host save area
3076+ * VMEXIT: Host state initialized to default(reset) values
3077+ *
3078+ * Manually save type-B state, i.e. state that is loaded by VMEXIT but
3079+ * isn't saved by VMRUN, that isn't already saved by VMSAVE (performed
3080+ * by common SVM code).
30253081 */
3026-
3027- /* XCR0 is restored on VMEXIT, save the current host value */
30283082 hostsa -> xcr0 = xgetbv (XCR_XFEATURE_ENABLED_MASK );
3029-
3030- /* PKRU is restored on VMEXIT, save the current host value */
30313083 hostsa -> pkru = read_pkru ();
3032-
3033- /* MSR_IA32_XSS is restored on VMEXIT, save the currnet host value */
30343084 hostsa -> xss = host_xss ;
3085+
3086+ /*
3087+ * If DebugSwap is enabled, debug registers are loaded but NOT saved by
3088+ * the CPU (Type-B). If DebugSwap is disabled/unsupported, the CPU both
3089+ * saves and loads debug registers (Type-A).
3090+ */
3091+ if (sev_es_debug_swap_enabled ) {
3092+ hostsa -> dr0 = native_get_debugreg (0 );
3093+ hostsa -> dr1 = native_get_debugreg (1 );
3094+ hostsa -> dr2 = native_get_debugreg (2 );
3095+ hostsa -> dr3 = native_get_debugreg (3 );
3096+ hostsa -> dr0_addr_mask = amd_get_dr_addr_mask (0 );
3097+ hostsa -> dr1_addr_mask = amd_get_dr_addr_mask (1 );
3098+ hostsa -> dr2_addr_mask = amd_get_dr_addr_mask (2 );
3099+ hostsa -> dr3_addr_mask = amd_get_dr_addr_mask (3 );
3100+ }
30353101}
30363102
30373103void sev_vcpu_deliver_sipi_vector (struct kvm_vcpu * vcpu , u8 vector )
0 commit comments