vmm_instruction_emul.c revision 267396
1240941Sneel/*- 2240941Sneel * Copyright (c) 2012 Sandvine, Inc. 3240941Sneel * Copyright (c) 2012 NetApp, Inc. 4240941Sneel * All rights reserved. 5240941Sneel * 6240941Sneel * Redistribution and use in source and binary forms, with or without 7240941Sneel * modification, are permitted provided that the following conditions 8240941Sneel * are met: 9240941Sneel * 1. Redistributions of source code must retain the above copyright 10240941Sneel * notice, this list of conditions and the following disclaimer. 11240941Sneel * 2. Redistributions in binary form must reproduce the above copyright 12240941Sneel * notice, this list of conditions and the following disclaimer in the 13240941Sneel * documentation and/or other materials provided with the distribution. 14240941Sneel * 15250175Semaste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16240941Sneel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17240941Sneel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18250175Semaste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19240941Sneel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20240941Sneel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21240941Sneel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22240941Sneel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23240941Sneel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24240941Sneel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25240941Sneel * SUCH DAMAGE. 26240941Sneel * 27240941Sneel * $FreeBSD: stable/10/sys/amd64/vmm/vmm_instruction_emul.c 267396 2014-06-12 13:48:52Z jhb $ 28240941Sneel */ 29240941Sneel 30240941Sneel#include <sys/cdefs.h> 31240941Sneel__FBSDID("$FreeBSD: stable/10/sys/amd64/vmm/vmm_instruction_emul.c 267396 2014-06-12 13:48:52Z jhb $"); 32240941Sneel 33243640Sneel#ifdef _KERNEL 34240941Sneel#include <sys/param.h> 35240941Sneel#include <sys/pcpu.h> 36240941Sneel#include <sys/systm.h> 37240941Sneel 38240941Sneel#include <vm/vm.h> 39240941Sneel#include <vm/pmap.h> 40240941Sneel 41240941Sneel#include <machine/vmparam.h> 42240941Sneel#include <machine/vmm.h> 43243640Sneel#else /* !_KERNEL */ 44243640Sneel#include <sys/types.h> 45243640Sneel#include <sys/errno.h> 46240941Sneel 47243640Sneel#include <machine/vmm.h> 48240941Sneel 49243640Sneel#include <vmmapi.h> 50243640Sneel#endif /* _KERNEL */ 51240941Sneel 52249879Sgrehanenum cpu_mode { 53249879Sgrehan CPU_MODE_COMPATIBILITY, /* IA-32E mode (CS.L = 0) */ 54249879Sgrehan CPU_MODE_64BIT, /* IA-32E mode (CS.L = 1) */ 55249879Sgrehan}; 56243640Sneel 57243640Sneel/* struct vie_op.op_type */ 58243640Sneelenum { 59243640Sneel VIE_OP_TYPE_NONE = 0, 60243640Sneel VIE_OP_TYPE_MOV, 61267396Sjhb VIE_OP_TYPE_MOVSX, 62267396Sjhb VIE_OP_TYPE_MOVZX, 63243640Sneel VIE_OP_TYPE_AND, 64253585Sneel VIE_OP_TYPE_OR, 65267396Sjhb VIE_OP_TYPE_TWO_BYTE, 66243640Sneel VIE_OP_TYPE_LAST 67243640Sneel}; 68243640Sneel 69243640Sneel/* struct vie_op.op_flags */ 70243640Sneel#define VIE_OP_F_IMM (1 << 0) /* immediate operand present */ 71243640Sneel#define VIE_OP_F_IMM8 (1 << 1) /* 8-bit immediate operand */ 72243640Sneel 73267396Sjhbstatic const struct vie_op two_byte_opcodes[256] = { 74267396Sjhb [0xB6] = { 75267396Sjhb .op_byte = 0xB6, 76267396Sjhb .op_type = VIE_OP_TYPE_MOVZX, 77267396Sjhb }, 78267396Sjhb [0xBE] = { 79267396Sjhb .op_byte = 0xBE, 80267396Sjhb .op_type = VIE_OP_TYPE_MOVSX, 81267396Sjhb }, 82267396Sjhb}; 83267396Sjhb 84243640Sneelstatic const struct vie_op one_byte_opcodes[256] = { 85267396Sjhb [0x0F] = { 86267396Sjhb .op_byte = 0x0F, 87267396Sjhb .op_type = VIE_OP_TYPE_TWO_BYTE 88267396Sjhb }, 89246108Sneel [0x88] = { 90246108Sneel .op_byte = 0x88, 91246108Sneel .op_type = VIE_OP_TYPE_MOV, 92246108Sneel }, 93243640Sneel [0x89] = { 94243640Sneel .op_byte = 0x89, 95243640Sneel .op_type = VIE_OP_TYPE_MOV, 96243640Sneel }, 97254964Sneel [0x8A] = { 98254964Sneel .op_byte = 0x8A, 99254964Sneel .op_type = VIE_OP_TYPE_MOV, 100254964Sneel }, 101243640Sneel [0x8B] = { 102243640Sneel .op_byte = 0x8B, 103243640Sneel .op_type = VIE_OP_TYPE_MOV, 104243640Sneel }, 105243640Sneel [0xC7] = { 106243640Sneel .op_byte = 0xC7, 107243640Sneel .op_type = VIE_OP_TYPE_MOV, 108243640Sneel .op_flags = VIE_OP_F_IMM, 109243640Sneel }, 110243640Sneel [0x23] = { 111243640Sneel .op_byte = 0x23, 112243640Sneel .op_type = VIE_OP_TYPE_AND, 113243667Sgrehan }, 114243667Sgrehan [0x81] = { 115243703Sgrehan /* XXX Group 1 extended opcode - not just AND */ 116243667Sgrehan .op_byte = 0x81, 117243667Sgrehan .op_type = VIE_OP_TYPE_AND, 118243667Sgrehan .op_flags = VIE_OP_F_IMM, 119253585Sneel }, 120253585Sneel [0x83] = { 121253585Sneel /* XXX Group 1 extended opcode - not just OR */ 122253585Sneel .op_byte = 0x83, 123253585Sneel .op_type = VIE_OP_TYPE_OR, 124253585Sneel .op_flags = VIE_OP_F_IMM8, 125253585Sneel }, 126243640Sneel}; 127243640Sneel 128243640Sneel/* struct vie.mod */ 129243640Sneel#define VIE_MOD_INDIRECT 0 130243640Sneel#define VIE_MOD_INDIRECT_DISP8 1 131243640Sneel#define VIE_MOD_INDIRECT_DISP32 2 132243640Sneel#define VIE_MOD_DIRECT 3 133243640Sneel 134243640Sneel/* struct vie.rm */ 135243640Sneel#define VIE_RM_SIB 4 136243640Sneel#define VIE_RM_DISP32 5 137243640Sneel 138243640Sneel#define GB (1024 * 1024 * 1024) 139243640Sneel 140240941Sneelstatic enum vm_reg_name gpr_map[16] = { 141240941Sneel VM_REG_GUEST_RAX, 142240941Sneel VM_REG_GUEST_RCX, 143240941Sneel VM_REG_GUEST_RDX, 144240941Sneel VM_REG_GUEST_RBX, 145240941Sneel VM_REG_GUEST_RSP, 146240941Sneel VM_REG_GUEST_RBP, 147240941Sneel VM_REG_GUEST_RSI, 148240941Sneel VM_REG_GUEST_RDI, 149240941Sneel VM_REG_GUEST_R8, 150240941Sneel VM_REG_GUEST_R9, 151240941Sneel VM_REG_GUEST_R10, 152240941Sneel VM_REG_GUEST_R11, 153240941Sneel VM_REG_GUEST_R12, 154240941Sneel VM_REG_GUEST_R13, 155240941Sneel VM_REG_GUEST_R14, 156240941Sneel VM_REG_GUEST_R15 157240941Sneel}; 158240941Sneel 159243640Sneelstatic uint64_t size2mask[] = { 160243640Sneel [1] = 0xff, 161243640Sneel [2] = 0xffff, 162243640Sneel [4] = 0xffffffff, 163243640Sneel [8] = 0xffffffffffffffff, 164243640Sneel}; 165243640Sneel 166243640Sneelstatic int 167243640Sneelvie_read_register(void *vm, int vcpuid, enum vm_reg_name reg, uint64_t *rval) 168243640Sneel{ 169243640Sneel int error; 170243640Sneel 171243640Sneel error = vm_get_register(vm, vcpuid, reg, rval); 172243640Sneel 173243640Sneel return (error); 174243640Sneel} 175243640Sneel 176243640Sneelstatic int 177246108Sneelvie_read_bytereg(void *vm, int vcpuid, struct vie *vie, uint8_t *rval) 178246108Sneel{ 179246108Sneel uint64_t val; 180246108Sneel int error, rshift; 181246108Sneel enum vm_reg_name reg; 182246108Sneel 183246108Sneel rshift = 0; 184246108Sneel reg = gpr_map[vie->reg]; 185246108Sneel 186246108Sneel /* 187246108Sneel * 64-bit mode imposes limitations on accessing legacy byte registers. 188246108Sneel * 189246108Sneel * The legacy high-byte registers cannot be addressed if the REX 190246108Sneel * prefix is present. In this case the values 4, 5, 6 and 7 of the 191246108Sneel * 'ModRM:reg' field address %spl, %bpl, %sil and %dil respectively. 192246108Sneel * 193246108Sneel * If the REX prefix is not present then the values 4, 5, 6 and 7 194246108Sneel * of the 'ModRM:reg' field address the legacy high-byte registers, 195246108Sneel * %ah, %ch, %dh and %bh respectively. 196246108Sneel */ 197246108Sneel if (!vie->rex_present) { 198246108Sneel if (vie->reg & 0x4) { 199246108Sneel /* 200246108Sneel * Obtain the value of %ah by reading %rax and shifting 201246108Sneel * right by 8 bits (same for %bh, %ch and %dh). 202246108Sneel */ 203246108Sneel rshift = 8; 204246108Sneel reg = gpr_map[vie->reg & 0x3]; 205246108Sneel } 206246108Sneel } 207246108Sneel 208246108Sneel error = vm_get_register(vm, vcpuid, reg, &val); 209246108Sneel *rval = val >> rshift; 210246108Sneel return (error); 211246108Sneel} 212246108Sneel 213246108Sneelstatic int 214243640Sneelvie_update_register(void *vm, int vcpuid, enum vm_reg_name reg, 215243640Sneel uint64_t val, int size) 216243640Sneel{ 217243640Sneel int error; 218243640Sneel uint64_t origval; 219243640Sneel 220243640Sneel switch (size) { 221243640Sneel case 1: 222243640Sneel case 2: 223243640Sneel error = vie_read_register(vm, vcpuid, reg, &origval); 224243640Sneel if (error) 225243640Sneel return (error); 226243640Sneel val &= size2mask[size]; 227243640Sneel val |= origval & ~size2mask[size]; 228243640Sneel break; 229243640Sneel case 4: 230243640Sneel val &= 0xffffffffUL; 231243640Sneel break; 232243640Sneel case 8: 233243640Sneel break; 234243640Sneel default: 235243640Sneel return (EINVAL); 236243640Sneel } 237243640Sneel 238243640Sneel error = vm_set_register(vm, vcpuid, reg, val); 239243640Sneel return (error); 240243640Sneel} 241243640Sneel 242243640Sneel/* 243243640Sneel * The following simplifying assumptions are made during emulation: 244243640Sneel * 245243640Sneel * - guest is in 64-bit mode 246243640Sneel * - default address size is 64-bits 247243640Sneel * - default operand size is 32-bits 248243640Sneel * 249243640Sneel * - operand size override is not supported 250243640Sneel * 251243640Sneel * - address size override is not supported 252243640Sneel */ 253243640Sneelstatic int 254243640Sneelemulate_mov(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, 255243640Sneel mem_region_read_t memread, mem_region_write_t memwrite, void *arg) 256243640Sneel{ 257243640Sneel int error, size; 258243640Sneel enum vm_reg_name reg; 259246108Sneel uint8_t byte; 260243640Sneel uint64_t val; 261243640Sneel 262243640Sneel size = 4; 263243640Sneel error = EINVAL; 264243640Sneel 265243640Sneel switch (vie->op.op_byte) { 266246108Sneel case 0x88: 267246108Sneel /* 268246108Sneel * MOV byte from reg (ModRM:reg) to mem (ModRM:r/m) 269246108Sneel * 88/r: mov r/m8, r8 270246108Sneel * REX + 88/r: mov r/m8, r8 (%ah, %ch, %dh, %bh not available) 271246108Sneel */ 272246108Sneel size = 1; 273246108Sneel error = vie_read_bytereg(vm, vcpuid, vie, &byte); 274246108Sneel if (error == 0) 275246108Sneel error = memwrite(vm, vcpuid, gpa, byte, size, arg); 276246108Sneel break; 277243640Sneel case 0x89: 278243640Sneel /* 279243640Sneel * MOV from reg (ModRM:reg) to mem (ModRM:r/m) 280243640Sneel * 89/r: mov r/m32, r32 281243640Sneel * REX.W + 89/r mov r/m64, r64 282243640Sneel */ 283243640Sneel if (vie->rex_w) 284243640Sneel size = 8; 285243640Sneel reg = gpr_map[vie->reg]; 286243640Sneel error = vie_read_register(vm, vcpuid, reg, &val); 287243640Sneel if (error == 0) { 288243640Sneel val &= size2mask[size]; 289243640Sneel error = memwrite(vm, vcpuid, gpa, val, size, arg); 290243640Sneel } 291243640Sneel break; 292254964Sneel case 0x8A: 293243640Sneel case 0x8B: 294243640Sneel /* 295243640Sneel * MOV from mem (ModRM:r/m) to reg (ModRM:reg) 296254964Sneel * 8A/r: mov r/m8, r8 297254964Sneel * REX + 8A/r: mov r/m8, r8 298243640Sneel * 8B/r: mov r32, r/m32 299243640Sneel * REX.W 8B/r: mov r64, r/m64 300243640Sneel */ 301254964Sneel if (vie->op.op_byte == 0x8A) 302254964Sneel size = 1; 303254964Sneel else if (vie->rex_w) 304243640Sneel size = 8; 305243640Sneel error = memread(vm, vcpuid, gpa, &val, size, arg); 306243640Sneel if (error == 0) { 307243640Sneel reg = gpr_map[vie->reg]; 308243640Sneel error = vie_update_register(vm, vcpuid, reg, val, size); 309243640Sneel } 310243640Sneel break; 311243640Sneel case 0xC7: 312243640Sneel /* 313243640Sneel * MOV from imm32 to mem (ModRM:r/m) 314243640Sneel * C7/0 mov r/m32, imm32 315243640Sneel * REX.W + C7/0 mov r/m64, imm32 (sign-extended to 64-bits) 316243640Sneel */ 317243640Sneel val = vie->immediate; /* already sign-extended */ 318243640Sneel 319243640Sneel if (vie->rex_w) 320243640Sneel size = 8; 321243640Sneel 322243640Sneel if (size != 8) 323243640Sneel val &= size2mask[size]; 324243640Sneel 325243640Sneel error = memwrite(vm, vcpuid, gpa, val, size, arg); 326243640Sneel break; 327243640Sneel default: 328243640Sneel break; 329243640Sneel } 330243640Sneel 331243640Sneel return (error); 332243640Sneel} 333243640Sneel 334267396Sjhb/* 335267396Sjhb * The following simplifying assumptions are made during emulation: 336267396Sjhb * 337267396Sjhb * - guest is in 64-bit mode 338267396Sjhb * - default address size is 64-bits 339267396Sjhb * - default operand size is 32-bits 340267396Sjhb * 341267396Sjhb * - operand size override is not supported 342267396Sjhb * 343267396Sjhb * - address size override is not supported 344267396Sjhb */ 345243640Sneelstatic int 346267396Sjhbemulate_movx(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, 347267396Sjhb mem_region_read_t memread, mem_region_write_t memwrite, 348267396Sjhb void *arg) 349267396Sjhb{ 350267396Sjhb int error, size; 351267396Sjhb enum vm_reg_name reg; 352267396Sjhb uint64_t val; 353267396Sjhb 354267396Sjhb size = 4; 355267396Sjhb error = EINVAL; 356267396Sjhb 357267396Sjhb switch (vie->op.op_byte) { 358267396Sjhb case 0xB6: 359267396Sjhb /* 360267396Sjhb * MOV and zero extend byte from mem (ModRM:r/m) to 361267396Sjhb * reg (ModRM:reg). 362267396Sjhb * 363267396Sjhb * 0F B6/r movzx r/m8, r32 364267396Sjhb * REX.W + 0F B6/r movzx r/m8, r64 365267396Sjhb */ 366267396Sjhb 367267396Sjhb /* get the first operand */ 368267396Sjhb error = memread(vm, vcpuid, gpa, &val, 1, arg); 369267396Sjhb if (error) 370267396Sjhb break; 371267396Sjhb 372267396Sjhb /* get the second operand */ 373267396Sjhb reg = gpr_map[vie->reg]; 374267396Sjhb 375267396Sjhb if (vie->rex_w) 376267396Sjhb size = 8; 377267396Sjhb 378267396Sjhb /* write the result */ 379267396Sjhb error = vie_update_register(vm, vcpuid, reg, val, size); 380267396Sjhb break; 381267396Sjhb case 0xBE: 382267396Sjhb /* 383267396Sjhb * MOV and sign extend byte from mem (ModRM:r/m) to 384267396Sjhb * reg (ModRM:reg). 385267396Sjhb * 386267396Sjhb * 0F BE/r movsx r/m8, r32 387267396Sjhb * REX.W + 0F BE/r movsx r/m8, r64 388267396Sjhb */ 389267396Sjhb 390267396Sjhb /* get the first operand */ 391267396Sjhb error = memread(vm, vcpuid, gpa, &val, 1, arg); 392267396Sjhb if (error) 393267396Sjhb break; 394267396Sjhb 395267396Sjhb /* get the second operand */ 396267396Sjhb reg = gpr_map[vie->reg]; 397267396Sjhb 398267396Sjhb if (vie->rex_w) 399267396Sjhb size = 8; 400267396Sjhb 401267396Sjhb /* sign extend byte */ 402267396Sjhb val = (int8_t)val; 403267396Sjhb 404267396Sjhb /* write the result */ 405267396Sjhb error = vie_update_register(vm, vcpuid, reg, val, size); 406267396Sjhb break; 407267396Sjhb default: 408267396Sjhb break; 409267396Sjhb } 410267396Sjhb return (error); 411267396Sjhb} 412267396Sjhb 413267396Sjhbstatic int 414243640Sneelemulate_and(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, 415243640Sneel mem_region_read_t memread, mem_region_write_t memwrite, void *arg) 416243640Sneel{ 417243640Sneel int error, size; 418243640Sneel enum vm_reg_name reg; 419243640Sneel uint64_t val1, val2; 420243640Sneel 421243640Sneel size = 4; 422243640Sneel error = EINVAL; 423243640Sneel 424243640Sneel switch (vie->op.op_byte) { 425243640Sneel case 0x23: 426243640Sneel /* 427243640Sneel * AND reg (ModRM:reg) and mem (ModRM:r/m) and store the 428243640Sneel * result in reg. 429243640Sneel * 430243640Sneel * 23/r and r32, r/m32 431243640Sneel * REX.W + 23/r and r64, r/m64 432243640Sneel */ 433243640Sneel if (vie->rex_w) 434243640Sneel size = 8; 435243640Sneel 436243640Sneel /* get the first operand */ 437243640Sneel reg = gpr_map[vie->reg]; 438243640Sneel error = vie_read_register(vm, vcpuid, reg, &val1); 439243640Sneel if (error) 440243640Sneel break; 441243640Sneel 442243640Sneel /* get the second operand */ 443243640Sneel error = memread(vm, vcpuid, gpa, &val2, size, arg); 444243640Sneel if (error) 445243640Sneel break; 446243640Sneel 447243640Sneel /* perform the operation and write the result */ 448243640Sneel val1 &= val2; 449243640Sneel error = vie_update_register(vm, vcpuid, reg, val1, size); 450243640Sneel break; 451243667Sgrehan case 0x81: 452243667Sgrehan /* 453253585Sneel * AND mem (ModRM:r/m) with immediate and store the 454253585Sneel * result in mem. 455243667Sgrehan * 456243667Sgrehan * 81/ and r/m32, imm32 457243667Sgrehan * REX.W + 81/ and r/m64, imm32 sign-extended to 64 458243703Sgrehan * 459243703Sgrehan * Currently, only the AND operation of the 0x81 opcode 460243703Sgrehan * is implemented (ModRM:reg = b100). 461243667Sgrehan */ 462243703Sgrehan if ((vie->reg & 7) != 4) 463243703Sgrehan break; 464243703Sgrehan 465243667Sgrehan if (vie->rex_w) 466243667Sgrehan size = 8; 467243667Sgrehan 468243667Sgrehan /* get the first operand */ 469243667Sgrehan error = memread(vm, vcpuid, gpa, &val1, size, arg); 470243667Sgrehan if (error) 471243667Sgrehan break; 472243667Sgrehan 473243667Sgrehan /* 474243667Sgrehan * perform the operation with the pre-fetched immediate 475243667Sgrehan * operand and write the result 476243667Sgrehan */ 477243667Sgrehan val1 &= vie->immediate; 478243667Sgrehan error = memwrite(vm, vcpuid, gpa, val1, size, arg); 479243667Sgrehan break; 480243640Sneel default: 481243640Sneel break; 482243640Sneel } 483243640Sneel return (error); 484243640Sneel} 485243640Sneel 486253585Sneelstatic int 487253585Sneelemulate_or(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, 488253585Sneel mem_region_read_t memread, mem_region_write_t memwrite, void *arg) 489253585Sneel{ 490253585Sneel int error, size; 491253585Sneel uint64_t val1; 492253585Sneel 493253585Sneel size = 4; 494253585Sneel error = EINVAL; 495253585Sneel 496253585Sneel switch (vie->op.op_byte) { 497253585Sneel case 0x83: 498253585Sneel /* 499253585Sneel * OR mem (ModRM:r/m) with immediate and store the 500253585Sneel * result in mem. 501253585Sneel * 502253585Sneel * 83/ OR r/m32, imm8 sign-extended to 32 503253585Sneel * REX.W + 83/ OR r/m64, imm8 sign-extended to 64 504253585Sneel * 505253585Sneel * Currently, only the OR operation of the 0x83 opcode 506253585Sneel * is implemented (ModRM:reg = b001). 507253585Sneel */ 508253585Sneel if ((vie->reg & 7) != 1) 509253585Sneel break; 510253585Sneel 511253585Sneel if (vie->rex_w) 512253585Sneel size = 8; 513253585Sneel 514253585Sneel /* get the first operand */ 515253585Sneel error = memread(vm, vcpuid, gpa, &val1, size, arg); 516253585Sneel if (error) 517253585Sneel break; 518253585Sneel 519253585Sneel /* 520253585Sneel * perform the operation with the pre-fetched immediate 521253585Sneel * operand and write the result 522253585Sneel */ 523253585Sneel val1 |= vie->immediate; 524253585Sneel error = memwrite(vm, vcpuid, gpa, val1, size, arg); 525253585Sneel break; 526253585Sneel default: 527253585Sneel break; 528253585Sneel } 529253585Sneel return (error); 530253585Sneel} 531253585Sneel 532243640Sneelint 533243640Sneelvmm_emulate_instruction(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, 534243640Sneel mem_region_read_t memread, mem_region_write_t memwrite, 535243640Sneel void *memarg) 536243640Sneel{ 537243640Sneel int error; 538243640Sneel 539243640Sneel if (!vie->decoded) 540243640Sneel return (EINVAL); 541243640Sneel 542243640Sneel switch (vie->op.op_type) { 543243640Sneel case VIE_OP_TYPE_MOV: 544243640Sneel error = emulate_mov(vm, vcpuid, gpa, vie, 545243640Sneel memread, memwrite, memarg); 546243640Sneel break; 547267396Sjhb case VIE_OP_TYPE_MOVSX: 548267396Sjhb case VIE_OP_TYPE_MOVZX: 549267396Sjhb error = emulate_movx(vm, vcpuid, gpa, vie, 550267396Sjhb memread, memwrite, memarg); 551267396Sjhb break; 552243640Sneel case VIE_OP_TYPE_AND: 553243640Sneel error = emulate_and(vm, vcpuid, gpa, vie, 554243640Sneel memread, memwrite, memarg); 555243640Sneel break; 556253585Sneel case VIE_OP_TYPE_OR: 557253585Sneel error = emulate_or(vm, vcpuid, gpa, vie, 558253585Sneel memread, memwrite, memarg); 559253585Sneel break; 560243640Sneel default: 561243640Sneel error = EINVAL; 562243640Sneel break; 563243640Sneel } 564243640Sneel 565243640Sneel return (error); 566243640Sneel} 567243640Sneel 568243640Sneel#ifdef _KERNEL 569256072Sneelvoid 570240941Sneelvie_init(struct vie *vie) 571240941Sneel{ 572240941Sneel 573240941Sneel bzero(vie, sizeof(struct vie)); 574240941Sneel 575240941Sneel vie->base_register = VM_REG_LAST; 576240941Sneel vie->index_register = VM_REG_LAST; 577240941Sneel} 578240941Sneel 579240941Sneelstatic int 580240941Sneelgla2gpa(struct vm *vm, uint64_t gla, uint64_t ptpphys, 581240941Sneel uint64_t *gpa, uint64_t *gpaend) 582240941Sneel{ 583240941Sneel int nlevels, ptpshift, ptpindex; 584240941Sneel uint64_t *ptpbase, pte, pgsize; 585256072Sneel void *cookie; 586240941Sneel 587240941Sneel /* 588240941Sneel * XXX assumes 64-bit guest with 4 page walk levels 589240941Sneel */ 590240941Sneel nlevels = 4; 591240941Sneel while (--nlevels >= 0) { 592240941Sneel /* Zero out the lower 12 bits and the upper 12 bits */ 593240941Sneel ptpphys >>= 12; ptpphys <<= 24; ptpphys >>= 12; 594240941Sneel 595256072Sneel ptpbase = vm_gpa_hold(vm, ptpphys, PAGE_SIZE, VM_PROT_READ, 596256072Sneel &cookie); 597256072Sneel if (ptpbase == NULL) 598240941Sneel goto error; 599240941Sneel 600240941Sneel ptpshift = PAGE_SHIFT + nlevels * 9; 601240941Sneel ptpindex = (gla >> ptpshift) & 0x1FF; 602240941Sneel pgsize = 1UL << ptpshift; 603240941Sneel 604240941Sneel pte = ptpbase[ptpindex]; 605240941Sneel 606256072Sneel vm_gpa_release(cookie); 607256072Sneel 608240941Sneel if ((pte & PG_V) == 0) 609240941Sneel goto error; 610240941Sneel 611240941Sneel if (pte & PG_PS) { 612240941Sneel if (pgsize > 1 * GB) 613240941Sneel goto error; 614240941Sneel else 615240941Sneel break; 616240941Sneel } 617240941Sneel 618240941Sneel ptpphys = pte; 619240941Sneel } 620240941Sneel 621240941Sneel /* Zero out the lower 'ptpshift' bits and the upper 12 bits */ 622240941Sneel pte >>= ptpshift; pte <<= (ptpshift + 12); pte >>= 12; 623240941Sneel *gpa = pte | (gla & (pgsize - 1)); 624240941Sneel *gpaend = pte + pgsize; 625240941Sneel return (0); 626240941Sneel 627240941Sneelerror: 628240941Sneel return (-1); 629240941Sneel} 630240941Sneel 631240978Sneelint 632243640Sneelvmm_fetch_instruction(struct vm *vm, int cpuid, uint64_t rip, int inst_length, 633240978Sneel uint64_t cr3, struct vie *vie) 634240941Sneel{ 635256072Sneel int n, err, prot; 636256072Sneel uint64_t gpa, gpaend, off; 637256072Sneel void *hpa, *cookie; 638240941Sneel 639240941Sneel /* 640240941Sneel * XXX cache previously fetched instructions using 'rip' as the tag 641240941Sneel */ 642240941Sneel 643256072Sneel prot = VM_PROT_READ | VM_PROT_EXECUTE; 644240978Sneel if (inst_length > VIE_INST_SIZE) 645240978Sneel panic("vmm_fetch_instruction: invalid length %d", inst_length); 646240978Sneel 647240978Sneel /* Copy the instruction into 'vie' */ 648240978Sneel while (vie->num_valid < inst_length) { 649240941Sneel err = gla2gpa(vm, rip, cr3, &gpa, &gpaend); 650240941Sneel if (err) 651240941Sneel break; 652240941Sneel 653241148Sneel off = gpa & PAGE_MASK; 654241148Sneel n = min(inst_length - vie->num_valid, PAGE_SIZE - off); 655240941Sneel 656256072Sneel if ((hpa = vm_gpa_hold(vm, gpa, n, prot, &cookie)) == NULL) 657240941Sneel break; 658240941Sneel 659256072Sneel bcopy(hpa, &vie->inst[vie->num_valid], n); 660240941Sneel 661256072Sneel vm_gpa_release(cookie); 662256072Sneel 663240941Sneel rip += n; 664240941Sneel vie->num_valid += n; 665240941Sneel } 666240978Sneel 667240978Sneel if (vie->num_valid == inst_length) 668240978Sneel return (0); 669240978Sneel else 670240978Sneel return (-1); 671240941Sneel} 672240941Sneel 673240941Sneelstatic int 674240941Sneelvie_peek(struct vie *vie, uint8_t *x) 675240941Sneel{ 676243640Sneel 677240941Sneel if (vie->num_processed < vie->num_valid) { 678240941Sneel *x = vie->inst[vie->num_processed]; 679240941Sneel return (0); 680240941Sneel } else 681240941Sneel return (-1); 682240941Sneel} 683240941Sneel 684240941Sneelstatic void 685240941Sneelvie_advance(struct vie *vie) 686240941Sneel{ 687240941Sneel 688240941Sneel vie->num_processed++; 689240941Sneel} 690240941Sneel 691240941Sneelstatic int 692240941Sneeldecode_rex(struct vie *vie) 693240941Sneel{ 694240941Sneel uint8_t x; 695240941Sneel 696240941Sneel if (vie_peek(vie, &x)) 697240941Sneel return (-1); 698240941Sneel 699240941Sneel if (x >= 0x40 && x <= 0x4F) { 700246108Sneel vie->rex_present = 1; 701246108Sneel 702240941Sneel vie->rex_w = x & 0x8 ? 1 : 0; 703240941Sneel vie->rex_r = x & 0x4 ? 1 : 0; 704240941Sneel vie->rex_x = x & 0x2 ? 1 : 0; 705240941Sneel vie->rex_b = x & 0x1 ? 1 : 0; 706240941Sneel 707240941Sneel vie_advance(vie); 708240941Sneel } 709240941Sneel 710240941Sneel return (0); 711240941Sneel} 712240941Sneel 713240941Sneelstatic int 714267396Sjhbdecode_two_byte_opcode(struct vie *vie) 715267396Sjhb{ 716267396Sjhb uint8_t x; 717267396Sjhb 718267396Sjhb if (vie_peek(vie, &x)) 719267396Sjhb return (-1); 720267396Sjhb 721267396Sjhb vie->op = two_byte_opcodes[x]; 722267396Sjhb 723267396Sjhb if (vie->op.op_type == VIE_OP_TYPE_NONE) 724267396Sjhb return (-1); 725267396Sjhb 726267396Sjhb vie_advance(vie); 727267396Sjhb return (0); 728267396Sjhb} 729267396Sjhb 730267396Sjhbstatic int 731240941Sneeldecode_opcode(struct vie *vie) 732240941Sneel{ 733240941Sneel uint8_t x; 734240941Sneel 735240941Sneel if (vie_peek(vie, &x)) 736240941Sneel return (-1); 737240941Sneel 738243640Sneel vie->op = one_byte_opcodes[x]; 739240941Sneel 740243640Sneel if (vie->op.op_type == VIE_OP_TYPE_NONE) 741243640Sneel return (-1); 742243640Sneel 743240941Sneel vie_advance(vie); 744267396Sjhb 745267396Sjhb if (vie->op.op_type == VIE_OP_TYPE_TWO_BYTE) 746267396Sjhb return (decode_two_byte_opcode(vie)); 747267396Sjhb 748243640Sneel return (0); 749240941Sneel} 750240941Sneel 751240941Sneelstatic int 752240941Sneeldecode_modrm(struct vie *vie) 753240941Sneel{ 754240941Sneel uint8_t x; 755249879Sgrehan enum cpu_mode cpu_mode; 756240941Sneel 757249879Sgrehan /* 758249879Sgrehan * XXX assuming that guest is in IA-32E 64-bit mode 759249879Sgrehan */ 760249879Sgrehan cpu_mode = CPU_MODE_64BIT; 761249879Sgrehan 762240941Sneel if (vie_peek(vie, &x)) 763240941Sneel return (-1); 764240941Sneel 765240941Sneel vie->mod = (x >> 6) & 0x3; 766240941Sneel vie->rm = (x >> 0) & 0x7; 767240941Sneel vie->reg = (x >> 3) & 0x7; 768240941Sneel 769243640Sneel /* 770243640Sneel * A direct addressing mode makes no sense in the context of an EPT 771243640Sneel * fault. There has to be a memory access involved to cause the 772243640Sneel * EPT fault. 773243640Sneel */ 774243640Sneel if (vie->mod == VIE_MOD_DIRECT) 775243640Sneel return (-1); 776243640Sneel 777240941Sneel if ((vie->mod == VIE_MOD_INDIRECT && vie->rm == VIE_RM_DISP32) || 778240941Sneel (vie->mod != VIE_MOD_DIRECT && vie->rm == VIE_RM_SIB)) { 779243640Sneel /* 780243640Sneel * Table 2-5: Special Cases of REX Encodings 781243640Sneel * 782243640Sneel * mod=0, r/m=5 is used in the compatibility mode to 783243640Sneel * indicate a disp32 without a base register. 784243640Sneel * 785243640Sneel * mod!=3, r/m=4 is used in the compatibility mode to 786243640Sneel * indicate that the SIB byte is present. 787243640Sneel * 788243640Sneel * The 'b' bit in the REX prefix is don't care in 789243640Sneel * this case. 790243640Sneel */ 791240941Sneel } else { 792240941Sneel vie->rm |= (vie->rex_b << 3); 793240941Sneel } 794240941Sneel 795240941Sneel vie->reg |= (vie->rex_r << 3); 796240941Sneel 797243640Sneel /* SIB */ 798240941Sneel if (vie->mod != VIE_MOD_DIRECT && vie->rm == VIE_RM_SIB) 799243640Sneel goto done; 800240941Sneel 801240941Sneel vie->base_register = gpr_map[vie->rm]; 802240941Sneel 803240941Sneel switch (vie->mod) { 804240941Sneel case VIE_MOD_INDIRECT_DISP8: 805240941Sneel vie->disp_bytes = 1; 806240941Sneel break; 807240941Sneel case VIE_MOD_INDIRECT_DISP32: 808240941Sneel vie->disp_bytes = 4; 809240941Sneel break; 810240941Sneel case VIE_MOD_INDIRECT: 811240941Sneel if (vie->rm == VIE_RM_DISP32) { 812240941Sneel vie->disp_bytes = 4; 813249879Sgrehan /* 814249879Sgrehan * Table 2-7. RIP-Relative Addressing 815249879Sgrehan * 816249879Sgrehan * In 64-bit mode mod=00 r/m=101 implies [rip] + disp32 817249879Sgrehan * whereas in compatibility mode it just implies disp32. 818249879Sgrehan */ 819249879Sgrehan 820249879Sgrehan if (cpu_mode == CPU_MODE_64BIT) 821249879Sgrehan vie->base_register = VM_REG_GUEST_RIP; 822249879Sgrehan else 823249879Sgrehan vie->base_register = VM_REG_LAST; 824240941Sneel } 825240941Sneel break; 826240941Sneel } 827240941Sneel 828243640Sneeldone: 829240941Sneel vie_advance(vie); 830240941Sneel 831240941Sneel return (0); 832240941Sneel} 833240941Sneel 834240941Sneelstatic int 835243640Sneeldecode_sib(struct vie *vie) 836243640Sneel{ 837243640Sneel uint8_t x; 838243640Sneel 839243640Sneel /* Proceed only if SIB byte is present */ 840243640Sneel if (vie->mod == VIE_MOD_DIRECT || vie->rm != VIE_RM_SIB) 841243640Sneel return (0); 842243640Sneel 843243640Sneel if (vie_peek(vie, &x)) 844243640Sneel return (-1); 845243640Sneel 846243640Sneel /* De-construct the SIB byte */ 847243640Sneel vie->ss = (x >> 6) & 0x3; 848243640Sneel vie->index = (x >> 3) & 0x7; 849243640Sneel vie->base = (x >> 0) & 0x7; 850243640Sneel 851243640Sneel /* Apply the REX prefix modifiers */ 852243640Sneel vie->index |= vie->rex_x << 3; 853243640Sneel vie->base |= vie->rex_b << 3; 854243640Sneel 855243640Sneel switch (vie->mod) { 856243640Sneel case VIE_MOD_INDIRECT_DISP8: 857243640Sneel vie->disp_bytes = 1; 858243640Sneel break; 859243640Sneel case VIE_MOD_INDIRECT_DISP32: 860243640Sneel vie->disp_bytes = 4; 861243640Sneel break; 862243640Sneel } 863243640Sneel 864243640Sneel if (vie->mod == VIE_MOD_INDIRECT && 865243640Sneel (vie->base == 5 || vie->base == 13)) { 866243640Sneel /* 867243640Sneel * Special case when base register is unused if mod = 0 868243640Sneel * and base = %rbp or %r13. 869243640Sneel * 870243640Sneel * Documented in: 871243640Sneel * Table 2-3: 32-bit Addressing Forms with the SIB Byte 872243640Sneel * Table 2-5: Special Cases of REX Encodings 873243640Sneel */ 874243640Sneel vie->disp_bytes = 4; 875243640Sneel } else { 876243640Sneel vie->base_register = gpr_map[vie->base]; 877243640Sneel } 878243640Sneel 879243640Sneel /* 880243640Sneel * All encodings of 'index' are valid except for %rsp (4). 881243640Sneel * 882243640Sneel * Documented in: 883243640Sneel * Table 2-3: 32-bit Addressing Forms with the SIB Byte 884243640Sneel * Table 2-5: Special Cases of REX Encodings 885243640Sneel */ 886243640Sneel if (vie->index != 4) 887243640Sneel vie->index_register = gpr_map[vie->index]; 888243640Sneel 889243640Sneel /* 'scale' makes sense only in the context of an index register */ 890243640Sneel if (vie->index_register < VM_REG_LAST) 891243640Sneel vie->scale = 1 << vie->ss; 892243640Sneel 893243640Sneel vie_advance(vie); 894243640Sneel 895243640Sneel return (0); 896243640Sneel} 897243640Sneel 898243640Sneelstatic int 899240941Sneeldecode_displacement(struct vie *vie) 900240941Sneel{ 901240941Sneel int n, i; 902240941Sneel uint8_t x; 903240941Sneel 904240941Sneel union { 905240941Sneel char buf[4]; 906240941Sneel int8_t signed8; 907240941Sneel int32_t signed32; 908240941Sneel } u; 909240941Sneel 910240941Sneel if ((n = vie->disp_bytes) == 0) 911240941Sneel return (0); 912240941Sneel 913240941Sneel if (n != 1 && n != 4) 914240941Sneel panic("decode_displacement: invalid disp_bytes %d", n); 915240941Sneel 916240941Sneel for (i = 0; i < n; i++) { 917240941Sneel if (vie_peek(vie, &x)) 918240941Sneel return (-1); 919240941Sneel 920240941Sneel u.buf[i] = x; 921240941Sneel vie_advance(vie); 922240941Sneel } 923240941Sneel 924240941Sneel if (n == 1) 925240941Sneel vie->displacement = u.signed8; /* sign-extended */ 926240941Sneel else 927240941Sneel vie->displacement = u.signed32; /* sign-extended */ 928240941Sneel 929240941Sneel return (0); 930240941Sneel} 931240941Sneel 932240941Sneelstatic int 933240941Sneeldecode_immediate(struct vie *vie) 934240941Sneel{ 935240941Sneel int i, n; 936240941Sneel uint8_t x; 937240941Sneel union { 938240941Sneel char buf[4]; 939243640Sneel int8_t signed8; 940240941Sneel int32_t signed32; 941240941Sneel } u; 942240941Sneel 943255638Sneel /* Figure out immediate operand size (if any) */ 944255638Sneel if (vie->op.op_flags & VIE_OP_F_IMM) 945255638Sneel vie->imm_bytes = 4; 946255638Sneel else if (vie->op.op_flags & VIE_OP_F_IMM8) 947255638Sneel vie->imm_bytes = 1; 948255638Sneel 949240941Sneel if ((n = vie->imm_bytes) == 0) 950240941Sneel return (0); 951240941Sneel 952243640Sneel if (n != 1 && n != 4) 953240941Sneel panic("decode_immediate: invalid imm_bytes %d", n); 954240941Sneel 955240941Sneel for (i = 0; i < n; i++) { 956240941Sneel if (vie_peek(vie, &x)) 957240941Sneel return (-1); 958240941Sneel 959240941Sneel u.buf[i] = x; 960240941Sneel vie_advance(vie); 961240941Sneel } 962240941Sneel 963243640Sneel if (n == 1) 964243640Sneel vie->immediate = u.signed8; /* sign-extended */ 965243640Sneel else 966243640Sneel vie->immediate = u.signed32; /* sign-extended */ 967240941Sneel 968240941Sneel return (0); 969240941Sneel} 970240941Sneel 971243640Sneel/* 972252641Sneel * Verify that all the bytes in the instruction buffer were consumed. 973252641Sneel */ 974252641Sneelstatic int 975252641Sneelverify_inst_length(struct vie *vie) 976252641Sneel{ 977252641Sneel 978252641Sneel if (vie->num_processed == vie->num_valid) 979252641Sneel return (0); 980252641Sneel else 981252641Sneel return (-1); 982252641Sneel} 983252641Sneel 984252641Sneel/* 985243640Sneel * Verify that the 'guest linear address' provided as collateral of the nested 986243640Sneel * page table fault matches with our instruction decoding. 987243640Sneel */ 988243640Sneelstatic int 989243640Sneelverify_gla(struct vm *vm, int cpuid, uint64_t gla, struct vie *vie) 990243640Sneel{ 991243640Sneel int error; 992243640Sneel uint64_t base, idx; 993243640Sneel 994248855Sneel /* Skip 'gla' verification */ 995248855Sneel if (gla == VIE_INVALID_GLA) 996248855Sneel return (0); 997248855Sneel 998243640Sneel base = 0; 999243640Sneel if (vie->base_register != VM_REG_LAST) { 1000243640Sneel error = vm_get_register(vm, cpuid, vie->base_register, &base); 1001243640Sneel if (error) { 1002243640Sneel printf("verify_gla: error %d getting base reg %d\n", 1003243640Sneel error, vie->base_register); 1004243640Sneel return (-1); 1005243640Sneel } 1006249879Sgrehan 1007249879Sgrehan /* 1008249879Sgrehan * RIP-relative addressing starts from the following 1009249879Sgrehan * instruction 1010249879Sgrehan */ 1011249879Sgrehan if (vie->base_register == VM_REG_GUEST_RIP) 1012249879Sgrehan base += vie->num_valid; 1013243640Sneel } 1014243640Sneel 1015243640Sneel idx = 0; 1016243640Sneel if (vie->index_register != VM_REG_LAST) { 1017243640Sneel error = vm_get_register(vm, cpuid, vie->index_register, &idx); 1018243640Sneel if (error) { 1019243640Sneel printf("verify_gla: error %d getting index reg %d\n", 1020243640Sneel error, vie->index_register); 1021243640Sneel return (-1); 1022243640Sneel } 1023243640Sneel } 1024243640Sneel 1025243640Sneel if (base + vie->scale * idx + vie->displacement != gla) { 1026243640Sneel printf("verify_gla mismatch: " 1027243640Sneel "base(0x%0lx), scale(%d), index(0x%0lx), " 1028243640Sneel "disp(0x%0lx), gla(0x%0lx)\n", 1029243640Sneel base, vie->scale, idx, vie->displacement, gla); 1030243640Sneel return (-1); 1031243640Sneel } 1032243640Sneel 1033243640Sneel return (0); 1034243640Sneel} 1035243640Sneel 1036240941Sneelint 1037243640Sneelvmm_decode_instruction(struct vm *vm, int cpuid, uint64_t gla, struct vie *vie) 1038240941Sneel{ 1039243640Sneel 1040240941Sneel if (decode_rex(vie)) 1041240941Sneel return (-1); 1042240941Sneel 1043240941Sneel if (decode_opcode(vie)) 1044240941Sneel return (-1); 1045240941Sneel 1046240941Sneel if (decode_modrm(vie)) 1047240941Sneel return (-1); 1048240941Sneel 1049243640Sneel if (decode_sib(vie)) 1050243640Sneel return (-1); 1051243640Sneel 1052240941Sneel if (decode_displacement(vie)) 1053240941Sneel return (-1); 1054240941Sneel 1055240941Sneel if (decode_immediate(vie)) 1056240941Sneel return (-1); 1057240941Sneel 1058252641Sneel if (verify_inst_length(vie)) 1059252641Sneel return (-1); 1060252641Sneel 1061243640Sneel if (verify_gla(vm, cpuid, gla, vie)) 1062243640Sneel return (-1); 1063243640Sneel 1064243640Sneel vie->decoded = 1; /* success */ 1065243640Sneel 1066240941Sneel return (0); 1067240941Sneel} 1068243640Sneel#endif /* _KERNEL */ 1069