Skip to content

Commit be47941

Browse files
committed
Merge tag 'kvm-x86-svm-6.7' of https://github.com/kvm-x86/linux into HEAD
KVM SVM changes for 6.7: - Report KVM_EXIT_SHUTDOWN instead of EINVAL if KVM intercepts SHUTDOWN while running an SEV-ES guest. - Clean up handling "failures" when KVM detects it can't emulate the "skip" action for an instruction that has already been partially emulated. Drop a hack in the SVM code that was fudging around the emulator code not giving SVM enough information to do the right thing.
2 parents d5cde2e + 0068299 commit be47941

File tree

5 files changed

+45
-45
lines changed

5 files changed

+45
-45
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ KVM_X86_OP_OPTIONAL(vm_copy_enc_context_from)
127127
KVM_X86_OP_OPTIONAL(vm_move_enc_context_from)
128128
KVM_X86_OP_OPTIONAL(guest_memory_reclaimed)
129129
KVM_X86_OP(get_msr_feature)
130-
KVM_X86_OP(can_emulate_instruction)
130+
KVM_X86_OP(check_emulate_instruction)
131131
KVM_X86_OP(apic_init_signal_blocked)
132132
KVM_X86_OP_OPTIONAL(enable_l2_tlb_flush)
133133
KVM_X86_OP_OPTIONAL(migrate_timers)

arch/x86/include/asm/kvm_host.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,8 +1745,8 @@ struct kvm_x86_ops {
17451745

17461746
int (*get_msr_feature)(struct kvm_msr_entry *entry);
17471747

1748-
bool (*can_emulate_instruction)(struct kvm_vcpu *vcpu, int emul_type,
1749-
void *insn, int insn_len);
1748+
int (*check_emulate_instruction)(struct kvm_vcpu *vcpu, int emul_type,
1749+
void *insn, int insn_len);
17501750

17511751
bool (*apic_init_signal_blocked)(struct kvm_vcpu *vcpu);
17521752
int (*enable_l2_tlb_flush)(struct kvm_vcpu *vcpu);

arch/x86/kvm/svm/svm.c

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -364,8 +364,6 @@ static void svm_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask)
364364
svm->vmcb->control.int_state |= SVM_INTERRUPT_SHADOW_MASK;
365365

366366
}
367-
static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
368-
void *insn, int insn_len);
369367

370368
static int __svm_skip_emulated_instruction(struct kvm_vcpu *vcpu,
371369
bool commit_side_effects)
@@ -386,14 +384,6 @@ static int __svm_skip_emulated_instruction(struct kvm_vcpu *vcpu,
386384
}
387385

388386
if (!svm->next_rip) {
389-
/*
390-
* FIXME: Drop this when kvm_emulate_instruction() does the
391-
* right thing and treats "can't emulate" as outright failure
392-
* for EMULTYPE_SKIP.
393-
*/
394-
if (!svm_can_emulate_instruction(vcpu, EMULTYPE_SKIP, NULL, 0))
395-
return 0;
396-
397387
if (unlikely(!commit_side_effects))
398388
old_rflags = svm->vmcb->save.rflags;
399389

@@ -2202,12 +2192,6 @@ static int shutdown_interception(struct kvm_vcpu *vcpu)
22022192
struct kvm_run *kvm_run = vcpu->run;
22032193
struct vcpu_svm *svm = to_svm(vcpu);
22042194

2205-
/*
2206-
* The VM save area has already been encrypted so it
2207-
* cannot be reinitialized - just terminate.
2208-
*/
2209-
if (sev_es_guest(vcpu->kvm))
2210-
return -EINVAL;
22112195

22122196
/*
22132197
* VMCB is undefined after a SHUTDOWN intercept. INIT the vCPU to put
@@ -2216,9 +2200,14 @@ static int shutdown_interception(struct kvm_vcpu *vcpu)
22162200
* userspace. At a platform view, INIT is acceptable behavior as
22172201
* there exist bare metal platforms that automatically INIT the CPU
22182202
* in response to shutdown.
2203+
*
2204+
* The VM save area for SEV-ES guests has already been encrypted so it
2205+
* cannot be reinitialized, i.e. synthesizing INIT is futile.
22192206
*/
2220-
clear_page(svm->vmcb);
2221-
kvm_vcpu_reset(vcpu, true);
2207+
if (!sev_es_guest(vcpu->kvm)) {
2208+
clear_page(svm->vmcb);
2209+
kvm_vcpu_reset(vcpu, true);
2210+
}
22222211

22232212
kvm_run->exit_reason = KVM_EXIT_SHUTDOWN;
22242213
return 0;
@@ -4727,15 +4716,15 @@ static void svm_enable_smi_window(struct kvm_vcpu *vcpu)
47274716
}
47284717
#endif
47294718

