From patchwork Fri Mar 25 09:29:08 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joerg Roedel X-Patchwork-Id: 661401 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 p2P9TYmu015335 for ; Fri, 25 Mar 2011 09:29:49 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933924Ab1CYJ3i (ORCPT ); Fri, 25 Mar 2011 05:29:38 -0400 Received: from ch1outboundpool.messaging.microsoft.com ([216.32.181.183]:31420 "EHLO ch1outboundpool.messaging.microsoft.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933830Ab1CYJ3c (ORCPT ); Fri, 25 Mar 2011 05:29:32 -0400 Received: from mail126-ch1-R.bigfish.com (216.32.181.171) by CH1EHSOBE017.bigfish.com (10.43.70.67) with Microsoft SMTP Server id 14.1.225.8; Fri, 25 Mar 2011 09:29:29 +0000 Received: from mail126-ch1 (localhost.localdomain [127.0.0.1]) by mail126-ch1-R.bigfish.com (Postfix) with ESMTP id 7987117A8311; Fri, 25 Mar 2011 09:29:29 +0000 (UTC) X-SpamScore: -2 X-BigFish: VPS-2(zzbb2cKzz1202hzz8275bhz32i668h64h) X-Spam-TCS-SCL: 3:0 X-Forefront-Antispam-Report: KIP:(null); UIP:(null); IPVD:NLI; H:ausb3twp02.amd.com; RD:none; EFVD:NLI Received: from mail126-ch1 (localhost.localdomain [127.0.0.1]) by mail126-ch1 (MessageSwitch) id 1301045369203654_17448; Fri, 25 Mar 2011 09:29:29 +0000 (UTC) Received: from CH1EHSMHS034.bigfish.com (snatpool1.int.messaging.microsoft.com [10.43.68.250]) by mail126-ch1.bigfish.com (Postfix) with ESMTP id 2D1348B804E; Fri, 25 Mar 2011 09:29:29 +0000 (UTC) Received: from ausb3twp02.amd.com (163.181.249.109) by CH1EHSMHS034.bigfish.com (10.43.70.34) with Microsoft SMTP Server id 14.1.225.8; Fri, 25 Mar 2011 09:29:28 +0000 X-WSS-ID: 0LILX0Z-02-630-02 X-M-MSG: Received: from sausexedgep02.amd.com (sausexedgep02-ext.amd.com [163.181.249.73]) (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 214ADC879E; Fri, 25 Mar 2011 04:29:23 -0500 (CDT) Received: from sausexhtp02.amd.com (163.181.3.152) by sausexedgep02.amd.com (163.181.36.59) with Microsoft SMTP Server (TLS) id 8.3.106.1; Fri, 25 Mar 2011 04:36:51 -0500 Received: from storexhtp01.amd.com (172.24.4.3) by sausexhtp02.amd.com (163.181.3.152) with Microsoft SMTP Server (TLS) id 8.3.83.0; Fri, 25 Mar 2011 04:29:26 -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; Fri, 25 Mar 2011 05:29:25 -0400 Received: from lemmy.osrc.amd.com (lemmy.osrc.amd.com [165.204.15.93]) by gwo.osrc.amd.com (Postfix) with ESMTP id 59A1949C597; Fri, 25 Mar 2011 09:29:23 +0000 (GMT) Received: by lemmy.osrc.amd.com (Postfix, from userid 1000) id 491C8101BA4; Fri, 25 Mar 2011 10:29:23 +0100 (CET) From: Joerg Roedel To: Avi Kivity , Marcelo Tosatti CC: , Joerg Roedel Subject: [PATCH 05/13] KVM: SVM: Add intercept check for emulated cr accesses Date: Fri, 25 Mar 2011 10:29:08 +0100 Message-ID: <1301045356-25257-6-git-send-email-joerg.roedel@amd.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1301045356-25257-1-git-send-email-joerg.roedel@amd.com> References: <1301045356-25257-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]); Fri, 25 Mar 2011 09:29:49 +0000 (UTC) diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index 7960eeb..c1489e1 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h @@ -275,6 +275,9 @@ enum x86_intercept_stage { enum x86_intercept { x86_intercept_none, + x86_intercept_cr_read, + x86_intercept_cr_write, + x86_intercept_clts, x86_intercept_lmsw, x86_intercept_smsw, x86_intercept_lidt, diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 078acc4..384cfa2 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -2503,14 +2503,16 @@ static struct opcode opcode_table[256] = { static struct opcode twobyte_table[256] = { /* 0x00 - 0x0F */ N, GD(0, &group7), N, N, - N, D(ImplicitOps | VendorSpecific), D(ImplicitOps | Priv), N, + N, D(ImplicitOps | VendorSpecific), DI(ImplicitOps | Priv, clts), N, DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N, N, D(ImplicitOps | ModRM), N, N, /* 0x10 - 0x1F */ N, N, N, N, N, N, N, N, D(ImplicitOps | ModRM), N, N, N, N, N, N, N, /* 0x20 - 0x2F */ - D(ModRM | DstMem | Priv | Op3264), D(ModRM | DstMem | Priv | Op3264), - D(ModRM | SrcMem | Priv | Op3264), D(ModRM | SrcMem | Priv | Op3264), + DI(ModRM | DstMem | Priv | Op3264, cr_read), + D(ModRM | DstMem | Priv | Op3264), + DI(ModRM | SrcMem | Priv | Op3264, cr_write), + D(ModRM | SrcMem | Priv | Op3264), N, N, N, N, N, N, N, N, N, N, N, N, /* 0x30 - 0x3F */ diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index b36df64..3b6992e 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -3871,11 +3871,89 @@ static void svm_fpu_deactivate(struct kvm_vcpu *vcpu) update_cr0_intercept(svm); } +#define POST_EX(exit) { .exit_code = (exit), \ + .stage = x86_icpt_post_except, \ + .valid = true } + +static struct __x86_intercept { + u32 exit_code; + enum x86_intercept_stage stage; + bool valid; +} x86_intercept_map[] = { + [x86_intercept_cr_read] = POST_EX(SVM_EXIT_READ_CR0), + [x86_intercept_cr_write] = POST_EX(SVM_EXIT_WRITE_CR0), + [x86_intercept_clts] = POST_EX(SVM_EXIT_WRITE_CR0), + [x86_intercept_lmsw] = POST_EX(SVM_EXIT_WRITE_CR0), + [x86_intercept_smsw] = POST_EX(SVM_EXIT_READ_CR0), +}; + +#undef POST_EX + static int svm_check_intercept(struct kvm_vcpu *vcpu, struct x86_instruction_info *info, enum x86_intercept_stage stage) { - return X86EMUL_CONTINUE; + struct vcpu_svm *svm = to_svm(vcpu); + int vmexit, ret = X86EMUL_CONTINUE; + struct __x86_intercept icpt_info; + struct vmcb *vmcb = svm->vmcb; + int reg; + + if (info->intercept >= ARRAY_SIZE(x86_intercept_map)) + goto out; + + icpt_info = x86_intercept_map[info->intercept]; + + if (!icpt_info.valid || stage != icpt_info.stage) + goto out; + + reg = (info->modrm >> 3) & 7; + + switch (icpt_info.exit_code) { + case SVM_EXIT_READ_CR0: + if (info->intercept == x86_intercept_cr_read) + icpt_info.exit_code += reg; + case SVM_EXIT_WRITE_CR0: { + unsigned long cr0, val; + u64 intercept; + + if (info->intercept == x86_intercept_cr_write) + icpt_info.exit_code += reg; + + if (icpt_info.exit_code != SVM_EXIT_WRITE_CR0) + break; + + intercept = svm->nested.intercept; + + if (!(intercept & (1ULL << INTERCEPT_SELECTIVE_CR0))) + break; + + cr0 = vcpu->arch.cr0 & ~SVM_CR0_SELECTIVE_MASK; + val = info->src_val & ~SVM_CR0_SELECTIVE_MASK; + + if (info->intercept == x86_intercept_lmsw) { + cr0 &= 0xfUL; + val &= 0xfUL; + } + + if (cr0 ^ val) + icpt_info.exit_code = SVM_EXIT_CR0_SEL_WRITE; + + break; + } + default: + break; + } + + vmcb->control.next_rip = info->next_rip; + vmcb->control.exit_code = icpt_info.exit_code; + vmexit = nested_svm_exit_handled(svm); + + ret = (vmexit == NESTED_EXIT_DONE) ? X86EMUL_INTERCEPTED + : X86EMUL_CONTINUE; + +out: + return ret; } static struct kvm_x86_ops svm_x86_ops = {