2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Authors: Jack Lange <jarusl@cs.northwestern.edu>
15 * Peter Dinda <pdinda@northwestern.edu> (full hook/string ops)
17 * This is free software. You are permitted to use,
18 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_emulator.h>
23 #include <palacios/vmm_decoder.h>
24 #include <palacios/vmm_instr_emulator.h>
25 #include <palacios/vmm_ctrl_regs.h>
27 #ifndef CONFIG_DEBUG_EMULATOR
29 #define PrintDebug(fmt, args...)
33 static int run_op(struct guest_info * info, v3_op_type_t op_type,
34 addr_t src_addr, addr_t dst_addr,
35 int src_op_size, int dst_op_size) {
37 if (src_op_size == 1) {
38 PrintDebug("Executing 8 bit instruction\n");
42 adc8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
45 add8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
48 and8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
51 or8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
54 xor8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
57 sub8((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
61 mov8((addr_t *)dst_addr, (addr_t *)src_addr);
65 movzx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
68 movsx8((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
72 not8((addr_t *)dst_addr);
75 xchg8((addr_t *)dst_addr, (addr_t *)src_addr);
80 inc8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
83 dec8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
86 neg8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
89 setb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
92 setbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
95 setl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
98 setle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
101 setnb8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
104 setnbe8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
107 setnl8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
110 setnle8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
113 setno8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
116 setnp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
119 setns8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
122 setnz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
125 seto8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
128 setp8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
131 sets8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
134 setz8((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
138 PrintError("Unknown 8 bit instruction\n");
142 } else if (src_op_size == 2) {
143 PrintDebug("Executing 16 bit instruction\n");
147 adc16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
150 add16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
153 and16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
156 or16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
159 xor16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
162 sub16((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
167 inc16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
170 dec16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
173 neg16((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
177 mov16((addr_t *)dst_addr, (addr_t *)src_addr);
180 movzx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
183 movsx16((addr_t *)dst_addr, (addr_t *)src_addr, dst_op_size);
186 not16((addr_t *)dst_addr);
189 xchg16((addr_t *)dst_addr, (addr_t *)src_addr);
193 PrintError("Unknown 16 bit instruction\n");
197 } else if (src_op_size == 4) {
198 PrintDebug("Executing 32 bit instruction\n");
202 adc32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
205 add32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
208 and32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
211 or32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
214 xor32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
217 sub32((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
221 inc32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
224 dec32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
227 neg32((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
231 mov32((addr_t *)dst_addr, (addr_t *)src_addr);
235 not32((addr_t *)dst_addr);
238 xchg32((addr_t *)dst_addr, (addr_t *)src_addr);
242 PrintError("Unknown 32 bit instruction\n");
247 } else if (src_op_size == 8) {
248 PrintDebug("Executing 64 bit instruction\n");
252 adc64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
255 add64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
258 and64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
261 or64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
264 xor64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
267 sub64((addr_t *)dst_addr, (addr_t *)src_addr, (addr_t *)&(info->ctrl_regs.rflags));
271 inc64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
274 dec64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
277 neg64((addr_t *)dst_addr, (addr_t *)&(info->ctrl_regs.rflags));
281 mov64((addr_t *)dst_addr, (addr_t *)src_addr);
285 not64((addr_t *)dst_addr);
288 xchg64((addr_t *)dst_addr, (addr_t *)src_addr);
292 PrintError("Unknown 64 bit instruction\n");
298 PrintError("Invalid Operation Size\n");
307 /* Returns the number of bytes written, or -1 if there is an error */
308 static int run_str_op(struct guest_info * core, struct x86_instr * instr,
309 addr_t src_addr, addr_t dst_addr,
310 int op_size, int rep_cnt) {
312 addr_t tmp_rcx = rep_cnt;
313 int emulation_length = op_size * rep_cnt;
314 struct rflags * flags_reg = (struct rflags *)&(core->ctrl_regs.rflags);
316 if (instr->op_type == V3_OP_MOVS) {
318 movs8((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
319 } else if (op_size == 2) {
320 movs16((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
321 } else if (op_size == 4) {
322 movs32((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
324 } else if (op_size == 8) {
325 movs64((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
328 PrintError("Invalid operand length\n");
332 if (flags_reg->df == 0) {
333 core->vm_regs.rdi += emulation_length;
334 core->vm_regs.rsi += emulation_length;
336 core->vm_regs.rdi -= emulation_length;
337 core->vm_regs.rsi -= emulation_length;
340 // RCX is only modified if the rep prefix is present
341 if (instr->prefixes.rep == 1) {
342 core->vm_regs.rcx -= rep_cnt;
345 } else if (instr->op_type == V3_OP_STOS) {
347 stos8((addr_t *)&dst_addr, (addr_t *)&(core->vm_regs.rax), &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
348 } else if (op_size == 2) {
349 stos16((addr_t *)&dst_addr, (addr_t *)&(core->vm_regs.rax), &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
350 } else if (op_size == 4) {
351 stos32((addr_t *)&dst_addr, (addr_t *)&(core->vm_regs.rax), &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
353 } else if (op_size == 8) {
354 stos64((addr_t *)&dst_addr, (addr_t *)&(core->vm_regs.rax), &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
357 PrintError("Invalid operand length\n");
361 if (flags_reg->df == 0) {
362 core->vm_regs.rdi += emulation_length;
364 core->vm_regs.rdi -= emulation_length;
367 // RCX is only modified if the rep prefix is present
368 if (instr->prefixes.rep == 1) {
369 core->vm_regs.rcx -= rep_cnt;
372 PrintError("Unimplemented String operation\n");
376 return emulation_length;
381 int v3_emulate(struct guest_info * core, struct x86_instr * instr,
382 int mem_op_size, addr_t mem_hva_src, addr_t mem_hva_dst) {
387 PrintError("USING THE NEW EMULATOR\n");
389 if (instr->src_operand.type == MEM_OPERAND) {
390 src_hva = mem_hva_src;
391 } else if (instr->src_operand.type == REG_OPERAND) {
392 src_hva = instr->src_operand.operand;
394 src_hva = (addr_t)&(instr->src_operand.operand);
397 if (instr->dst_operand.type == MEM_OPERAND) {
398 dst_hva = mem_hva_dst;
399 } else if (instr->dst_operand.type == REG_OPERAND) {
400 dst_hva = instr->dst_operand.operand;
402 dst_hva = (addr_t)&(instr->dst_operand.operand);
406 if (instr->is_str_op == 0) {
407 int src_op_len = instr->src_operand.size;
408 int dst_op_len = instr->dst_operand.size;
410 run_op(core, instr->op_type, src_hva, dst_hva, src_op_len, dst_op_len);
417 /* Both src and dst operand sizes should be identical */
418 rep_cnt = mem_op_size / instr->src_operand.size;
420 return run_str_op(core, instr, src_hva, dst_hva, instr->src_operand.size, rep_cnt);