Deleted Added
sdiff udiff text old ( 241148 ) new ( 243640 )
full compact
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 $
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 $");
32
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>
43
44#include "vmm_instruction_emul.h"
45
46#define GB (1024 * 1024 * 1024)
47
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
67static void
68vie_init(struct vie *vie)
69{
70
71 bzero(vie, sizeof(struct vie));
72
73 vie->op_size = VIE_OP_SIZE_32BIT;
74
75 vie->base_register = VM_REG_LAST;
76 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
132vmm_fetch_instruction(struct vm *vm, 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{
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{
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
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
225 vie->opcode_byte = x;
226 vie->opcode_flags = flags[x];
227
228 vie_advance(vie);
229
230 if (vie->opcode_flags == 0)
231 return (-1);
232 else
233 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
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
254 if ((vie->mod == VIE_MOD_INDIRECT && vie->rm == VIE_RM_DISP32) ||
255 (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 */
268 } else {
269 vie->rm |= (vie->rex_b << 3);
270 }
271
272 vie->reg |= (vie->rex_r << 3);
273
274 /* SIB addressing not supported yet */
275 if (vie->mod != VIE_MOD_DIRECT && vie->rm == VIE_RM_SIB)
276 return (-1);
277
278 vie->base_register = gpr_map[vie->rm];
279
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
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)
303 vie->imm_bytes = 4;
304
305 vie_advance(vie);
306
307 return (0);
308}
309
310static 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];
351 int32_t signed32;
352 } u;
353
354 if ((n = vie->imm_bytes) == 0)
355 return (0);
356
357 if (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
368 vie->immediate = u.signed32; /* sign-extended */
369
370 return (0);
371}
372
373int
374vmm_decode_instruction(struct vie *vie)
375{
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
385 if (decode_displacement(vie))
386 return (-1);
387
388 if (decode_immediate(vie))
389 return (-1);
390
391 return (0);
392}