Skip to content

Commit 8a76d7f

Browse files
joergroedelavikivity
authored andcommitted
KVM: x86: Add x86 callback for intercept check
This patch adds a callback into kvm_x86_ops so that svm and vmx code can do intercept checks on emulated instructions. Signed-off-by: Joerg Roedel <[email protected]> Signed-off-by: Avi Kivity <[email protected]>
1 parent 8ea7d6a commit 8a76d7f

File tree

6 files changed

+74
-11
lines changed

6 files changed

+74
-11
lines changed

arch/x86/include/asm/kvm_emulate.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,24 @@ struct x86_exception {
2525
u64 address; /* cr2 or nested page fault gpa */
2626
};
2727

28+
/*
29+
* This struct is used to carry enough information from the instruction
30+
* decoder to main KVM so that a decision can be made whether the
31+
* instruction needs to be intercepted or not.
32+
*/
33+
struct x86_instruction_info {
34+
u8 intercept; /* which intercept */
35+
u8 rep_prefix; /* rep prefix? */
36+
u8 modrm_mod; /* mod part of modrm */
37+
u8 modrm_reg; /* index of register used */
38+
u8 modrm_rm; /* rm part of modrm */
39+
u64 src_val; /* value of source operand */
40+
u8 src_bytes; /* size of source operand */
41+
u8 dst_bytes; /* size of destination operand */
42+
u8 ad_bytes; /* size of src/dst address */
43+
u64 next_rip; /* rip following the instruction */
44+
};
45+
2846
/*
2947
* x86_emulate_ops:
3048
*
@@ -163,8 +181,8 @@ struct x86_emulate_ops {
163181
int (*get_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata);
164182
void (*get_fpu)(struct x86_emulate_ctxt *ctxt); /* disables preempt */
165183
void (*put_fpu)(struct x86_emulate_ctxt *ctxt); /* reenables preempt */
166-
int (*intercept)(struct x86_emulate_ctxt *ctxt,
167-
enum x86_intercept intercept,
184+
int (*intercept)(struct kvm_vcpu *vcpu,
185+
struct x86_instruction_info *info,
168186
enum x86_intercept_stage stage);
169187
};
170188

arch/x86/include/asm/kvm_host.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,8 @@ struct kvm_vcpu_stat {
505505
u32 nmi_injections;
506506
};
507507

508+
struct x86_instruction_info;
509+
508510
struct kvm_x86_ops {
509511
int (*cpu_has_kvm_support)(void); /* __init */
510512
int (*disabled_by_bios)(void); /* __init */
@@ -592,6 +594,11 @@ struct kvm_x86_ops {
592594
void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
593595

594596
void (*get_exit_info)(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2);
597+
598+
int (*check_intercept)(struct kvm_vcpu *vcpu,
599+
struct x86_instruction_info *info,
600+
enum x86_intercept_stage stage);
601+
595602
const struct trace_print_flags *exit_reasons_str;
596603
};
597604

arch/x86/kvm/emulate.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,26 @@ struct gprefix {
408408
(_eip) += (_size); \
409409
})
410410

411+
static int emulator_check_intercept(struct x86_emulate_ctxt *ctxt,
412+
enum x86_intercept intercept,
413+
enum x86_intercept_stage stage)
414+
{
415+
struct x86_instruction_info info = {
416+
.intercept = intercept,
417+
.rep_prefix = ctxt->decode.rep_prefix,
418+
.modrm_mod = ctxt->decode.modrm_mod,
419+
.modrm_reg = ctxt->decode.modrm_reg,
420+
.modrm_rm = ctxt->decode.modrm_rm,
421+
.src_val = ctxt->decode.src.val64,
422+
.src_bytes = ctxt->decode.src.bytes,
423+
.dst_bytes = ctxt->decode.dst.bytes,
424+
.ad_bytes = ctxt->decode.ad_bytes,
425+
.next_rip = ctxt->eip,
426+
};
427+
428+
return ctxt->ops->intercept(ctxt->vcpu, &info, stage);
429+
}
430+
411431
static inline unsigned long ad_mask(struct decode_cache *c)
412432
{
413433
return (1UL << (c->ad_bytes << 3)) - 1;
@@ -3132,8 +3152,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
31323152
}
31333153

