Skip to content

Commit c506355

Browse files
marc-orrbonzini
authored andcommitted
KVM: x86: Always set kvm_run->if_flag
The kvm_run struct's if_flag is a part of the userspace/kernel API. The SEV-ES patches failed to set this flag because it's no longer needed by QEMU (according to the comment in the source code). However, other hypervisors may make use of this flag. Therefore, set the flag for guests with encrypted registers (i.e., with guest_state_protected set). Fixes: f1c6366 ("KVM: SVM: Add required changes to support intercepts under SEV-ES") Signed-off-by: Marc Orr <[email protected]> Message-Id: <[email protected]> Cc: [email protected] Signed-off-by: Paolo Bonzini <[email protected]> Reviewed-by: Maxim Levitsky <[email protected]>
1 parent 3a0f64d commit c506355

File tree

5 files changed

+21
-17
lines changed

5 files changed

+21
-17
lines changed

arch/x86/include/asm/kvm-x86-ops.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ KVM_X86_OP(set_dr7)
4747
KVM_X86_OP(cache_reg)
4848
KVM_X86_OP(get_rflags)
4949
KVM_X86_OP(set_rflags)
50+
KVM_X86_OP(get_if_flag)
5051
KVM_X86_OP(tlb_flush_all)
5152
KVM_X86_OP(tlb_flush_current)
5253
KVM_X86_OP_NULL(tlb_remote_flush)

arch/x86/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1349,6 +1349,7 @@ struct kvm_x86_ops {
13491349
void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg);
13501350
unsigned long (*get_rflags)(struct kvm_vcpu *vcpu);
13511351
void (*set_rflags)(struct kvm_vcpu *vcpu, unsigned long rflags);
1352+
bool (*get_if_flag)(struct kvm_vcpu *vcpu);
13521353

13531354
void (*tlb_flush_all)(struct kvm_vcpu *vcpu);
13541355
void (*tlb_flush_current)(struct kvm_vcpu *vcpu);

arch/x86/kvm/svm/svm.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,6 +1585,15 @@ static void svm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
15851585
to_svm(vcpu)->vmcb->save.rflags = rflags;
15861586
}
15871587

1588+
static bool svm_get_if_flag(struct kvm_vcpu *vcpu)
1589+
{
1590+
struct vmcb *vmcb = to_svm(vcpu)->vmcb;
1591+
1592+
return sev_es_guest(vcpu->kvm)
1593+
? vmcb->control.int_state & SVM_GUEST_INTERRUPT_MASK
1594+
: kvm_get_rflags(vcpu) & X86_EFLAGS_IF;
1595+
}
1596+
15881597
static void svm_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
15891598
{
15901599
switch (reg) {
@@ -3568,14 +3577,7 @@ bool svm_interrupt_blocked(struct kvm_vcpu *vcpu)
35683577
if (!gif_set(svm))
35693578
return true;
35703579

3571-
if (sev_es_guest(vcpu->kvm)) {
3572-
/*
3573-
* SEV-ES guests to not expose RFLAGS. Use the VMCB interrupt mask
3574-
* bit to determine the state of the IF flag.
3575-
*/
3576-
if (!(vmcb->control.int_state & SVM_GUEST_INTERRUPT_MASK))
3577-
return true;
3578-
} else if (is_guest_mode(vcpu)) {
3580+
if (is_guest_mode(vcpu)) {
35793581
/* As long as interrupts are being delivered... */
35803582
if ((svm->nested.ctl.int_ctl & V_INTR_MASKING_MASK)
35813583
? !(svm->vmcb01.ptr->save.rflags & X86_EFLAGS_IF)
@@ -3586,7 +3588,7 @@ bool svm_interrupt_blocked(struct kvm_vcpu *vcpu)
35863588
if (nested_exit_on_intr(svm))
35873589
return false;
35883590
} else {
3589-
if (!(kvm_get_rflags(vcpu) & X86_EFLAGS_IF))
3591+
if (!svm_get_if_flag(vcpu))
35903592
return true;
35913593
}
35923594

@@ -4621,6 +4623,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
46214623
.cache_reg = svm_cache_reg,
46224624
.get_rflags = svm_get_rflags,
46234625
.set_rflags = svm_set_rflags,
4626+
.get_if_flag = svm_get_if_flag,
46244627

46254628
.tlb_flush_all = svm_flush_tlb,
46264629
.tlb_flush_current = svm_flush_tlb,

arch/x86/kvm/vmx/vmx.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,6 +1363,11 @@ void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
13631363
vmx->emulation_required = vmx_emulation_required(vcpu);
13641364
}
13651365

1366+
static bool vmx_get_if_flag(struct kvm_vcpu *vcpu)
1367+
{
1368+
return vmx_get_rflags(vcpu) & X86_EFLAGS_IF;
1369+
}
1370+
13661371
u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu)
13671372
{
13681373
u32 interruptibility = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO);
@@ -7579,6 +7584,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
75797584
.cache_reg = vmx_cache_reg,
75807585
.get_rflags = vmx_get_rflags,
75817586
.set_rflags = vmx_set_rflags,
7587+
.get_if_flag = vmx_get_if_flag,
75827588

75837589
.tlb_flush_all = vmx_flush_tlb_all,
75847590
.tlb_flush_current = vmx_flush_tlb_current,

arch/x86/kvm/x86.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9001,14 +9001,7 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu)
90019001
{
90029002
struct kvm_run *kvm_run = vcpu->run;
90039003

9004-
/*
9005-
* if_flag is obsolete and useless, so do not bother
9006-
* setting it for SEV-ES guests. Userspace can just
9007-
* use kvm_run->ready_for_interrupt_injection.
9008-
*/
9009-
kvm_run->if_flag = !vcpu->arch.guest_state_protected
9010-
&& (kvm_get_rflags(vcpu) & X86_EFLAGS_IF) != 0;
9011-
9004+
kvm_run->if_flag = static_call(kvm_x86_get_if_flag)(vcpu);
90129005
kvm_run->cr8 = kvm_get_cr8(vcpu);
90139006
kvm_run->apic_base = kvm_get_apic_base(vcpu);
90149007

0 commit comments

Comments
 (0)