aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2011-04-04 06:39:27 -0400
committerAvi Kivity <avi@redhat.com>2011-05-11 07:57:01 -0400
commit8a76d7f25f8f24fc5a328c8e15e4a7313cf141b9 (patch)
tree7adadd7663b006d75563c457c6b7c5f91a4d16d2
parent8ea7d6aef84e278fcb121acff1bd4c3edaa95b8b (diff)
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 <joerg.roedel@amd.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--arch/x86/include/asm/kvm_emulate.h22
-rw-r--r--arch/x86/include/asm/kvm_host.h7
-rw-r--r--arch/x86/kvm/emulate.c32
-rw-r--r--arch/x86/kvm/svm.c9
-rw-r--r--arch/x86/kvm/vmx.c9
-rw-r--r--arch/x86/kvm/x86.c6
6 files changed, 74 insertions, 11 deletions
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index cab841a034f9..eb7033cefe8e 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -26,6 +26,24 @@ struct x86_exception {
26}; 26};
27 27
28/* 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 */
33struct 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
46/*
29 * x86_emulate_ops: 47 * x86_emulate_ops:
30 * 48 *
31 * These operations represent the instruction emulator's interface to memory. 49 * These operations represent the instruction emulator's interface to memory.
@@ -163,8 +181,8 @@ struct x86_emulate_ops {
163 int (*get_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata); 181 int (*get_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata);
164 void (*get_fpu)(struct x86_emulate_ctxt *ctxt); /* disables preempt */ 182 void (*get_fpu)(struct x86_emulate_ctxt *ctxt); /* disables preempt */
165 void (*put_fpu)(struct x86_emulate_ctxt *ctxt); /* reenables preempt */ 183 void (*put_fpu)(struct x86_emulate_ctxt *ctxt); /* reenables preempt */
166 int (*intercept)(struct x86_emulate_ctxt *ctxt, 184 int (*intercept)(struct kvm_vcpu *vcpu,
167 enum x86_intercept intercept, 185 struct x86_instruction_info *info,
168 enum x86_intercept_stage stage); 186 enum x86_intercept_stage stage);
169}; 187};
170 188
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index e820c6339b8b..038562c222e8 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -505,6 +505,8 @@ struct kvm_vcpu_stat {
505 u32 nmi_injections; 505 u32 nmi_injections;
506}; 506};
507 507
508struct x86_instruction_info;
509
508struct kvm_x86_ops { 510struct kvm_x86_ops {
509 int (*cpu_has_kvm_support)(void); /* __init */ 511 int (*cpu_has_kvm_support)(void); /* __init */
510 int (*disabled_by_bios)(void); /* __init */ 512 int (*disabled_by_bios)(void); /* __init */
@@ -592,6 +594,11 @@ struct kvm_x86_ops {
592 void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset); 594 void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
593 595
594 void (*get_exit_info)(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2); 596 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
595 const struct trace_print_flags *exit_reasons_str; 602 const struct trace_print_flags *exit_reasons_str;
596}; 603};
597 604
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 3f32a6699fbd..e3e96eada6f3 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -408,6 +408,26 @@ struct gprefix {
408 (_eip) += (_size); \ 408 (_eip) += (_size); \
409}) 409})
410 410
411static 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
411static inline unsigned long ad_mask(struct decode_cache *c) 431static inline unsigned long ad_mask(struct decode_cache *c)
412{ 432{
413 return (1UL << (c->ad_bytes << 3)) - 1; 433 return (1UL << (c->ad_bytes << 3)) - 1;
@@ -3132,8 +3152,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
3132 } 3152 }
3133 3153
3134 if (unlikely(ctxt->guest_mode) && c->intercept) { 3154 if (unlikely(ctxt->guest_mode) && c->intercept) {
3135 rc = ops->intercept(ctxt, c->intercept, 3155 rc = emulator_check_intercept(ctxt, c->intercept,
3136 X86_ICPT_PRE_EXCEPT); 3156 X86_ICPT_PRE_EXCEPT);
3137 if (rc != X86EMUL_CONTINUE) 3157 if (rc != X86EMUL_CONTINUE)
3138 goto done; 3158 goto done;
3139 } 3159 }
@@ -3158,8 +3178,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
3158 } 3178 }
3159 3179
3160 if (unlikely(ctxt->guest_mode) && c->intercept) { 3180 if (unlikely(ctxt->guest_mode) && c->intercept) {
3161 rc = ops->intercept(ctxt, c->intercept, 3181 rc = emulator_check_intercept(ctxt, c->intercept,
3162 X86_ICPT_POST_EXCEPT); 3182 X86_ICPT_POST_EXCEPT);
3163 if (rc != X86EMUL_CONTINUE) 3183 if (rc != X86EMUL_CONTINUE)
3164 goto done; 3184 goto done;
3165 } 3185 }
@@ -3203,8 +3223,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt)
3203special_insn: 3223special_insn:
3204 3224
3205 if (unlikely(ctxt->guest_mode) && c->intercept) { 3225 if (unlikely(ctxt->guest_mode) && c->intercept) {
3206 rc = ops->intercept(ctxt, c->intercept, 3226 rc = emulator_check_intercept(ctxt, c->intercept,
3207 X86_ICPT_POST_MEMACCESS); 3227 X86_ICPT_POST_MEMACCESS);
3208 if (rc != X86EMUL_CONTINUE) 3228 if (rc != X86EMUL_CONTINUE)
3209 goto done; 3229 goto done;
3210 } 3230 }
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index cb43e98eff63..798ebe695f1d 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -3868,6 +3868,13 @@ static void svm_fpu_deactivate(struct kvm_vcpu *vcpu)
3868 update_cr0_intercept(svm); 3868 update_cr0_intercept(svm);
3869} 3869}
3870 3870
3871static 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
3871static struct kvm_x86_ops svm_x86_ops = { 3878static struct kvm_x86_ops svm_x86_ops = {
3872 .cpu_has_kvm_support = has_svm, 3879 .cpu_has_kvm_support = has_svm,
3873 .disabled_by_bios = is_disabled, 3880 .disabled_by_bios = is_disabled,
@@ -3953,6 +3960,8 @@ static struct kvm_x86_ops svm_x86_ops = {
3953 .adjust_tsc_offset = svm_adjust_tsc_offset, 3960 .adjust_tsc_offset = svm_adjust_tsc_offset,
3954 3961
3955 .set_tdp_cr3 = set_tdp_cr3, 3962 .set_tdp_cr3 = set_tdp_cr3,
3963
3964 .check_intercept = svm_check_intercept,
3956}; 3965};
3957 3966
3958static int __init svm_init(void) 3967static int __init svm_init(void)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 2b99ae72481f..3dfefe3bcd05 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4409,6 +4409,13 @@ static void vmx_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
4409{ 4409{
4410} 4410}
4411 4411
4412static 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
4412static struct kvm_x86_ops vmx_x86_ops = { 4419static struct kvm_x86_ops vmx_x86_ops = {
4413 .cpu_has_kvm_support = cpu_has_kvm_support, 4420 .cpu_has_kvm_support = cpu_has_kvm_support,
4414 .disabled_by_bios = vmx_disabled_by_bios, 4421 .disabled_by_bios = vmx_disabled_by_bios,
@@ -4494,6 +4501,8 @@ static struct kvm_x86_ops vmx_x86_ops = {
4494 .adjust_tsc_offset = vmx_adjust_tsc_offset, 4501 .adjust_tsc_offset = vmx_adjust_tsc_offset,
4495 4502
4496 .set_tdp_cr3 = vmx_set_cr3, 4503 .set_tdp_cr3 = vmx_set_cr3,
4504
4505 .check_intercept = vmx_check_intercept,
4497}; 4506};
4498 4507
4499static int __init vmx_init(void) 4508static int __init vmx_init(void)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 99bed74779d2..eebe5465c8ce 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4297,11 +4297,11 @@ static void emulator_put_fpu(struct x86_emulate_ctxt *ctxt)
4297 preempt_enable(); 4297 preempt_enable();
4298} 4298}
4299 4299
4300static int emulator_intercept(struct x86_emulate_ctxt *ctxt, 4300static int emulator_intercept(struct kvm_vcpu *vcpu,
4301 enum x86_intercept intercept, 4301 struct x86_instruction_info *info,
4302 enum x86_intercept_stage stage) 4302 enum x86_intercept_stage stage)
4303{ 4303{
4304 return X86EMUL_CONTINUE; 4304 return kvm_x86_ops->check_intercept(vcpu, info, stage);
4305} 4305}
4306 4306
4307static struct x86_emulate_ops emulate_ops = { 4307static struct x86_emulate_ops emulate_ops = {