31343154
if (unlikely(ctxt->guest_mode) && c->intercept) {
3135-
rc = ops->intercept(ctxt, c->intercept,
3136-
X86_ICPT_PRE_EXCEPT);
3155+
rc = emulator_check_intercept(ctxt, c->intercept,
3156+
X86_ICPT_PRE_EXCEPT);
31373157
if (rc != X86EMUL_CONTINUE)
31383158
goto done;
31393159
}
@@ -3158,8 +3178,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
31583178
}
31593179

31603180
if (unlikely(ctxt->guest_mode) && c->intercept) {
3161-
rc = ops->intercept(ctxt, c->intercept,
3162-
X86_ICPT_POST_EXCEPT);
3181+
rc = emulator_check_intercept(ctxt, c->intercept,
3182+
X86_ICPT_POST_EXCEPT);
31633183
if (rc != X86EMUL_CONTINUE)
31643184
goto done;
31653185
}
@@ -3203,8 +3223,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
32033223
special_insn:
32043224

32053225
if (unlikely(ctxt->guest_mode) && c->intercept) {
3206-
rc = ops->intercept(ctxt, c->intercept,
3207-
X86_ICPT_POST_MEMACCESS);
3226+
rc = emulator_check_intercept(ctxt, c->intercept,
3227+
X86_ICPT_POST_MEMACCESS);
32083228
if (rc != X86EMUL_CONTINUE)
32093229
goto done;
32103230
}

arch/x86/kvm/svm.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3868,6 +3868,13 @@ static void svm_fpu_deactivate(struct kvm_vcpu *vcpu)
38683868
update_cr0_intercept(svm);
38693869
}
38703870

3871+
static int svm_check_intercept(struct kvm_vcpu *vcpu,
3872+
struct x86_instruction_info *info,
3873+
enum x86_intercept_stage stage)
3874+
{
3875+
return X86EMUL_CONTINUE;
3876+
}
3877+
38713878
static struct kvm_x86_ops svm_x86_ops = {
38723879
.cpu_has_kvm_support = has_svm,
38733880
.disabled_by_bios = is_disabled,
@@ -3953,6 +3960,8 @@ static struct kvm_x86_ops svm_x86_ops = {
39533960
.adjust_tsc_offset = svm_adjust_tsc_offset,
39543961

39553962
.set_tdp_cr3 = set_tdp_cr3,
3963+
3964+
.check_intercept = svm_check_intercept,
39563965
};
39573966

39583967
static int __init svm_init(void)

arch/x86/kvm/vmx.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4409,6 +4409,13 @@ static void vmx_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
44094409
{
44104410
}
44114411

4412+
static int vmx_check_intercept(struct kvm_vcpu *vcpu,
4413+
struct x86_instruction_info *info,
4414+
enum x86_intercept_stage stage)
4415+
{
4416+
return X86EMUL_CONTINUE;
4417+
}
4418+
44124419
static struct kvm_x86_ops vmx_x86_ops = {
44134420
.cpu_has_kvm_support = cpu_has_kvm_support,
44144421
.disabled_by_bios = vmx_disabled_by_bios,
@@ -4494,6 +4501,8 @@ static struct kvm_x86_ops vmx_x86_ops = {
44944501
.adjust_tsc_offset = vmx_adjust_tsc_offset,
44954502

44964503
.set_tdp_cr3 = vmx_set_cr3,
4504+
4505+
.check_intercept = vmx_check_intercept,
44974506
};
44984507

44994508
static int __init vmx_init(void)

arch/x86/kvm/x86.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4297,11 +4297,11 @@ static void emulator_put_fpu(struct x86_emulate_ctxt *ctxt)
42974297
preempt_enable();
42984298
}
42994299

4300-
static int emulator_intercept(struct x86_emulate_ctxt *ctxt,
4301-
enum x86_intercept intercept,
4300+
static int emulator_intercept(struct kvm_vcpu *vcpu,
4301+
struct x86_instruction_info *info,
43024302
enum x86_intercept_stage stage)
43034303
{
4304-
return X86EMUL_CONTINUE;
4304+
return kvm_x86_ops->check_intercept(vcpu, info, stage);
43054305
}
43064306

43074307
static struct x86_emulate_ops emulate_ops = {

0 commit comments

Comments
 (0)