4730-
static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
4731-
void *insn, int insn_len)
4719+
static int svm_check_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
4720+
void *insn, int insn_len)
47324721
{
47334722
bool smep, smap, is_user;
47344723
u64 error_code;
47354724

47364725
/* Emulation is always possible when KVM has access to all guest state. */
47374726
if (!sev_guest(vcpu->kvm))
4738-
return true;
4727+
return X86EMUL_CONTINUE;
47394728

47404729
/* #UD and #GP should never be intercepted for SEV guests. */
47414730
WARN_ON_ONCE(emul_type & (EMULTYPE_TRAP_UD |
@@ -4747,14 +4736,14 @@ static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
47474736
* to guest register state.
47484737
*/
47494738
if (sev_es_guest(vcpu->kvm))
4750-
return false;
4739+
return X86EMUL_RETRY_INSTR;
47514740

47524741
/*
47534742
* Emulation is possible if the instruction is already decoded, e.g.
47544743
* when completing I/O after returning from userspace.
47554744
*/
47564745
if (emul_type & EMULTYPE_NO_DECODE)
4757-
return true;
4746+
return X86EMUL_CONTINUE;
47584747

47594748
/*
47604749
* Emulation is possible for SEV guests if and only if a prefilled
@@ -4780,9 +4769,11 @@ static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
47804769
* success (and in practice it will work the vast majority of the time).
47814770
*/
47824771
if (unlikely(!insn)) {
4783-
if (!(emul_type & EMULTYPE_SKIP))
4784-
kvm_queue_exception(vcpu, UD_VECTOR);
4785-
return false;
4772+
if (emul_type & EMULTYPE_SKIP)
4773+
return X86EMUL_UNHANDLEABLE;
4774+
4775+
kvm_queue_exception(vcpu, UD_VECTOR);
4776+
return X86EMUL_PROPAGATE_FAULT;
47864777
}
47874778

47884779
/*
@@ -4793,7 +4784,7 @@ static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
47934784
* table used to translate CS:RIP resides in emulated MMIO.
47944785
*/
47954786
if (likely(insn_len))
4796-
return true;
4787+
return X86EMUL_CONTINUE;
47974788

47984789
/*
47994790
* Detect and workaround Errata 1096 Fam_17h_00_0Fh.
@@ -4851,6 +4842,7 @@ static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
48514842
kvm_inject_gp(vcpu, 0);
48524843
else
48534844
kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
4845+
return X86EMUL_PROPAGATE_FAULT;
48544846
}
48554847

48564848
resume_guest:
@@ -4868,7 +4860,7 @@ static bool svm_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
48684860
* doesn't explicitly define "ignored", i.e. doing nothing and letting
48694861
* the guest spin is technically "ignoring" the access.
48704862
*/
4871-
return false;
4863+
return X86EMUL_RETRY_INSTR;
48724864
}
48734865

48744866
static bool svm_apic_init_signal_blocked(struct kvm_vcpu *vcpu)
@@ -5028,7 +5020,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
50285020
.vm_copy_enc_context_from = sev_vm_copy_enc_context_from,
50295021
.vm_move_enc_context_from = sev_vm_move_enc_context_from,
50305022

5031-
.can_emulate_instruction = svm_can_emulate_instruction,
5023+
.check_emulate_instruction = svm_check_emulate_instruction,
50325024

50335025
.apic_init_signal_blocked = svm_apic_init_signal_blocked,
50345026

arch/x86/kvm/vmx/vmx.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1657,8 +1657,8 @@ static int vmx_rtit_ctl_check(struct kvm_vcpu *vcpu, u64 data)
16571657
return 0;
16581658
}
16591659

1660-
static bool vmx_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
1661-
void *insn, int insn_len)
1660+
static int vmx_check_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
1661+
void *insn, int insn_len)
16621662
{
16631663
/*
16641664
* Emulation of instructions in SGX enclaves is impossible as RIP does
@@ -1669,9 +1669,9 @@ static bool vmx_can_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
16691669
*/
16701670
if (to_vmx(vcpu)->exit_reason.enclave_mode) {
16711671
kvm_queue_exception(vcpu, UD_VECTOR);
1672-
return false;
1672+
return X86EMUL_PROPAGATE_FAULT;
16731673
}
1674-
return true;
1674+
return X86EMUL_CONTINUE;
16751675
}
16761676

