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 V3_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(info->vm_info, info, "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(info->vm_info, info, "Unknown 8 bit instruction\n");
142 } else if (src_op_size == 2) {
143 PrintDebug(info->vm_info, info, "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(info->vm_info, info, "Unknown 16 bit instruction\n");
197 } else if (src_op_size == 4) {
198 PrintDebug(info->vm_info, info, "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(info->vm_info, info, "Unknown 32 bit instruction\n");
247 } else if (src_op_size == 8) {
248 PrintDebug(info->vm_info, info, "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(info->vm_info, info, "Unknown 64 bit instruction\n");
298 PrintError(info->vm_info, info, "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);
317 PrintDebug(core->vm_info, core, "Emulation_len=%d, tmp_rcx=%d\n", emulation_length, (uint_t)tmp_rcx);
320 if (instr->op_type == V3_OP_MOVS) {
322 movs8((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
323 } else if (op_size == 2) {
324 movs16((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
325 } else if (op_size == 4) {
326 movs32((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
328 } else if (op_size == 8) {
329 movs64((addr_t *)&dst_addr, &src_addr, &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
332 PrintError(core->vm_info, core, "Invalid operand length\n");
336 if (flags_reg->df == 0) {
337 core->vm_regs.rdi += emulation_length;
338 core->vm_regs.rsi += emulation_length;
340 core->vm_regs.rdi -= emulation_length;
341 core->vm_regs.rsi -= emulation_length;
344 // RCX is only modified if the rep prefix is present
345 if (instr->prefixes.rep == 1) {
346 core->vm_regs.rcx -= rep_cnt;
349 } else if (instr->op_type == V3_OP_STOS) {
351 stos8((addr_t *)&dst_addr, (addr_t *)&(core->vm_regs.rax), &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
352 } else if (op_size == 2) {
353 stos16((addr_t *)&dst_addr, (addr_t *)&(core->vm_regs.rax), &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
354 } else if (op_size == 4) {
355 stos32((addr_t *)&dst_addr, (addr_t *)&(core->vm_regs.rax), &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
357 } else if (op_size == 8) {
358 stos64((addr_t *)&dst_addr, (addr_t *)&(core->vm_regs.rax), &tmp_rcx, (addr_t *)&(core->ctrl_regs.rflags));
361 PrintError(core->vm_info, core, "Invalid operand length\n");
367 if (flags_reg->df == 0) {
368 core->vm_regs.rdi += emulation_length;
370 core->vm_regs.rdi -= emulation_length;
373 // RCX is only modified if the rep prefix is present
374 if (instr->prefixes.rep == 1) {
375 core->vm_regs.rcx -= rep_cnt;
378 PrintError(core->vm_info, core, "Unimplemented String operation\n");
382 return emulation_length;
387 int v3_emulate(struct guest_info * core, struct x86_instr * instr,
388 int mem_op_size, addr_t mem_hva_src, addr_t mem_hva_dst) {
394 if (instr->src_operand.type == MEM_OPERAND) {
395 src_hva = mem_hva_src;
396 } else if (instr->src_operand.type == REG_OPERAND) {
397 src_hva = instr->src_operand.operand;
399 src_hva = (addr_t)&(instr->src_operand.operand);
402 if (instr->dst_operand.type == MEM_OPERAND) {
403 dst_hva = mem_hva_dst;
404 } else if (instr->dst_operand.type == REG_OPERAND) {
405 dst_hva = instr->dst_operand.operand;
407 dst_hva = (addr_t)&(instr->dst_operand.operand);
411 if (instr->is_str_op == 0) {
412 int src_op_len = instr->src_operand.size;
413 int dst_op_len = instr->dst_operand.size;
415 run_op(core, instr->op_type, src_hva, dst_hva, src_op_len, dst_op_len);
422 /* Both src and dst operand sizes should be identical */
423 rep_cnt = mem_op_size / instr->src_operand.size;
425 return run_str_op(core, instr, src_hva, dst_hva, instr->src_operand.size, rep_cnt);