1 /* Northwestern University */
2 /* (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> */
4 #ifdef __DECODER_TEST__
5 #include "vmm_decoder.h"
7 #include <xed/xed-interface.h>
11 #include <palacios/vmm_decoder.h>
12 #include <palacios/vmm_xed.h>
13 #include <xed/xed-interface.h>
14 #include <palacios/vm_guest.h>
15 #include <palacios/vmm.h>
20 static xed_state_t decoder_state;
22 #define GPR_REGISTER 0
23 #define SEGMENT_REGISTER 1
24 #define CTRL_REGISTER 2
25 #define DEBUG_REGISTER 3
29 /* Disgusting mask hack...
30 I can't think right now, so we'll do it this way...
32 static const ullong_t mask_1 = 0x00000000000000ffLL;
33 static const ullong_t mask_2 = 0x000000000000ffffLL;
34 static const ullong_t mask_4 = 0x00000000ffffffffLL;
35 static const ullong_t mask_8 = 0xffffffffffffffffLL;
38 #define MASK(val, length) ({ \
39 ullong_t mask = 0x0LL; \
52 struct memory_operand {
60 uint_t displacement_size;
61 ullong_t displacement;
66 // This returns a pointer to a V3_OPCODE_[*] array defined in vmm_decoder.h
67 static int get_opcode(xed_iform_enum_t iform, addr_t * opcode);
69 static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, addr_t * v3_reg, uint_t * reg_len);
70 static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xed_instr, uint_t index, struct x86_operand * operand);
72 static int set_decoder_mode(struct guest_info * info, xed_state_t * state) {
73 switch (info->cpu_mode) {
75 if (state->mmode != XED_MACHINE_MODE_LEGACY_16) {
77 XED_MACHINE_MODE_LEGACY_16,
78 XED_ADDRESS_WIDTH_16b,
79 XED_ADDRESS_WIDTH_16b);
84 if (state->mmode != XED_MACHINE_MODE_LEGACY_32) {
86 XED_MACHINE_MODE_LEGACY_32,
87 XED_ADDRESS_WIDTH_32b,
88 XED_ADDRESS_WIDTH_32b);
92 if (state->mmode != XED_MACHINE_MODE_LONG_64) {
93 state->mmode = XED_MACHINE_MODE_LONG_64;
102 int is_flags_reg(xed_reg_enum_t xed_reg) {
117 xed_state_zero(&decoder_state);
123 int v3_basic_mem_decode(struct guest_info * info, addr_t instr_ptr, struct basic_instr_info * instr_info) {
124 xed_decoded_inst_t xed_instr;
125 xed_error_enum_t xed_error;
128 if (set_decoder_mode(info, &decoder_state) == -1) {
129 PrintError("Could not set decoder mode\n");
134 xed_decoded_inst_zero_set_mode(&xed_instr, &decoder_state);
136 xed_error = xed_decode(&xed_instr,
137 REINTERPRET_CAST(const xed_uint8_t *, instr_ptr),
138 XED_MAX_INSTRUCTION_BYTES);
140 if (xed_error != XED_ERROR_NONE) {
141 PrintError("Xed error: %s\n", xed_error_enum_t2str(xed_error));
145 instr_info->instr_length = xed_decoded_inst_get_length(&xed_instr);
148 if (xed_decoded_inst_number_of_memory_operands(&xed_instr) == 0) {
149 PrintError("Tried to decode memory operation with no memory operands\n");
153 instr_info->op_size = xed_decoded_inst_get_memory_operand_length(&xed_instr, 0);
156 xed_category_enum_t cat = xed_decoded_inst_get_category(&xed_instr);
157 if (cat == XED_CATEGORY_STRINGOP) {
158 instr_info->str_op = 1;
160 instr_info->str_op = 0;
163 xed_operand_values_t * operands = xed_decoded_inst_operands(&xed_instr);
164 if (xed_operand_values_has_real_rep(operands)) {
165 instr_info->has_rep = 1;
167 instr_info->has_rep = 0;
175 int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * instr) {
176 xed_decoded_inst_t xed_instr;
177 xed_error_enum_t xed_error;
181 if (set_decoder_mode(info, &decoder_state) == -1) {
182 PrintError("Could not set decoder mode\n");
188 xed_decoded_inst_zero_set_mode(&xed_instr, &decoder_state);
190 xed_error = xed_decode(&xed_instr,
191 REINTERPRET_CAST(const xed_uint8_t *, instr_ptr),
192 XED_MAX_INSTRUCTION_BYTES);
195 if (xed_error != XED_ERROR_NONE) {
196 PrintError("Xed error: %s\n", xed_error_enum_t2str(xed_error));
200 const xed_inst_t * xi = xed_decoded_inst_inst(&xed_instr);
202 instr->instr_length = xed_decoded_inst_get_length(&xed_instr);
203 instr->num_operands = xed_decoded_inst_noperands(&xed_instr);
205 xed_iform_enum_t iform = xed_decoded_inst_get_iform_enum(&xed_instr);
208 PrintDebug("iform=%s\n", xed_iform_enum_t2str(iform));
211 if (instr->num_operands > 3) {
212 PrintDebug("Special Case Not Handled\n");
215 } else if (instr->num_operands == 3) {
216 const xed_operand_t * op = xed_inst_operand(xi, 2);
217 xed_operand_enum_t op_enum = xed_operand_name(op);
219 if ((!xed_operand_is_register(op_enum)) ||
220 (!is_flags_reg(xed_decoded_inst_get_reg(&xed_instr, op_enum)))) {
222 PrintDebug("Special Case not handled\n");
231 if (get_opcode(iform, &(instr->opcode)) == -1) {
232 PrintDebug("Could not get opcode. (iform=%s)\n", xed_iform_enum_t2str(iform));
239 //PrintDebug("Number of operands: %d\n", instr->num_operands);
240 //PrintDebug("INSTR length: %d\n", instr->instr_length);
243 if (instr->num_operands >= 1) {
244 const xed_operand_t * op = xed_inst_operand(xi, 0);
245 xed_operand_enum_t op_enum = xed_operand_name(op);
247 struct x86_operand * v3_op = NULL;
249 if (xed_operand_written(op)) {
250 v3_op = &(instr->dst_operand);
252 v3_op = &(instr->src_operand);
256 if (xed_operand_is_register(op_enum)) {
257 xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum);
258 int v3_reg_type = xed_reg_to_v3_reg(info,
263 if (v3_reg_type == -1) {
264 PrintError("First operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
265 v3_op->type = INVALID_OPERAND;
267 } else if (v3_reg_type == SEGMENT_REGISTER) {
268 struct v3_segment * seg_reg = (struct v3_segment *)(v3_op->operand);
269 v3_op->operand = (addr_t)&(seg_reg->selector);
272 v3_op->type = REG_OPERAND;
277 case XED_OPERAND_MEM0:
280 struct x86_operand * operand = &(instr->dst_operand);
282 if (xed_decoded_inst_mem_read(&xed_instr, 0)) {
283 operand = &(instr->src_operand);
284 } else if (xed_decoded_inst_mem_written(&xed_instr, 0)) {
285 operand = &(instr->dst_operand);
289 if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) {
290 PrintError("Could not get first memory operand\n");
296 case XED_OPERAND_MEM1:
297 case XED_OPERAND_IMM1:
299 PrintError("Illegal Operand Order\n");
303 case XED_OPERAND_IMM0:
304 case XED_OPERAND_AGEN:
305 case XED_OPERAND_PTR:
306 case XED_OPERAND_RELBR:
308 PrintError("Unhandled Operand Type\n");
316 // set second operand
317 if (instr->num_operands >= 2) {
318 const xed_operand_t * op = xed_inst_operand(xi, 1);
319 // xed_operand_type_enum_t op_type = xed_operand_type(op);
320 xed_operand_enum_t op_enum = xed_operand_name(op);
322 struct x86_operand * v3_op;
324 if (xed_operand_written(op)) {
325 v3_op = &(instr->dst_operand);
327 v3_op = &(instr->src_operand);
331 if (xed_operand_is_register(op_enum)) {
332 xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum);
333 int v3_reg_type = xed_reg_to_v3_reg(info,
337 if (v3_reg_type == -1) {
338 PrintError("Second operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
339 v3_op->type = INVALID_OPERAND;
341 } else if (v3_reg_type == SEGMENT_REGISTER) {
342 struct v3_segment * seg_reg = (struct v3_segment *)(v3_op->operand);
343 v3_op->operand = (addr_t)&(seg_reg->selector);
346 v3_op->type = REG_OPERAND;
353 case XED_OPERAND_MEM0:
357 if (xed_decoded_inst_mem_read(&xed_instr, 0)) {
358 v3_op = &(instr->src_operand);
359 } else if (xed_decoded_inst_mem_written(&xed_instr, 0)) {
360 v3_op = &(instr->dst_operand);
364 if (get_memory_operand(info, &xed_instr, 0, v3_op) == -1) {
365 PrintError("Could not get first memory operand\n");
371 case XED_OPERAND_IMM0:
373 instr->src_operand.size = xed_decoded_inst_get_immediate_width(&xed_instr);
375 if (instr->src_operand.size > 4) {
376 PrintError("Unhandled 64 bit immediates\n");
379 instr->src_operand.operand = xed_decoded_inst_get_unsigned_immediate(&xed_instr);
381 instr->src_operand.type = IMM_OPERAND;
386 case XED_OPERAND_MEM1:
387 case XED_OPERAND_IMM1:
389 PrintError("Illegal Operand Order\n");
392 case XED_OPERAND_AGEN:
393 case XED_OPERAND_PTR:
394 case XED_OPERAND_RELBR:
396 PrintError("Unhandled Operand Type\n");
404 if (instr->num_operands >= 3) {
405 const xed_operand_t * op = xed_inst_operand(xi, 2);
406 // xed_operand_type_enum_t op_type = xed_operand_type(op);
407 xed_operand_enum_t op_enum = xed_operand_name(op);
409 if (xed_operand_is_register(op_enum)) {
410 xed_reg_enum_t xed_reg = xed_decoded_inst_get_reg(&xed_instr, op_enum);
411 int v3_reg_type = xed_reg_to_v3_reg(info,
413 &(instr->third_operand.operand),
414 &(instr->third_operand.size));
416 if (v3_reg_type == -1) {
417 PrintError("Third operand is an Unhandled Operand: %s\n", xed_reg_enum_t2str(xed_reg));
418 instr->third_operand.type = INVALID_OPERAND;
420 } else if (v3_reg_type == SEGMENT_REGISTER) {
421 struct v3_segment * seg_reg = (struct v3_segment *)(instr->third_operand.operand);
422 instr->third_operand.operand = (addr_t)&(seg_reg->selector);
426 instr->third_operand.type = REG_OPERAND;
430 // PrintError("Unhandled third operand type %s\n", xed_operand_type_enum_t2str(op_type));
443 int v3_encode(struct guest_info * info, struct x86_instr * instr, char * instr_buf) {
452 static int get_memory_operand(struct guest_info * info, xed_decoded_inst_t * xed_instr, uint_t op_index, struct x86_operand * operand) {
453 struct memory_operand mem_op;
459 ullong_t displacement;
460 // struct v3_segment * seg_reg;
465 memset((void*)&mem_op, '\0', sizeof(struct memory_operand));
467 xed_reg_enum_t xed_seg = xed_decoded_inst_get_seg_reg(xed_instr, op_index);
468 if (xed_seg != XED_REG_INVALID) {
469 struct v3_segment *tmp_segment;
470 if (xed_reg_to_v3_reg(info, xed_seg, (addr_t *)&tmp_segment, &(mem_op.segment_size)) == -1) {
471 PrintError("Unhandled Segment Register\n");
474 mem_op.segment = tmp_segment->base;
477 xed_reg_enum_t xed_base = xed_decoded_inst_get_base_reg(xed_instr, op_index);
478 if (xed_base != XED_REG_INVALID) {
480 if (xed_reg_to_v3_reg(info, xed_base, &base_reg, &(mem_op.base_size)) == -1) {
481 PrintError("Unhandled Base register\n");
484 mem_op.base = *(addr_t *)base_reg;
489 xed_reg_enum_t xed_idx = xed_decoded_inst_get_index_reg(xed_instr, op_index);
490 if ((op_index == 0) && (xed_idx != XED_REG_INVALID)) {
493 if (xed_reg_to_v3_reg(info, xed_idx, &index_reg, &(mem_op.index_size)) == -1) {
494 PrintError("Unhandled Index Register\n");
498 mem_op.index= *(addr_t *)index_reg;
500 xed_uint_t xed_scale = xed_decoded_inst_get_scale(xed_instr, op_index);
501 if (xed_scale != 0) {
502 mem_op.scale = xed_scale;
507 xed_uint_t disp_bits = xed_decoded_inst_get_memory_displacement_width(xed_instr, op_index);
509 xed_int64_t xed_disp = xed_decoded_inst_get_memory_displacement(xed_instr, op_index);
511 mem_op.displacement_size = disp_bits / 8;
512 mem_op.displacement = xed_disp;
516 operand->type = MEM_OPERAND;
517 operand->size = xed_decoded_inst_get_memory_operand_length(xed_instr, op_index);
521 PrintDebug("Struct: Seg=%x, base=%x, index=%x, scale=%x, displacement=%x\n",
522 mem_op.segment, mem_op.base, mem_op.index, mem_op.scale, mem_op.displacement);
525 seg = mem_op.segment;
526 base = MASK(mem_op.base, mem_op.base_size);
527 index = MASK(mem_op.index, mem_op.index_size);
528 scale = mem_op.scale;
529 displacement = MASK(mem_op.displacement, mem_op.displacement_size);
531 PrintDebug("Seg=%x, base=%x, index=%x, scale=%x, displacement=%x\n", seg, base, index, scale, displacement);
533 operand->operand = seg + base + (scale * index) + displacement;
538 static int xed_reg_to_v3_reg(struct guest_info * info, xed_reg_enum_t xed_reg, addr_t * v3_reg, uint_t * reg_len) {
541 case XED_REG_INVALID:
550 *v3_reg = (addr_t)&(info->vm_regs.rax);
554 *v3_reg = (addr_t)&(info->vm_regs.rax);
558 *v3_reg = (addr_t)&(info->vm_regs.rax);
562 *v3_reg = (addr_t)(&(info->vm_regs.rax)) + 1;
566 *v3_reg = (addr_t)&(info->vm_regs.rax);
571 *v3_reg = (addr_t)&(info->vm_regs.rcx);
575 *v3_reg = (addr_t)&(info->vm_regs.rcx);
579 *v3_reg = (addr_t)&(info->vm_regs.rcx);
583 *v3_reg = (addr_t)(&(info->vm_regs.rcx)) + 1;
587 *v3_reg = (addr_t)&(info->vm_regs.rcx);
592 *v3_reg = (addr_t)&(info->vm_regs.rdx);
596 *v3_reg = (addr_t)&(info->vm_regs.rdx);
600 *v3_reg = (addr_t)&(info->vm_regs.rdx);
604 *v3_reg = (addr_t)(&(info->vm_regs.rdx)) + 1;
608 *v3_reg = (addr_t)&(info->vm_regs.rdx);
613 *v3_reg = (addr_t)&(info->vm_regs.rbx);
617 *v3_reg = (addr_t)&(info->vm_regs.rbx);
621 *v3_reg = (addr_t)&(info->vm_regs.rbx);
625 *v3_reg = (addr_t)(&(info->vm_regs.rbx)) + 1;
629 *v3_reg = (addr_t)&(info->vm_regs.rbx);
635 *v3_reg = (addr_t)&(info->vm_regs.rsp);
639 *v3_reg = (addr_t)&(info->vm_regs.rsp);
643 *v3_reg = (addr_t)&(info->vm_regs.rsp);
647 *v3_reg = (addr_t)&(info->vm_regs.rsp);
652 *v3_reg = (addr_t)&(info->vm_regs.rbp);
656 *v3_reg = (addr_t)&(info->vm_regs.rbp);
660 *v3_reg = (addr_t)&(info->vm_regs.rbp);
664 *v3_reg = (addr_t)&(info->vm_regs.rbp);
671 *v3_reg = (addr_t)&(info->vm_regs.rsi);
675 *v3_reg = (addr_t)&(info->vm_regs.rsi);
679 *v3_reg = (addr_t)&(info->vm_regs.rsi);
683 *v3_reg = (addr_t)&(info->vm_regs.rsi);
689 *v3_reg = (addr_t)&(info->vm_regs.rdi);
693 *v3_reg = (addr_t)&(info->vm_regs.rdi);
697 *v3_reg = (addr_t)&(info->vm_regs.rdi);
701 *v3_reg = (addr_t)&(info->vm_regs.rdi);
710 *v3_reg = (addr_t)&(info->rip);
712 return CTRL_REGISTER;
714 *v3_reg = (addr_t)&(info->rip);
716 return CTRL_REGISTER;
718 *v3_reg = (addr_t)&(info->rip);
720 return CTRL_REGISTER;
723 *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
725 return CTRL_REGISTER;
727 *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
729 return CTRL_REGISTER;
731 *v3_reg = (addr_t)&(info->ctrl_regs.rflags);
733 return CTRL_REGISTER;
736 *v3_reg = (addr_t)&(info->ctrl_regs.cr0);
738 return CTRL_REGISTER;
740 *v3_reg = (addr_t)&(info->ctrl_regs.cr2);
742 return CTRL_REGISTER;
744 *v3_reg = (addr_t)&(info->ctrl_regs.cr3);
746 return CTRL_REGISTER;
748 *v3_reg = (addr_t)&(info->ctrl_regs.cr4);
750 return CTRL_REGISTER;
752 *v3_reg = (addr_t)&(info->ctrl_regs.cr8);
754 return CTRL_REGISTER;
776 *v3_reg = (addr_t)&(info->segments.cs);
777 return SEGMENT_REGISTER;
779 *v3_reg = (addr_t)&(info->segments.ds);
780 return SEGMENT_REGISTER;
782 *v3_reg = (addr_t)&(info->segments.es);
783 return SEGMENT_REGISTER;
785 *v3_reg = (addr_t)&(info->segments.ss);
786 return SEGMENT_REGISTER;
788 *v3_reg = (addr_t)&(info->segments.fs);
789 return SEGMENT_REGISTER;
791 *v3_reg = (addr_t)&(info->segments.gs);
792 return SEGMENT_REGISTER;
799 PrintError("Segment selector operand... Don't know how to handle this...\n");
902 case XED_REG_STACKPUSH:
903 case XED_REG_STACKPOP:
909 case XED_REG_X87CONTROL:
910 case XED_REG_X87STATUS:
913 case XED_REG_X87PUSH:
915 case XED_REG_X87POP2:
950 static int get_opcode(xed_iform_enum_t iform, addr_t * opcode) {
953 case XED_IFORM_MOV_CR_GPR64_CR:
954 case XED_IFORM_MOV_CR_GPR32_CR:
955 *opcode = (addr_t)&V3_OPCODE_MOVCR2;
958 case XED_IFORM_MOV_CR_CR_GPR64:
959 case XED_IFORM_MOV_CR_CR_GPR32:
960 *opcode = (addr_t)&V3_OPCODE_MOV2CR;
964 case XED_IFORM_LMSW_GPR16:
965 *opcode = (addr_t)&V3_OPCODE_LMSW;
969 *opcode = (addr_t)&V3_OPCODE_CLTS;