From patchwork Thu Apr 11 00:18:15 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Borislav Petkov X-Patchwork-Id: 2426001 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id C0C92DF2E5 for ; Thu, 11 Apr 2013 00:18:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935553Ab3DKASV (ORCPT ); Wed, 10 Apr 2013 20:18:21 -0400 Received: from mail.skyhub.de ([78.46.96.112]:35126 "EHLO mail.skyhub.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1763122Ab3DKASU (ORCPT ); Wed, 10 Apr 2013 20:18:20 -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=1365639499; bh=BYCrx4ZAu3Atw3PAt/0is4Ywoi9XxEaweCB1O66sQwI=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:In-Reply-To; b=o2PIw+KWYVFRE/sMHB5ShnLqAyY4qWrGVDJb0g 3ZGTO5iYORmr8aNKQlslmRqInJEWwkSMrEyMFfw8E5jJ2j4cv/lQcRxcgXYTZp4ZLVl Mx57+5ez5Q7r3Orqq/FXvKwAS3eOLk8igYaSFLuokdFRUTLltk+ttrvPJUK+WQmT8c= 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 J8VwlvBJX-xh; Thu, 11 Apr 2013 02:18:18 +0200 (CEST) Received: from liondog.tnic (p54B7FE19.dip.t-dialin.net [84.183.254.25]) (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 1B5B91D9CF2; Thu, 11 Apr 2013 02:18:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alien8.de; s=alien8; t=1365639498; bh=BYCrx4ZAu3Atw3PAt/0is4Ywoi9XxEaweCB1O66sQwI=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:In-Reply-To; b=JisO5vvksG8gbVd50HdO8RoF+u0zDJZOQqjKMu ZLEeIR3Yac92qJoQOy8kGibU3nXPfgp1UZ1Ri84Uz5VfL9hIgOKgJefcoUUjqtoJmEe +nNui8mDuCnYtaJCCH6ckx3Yqmpk2HC4nPYhBXP2YF/hn9+KK+b8LxHt6fJWakNiZg= Received: by liondog.tnic (Postfix, from userid 1000) id 86630100819; Thu, 11 Apr 2013 02:18:15 +0200 (CEST) Date: Thu, 11 Apr 2013 02:18:15 +0200 From: Borislav Petkov To: Gleb Natapov Cc: Andre Przywara , kvm@vger.kernel.org, =?utf-8?B?SsO2cmcgUsO2ZGVs?= , "H. Peter Anvin" , x86-ml Subject: [PATCH -v2] kvm: Emulate MOVBE Message-ID: <20130411001815.GA17544@pd.tnic> References: <20130409234602.GI5077@pd.tnic> <20130410112942.07dfc167@slackpad> <20130410100845.GB17919@redhat.com> <20130410123901.46b65169@slackpad> <20130410121639.GE17919@redhat.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20130410121639.GE17919@redhat.com> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org On Wed, Apr 10, 2013 at 03:16:39PM +0300, Gleb Natapov wrote: > Right, the question is how kernel can tell QEMU that the cpuid bit is > supported but should not be set unless explicitly asked by an user. Actually, this seems to work with the patch below based on whether you have "+movbe" in the -cpu option or not. Anyway, here's the second version with hopefully all comments and suggestions addressed. Thanks. --- From 612fc75a732ad16332f270b7c52a68c89e3565ca Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Thu, 11 Apr 2013 02:06:30 +0200 Subject: [PATCH] kvm: Emulate MOVBE This basically came from the need to be able to boot 32-bit Atom SMP guests on an AMD host, i.e. 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 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... Signed-off-by: Andre Przywara Signed-off-by: Borislav Petkov --- arch/x86/kvm/cpuid.c | 2 +- arch/x86/kvm/emulate.c | 39 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index a20ecb5b6cbf..2d44fc4fd855 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -273,7 +273,7 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, cpuid_mask(&entry->ecx, 4); /* we support x2apic emulation even if host does not support * it since we emulate x2apic in software */ - entry->ecx |= F(X2APIC); + entry->ecx |= F(X2APIC) | F(MOVBE); break; /* function 2 entries are STATEFUL. That is, repeated cpuid commands * may return different values. This forces us to get_cpu() before diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index a335cc6cde72..9011c7a656ad 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -152,6 +152,7 @@ #define Avx ((u64)1 << 43) /* Advanced Vector Extensions */ #define Fastop ((u64)1 << 44) /* Use opcode::u.fastop */ #define NoWrite ((u64)1 << 45) /* No writeback */ +#define EmulateOnUD ((u64)1 << 46) /* emulate if unsupported by the host */ #define X2(x...) x, x #define X3(x...) X2(x), x @@ -3107,6 +3108,30 @@ static int em_mov(struct x86_emulate_ctxt *ctxt) return X86EMUL_CONTINUE; } +static int em_movbe(struct x86_emulate_ctxt *ctxt) +{ + switch (ctxt->op_bytes) { + case 2: + *(u16 *)ctxt->dst.valptr = swab16(*(u16 *)ctxt->src.valptr); + break; + case 4: + *(u32 *)ctxt->dst.valptr = swab32(*(u32 *)ctxt->src.valptr); + + /* + * clear upper dword for 32-bit operand size in 64-bit mode. + */ + if (ctxt->mode == X86EMUL_MODE_PROT64) + *((u32 *)ctxt->dst.valptr + 1) = 0x0; + break; + case 8: + *(u64 *)ctxt->dst.valptr = swab64(*(u64 *)ctxt->src.valptr); + 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)) @@ -4033,6 +4058,11 @@ static const struct opcode twobyte_table[256] = { N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N }; +static const struct opcode threebyte_table[] = { + [0xf0] = I(DstReg | SrcMem | ModRM | Mov | EmulateOnUD, em_movbe), + [0xf1] = I(DstMem | SrcReg | ModRM | Mov | EmulateOnUD, em_movbe), +}; + #undef D #undef N #undef G @@ -4320,6 +4350,9 @@ done_prefixes: ctxt->twobyte = 1; ctxt->b = insn_fetch(u8, ctxt); opcode = twobyte_table[ctxt->b]; + + if (ctxt->b == 0x38) + opcode = threebyte_table[insn_fetch(u8, ctxt)]; } ctxt->d = opcode.flags; @@ -4376,8 +4409,10 @@ done_prefixes: if (ctxt->d == 0 || (ctxt->d & Undefined)) return EMULATION_FAILED; - if (!(ctxt->d & VendorSpecific) && ctxt->only_vendor_specific_insn) - return EMULATION_FAILED; + if (!(ctxt->d & VendorSpecific) && ctxt->only_vendor_specific_insn) { + if (!(ctxt->d & EmulateOnUD)) + return EMULATION_FAILED; + } if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack)) ctxt->op_bytes = 8;