From patchwork Sun Sep 22 14:44:54 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Borislav Petkov X-Patchwork-Id: 2924511 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 4978A9F288 for ; Sun, 22 Sep 2013 14:46:49 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 623342010E for ; Sun, 22 Sep 2013 14:46:48 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 73E1920111 for ; Sun, 22 Sep 2013 14:46:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752751Ab3IVOqV (ORCPT ); Sun, 22 Sep 2013 10:46:21 -0400 Received: from mail.skyhub.de ([78.46.96.112]:53489 "EHLO mail.skyhub.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752365Ab3IVOpH (ORCPT ); Sun, 22 Sep 2013 10:45:07 -0400 X-Virus-Scanned: Nedap ESD1 at mail.skyhub.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alien8.de; s=alien8; t=1379861106; bh=pu8eM0Rny1la2nS+Xma61VnHzcnLexeYj3VEAUa/TiU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=jj5l lK+b+GhpaMwJnat3oFE7iqZaAXDaM1eRMD93Uqo7pDIsEyQn7n/7JvPfo/StsjmSWen pLGg676gpVQWeJnBfer1uMHsuURmiaRc33MOuECfAKw6MrGV/SvZujNB3q/XkoHNPgM svyoERJO4774XtvJli0nSHIaXKhfWKQhw= Received: from mail.skyhub.de ([127.0.0.1]) by localhost (door.skyhub.de [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id VkjgAnfcLAJZ; Sun, 22 Sep 2013 16:45:05 +0200 (CEST) Received: from liondog.tnic (p54B47BC4.dip0.t-ipconnect.de [84.180.123.196]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.skyhub.de (SuperMail on ZX Spectrum 128k) with ESMTPSA id 261771DA241; Sun, 22 Sep 2013 16:45:05 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alien8.de; s=alien8; t=1379861105; bh=pu8eM0Rny1la2nS+Xma61VnHzcnLexeYj3VEAUa/TiU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=crxB Hh8IYh7M44/7kw9F41ZzX6sihGSAfzuhA9SEhfhUDZKiFG196I8mkMbYjO9i+Mw3VmQ BNEuIRxMHYQmwIF1xQzwnFFadK0smeMYtm1yoyIrgmSS0Bq5XcUZBNj7CnXJnKcX66d TtZWp3SrRDb+r6Z5WpTwvZuefAod8PvqU= Received: by liondog.tnic (Postfix, from userid 1000) id EEA1710219E; Sun, 22 Sep 2013 16:44:56 +0200 (CEST) From: Borislav Petkov To: LKML Cc: Borislav Petkov , Andre Przywara , "H. Peter Anvin" , Gleb Natapov , Paolo Bonzini , Joerg Roedel , X86 ML , KVM Subject: [PATCH 5/6] kvm: Emulate MOVBE Date: Sun, 22 Sep 2013 16:44:54 +0200 Message-Id: <1379861095-628-6-git-send-email-bp@alien8.de> X-Mailer: git-send-email 1.8.4 In-Reply-To: <1379861095-628-1-git-send-email-bp@alien8.de> References: <1379861095-628-1-git-send-email-bp@alien8.de> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-9.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Borislav Petkov This basically came from the need to be able to boot 32-bit Atom SMP guests on an AMD host, i.e. a host which doesn't support MOVBE. As a matter of fact, qemu has since recently received MOVBE support but we cannot share that with kvm emulation and thus we have to do this in the host. We're waay faster in kvm anyway. :-) So, we piggyback on the #UD path and emulate the MOVBE functionality. With it, an 8-core SMP guest boots in under 6 seconds. Also, requesting MOVBE emulation needs to happen explicitly to work, i.e. qemu -cpu n270,+movbe... Just FYI, a fairly straight-forward boot of a MOVBE-enabled 3.9-rc6+ kernel in kvm executes MOVBE ~60K times. Signed-off-by: Andre Przywara Signed-off-by: Borislav Petkov --- arch/x86/kvm/cpuid.c | 18 ++++++++++++++++- arch/x86/kvm/emulate.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index eca357095a49..986cf7cc74f3 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -190,6 +190,22 @@ static bool supported_xcr0_bit(unsigned bit) static int __do_cpuid_ent_emulated(struct kvm_cpuid_entry2 *entry, u32 func, u32 index, int *nent, int maxnent) { + switch (func) { + case 0: + entry->eax = 1; /* only one leaf currently */ + ++*nent; + break; + case 1: + entry->ecx = F(MOVBE); + ++*nent; + break; + default: + break; + } + + entry->function = func; + entry->index = index; + return 0; } @@ -559,7 +575,7 @@ int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid, return -EINVAL; r = -ENOMEM; - cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry2) * cpuid->nent); + cpuid_entries = vzalloc(sizeof(struct kvm_cpuid_entry2) * cpuid->nent); if (!cpuid_entries) goto out; diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 72093d76c769..fba4a75d82cf 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -2950,6 +2950,46 @@ static int em_mov(struct x86_emulate_ctxt *ctxt) return X86EMUL_CONTINUE; } +#define FFL(x) bit(X86_FEATURE_##x) + +static int em_movbe(struct x86_emulate_ctxt *ctxt) +{ + u32 ebx, ecx, edx, eax = 1; + u16 tmp; + + /* + * Check MOVBE is set in the guest-visible CPUID leaf. + */ + ctxt->ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx); + if (!(ecx & FFL(MOVBE))) + return emulate_ud(ctxt); + + switch (ctxt->op_bytes) { + case 2: + /* + * From MOVBE definition: "...When the operand size is 16 bits, + * the upper word of the destination register remains unchanged + * ..." + * + * Both casting ->valptr and ->val to u16 breaks strict aliasing + * rules so we have to do the operation almost per hand. + */ + tmp = (u16)ctxt->src.val; + ctxt->dst.val &= ~0xffffUL; + ctxt->dst.val |= (unsigned long)swab16(tmp); + break; + case 4: + ctxt->dst.val = swab32((u32)ctxt->src.val); + break; + case 8: + ctxt->dst.val = swab64(ctxt->src.val); + break; + default: + return X86EMUL_PROPAGATE_FAULT; + } + return X86EMUL_CONTINUE; +} + static int em_cr_write(struct x86_emulate_ctxt *ctxt) { if (ctxt->ops->set_cr(ctxt, ctxt->modrm_reg, ctxt->src.val)) @@ -3881,11 +3921,11 @@ static const struct opcode twobyte_table[256] = { }; static const struct gprefix third_opcode_byte_0xf0 = { - N, N, N, N + I(DstReg | SrcMem | Mov, em_movbe), N, N, N }; static const struct gprefix third_opcode_byte_0xf1 = { - N, N, N, N + I(DstMem | SrcReg | Mov, em_movbe), N, N, N }; /* @@ -3895,8 +3935,13 @@ static const struct gprefix third_opcode_byte_0xf1 = { static const struct opcode opcode_map_0f_38[256] = { /* 0x00 - 0x7f */ X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), - /* 0x80 - 0xff */ - X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N) + /* 0x80 - 0xef */ + X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), X16(N), + /* 0xf0 - 0xf1 */ + GP(EmulateOnUD | ModRM | Prefix, &third_opcode_byte_0xf0), + GP(EmulateOnUD | ModRM | Prefix, &third_opcode_byte_0xf1), + /* 0xf2 - 0xff */ + N, N, X4(N), X8(N) }; #undef D