3535#include <asm/irq_remapping.h>
3636#include <asm/spec-ctrl.h>
3737#include <asm/cpu_device_id.h>
38+ #include <asm/traps.h>
3839
3940#include <asm/virtext.h>
4041#include "trace.h"
@@ -339,6 +340,13 @@ static int skip_emulated_instruction(struct kvm_vcpu *vcpu)
339340{
340341 struct vcpu_svm * svm = to_svm (vcpu );
341342
343+ /*
344+ * SEV-ES does not expose the next RIP. The RIP update is controlled by
345+ * the type of exit and the #VC handler in the guest.
346+ */
347+ if (sev_es_guest (vcpu -> kvm ))
348+ goto done ;
349+
342350 if (nrips && svm -> vmcb -> control .next_rip != 0 ) {
343351 WARN_ON_ONCE (!static_cpu_has (X86_FEATURE_NRIPS ));
344352 svm -> next_rip = svm -> vmcb -> control .next_rip ;
@@ -350,6 +358,8 @@ static int skip_emulated_instruction(struct kvm_vcpu *vcpu)
350358 } else {
351359 kvm_rip_write (vcpu , svm -> next_rip );
352360 }
361+
362+ done :
353363 svm_set_interrupt_shadow (vcpu , 0 );
354364
355365 return 1 ;
@@ -1651,9 +1661,18 @@ static void svm_set_gdt(struct kvm_vcpu *vcpu, struct desc_ptr *dt)
16511661
16521662static void update_cr0_intercept (struct vcpu_svm * svm )
16531663{
1654- ulong gcr0 = svm -> vcpu .arch .cr0 ;
1655- u64 * hcr0 = & svm -> vmcb -> save .cr0 ;
1664+ ulong gcr0 ;
1665+ u64 * hcr0 ;
1666+
1667+ /*
1668+ * SEV-ES guests must always keep the CR intercepts cleared. CR
1669+ * tracking is done using the CR write traps.
1670+ */
1671+ if (sev_es_guest (svm -> vcpu .kvm ))
1672+ return ;
16561673
1674+ gcr0 = svm -> vcpu .arch .cr0 ;
1675+ hcr0 = & svm -> vmcb -> save .cr0 ;
16571676 * hcr0 = (* hcr0 & ~SVM_CR0_SELECTIVE_MASK )
16581677 | (gcr0 & SVM_CR0_SELECTIVE_MASK );
16591678
@@ -1673,7 +1692,7 @@ void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
16731692 struct vcpu_svm * svm = to_svm (vcpu );
16741693
16751694#ifdef CONFIG_X86_64
1676- if (vcpu -> arch .efer & EFER_LME ) {
1695+ if (vcpu -> arch .efer & EFER_LME && ! vcpu -> arch . guest_state_protected ) {
16771696 if (!is_paging (vcpu ) && (cr0 & X86_CR0_PG )) {
16781697 vcpu -> arch .efer |= EFER_LMA ;
16791698 svm -> vmcb -> save .efer |= EFER_LMA | EFER_LME ;
@@ -2583,6 +2602,20 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
25832602 return 0 ;
25842603}
25852604
2605+ static int svm_complete_emulated_msr (struct kvm_vcpu * vcpu , int err )
2606+ {
2607+ struct vcpu_svm * svm = to_svm (vcpu );
2608+ if (!sev_es_guest (svm -> vcpu .kvm ) || !err )
2609+ return kvm_complete_insn_gp (& svm -> vcpu , err );
2610+
2611+ ghcb_set_sw_exit_info_1 (svm -> ghcb , 1 );
2612+ ghcb_set_sw_exit_info_2 (svm -> ghcb ,
2613+ X86_TRAP_GP |
2614+ SVM_EVTINJ_TYPE_EXEPT |
2615+ SVM_EVTINJ_VALID );
2616+ return 1 ;
2617+ }
2618+
25862619static int rdmsr_interception (struct vcpu_svm * svm )
25872620{
25882621 return kvm_emulate_rdmsr (& svm -> vcpu );
@@ -2801,7 +2834,14 @@ static int interrupt_window_interception(struct vcpu_svm *svm)
28012834static int pause_interception (struct vcpu_svm * svm )
28022835{
28032836 struct kvm_vcpu * vcpu = & svm -> vcpu ;
2804- bool in_kernel = (svm_get_cpl (vcpu ) == 0 );
2837+ bool in_kernel ;
2838+
2839+ /*
2840+ * CPL is not made available for an SEV-ES guest, therefore
2841+ * vcpu->arch.preempted_in_kernel can never be true. Just
2842+ * set in_kernel to false as well.
2843+ */
2844+ in_kernel = !sev_es_guest (svm -> vcpu .kvm ) && svm_get_cpl (vcpu ) == 0 ;
28052845
28062846 if (!kvm_pause_in_guest (vcpu -> kvm ))
28072847 grow_ple_window (vcpu );
@@ -3064,10 +3104,13 @@ static int handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
30643104
30653105 trace_kvm_exit (exit_code , vcpu , KVM_ISA_SVM );
30663106
3067- if (!svm_is_intercept (svm , INTERCEPT_CR0_WRITE ))
3068- vcpu -> arch .cr0 = svm -> vmcb -> save .cr0 ;
3069- if (npt_enabled )
3070- vcpu -> arch .cr3 = svm -> vmcb -> save .cr3 ;
3107+ /* SEV-ES guests must use the CR write traps to track CR registers. */
3108+ if (!sev_es_guest (vcpu -> kvm )) {
3109+ if (!svm_is_intercept (svm , INTERCEPT_CR0_WRITE ))
3110+ vcpu -> arch .cr0 = svm -> vmcb -> save .cr0 ;
3111+ if (npt_enabled )
3112+ vcpu -> arch .cr3 = svm -> vmcb -> save .cr3 ;
3113+ }
30713114
30723115 if (is_guest_mode (vcpu )) {
30733116 int vmexit ;
@@ -3179,6 +3222,13 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
31793222{
31803223 struct vcpu_svm * svm = to_svm (vcpu );
31813224
3225+ /*
3226+ * SEV-ES guests must always keep the CR intercepts cleared. CR
3227+ * tracking is done using the CR write traps.
3228+ */
3229+ if (sev_es_guest (vcpu -> kvm ))
3230+ return ;
3231+
31823232 if (nested_svm_virtualize_tpr (vcpu ))
31833233 return ;
31843234
@@ -3250,7 +3300,14 @@ bool svm_interrupt_blocked(struct kvm_vcpu *vcpu)
32503300 if (!gif_set (svm ))
32513301 return true;
32523302
3253- if (is_guest_mode (vcpu )) {
3303+ if (sev_es_guest (svm -> vcpu .kvm )) {
3304+ /*
3305+ * SEV-ES guests to not expose RFLAGS. Use the VMCB interrupt mask
3306+ * bit to determine the state of the IF flag.
3307+ */
3308+ if (!(vmcb -> control .int_state & SVM_GUEST_INTERRUPT_MASK ))
3309+ return true;
3310+ } else if (is_guest_mode (vcpu )) {
32543311 /* As long as interrupts are being delivered... */
32553312 if ((svm -> nested .ctl .int_ctl & V_INTR_MASKING_MASK )
32563313 ? !(svm -> nested .hsave -> save .rflags & X86_EFLAGS_IF )
@@ -3432,6 +3489,12 @@ static void svm_complete_interrupts(struct vcpu_svm *svm)
34323489 svm -> vcpu .arch .nmi_injected = true;
34333490 break ;
34343491 case SVM_EXITINTINFO_TYPE_EXEPT :
3492+ /*
3493+ * Never re-inject a #VC exception.
3494+ */
3495+ if (vector == X86_TRAP_VC )
3496+ break ;
3497+
34353498 /*
34363499 * In case of software exceptions, do not reinject the vector,
34373500 * but re-execute the instruction instead. Rewind RIP first
@@ -4306,7 +4369,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
43064369 .apic_init_signal_blocked = svm_apic_init_signal_blocked ,
43074370
43084371 .msr_filter_changed = svm_msr_filter_changed ,
4309- .complete_emulated_msr = kvm_complete_insn_gp ,
4372+ .complete_emulated_msr = svm_complete_emulated_msr ,
43104373};
43114374
43124375static struct kvm_x86_init_ops svm_init_ops __initdata = {
0 commit comments