16771677
static int skip_emulated_instruction(struct kvm_vcpu *vcpu)
@@ -5792,7 +5792,7 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
57925792
{
57935793
gpa_t gpa;
57945794

5795-
if (!vmx_can_emulate_instruction(vcpu, EMULTYPE_PF, NULL, 0))
5795+
if (vmx_check_emulate_instruction(vcpu, EMULTYPE_PF, NULL, 0))
57965796
return 1;
57975797

57985798
/*
@@ -8338,7 +8338,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
83388338
.enable_smi_window = vmx_enable_smi_window,
83398339
#endif
83408340

8341-
.can_emulate_instruction = vmx_can_emulate_instruction,
8341+
.check_emulate_instruction = vmx_check_emulate_instruction,
83428342
.apic_init_signal_blocked = vmx_apic_init_signal_blocked,
83438343
.migrate_timers = vmx_migrate_timers,
83448344

arch/x86/kvm/x86.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7596,11 +7596,11 @@ int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu, gva_t addr, void *val,
75967596
}
75977597
EXPORT_SYMBOL_GPL(kvm_write_guest_virt_system);
75987598

7599-
static int kvm_can_emulate_insn(struct kvm_vcpu *vcpu, int emul_type,
7600-
void *insn, int insn_len)
7599+
static int kvm_check_emulate_insn(struct kvm_vcpu *vcpu, int emul_type,
7600+
void *insn, int insn_len)
76017601
{
7602-
return static_call(kvm_x86_can_emulate_instruction)(vcpu, emul_type,
7603-
insn, insn_len);
7602+
return static_call(kvm_x86_check_emulate_instruction)(vcpu, emul_type,
7603+
insn, insn_len);
76047604
}
76057605

76067606
int handle_ud(struct kvm_vcpu *vcpu)
@@ -7610,8 +7610,10 @@ int handle_ud(struct kvm_vcpu *vcpu)
76107610
int emul_type = EMULTYPE_TRAP_UD;
76117611
char sig[5]; /* ud2; .ascii "kvm" */
76127612
struct x86_exception e;
7613+
int r;
76137614

7614-
if (unlikely(!kvm_can_emulate_insn(vcpu, emul_type, NULL, 0)))
7615+
r = kvm_check_emulate_insn(vcpu, emul_type, NULL, 0);
7616+
if (r != X86EMUL_CONTINUE)
76157617
return 1;
76167618

76177619
if (fep_flags &&
@@ -8993,8 +8995,14 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
89938995
struct x86_emulate_ctxt *ctxt = vcpu->arch.emulate_ctxt;
89948996
bool writeback = true;
89958997

8996-
if (unlikely(!kvm_can_emulate_insn(vcpu, emulation_type, insn, insn_len)))
8997-
return 1;
8998+
r = kvm_check_emulate_insn(vcpu, emulation_type, insn, insn_len);
8999+
if (r != X86EMUL_CONTINUE) {
9000+
if (r == X86EMUL_RETRY_INSTR || r == X86EMUL_PROPAGATE_FAULT)
9001+
return 1;
9002+
9003+
WARN_ON_ONCE(r != X86EMUL_UNHANDLEABLE);
9004+
return handle_emulation_failure(vcpu, emulation_type);
9005+
}
89989006

89999007
vcpu->arch.l1tf_flush_l1d = true;
90009008

0 commit comments

Comments
 (0)