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 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <palacios/vmm_types.h>
23 /* .... Giant fucking switch tables */
138 static int get_addr_width(struct guest_info * info, struct x86_instr * instr) {
140 switch (v3_get_vm_cpu_mode(info)) {
142 return (instr->prefixes.addr_size) ? 4 : 2;
148 if (info->segments.cs.db) {
149 return (instr->prefixes.addr_size) ? 2 : 4;
151 return (instr->prefixes.addr_size) ? 4 : 2;
154 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
159 static int get_operand_width(struct guest_info * info, struct x86_instr * instr,
259 switch (v3_get_vm_cpu_mode(info)) {
261 return (instr->prefixes.op_size) ? 4 : 2;
263 if (instr->prefixes.rex.op_size) {
269 if (info->segments.cs.db) {
271 return (instr->prefixes.op_size) ? 2 : 4;
273 return (instr->prefixes.op_size) ? 4 : 2;
276 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
281 switch (v3_get_vm_cpu_mode(info)) {
283 PrintError("Invalid instruction given operating mode (%d)\n", form);
292 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
298 switch (v3_get_vm_cpu_mode(info)) {
308 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
316 switch (v3_get_vm_cpu_mode(info)) {
326 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
333 PrintError("Unsupported instruction form %d\n", form);
342 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
343 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
350 } __attribute__((packed));
357 } __attribute__((packed));
364 static inline int decode_gpr(struct guest_info * core,
366 struct x86_operand * reg) {
368 struct v3_gprs * gprs = &(core->vm_regs);
372 reg->operand = (addr_t)&(gprs->rax);
375 reg->operand = (addr_t)&(gprs->rcx);
378 reg->operand = (addr_t)&(gprs->rdx);
381 reg->operand = (addr_t)&(gprs->rbx);
384 if (reg->size == 1) {
385 reg->operand = (addr_t)&(gprs->rax) + 1;
387 reg->operand = (addr_t)&(gprs->rsp);
391 if (reg->size == 1) {
392 reg->operand = (addr_t)&(gprs->rcx) + 1;
394 reg->operand = (addr_t)&(gprs->rbp);
398 if (reg->size == 1) {
399 reg->operand = (addr_t)&(gprs->rdx) + 1;
401 reg->operand = (addr_t)&(gprs->rsi);
405 if (reg->size == 1) {
406 reg->operand = (addr_t)&(gprs->rbx) + 1;
408 reg->operand = (addr_t)&(gprs->rdi);
412 PrintError("Invalid Reg Code (%d)\n", reg_code);
423 static inline int decode_cr(struct guest_info * core,
425 struct x86_operand * reg) {
427 struct v3_ctrl_regs * crs = &(core->ctrl_regs);
429 PrintDebug("\t Ctrl regs %d\n", reg_code);
433 reg->operand = (addr_t)&(crs->cr0);
436 reg->operand = (addr_t)&(crs->cr2);
439 reg->operand = (addr_t)&(crs->cr3);
442 reg->operand = (addr_t)&(crs->cr4);
446 PrintError("Invalid Reg Code (%d)\n", reg_code);
453 // This converts the displacement into the appropriate masked value
455 QUESTION: Are the register Values signed ?????
457 #define MASK_DISPLACEMENT(reg, mode) ({ \
459 if (mode == DISP8) { \
460 val = (sint8_t)(reg & 0xff); \
461 } else if (mode == DISP16) { \
462 val = (sint16_t)(reg & 0xffff); \
463 } else if (mode == DISP32) { \
464 val = (sint32_t)(reg & 0xffffffff); \
466 PrintError("Error invalid displacement size (%d)\n", mode); \
473 #define ADDR_MASK(val, length) ({ \
474 ullong_t mask = 0x0LL; \
477 mask = 0x00000000000fffffLL; \
480 mask = 0x00000000ffffffffLL; \
483 mask = 0xffffffffffffffffLL; \
491 static int decode_rm_operand16(struct guest_info * core,
492 uint8_t * modrm_instr,
493 struct x86_instr * instr,
494 struct x86_operand * operand,
495 uint8_t * reg_code) {
497 struct v3_gprs * gprs = &(core->vm_regs);
498 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
499 addr_t base_addr = 0;
500 modrm_mode_t mod_mode = 0;
501 uint8_t * instr_cursor = modrm_instr;
503 // PrintDebug("ModRM mod=%d\n", modrm->mod);
505 *reg_code = modrm->reg;
509 if (modrm->mod == 3) {
510 //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
511 operand->type = REG_OPERAND;
513 decode_gpr(core, modrm->rm, operand);
516 struct v3_segment * seg = NULL;
518 operand->type = MEM_OPERAND;
520 if (modrm->mod == 0) {
522 } else if (modrm->mod == 1) {
524 } else if (modrm->mod == 2) {
530 base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
533 base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
536 base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
539 base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
542 base_addr = gprs->rsi;
545 base_addr = gprs->rdi;
548 if (modrm->mod == 0) {
552 base_addr = gprs->rbp;
556 base_addr = gprs->rbx;
562 if (mod_mode == DISP8) {
563 base_addr += *(sint8_t *)instr_cursor;
565 } else if (mod_mode == DISP16) {
566 base_addr += *(sint16_t *)instr_cursor;
571 // get appropriate segment
572 if (instr->prefixes.cs_override) {
573 seg = &(core->segments.cs);
574 } else if (instr->prefixes.es_override) {
575 seg = &(core->segments.es);
576 } else if (instr->prefixes.ss_override) {
577 seg = &(core->segments.ss);
578 } else if (instr->prefixes.fs_override) {
579 seg = &(core->segments.fs);
580 } else if (instr->prefixes.gs_override) {
581 seg = &(core->segments.gs);
583 seg = &(core->segments.ds);
586 operand->operand = ADDR_MASK(get_addr_linear(core, base_addr, seg),
587 get_addr_width(core, instr));
591 return (instr_cursor - modrm_instr);
595 // returns num_bytes parsed
596 static int decode_rm_operand32(struct guest_info * core,
597 uint8_t * modrm_instr,
598 struct x86_instr * instr,
599 struct x86_operand * operand,
600 uint8_t * reg_code) {
602 struct v3_gprs * gprs = &(core->vm_regs);
603 uint8_t * instr_cursor = modrm_instr;
604 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
605 addr_t base_addr = 0;
606 modrm_mode_t mod_mode = 0;
607 uint_t has_sib_byte = 0;
610 *reg_code = modrm->reg;
614 if (modrm->mod == 3) {
615 operand->type = REG_OPERAND;
616 // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
618 decode_gpr(core, modrm->rm, operand);
621 struct v3_segment * seg = NULL;
623 operand->type = MEM_OPERAND;
625 if (modrm->mod == 0) {
627 } else if (modrm->mod == 1) {
629 } else if (modrm->mod == 2) {
635 base_addr = gprs->rax;
638 base_addr = gprs->rcx;
641 base_addr = gprs->rdx;
644 base_addr = gprs->rbx;
650 if (modrm->mod == 0) {
654 base_addr = gprs->rbp;
658 base_addr = gprs->rsi;
661 base_addr = gprs->rdi;
667 struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
668 int scale = 0x1 << sib->scale;
672 switch (sib->index) {
674 base_addr = gprs->rax;
677 base_addr = gprs->rcx;
680 base_addr = gprs->rdx;
683 base_addr = gprs->rbx;
689 base_addr = gprs->rbp;
692 base_addr = gprs->rsi;
695 base_addr = gprs->rdi;
704 base_addr += MASK_DISPLACEMENT(gprs->rax, mod_mode);
707 base_addr += MASK_DISPLACEMENT(gprs->rcx, mod_mode);
710 base_addr += MASK_DISPLACEMENT(gprs->rdx, mod_mode);
713 base_addr += MASK_DISPLACEMENT(gprs->rbx, mod_mode);
716 base_addr += MASK_DISPLACEMENT(gprs->rsp, mod_mode);
719 if (modrm->mod != 0) {
720 base_addr += MASK_DISPLACEMENT(gprs->rbp, mod_mode);
724 base_addr += MASK_DISPLACEMENT(gprs->rsi, mod_mode);
727 base_addr += MASK_DISPLACEMENT(gprs->rdi, mod_mode);
734 if (mod_mode == DISP8) {
735 base_addr += *(sint8_t *)instr_cursor;
737 } else if (mod_mode == DISP32) {
738 base_addr += *(sint32_t *)instr_cursor;
742 // get appropriate segment
743 if (instr->prefixes.cs_override) {
744 seg = &(core->segments.cs);
745 } else if (instr->prefixes.es_override) {
746 seg = &(core->segments.es);
747 } else if (instr->prefixes.ss_override) {
748 seg = &(core->segments.ss);
749 } else if (instr->prefixes.fs_override) {
750 seg = &(core->segments.fs);
751 } else if (instr->prefixes.gs_override) {
752 seg = &(core->segments.gs);
754 seg = &(core->segments.ds);
757 operand->operand = ADDR_MASK(get_addr_linear(core, base_addr, seg),
758 get_addr_width(core, instr));
762 return (instr_cursor - modrm_instr);
766 int decode_rm_operand64(struct guest_info * core, uint8_t * instr_ptr,
767 struct x86_instr * instr, struct x86_operand * operand,
768 uint8_t * reg_code) {
776 static int decode_rm_operand(struct guest_info * core,
777 uint8_t * instr_ptr, // input
779 struct x86_instr * instr,
780 struct x86_operand * operand,
781 uint8_t * reg_code) {
783 v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
785 operand->size = get_operand_width(core, instr, form);
789 return decode_rm_operand16(core, instr_ptr, instr, operand, reg_code);
791 if (instr->prefixes.rex.op_size) {
792 return decode_rm_operand64(core, instr_ptr, instr, operand, reg_code);
797 return decode_rm_operand32(core, instr_ptr, instr, operand, reg_code);
799 PrintError("Invalid CPU_MODE (%d)\n", mode);
806 static inline op_form_t op_code_to_form_0f(uint8_t * instr, int * length) {
811 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[2]);
813 switch (modrm->reg) {
821 return INVALID_INSTR;
882 return INVALID_INSTR;
887 static op_form_t op_code_to_form(uint8_t * instr, int * length) {
911 return op_code_to_form_0f(instr, length);
951 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
953 switch (modrm->reg) {
967 return INVALID_INSTR;
971 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
973 switch (modrm->reg) {
987 return INVALID_INSTR;
991 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
993 switch (modrm->reg) {
1001 return AND_IMM2SX_8;
1003 return SUB_IMM2SX_8;
1005 return XOR_IMM2SX_8;
1007 return INVALID_INSTR;
1036 return MOV_MEM2AL_8;
1040 return MOV_AL2MEM_8;
1064 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1066 switch (modrm->reg) {
1072 return INVALID_INSTR;
1076 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1078 switch (modrm->reg) {
1084 return INVALID_INSTR;
1090 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1092 switch (modrm->reg) {
1098 return INVALID_INSTR;
1103 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1105 switch (modrm->reg) {
1111 return INVALID_INSTR;
1116 return INVALID_INSTR;
1122 static char * op_form_to_str(op_form_t form) {
1125 case LMSW: return "LMSW";
1126 case SMSW: return "SMSW";
1127 case CLTS: return "CLTS";
1128 case INVLPG: return "INVLPG";
1129 case MOV_CR2: return "MOV_CR2";
1130 case MOV_2CR: return "MOV_2CR";
1131 case MOV_DR2: return "MOV_DR2";
1132 case MOV_2DR: return "MOV_2DR";
1133 case MOV_SR2: return "MOV_SR2";
1134 case MOV_2SR: return "MOV_2SR";
1135 case MOV_MEM2_8: return "MOV_MEM2_8";
1136 case MOV_MEM2: return "MOV_MEM2";
1137 case MOV_2MEM_8: return "MOV_2MEM_8";
1138 case MOV_2MEM: return "MOV_2MEM";
1139 case MOV_MEM2AL_8: return "MOV_MEM2AL_8";
1140 case MOV_MEM2AX: return "MOV_MEM2AX";
1141 case MOV_AL2MEM_8: return "MOV_AL2MEM_8";
1142 case MOV_AX2MEM: return "MOV_AX2MEM";
1143 case MOV_IMM2_8: return "MOV_IMM2_8";
1144 case MOV_IMM2: return "MOV_IMM2";
1145 case MOVS_8: return "MOVS_8";
1146 case MOVS: return "MOVS";
1147 case MOVSX_8: return "MOVSX_8";
1148 case MOVSX: return "MOVSX";
1149 case MOVZX_8: return "MOVZX_8";
1150 case MOVZX: return "MOVZX";
1151 case HLT: return "HLT";
1152 case PUSHF: return "PUSHF";
1153 case POPF: return "POPF";
1154 case ADC_2MEM_8: return "ADC_2MEM_8";
1155 case ADC_2MEM: return "ADC_2MEM";
1156 case ADC_MEM2_8: return "ADC_MEM2_8";
1157 case ADC_MEM2: return "ADC_MEM2";
1158 case ADC_IMM2_8: return "ADC_IMM2_8";
1159 case ADC_IMM2: return "ADC_IMM2";
1160 case ADC_IMM2SX_8: return "ADC_IMM2SX_8";
1161 case ADD_IMM2_8: return "ADD_IMM2_8";
1162 case ADD_IMM2: return "ADD_IMM2";
1163 case ADD_IMM2SX_8: return "ADD_IMM2SX_8";
1164 case ADD_2MEM_8: return "ADD_2MEM_8";
1165 case ADD_2MEM: return "ADD_2MEM";
1166 case ADD_MEM2_8: return "ADD_MEM2_8";
1167 case ADD_MEM2: return "ADD_MEM2";
1168 case AND_MEM2_8: return "AND_MEM2_8";
1169 case AND_MEM2: return "AND_MEM2";
1170 case AND_2MEM_8: return "AND_2MEM_8";
1171 case AND_2MEM: return "AND_2MEM";
1172 case AND_IMM2_8: return "AND_IMM2_8";
1173 case AND_IMM2: return "AND_IMM2";
1174 case AND_IMM2SX_8: return "AND_IMM2SX_8";
1175 case OR_2MEM_8: return "OR_2MEM_8";
1176 case OR_2MEM: return "OR_2MEM";
1177 case OR_MEM2_8: return "OR_MEM2_8";
1178 case OR_MEM2: return "OR_MEM2";
1179 case OR_IMM2_8: return "OR_IMM2_8";
1180 case OR_IMM2: return "OR_IMM2";
1181 case OR_IMM2SX_8: return "OR_IMM2SX_8";
1182 case SUB_2MEM_8: return "SUB_2MEM_8";
1183 case SUB_2MEM: return "SUB_2MEM";
1184 case SUB_MEM2_8: return "SUB_MEM2_8";
1185 case SUB_MEM2: return "SUB_MEM2";
1186 case SUB_IMM2_8: return "SUB_IMM2_8";
1187 case SUB_IMM2: return "SUB_IMM2";
1188 case SUB_IMM2SX_8: return "SUB_IMM2SX_8";
1189 case XOR_2MEM_8: return "XOR_2MEM_8";
1190 case XOR_2MEM: return "XOR_2MEM";
1191 case XOR_MEM2_8: return "XOR_MEM2_8";
1192 case XOR_MEM2: return "XOR_MEM2";
1193 case XOR_IMM2_8: return "XOR_IMM2_8";
1194 case XOR_IMM2: return "XOR_IMM2";
1195 case XOR_IMM2SX_8: return "XOR_IMM2SX_8";
1196 case INC_8: return "INC_8";
1197 case INC: return "INC";
1198 case DEC_8: return "DEC_8";
1199 case DEC: return "DEC";
1200 case NEG_8: return "NEG_8";
1201 case NEG: return "NEG";
1202 case NOT_8: return "NOT_8";
1203 case NOT: return "NOT";
1204 case XCHG_8: return "XCHG_8";
1205 case XCHG: return "XCHG";
1206 case SETB: return "SETB";
1207 case SETBE: return "SETBE";
1208 case SETL: return "SETL";
1209 case SETLE: return "SETLE";
1210 case SETNB: return "SETNB";
1211 case SETNBE: return "SETNBE";
1212 case SETNL: return "SETNL";
1213 case SETNLE: return "SETNLE";
1214 case SETNO: return "SETNO";
1215 case SETNP: return "SETNP";
1216 case SETNS: return "SETNS";
1217 case SETNZ: return "SETNZ";
1218 case SETP: return "SETP";
1219 case SETS: return "SETS";
1220 case SETZ: return "SETZ";
1221 case SETO: return "SETO";
1222 case STOS_8: return "STOS_8";
1223 case STOS: return "STOS";
1227 return "INVALID_INSTR";