diff mbox

[04/13] KVM: X86: Add x86 callback for intercept check

Message ID 1301045356-25257-5-git-send-email-joerg.roedel@amd.com (mailing list archive)
State New, archived
Headers show

Commit Message

Joerg Roedel March 25, 2011, 9:29 a.m. UTC
None
diff mbox

Patch

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 35f81b1..7544964 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -504,6 +504,22 @@  struct kvm_vcpu_stat {
 	u32 nmi_injections;
 };
 
+/*
+ * This struct is used to carry enough information from the instruction
+ * decoder to main KVM so that a decision can be made whether the
+ * instruction needs to be intercepted or not.
+ */
+struct x86_instruction_info {
+	u8  intercept;		/* which intercept			*/
+	u8  rep_prefix;		/* rep prefix?				*/
+	u8  modrm;		/* index of register used		*/
+	u64 src_val;		/* value of source operand		*/
+	u8  src_bytes;		/* size of source operand		*/
+	u8  dst_bytes;		/* size of destination operand		*/
+	u8  ad_bytes;		/* size of src/dst address		*/
+	u64 next_rip;		/* rip following the instruction	*/
+};
+
 struct kvm_x86_ops {
 	int (*cpu_has_kvm_support)(void);          /* __init */
 	int (*disabled_by_bios)(void);             /* __init */
@@ -591,6 +607,11 @@  struct kvm_x86_ops {
 	void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
 
 	void (*get_exit_info)(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2);
+
+	int (*check_intercept)(struct kvm_vcpu *vcpu,
+			       struct x86_instruction_info *info,
+			       enum x86_intercept_stage stage);
+
 	const struct trace_print_flags *exit_reasons_str;
 };
 
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 2a19322..b36df64 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -3871,6 +3871,13 @@  static void svm_fpu_deactivate(struct kvm_vcpu *vcpu)
 	update_cr0_intercept(svm);
 }
 
+static int svm_check_intercept(struct kvm_vcpu *vcpu,
+			       struct x86_instruction_info *info,
+			       enum x86_intercept_stage stage)
+{
+	return X86EMUL_CONTINUE;
+}
+
 static struct kvm_x86_ops svm_x86_ops = {
 	.cpu_has_kvm_support = has_svm,
 	.disabled_by_bios = is_disabled,
@@ -3956,6 +3963,8 @@  static struct kvm_x86_ops svm_x86_ops = {
 	.adjust_tsc_offset = svm_adjust_tsc_offset,
 
 	.set_tdp_cr3 = set_tdp_cr3,
+
+	.check_intercept = svm_check_intercept,
 };
 
 static int __init svm_init(void)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 90a41aa..bf72ec6 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4245,7 +4245,25 @@  static int emulator_intercept(struct x86_emulate_ctxt *ctxt,
 			      enum x86_intercept intercept,
 			      enum x86_intercept_stage stage)
 {
-	return X86EMUL_CONTINUE;
+	struct x86_instruction_info info = {
+		.intercept  = intercept,
+		.rep_prefix = ctxt->decode.rep_prefix,
+		.modrm      = ctxt->decode.modrm,
+		.src_val    = ctxt->decode.src.val64,
+		.src_bytes  = ctxt->decode.src.bytes,
+		.dst_bytes  = ctxt->decode.dst.bytes,
+		.ad_bytes   = ctxt->decode.ad_bytes,
+		.next_rip   = ctxt->eip,
+	};
+
+	/*
+	 * The callback only needs to be implemented if the architecture
+	 * supports emulated guest-mode. This BUG_ON reminds the
+	 * programmer that this callback needs to be implemented.
+	 */
+	BUG_ON(kvm_x86_ops->check_intercept == NULL);
+
+	return kvm_x86_ops->check_intercept(ctxt->vcpu, &info, stage);
 }
 
 static struct x86_emulate_ops emulate_ops = {