From patchwork Mon Mar 28 10:46:38 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joerg Roedel X-Patchwork-Id: 668071 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p2SAldMK016261 for ; Mon, 28 Mar 2011 10:47:40 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753234Ab1C1KrY (ORCPT ); Mon, 28 Mar 2011 06:47:24 -0400 Received: from va3ehsobe005.messaging.microsoft.com ([216.32.180.31]:13532 "EHLO VA3EHSOBE005.bigfish.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753143Ab1C1KrC (ORCPT ); Mon, 28 Mar 2011 06:47:02 -0400 Received: from mail117-va3-R.bigfish.com (10.7.14.238) by VA3EHSOBE005.bigfish.com (10.7.40.25) with Microsoft SMTP Server id 14.1.225.8; Mon, 28 Mar 2011 10:46:59 +0000 Received: from mail117-va3 (localhost.localdomain [127.0.0.1]) by mail117-va3-R.bigfish.com (Postfix) with ESMTP id 6B907171821E; Mon, 28 Mar 2011 10:46:59 +0000 (UTC) X-SpamScore: -2 X-BigFish: VPS-2(zzbb2cKzz1202hzz8275bhz32i668h61h) X-Spam-TCS-SCL: 0:0 X-Forefront-Antispam-Report: KIP:(null); UIP:(null); IPVD:NLI; H:ausb3twp02.amd.com; RD:none; EFVD:NLI Received: from mail117-va3 (localhost.localdomain [127.0.0.1]) by mail117-va3 (MessageSwitch) id 1301309218754624_18352; Mon, 28 Mar 2011 10:46:58 +0000 (UTC) Received: from VA3EHSMHS027.bigfish.com (unknown [10.7.14.245]) by mail117-va3.bigfish.com (Postfix) with ESMTP id A9FA41A6804B; Mon, 28 Mar 2011 10:46:58 +0000 (UTC) Received: from ausb3twp02.amd.com (163.181.249.109) by VA3EHSMHS027.bigfish.com (10.7.99.37) with Microsoft SMTP Server id 14.1.225.22; Mon, 28 Mar 2011 10:46:58 +0000 X-WSS-ID: 0LIRKM5-02-05D-02 X-M-MSG: Received: from sausexedgep01.amd.com (sausexedgep01-ext.amd.com [163.181.249.72]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) by ausb3twp02.amd.com (Tumbleweed MailGate 3.7.2) with ESMTP id 26226C87F5; Mon, 28 Mar 2011 05:46:53 -0500 (CDT) Received: from sausexhtp01.amd.com (163.181.3.165) by sausexedgep01.amd.com (163.181.36.54) with Microsoft SMTP Server (TLS) id 8.3.106.1; Mon, 28 Mar 2011 05:54:32 -0500 Received: from storexhtp01.amd.com (172.24.4.3) by sausexhtp01.amd.com (163.181.3.165) with Microsoft SMTP Server (TLS) id 8.3.83.0; Mon, 28 Mar 2011 05:46:57 -0500 Received: from gwo.osrc.amd.com (165.204.16.204) by storexhtp01.amd.com (172.24.4.3) with Microsoft SMTP Server id 8.3.83.0; Mon, 28 Mar 2011 06:46:55 -0400 Received: from lemmy.osrc.amd.com (lemmy.osrc.amd.com [165.204.15.93]) by gwo.osrc.amd.com (Postfix) with ESMTP id C0C5749C593; Mon, 28 Mar 2011 11:46:54 +0100 (BST) Received: by lemmy.osrc.amd.com (Postfix, from userid 1000) id AD01CFFC4C; Mon, 28 Mar 2011 12:46:54 +0200 (CEST) From: Joerg Roedel To: Avi Kivity , Marcelo Tosatti CC: , Avi Kivity , Joerg Roedel Subject: [PATCH 01/13] KVM: x86 emulator: add framework for instruction intercepts Date: Mon, 28 Mar 2011 12:46:38 +0200 Message-ID: <1301309210-11120-2-git-send-email-joerg.roedel@amd.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1301309210-11120-1-git-send-email-joerg.roedel@amd.com> References: <1301309210-11120-1-git-send-email-joerg.roedel@amd.com> MIME-Version: 1.0 X-OriginatorOrg: amd.com Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Mon, 28 Mar 2011 10:47:40 +0000 (UTC) diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index 0f52135..92e251d 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h @@ -14,6 +14,8 @@ #include struct x86_emulate_ctxt; +enum x86_intercept; +enum x86_intercept_stage; struct x86_exception { u8 vector; @@ -62,6 +64,7 @@ struct x86_exception { #define X86EMUL_RETRY_INSTR 3 /* retry the instruction for some reason */ #define X86EMUL_CMPXCHG_FAILED 4 /* cmpxchg did not see expected value */ #define X86EMUL_IO_NEEDED 5 /* IO is needed to complete emulation */ +#define X86EMUL_INTERCEPTED 6 /* Intercepted by nested VMCB/VMCS */ struct x86_emulate_ops { /* @@ -158,6 +161,9 @@ struct x86_emulate_ops { int (*set_dr)(int dr, unsigned long value, struct kvm_vcpu *vcpu); int (*set_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 data); int (*get_msr)(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata); + int (*intercept)(struct x86_emulate_ctxt *ctxt, + enum x86_intercept intercept, + enum x86_intercept_stage stage); }; /* Type, address-of, and value of an instruction's operand. */ @@ -197,6 +203,7 @@ struct read_cache { struct decode_cache { u8 twobyte; u8 b; + u8 intercept; u8 lock_prefix; u8 rep_prefix; u8 op_bytes; @@ -238,6 +245,7 @@ struct x86_emulate_ctxt { /* interruptibility state, as a result of execution of STI or MOV SS */ int interruptibility; + bool guest_mode; /* guest running a nested guest */ bool perm_ok; /* do not check permissions if true */ bool only_vendor_specific_insn; @@ -259,6 +267,18 @@ struct x86_emulate_ctxt { #define X86EMUL_MODE_PROT32 4 /* 32-bit protected mode. */ #define X86EMUL_MODE_PROT64 8 /* 64-bit (long) mode. */ +enum x86_intercept_stage { + X86_ICPT_PRE_EXCEPT, + X86_ICPT_POST_EXCEPT, + X86_ICPT_POST_MEMACCESS, +}; + +enum x86_intercept { + x86_intercept_none, + + nr_x86_intercepts +}; + /* Host execution mode. */ #if defined(CONFIG_X86_32) #define X86EMUL_MODE_HOST X86EMUL_MODE_PROT32 diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 14c5ad5..1c574ae 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -102,6 +102,7 @@ struct opcode { u32 flags; + u8 intercept; union { int (*execute)(struct x86_emulate_ctxt *ctxt); struct opcode *group; @@ -2326,10 +2327,13 @@ static int em_mov(struct x86_emulate_ctxt *ctxt) } #define D(_y) { .flags = (_y) } +#define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i } #define N D(0) #define G(_f, _g) { .flags = ((_f) | Group), .u.group = (_g) } #define GD(_f, _g) { .flags = ((_f) | Group | GroupDual), .u.gdual = (_g) } #define I(_f, _e) { .flags = (_f), .u.execute = (_e) } +#define II(_f, _e, _i) \ + { .flags = (_f), .u.execute = (_e), .intercept = x86_intercept_##_i } #define D2bv(_f) D((_f) | ByteOp), D(_f) #define I2bv(_f, _e) I((_f) | ByteOp, _e), I(_f, _e) @@ -2745,6 +2749,7 @@ done_prefixes: } c->execute = opcode.u.execute; + c->intercept = opcode.intercept; /* Unrecognised? */ if (c->d == 0 || (c->d & Undefined)) @@ -2979,12 +2984,26 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt) goto done; } + if (unlikely(ctxt->guest_mode) && c->intercept) { + rc = ops->intercept(ctxt, c->intercept, + X86_ICPT_PRE_EXCEPT); + if (rc != X86EMUL_CONTINUE) + goto done; + } + /* Privileged instruction can be executed only in CPL=0 */ if ((c->d & Priv) && ops->cpl(ctxt->vcpu)) { rc = emulate_gp(ctxt, 0); goto done; } + if (unlikely(ctxt->guest_mode) && c->intercept) { + rc = ops->intercept(ctxt, c->intercept, + X86_ICPT_POST_EXCEPT); + if (rc != X86EMUL_CONTINUE) + goto done; + } + if (c->rep_prefix && (c->d & String)) { /* All REP prefixes have the same first termination condition */ if (address_mask(c, c->regs[VCPU_REGS_RCX]) == 0) { @@ -3023,6 +3042,13 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt) special_insn: + if (unlikely(ctxt->guest_mode) && c->intercept) { + rc = ops->intercept(ctxt, c->intercept, + X86_ICPT_POST_MEMACCESS); + if (rc != X86EMUL_CONTINUE) + goto done; + } + if (c->execute) { rc = c->execute(ctxt); if (rc != X86EMUL_CONTINUE) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index bfd7763..829ea7c 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4242,6 +4242,13 @@ static void emulator_set_segment_selector(u16 sel, int seg, kvm_set_segment(vcpu, &kvm_seg, seg); } +static int emulator_intercept(struct x86_emulate_ctxt *ctxt, + enum x86_intercept intercept, + enum x86_intercept_stage stage) +{ + return X86EMUL_CONTINUE; +} + static struct x86_emulate_ops emulate_ops = { .read_std = kvm_read_guest_virt_system, .write_std = kvm_write_guest_virt_system, @@ -4265,6 +4272,7 @@ static struct x86_emulate_ops emulate_ops = { .set_dr = emulator_set_dr, .set_msr = kvm_set_msr, .get_msr = kvm_get_msr, + .intercept = emulator_intercept, }; static void cache_all_regs(struct kvm_vcpu *vcpu) @@ -4319,6 +4327,7 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu) ? X86EMUL_MODE_VM86 : cs_l ? X86EMUL_MODE_PROT64 : cs_db ? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16; + vcpu->arch.emulate_ctxt.guest_mode = is_guest_mode(vcpu); memset(c, 0, sizeof(struct decode_cache)); memcpy(c->regs, vcpu->arch.regs, sizeof c->regs); }