From owner-svn-src-all@FreeBSD.ORG Thu Jun 12 13:48:52 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id C1253A03; Thu, 12 Jun 2014 13:48:52 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id ADF052E1D; Thu, 12 Jun 2014 13:48:52 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s5CDmqWg055455; Thu, 12 Jun 2014 13:48:52 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s5CDmqdM055454; Thu, 12 Jun 2014 13:48:52 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <201406121348.s5CDmqdM055454@svn.freebsd.org> From: John Baldwin Date: Thu, 12 Jun 2014 13:48:52 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r267396 - stable/10/sys/amd64/vmm X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Jun 2014 13:48:53 -0000 Author: jhb Date: Thu Jun 12 13:48:52 2014 New Revision: 267396 URL: http://svnweb.freebsd.org/changeset/base/267396 Log: MFC 261503,264501: Emulate the byte move and zero/sign extend instructions. Modified: stable/10/sys/amd64/vmm/vmm_instruction_emul.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/amd64/vmm/vmm_instruction_emul.c ============================================================================== --- stable/10/sys/amd64/vmm/vmm_instruction_emul.c Thu Jun 12 13:33:01 2014 (r267395) +++ stable/10/sys/amd64/vmm/vmm_instruction_emul.c Thu Jun 12 13:48:52 2014 (r267396) @@ -58,8 +58,11 @@ enum cpu_mode { enum { VIE_OP_TYPE_NONE = 0, VIE_OP_TYPE_MOV, + VIE_OP_TYPE_MOVSX, + VIE_OP_TYPE_MOVZX, VIE_OP_TYPE_AND, VIE_OP_TYPE_OR, + VIE_OP_TYPE_TWO_BYTE, VIE_OP_TYPE_LAST }; @@ -67,7 +70,22 @@ enum { #define VIE_OP_F_IMM (1 << 0) /* immediate operand present */ #define VIE_OP_F_IMM8 (1 << 1) /* 8-bit immediate operand */ +static const struct vie_op two_byte_opcodes[256] = { + [0xB6] = { + .op_byte = 0xB6, + .op_type = VIE_OP_TYPE_MOVZX, + }, + [0xBE] = { + .op_byte = 0xBE, + .op_type = VIE_OP_TYPE_MOVSX, + }, +}; + static const struct vie_op one_byte_opcodes[256] = { + [0x0F] = { + .op_byte = 0x0F, + .op_type = VIE_OP_TYPE_TWO_BYTE + }, [0x88] = { .op_byte = 0x88, .op_type = VIE_OP_TYPE_MOV, @@ -313,6 +331,85 @@ emulate_mov(void *vm, int vcpuid, uint64 return (error); } +/* + * The following simplifying assumptions are made during emulation: + * + * - guest is in 64-bit mode + * - default address size is 64-bits + * - default operand size is 32-bits + * + * - operand size override is not supported + * + * - address size override is not supported + */ +static int +emulate_movx(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, + mem_region_read_t memread, mem_region_write_t memwrite, + void *arg) +{ + int error, size; + enum vm_reg_name reg; + uint64_t val; + + size = 4; + error = EINVAL; + + switch (vie->op.op_byte) { + case 0xB6: + /* + * MOV and zero extend byte from mem (ModRM:r/m) to + * reg (ModRM:reg). + * + * 0F B6/r movzx r/m8, r32 + * REX.W + 0F B6/r movzx r/m8, r64 + */ + + /* get the first operand */ + error = memread(vm, vcpuid, gpa, &val, 1, arg); + if (error) + break; + + /* get the second operand */ + reg = gpr_map[vie->reg]; + + if (vie->rex_w) + size = 8; + + /* write the result */ + error = vie_update_register(vm, vcpuid, reg, val, size); + break; + case 0xBE: + /* + * MOV and sign extend byte from mem (ModRM:r/m) to + * reg (ModRM:reg). + * + * 0F BE/r movsx r/m8, r32 + * REX.W + 0F BE/r movsx r/m8, r64 + */ + + /* get the first operand */ + error = memread(vm, vcpuid, gpa, &val, 1, arg); + if (error) + break; + + /* get the second operand */ + reg = gpr_map[vie->reg]; + + if (vie->rex_w) + size = 8; + + /* sign extend byte */ + val = (int8_t)val; + + /* write the result */ + error = vie_update_register(vm, vcpuid, reg, val, size); + break; + default: + break; + } + return (error); +} + static int emulate_and(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, mem_region_read_t memread, mem_region_write_t memwrite, void *arg) @@ -447,6 +544,11 @@ vmm_emulate_instruction(void *vm, int vc error = emulate_mov(vm, vcpuid, gpa, vie, memread, memwrite, memarg); break; + case VIE_OP_TYPE_MOVSX: + case VIE_OP_TYPE_MOVZX: + error = emulate_movx(vm, vcpuid, gpa, vie, + memread, memwrite, memarg); + break; case VIE_OP_TYPE_AND: error = emulate_and(vm, vcpuid, gpa, vie, memread, memwrite, memarg); @@ -609,6 +711,23 @@ decode_rex(struct vie *vie) } static int +decode_two_byte_opcode(struct vie *vie) +{ + uint8_t x; + + if (vie_peek(vie, &x)) + return (-1); + + vie->op = two_byte_opcodes[x]; + + if (vie->op.op_type == VIE_OP_TYPE_NONE) + return (-1); + + vie_advance(vie); + return (0); +} + +static int decode_opcode(struct vie *vie) { uint8_t x; @@ -622,6 +741,10 @@ decode_opcode(struct vie *vie) return (-1); vie_advance(vie); + + if (vie->op.op_type == VIE_OP_TYPE_TWO_BYTE) + return (decode_two_byte_opcode(vie)); + return (0); }