vmm_instruction_emul.c (241148) | vmm_instruction_emul.c (243640) |
---|---|
1/*- 2 * Copyright (c) 2012 Sandvine, Inc. 3 * Copyright (c) 2012 NetApp, Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 10 unchanged lines hidden (view full) --- 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * | 1/*- 2 * Copyright (c) 2012 Sandvine, Inc. 3 * Copyright (c) 2012 NetApp, Inc. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 10 unchanged lines hidden (view full) --- 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * |
27 * $FreeBSD: projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.c 241148 2012-10-03 01:18:51Z neel $ | 27 * $FreeBSD: projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.c 243640 2012-11-28 00:02:17Z neel $ |
28 */ 29 30#include <sys/cdefs.h> | 28 */ 29 30#include <sys/cdefs.h> |
31__FBSDID("$FreeBSD: projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.c 241148 2012-10-03 01:18:51Z neel $"); | 31__FBSDID("$FreeBSD: projects/bhyve/sys/amd64/vmm/vmm_instruction_emul.c 243640 2012-11-28 00:02:17Z neel $"); |
32 | 32 |
33#ifdef _KERNEL |
|
33#include <sys/param.h> 34#include <sys/pcpu.h> 35#include <sys/systm.h> 36 37#include <vm/vm.h> 38#include <vm/pmap.h> 39 40#include <machine/pmap.h> 41#include <machine/vmparam.h> 42#include <machine/vmm.h> | 34#include <sys/param.h> 35#include <sys/pcpu.h> 36#include <sys/systm.h> 37 38#include <vm/vm.h> 39#include <vm/pmap.h> 40 41#include <machine/pmap.h> 42#include <machine/vmparam.h> 43#include <machine/vmm.h> |
44#else /* !_KERNEL */ 45#include <sys/types.h> 46#include <sys/errno.h> |
|
43 | 47 |
44#include "vmm_instruction_emul.h" | 48#include <machine/vmm.h> |
45 | 49 |
46#define GB (1024 * 1024 * 1024) | 50#include <vmmapi.h> 51#endif /* _KERNEL */ |
47 | 52 |
53 54 55/* struct vie_op.op_type */ 56enum { 57 VIE_OP_TYPE_NONE = 0, 58 VIE_OP_TYPE_MOV, 59 VIE_OP_TYPE_AND, 60 VIE_OP_TYPE_LAST 61}; 62 63/* struct vie_op.op_flags */ 64#define VIE_OP_F_IMM (1 << 0) /* immediate operand present */ 65#define VIE_OP_F_IMM8 (1 << 1) /* 8-bit immediate operand */ 66 67static const struct vie_op one_byte_opcodes[256] = { 68 [0x89] = { 69 .op_byte = 0x89, 70 .op_type = VIE_OP_TYPE_MOV, 71 }, 72 [0x8B] = { 73 .op_byte = 0x8B, 74 .op_type = VIE_OP_TYPE_MOV, 75 }, 76 [0xC7] = { 77 .op_byte = 0xC7, 78 .op_type = VIE_OP_TYPE_MOV, 79 .op_flags = VIE_OP_F_IMM, 80 }, 81 [0x23] = { 82 .op_byte = 0x23, 83 .op_type = VIE_OP_TYPE_AND, 84 } 85}; 86 87/* struct vie.mod */ 88#define VIE_MOD_INDIRECT 0 89#define VIE_MOD_INDIRECT_DISP8 1 90#define VIE_MOD_INDIRECT_DISP32 2 91#define VIE_MOD_DIRECT 3 92 93/* struct vie.rm */ 94#define VIE_RM_SIB 4 95#define VIE_RM_DISP32 5 96 97#define GB (1024 * 1024 * 1024) 98 |
|
48static enum vm_reg_name gpr_map[16] = { 49 VM_REG_GUEST_RAX, 50 VM_REG_GUEST_RCX, 51 VM_REG_GUEST_RDX, 52 VM_REG_GUEST_RBX, 53 VM_REG_GUEST_RSP, 54 VM_REG_GUEST_RBP, 55 VM_REG_GUEST_RSI, 56 VM_REG_GUEST_RDI, 57 VM_REG_GUEST_R8, 58 VM_REG_GUEST_R9, 59 VM_REG_GUEST_R10, 60 VM_REG_GUEST_R11, 61 VM_REG_GUEST_R12, 62 VM_REG_GUEST_R13, 63 VM_REG_GUEST_R14, 64 VM_REG_GUEST_R15 65}; 66 | 99static enum vm_reg_name gpr_map[16] = { 100 VM_REG_GUEST_RAX, 101 VM_REG_GUEST_RCX, 102 VM_REG_GUEST_RDX, 103 VM_REG_GUEST_RBX, 104 VM_REG_GUEST_RSP, 105 VM_REG_GUEST_RBP, 106 VM_REG_GUEST_RSI, 107 VM_REG_GUEST_RDI, 108 VM_REG_GUEST_R8, 109 VM_REG_GUEST_R9, 110 VM_REG_GUEST_R10, 111 VM_REG_GUEST_R11, 112 VM_REG_GUEST_R12, 113 VM_REG_GUEST_R13, 114 VM_REG_GUEST_R14, 115 VM_REG_GUEST_R15 116}; 117 |
118static uint64_t size2mask[] = { 119 [1] = 0xff, 120 [2] = 0xffff, 121 [4] = 0xffffffff, 122 [8] = 0xffffffffffffffff, 123}; 124 125static int 126vie_valid_register(enum vm_reg_name reg) 127{ 128#ifdef _KERNEL 129 /* 130 * XXX 131 * The operand register in which we store the result of the 132 * read must be a GPR that we can modify even if the vcpu 133 * is "running". All the GPRs qualify except for %rsp. 134 * 135 * This is a limitation of the vm_set_register() API 136 * and can be fixed if necessary. 137 */ 138 if (reg == VM_REG_GUEST_RSP) 139 return (0); 140#endif 141 return (1); 142} 143 144static int 145vie_read_register(void *vm, int vcpuid, enum vm_reg_name reg, uint64_t *rval) 146{ 147 int error; 148 149 if (!vie_valid_register(reg)) 150 return (EINVAL); 151 152 error = vm_get_register(vm, vcpuid, reg, rval); 153 154 return (error); 155} 156 157static int 158vie_update_register(void *vm, int vcpuid, enum vm_reg_name reg, 159 uint64_t val, int size) 160{ 161 int error; 162 uint64_t origval; 163 164 if (!vie_valid_register(reg)) 165 return (EINVAL); 166 167 switch (size) { 168 case 1: 169 case 2: 170 error = vie_read_register(vm, vcpuid, reg, &origval); 171 if (error) 172 return (error); 173 val &= size2mask[size]; 174 val |= origval & ~size2mask[size]; 175 break; 176 case 4: 177 val &= 0xffffffffUL; 178 break; 179 case 8: 180 break; 181 default: 182 return (EINVAL); 183 } 184 185 error = vm_set_register(vm, vcpuid, reg, val); 186 return (error); 187} 188 189/* 190 * The following simplifying assumptions are made during emulation: 191 * 192 * - guest is in 64-bit mode 193 * - default address size is 64-bits 194 * - default operand size is 32-bits 195 * 196 * - operand size override is not supported 197 * 198 * - address size override is not supported 199 */ 200static int 201emulate_mov(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, 202 mem_region_read_t memread, mem_region_write_t memwrite, void *arg) 203{ 204 int error, size; 205 enum vm_reg_name reg; 206 uint64_t val; 207 208 size = 4; 209 error = EINVAL; 210 211 switch (vie->op.op_byte) { 212 case 0x89: 213 /* 214 * MOV from reg (ModRM:reg) to mem (ModRM:r/m) 215 * 89/r: mov r/m32, r32 216 * REX.W + 89/r mov r/m64, r64 217 */ 218 if (vie->rex_w) 219 size = 8; 220 reg = gpr_map[vie->reg]; 221 error = vie_read_register(vm, vcpuid, reg, &val); 222 if (error == 0) { 223 val &= size2mask[size]; 224 error = memwrite(vm, vcpuid, gpa, val, size, arg); 225 } 226 break; 227 case 0x8B: 228 /* 229 * MOV from mem (ModRM:r/m) to reg (ModRM:reg) 230 * 8B/r: mov r32, r/m32 231 * REX.W 8B/r: mov r64, r/m64 232 */ 233 if (vie->rex_w) 234 size = 8; 235 error = memread(vm, vcpuid, gpa, &val, size, arg); 236 if (error == 0) { 237 reg = gpr_map[vie->reg]; 238 error = vie_update_register(vm, vcpuid, reg, val, size); 239 } 240 break; 241 case 0xC7: 242 /* 243 * MOV from imm32 to mem (ModRM:r/m) 244 * C7/0 mov r/m32, imm32 245 * REX.W + C7/0 mov r/m64, imm32 (sign-extended to 64-bits) 246 */ 247 val = vie->immediate; /* already sign-extended */ 248 249 if (vie->rex_w) 250 size = 8; 251 252 if (size != 8) 253 val &= size2mask[size]; 254 255 error = memwrite(vm, vcpuid, gpa, val, size, arg); 256 break; 257 default: 258 break; 259 } 260 261 return (error); 262} 263 264static int 265emulate_and(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, 266 mem_region_read_t memread, mem_region_write_t memwrite, void *arg) 267{ 268 int error, size; 269 enum vm_reg_name reg; 270 uint64_t val1, val2; 271 272 size = 4; 273 error = EINVAL; 274 275 switch (vie->op.op_byte) { 276 case 0x23: 277 /* 278 * AND reg (ModRM:reg) and mem (ModRM:r/m) and store the 279 * result in reg. 280 * 281 * 23/r and r32, r/m32 282 * REX.W + 23/r and r64, r/m64 283 */ 284 if (vie->rex_w) 285 size = 8; 286 287 /* get the first operand */ 288 reg = gpr_map[vie->reg]; 289 error = vie_read_register(vm, vcpuid, reg, &val1); 290 if (error) 291 break; 292 293 /* get the second operand */ 294 error = memread(vm, vcpuid, gpa, &val2, size, arg); 295 if (error) 296 break; 297 298 /* perform the operation and write the result */ 299 val1 &= val2; 300 error = vie_update_register(vm, vcpuid, reg, val1, size); 301 break; 302 default: 303 break; 304 } 305 return (error); 306} 307 308int 309vmm_emulate_instruction(void *vm, int vcpuid, uint64_t gpa, struct vie *vie, 310 mem_region_read_t memread, mem_region_write_t memwrite, 311 void *memarg) 312{ 313 int error; 314 315 if (!vie->decoded) 316 return (EINVAL); 317 318 switch (vie->op.op_type) { 319 case VIE_OP_TYPE_MOV: 320 error = emulate_mov(vm, vcpuid, gpa, vie, 321 memread, memwrite, memarg); 322 break; 323 case VIE_OP_TYPE_AND: 324 error = emulate_and(vm, vcpuid, gpa, vie, 325 memread, memwrite, memarg); 326 break; 327 default: 328 error = EINVAL; 329 break; 330 } 331 332 return (error); 333} 334 335#ifdef _KERNEL |
|
67static void 68vie_init(struct vie *vie) 69{ 70 71 bzero(vie, sizeof(struct vie)); 72 | 336static void 337vie_init(struct vie *vie) 338{ 339 340 bzero(vie, sizeof(struct vie)); 341 |
73 vie->op_size = VIE_OP_SIZE_32BIT; 74 | |
75 vie->base_register = VM_REG_LAST; 76 vie->index_register = VM_REG_LAST; | 342 vie->base_register = VM_REG_LAST; 343 vie->index_register = VM_REG_LAST; |
77 vie->operand_register = VM_REG_LAST; | |
78} 79 80static int 81gla2gpa(struct vm *vm, uint64_t gla, uint64_t ptpphys, 82 uint64_t *gpa, uint64_t *gpaend) 83{ 84 vm_paddr_t hpa; 85 int nlevels, ptpshift, ptpindex; --- 38 unchanged lines hidden (view full) --- 124 *gpaend = pte + pgsize; 125 return (0); 126 127error: 128 return (-1); 129} 130 131int | 344} 345 346static int 347gla2gpa(struct vm *vm, uint64_t gla, uint64_t ptpphys, 348 uint64_t *gpa, uint64_t *gpaend) 349{ 350 vm_paddr_t hpa; 351 int nlevels, ptpshift, ptpindex; --- 38 unchanged lines hidden (view full) --- 390 *gpaend = pte + pgsize; 391 return (0); 392 393error: 394 return (-1); 395} 396 397int |
132vmm_fetch_instruction(struct vm *vm, uint64_t rip, int inst_length, | 398vmm_fetch_instruction(struct vm *vm, int cpuid, uint64_t rip, int inst_length, |
133 uint64_t cr3, struct vie *vie) 134{ 135 int n, err; 136 uint64_t hpa, gpa, gpaend, off; 137 138 /* 139 * XXX cache previously fetched instructions using 'rip' as the tag 140 */ --- 26 unchanged lines hidden (view full) --- 167 return (0); 168 else 169 return (-1); 170} 171 172static int 173vie_peek(struct vie *vie, uint8_t *x) 174{ | 399 uint64_t cr3, struct vie *vie) 400{ 401 int n, err; 402 uint64_t hpa, gpa, gpaend, off; 403 404 /* 405 * XXX cache previously fetched instructions using 'rip' as the tag 406 */ --- 26 unchanged lines hidden (view full) --- 433 return (0); 434 else 435 return (-1); 436} 437 438static int 439vie_peek(struct vie *vie, uint8_t *x) 440{ |
441 |
|
175 if (vie->num_processed < vie->num_valid) { 176 *x = vie->inst[vie->num_processed]; 177 return (0); 178 } else 179 return (-1); 180} 181 182static void 183vie_advance(struct vie *vie) 184{ | 442 if (vie->num_processed < vie->num_valid) { 443 *x = vie->inst[vie->num_processed]; 444 return (0); 445 } else 446 return (-1); 447} 448 449static void 450vie_advance(struct vie *vie) 451{ |
185 if (vie->num_processed >= vie->num_valid) 186 panic("vie_advance: %d/%d", vie->num_processed, vie->num_valid); | |
187 188 vie->num_processed++; 189} 190 191static int 192decode_rex(struct vie *vie) 193{ 194 uint8_t x; --- 13 unchanged lines hidden (view full) --- 208 return (0); 209} 210 211static int 212decode_opcode(struct vie *vie) 213{ 214 uint8_t x; 215 | 452 453 vie->num_processed++; 454} 455 456static int 457decode_rex(struct vie *vie) 458{ 459 uint8_t x; --- 13 unchanged lines hidden (view full) --- 473 return (0); 474} 475 476static int 477decode_opcode(struct vie *vie) 478{ 479 uint8_t x; 480 |
216 static const uint8_t flags[256] = { 217 [0x89] = VIE_F_HAS_MODRM | VIE_F_FROM_REG | VIE_F_TO_RM, 218 [0x8B] = VIE_F_HAS_MODRM | VIE_F_FROM_RM | VIE_F_TO_REG, 219 [0xC7] = VIE_F_HAS_MODRM | VIE_F_FROM_IMM | VIE_F_TO_RM, 220 }; 221 | |
222 if (vie_peek(vie, &x)) 223 return (-1); 224 | 481 if (vie_peek(vie, &x)) 482 return (-1); 483 |
225 vie->opcode_byte = x; 226 vie->opcode_flags = flags[x]; | 484 vie->op = one_byte_opcodes[x]; |
227 | 485 |
228 vie_advance(vie); 229 230 if (vie->opcode_flags == 0) | 486 if (vie->op.op_type == VIE_OP_TYPE_NONE) |
231 return (-1); | 487 return (-1); |
232 else 233 return (0); | 488 489 vie_advance(vie); 490 return (0); |
234} 235 236/* 237 * XXX assuming 32-bit or 64-bit guest 238 */ 239static int 240decode_modrm(struct vie *vie) 241{ 242 uint8_t x; 243 | 491} 492 493/* 494 * XXX assuming 32-bit or 64-bit guest 495 */ 496static int 497decode_modrm(struct vie *vie) 498{ 499 uint8_t x; 500 |
244 if ((vie->opcode_flags & VIE_F_HAS_MODRM) == 0) 245 return (0); 246 | |
247 if (vie_peek(vie, &x)) 248 return (-1); 249 250 vie->mod = (x >> 6) & 0x3; 251 vie->rm = (x >> 0) & 0x7; 252 vie->reg = (x >> 3) & 0x7; 253 | 501 if (vie_peek(vie, &x)) 502 return (-1); 503 504 vie->mod = (x >> 6) & 0x3; 505 vie->rm = (x >> 0) & 0x7; 506 vie->reg = (x >> 3) & 0x7; 507 |
508 /* 509 * A direct addressing mode makes no sense in the context of an EPT 510 * fault. There has to be a memory access involved to cause the 511 * EPT fault. 512 */ 513 if (vie->mod == VIE_MOD_DIRECT) 514 return (-1); 515 |
|
254 if ((vie->mod == VIE_MOD_INDIRECT && vie->rm == VIE_RM_DISP32) || 255 (vie->mod != VIE_MOD_DIRECT && vie->rm == VIE_RM_SIB)) { | 516 if ((vie->mod == VIE_MOD_INDIRECT && vie->rm == VIE_RM_DISP32) || 517 (vie->mod != VIE_MOD_DIRECT && vie->rm == VIE_RM_SIB)) { |
256 /* 257 * Table 2-5: Special Cases of REX Encodings 258 * 259 * mod=0, r/m=5 is used in the compatibility mode to 260 * indicate a disp32 without a base register. 261 * 262 * mod!=3, r/m=4 is used in the compatibility mode to 263 * indicate that the SIB byte is present. 264 * 265 * The 'b' bit in the REX prefix is don't care in 266 * this case. 267 */ | 518 /* 519 * Table 2-5: Special Cases of REX Encodings 520 * 521 * mod=0, r/m=5 is used in the compatibility mode to 522 * indicate a disp32 without a base register. 523 * 524 * mod!=3, r/m=4 is used in the compatibility mode to 525 * indicate that the SIB byte is present. 526 * 527 * The 'b' bit in the REX prefix is don't care in 528 * this case. 529 */ |
268 } else { 269 vie->rm |= (vie->rex_b << 3); 270 } 271 272 vie->reg |= (vie->rex_r << 3); 273 | 530 } else { 531 vie->rm |= (vie->rex_b << 3); 532 } 533 534 vie->reg |= (vie->rex_r << 3); 535 |
274 /* SIB addressing not supported yet */ | 536 /* SIB */ |
275 if (vie->mod != VIE_MOD_DIRECT && vie->rm == VIE_RM_SIB) | 537 if (vie->mod != VIE_MOD_DIRECT && vie->rm == VIE_RM_SIB) |
276 return (-1); | 538 goto done; |
277 278 vie->base_register = gpr_map[vie->rm]; 279 | 539 540 vie->base_register = gpr_map[vie->rm]; 541 |
280 if (vie->opcode_flags & (VIE_F_FROM_REG | VIE_F_TO_REG)) 281 vie->operand_register = gpr_map[vie->reg]; 282 | |
283 switch (vie->mod) { 284 case VIE_MOD_INDIRECT_DISP8: 285 vie->disp_bytes = 1; 286 break; 287 case VIE_MOD_INDIRECT_DISP32: 288 vie->disp_bytes = 4; 289 break; 290 case VIE_MOD_INDIRECT: 291 if (vie->rm == VIE_RM_DISP32) { 292 vie->disp_bytes = 4; 293 vie->base_register = VM_REG_LAST; /* no base */ 294 } 295 break; 296 } 297 | 542 switch (vie->mod) { 543 case VIE_MOD_INDIRECT_DISP8: 544 vie->disp_bytes = 1; 545 break; 546 case VIE_MOD_INDIRECT_DISP32: 547 vie->disp_bytes = 4; 548 break; 549 case VIE_MOD_INDIRECT: 550 if (vie->rm == VIE_RM_DISP32) { 551 vie->disp_bytes = 4; 552 vie->base_register = VM_REG_LAST; /* no base */ 553 } 554 break; 555 } 556 |
298 /* calculate the operand size */ 299 if (vie->rex_w) 300 vie->op_size = VIE_OP_SIZE_64BIT; 301 302 if (vie->opcode_flags & VIE_F_FROM_IMM) | 557 /* Figure out immediate operand size (if any) */ 558 if (vie->op.op_flags & VIE_OP_F_IMM) |
303 vie->imm_bytes = 4; | 559 vie->imm_bytes = 4; |
560 else if (vie->op.op_flags & VIE_OP_F_IMM8) 561 vie->imm_bytes = 1; |
|
304 | 562 |
563done: |
|
305 vie_advance(vie); 306 307 return (0); 308} 309 310static int | 564 vie_advance(vie); 565 566 return (0); 567} 568 569static int |
570decode_sib(struct vie *vie) 571{ 572 uint8_t x; 573 574 /* Proceed only if SIB byte is present */ 575 if (vie->mod == VIE_MOD_DIRECT || vie->rm != VIE_RM_SIB) 576 return (0); 577 578 if (vie_peek(vie, &x)) 579 return (-1); 580 581 /* De-construct the SIB byte */ 582 vie->ss = (x >> 6) & 0x3; 583 vie->index = (x >> 3) & 0x7; 584 vie->base = (x >> 0) & 0x7; 585 586 /* Apply the REX prefix modifiers */ 587 vie->index |= vie->rex_x << 3; 588 vie->base |= vie->rex_b << 3; 589 590 switch (vie->mod) { 591 case VIE_MOD_INDIRECT_DISP8: 592 vie->disp_bytes = 1; 593 break; 594 case VIE_MOD_INDIRECT_DISP32: 595 vie->disp_bytes = 4; 596 break; 597 } 598 599 if (vie->mod == VIE_MOD_INDIRECT && 600 (vie->base == 5 || vie->base == 13)) { 601 /* 602 * Special case when base register is unused if mod = 0 603 * and base = %rbp or %r13. 604 * 605 * Documented in: 606 * Table 2-3: 32-bit Addressing Forms with the SIB Byte 607 * Table 2-5: Special Cases of REX Encodings 608 */ 609 vie->disp_bytes = 4; 610 } else { 611 vie->base_register = gpr_map[vie->base]; 612 } 613 614 /* 615 * All encodings of 'index' are valid except for %rsp (4). 616 * 617 * Documented in: 618 * Table 2-3: 32-bit Addressing Forms with the SIB Byte 619 * Table 2-5: Special Cases of REX Encodings 620 */ 621 if (vie->index != 4) 622 vie->index_register = gpr_map[vie->index]; 623 624 /* 'scale' makes sense only in the context of an index register */ 625 if (vie->index_register < VM_REG_LAST) 626 vie->scale = 1 << vie->ss; 627 628 vie_advance(vie); 629 630 return (0); 631} 632 633static int |
|
311decode_displacement(struct vie *vie) 312{ 313 int n, i; 314 uint8_t x; 315 316 union { 317 char buf[4]; 318 int8_t signed8; --- 24 unchanged lines hidden (view full) --- 343 344static int 345decode_immediate(struct vie *vie) 346{ 347 int i, n; 348 uint8_t x; 349 union { 350 char buf[4]; | 634decode_displacement(struct vie *vie) 635{ 636 int n, i; 637 uint8_t x; 638 639 union { 640 char buf[4]; 641 int8_t signed8; --- 24 unchanged lines hidden (view full) --- 666 667static int 668decode_immediate(struct vie *vie) 669{ 670 int i, n; 671 uint8_t x; 672 union { 673 char buf[4]; |
674 int8_t signed8; |
|
351 int32_t signed32; 352 } u; 353 354 if ((n = vie->imm_bytes) == 0) 355 return (0); 356 | 675 int32_t signed32; 676 } u; 677 678 if ((n = vie->imm_bytes) == 0) 679 return (0); 680 |
357 if (n != 4) | 681 if (n != 1 && n != 4) |
358 panic("decode_immediate: invalid imm_bytes %d", n); 359 360 for (i = 0; i < n; i++) { 361 if (vie_peek(vie, &x)) 362 return (-1); 363 364 u.buf[i] = x; 365 vie_advance(vie); 366 } 367 | 682 panic("decode_immediate: invalid imm_bytes %d", n); 683 684 for (i = 0; i < n; i++) { 685 if (vie_peek(vie, &x)) 686 return (-1); 687 688 u.buf[i] = x; 689 vie_advance(vie); 690 } 691 |
368 vie->immediate = u.signed32; /* sign-extended */ | 692 if (n == 1) 693 vie->immediate = u.signed8; /* sign-extended */ 694 else 695 vie->immediate = u.signed32; /* sign-extended */ |
369 370 return (0); 371} 372 | 696 697 return (0); 698} 699 |
700#define VERIFY_GLA 701/* 702 * Verify that the 'guest linear address' provided as collateral of the nested 703 * page table fault matches with our instruction decoding. 704 */ 705#ifdef VERIFY_GLA 706static int 707verify_gla(struct vm *vm, int cpuid, uint64_t gla, struct vie *vie) 708{ 709 int error; 710 uint64_t base, idx; 711 712 base = 0; 713 if (vie->base_register != VM_REG_LAST) { 714 error = vm_get_register(vm, cpuid, vie->base_register, &base); 715 if (error) { 716 printf("verify_gla: error %d getting base reg %d\n", 717 error, vie->base_register); 718 return (-1); 719 } 720 } 721 722 idx = 0; 723 if (vie->index_register != VM_REG_LAST) { 724 error = vm_get_register(vm, cpuid, vie->index_register, &idx); 725 if (error) { 726 printf("verify_gla: error %d getting index reg %d\n", 727 error, vie->index_register); 728 return (-1); 729 } 730 } 731 732 if (base + vie->scale * idx + vie->displacement != gla) { 733 printf("verify_gla mismatch: " 734 "base(0x%0lx), scale(%d), index(0x%0lx), " 735 "disp(0x%0lx), gla(0x%0lx)\n", 736 base, vie->scale, idx, vie->displacement, gla); 737 return (-1); 738 } 739 740 return (0); 741} 742#endif /* VERIFY_GLA */ 743 |
|
373int | 744int |
374vmm_decode_instruction(struct vie *vie) | 745vmm_decode_instruction(struct vm *vm, int cpuid, uint64_t gla, struct vie *vie) |
375{ | 746{ |
747 |
|
376 if (decode_rex(vie)) 377 return (-1); 378 379 if (decode_opcode(vie)) 380 return (-1); 381 382 if (decode_modrm(vie)) 383 return (-1); 384 | 748 if (decode_rex(vie)) 749 return (-1); 750 751 if (decode_opcode(vie)) 752 return (-1); 753 754 if (decode_modrm(vie)) 755 return (-1); 756 |
757 if (decode_sib(vie)) 758 return (-1); 759 |
|
385 if (decode_displacement(vie)) 386 return (-1); 387 388 if (decode_immediate(vie)) 389 return (-1); 390 | 760 if (decode_displacement(vie)) 761 return (-1); 762 763 if (decode_immediate(vie)) 764 return (-1); 765 |
766#ifdef VERIFY_GLA 767 if (verify_gla(vm, cpuid, gla, vie)) 768 return (-1); 769#endif 770 771 vie->decoded = 1; /* success */ 772 |
|
391 return (0); 392} | 773 return (0); 774} |
775#endif /* _KERNEL */ |
|