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