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;
145 return (instr->prefixes.addr_size) ? 2 : 4;
149 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
154 static int get_operand_width(struct guest_info * info, struct x86_instr * instr,
254 switch (v3_get_vm_cpu_mode(info)) {
256 return (instr->prefixes.op_size) ? 4 : 2;
259 return (instr->prefixes.op_size) ? 2 : 4;
263 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
268 switch (v3_get_vm_cpu_mode(info)) {
270 PrintError("Invalid instruction given operating mode (%d)\n", form);
278 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
284 switch (v3_get_vm_cpu_mode(info)) {
293 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
301 switch (v3_get_vm_cpu_mode(info)) {
309 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
316 PrintError("Unsupported instruction form %d\n", form);
325 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
326 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
333 } __attribute__((packed));
340 } __attribute__((packed));
347 static inline int decode_gpr(struct guest_info * core,
349 struct x86_operand * reg) {
351 struct v3_gprs * gprs = &(core->vm_regs);
355 reg->operand = (addr_t)&(gprs->rax);
358 reg->operand = (addr_t)&(gprs->rcx);
361 reg->operand = (addr_t)&(gprs->rdx);
364 reg->operand = (addr_t)&(gprs->rbx);
367 if (reg->size == 1) {
368 reg->operand = (addr_t)&(gprs->rax) + 1;
370 reg->operand = (addr_t)&(gprs->rsp);
374 if (reg->size == 1) {
375 reg->operand = (addr_t)&(gprs->rcx) + 1;
377 reg->operand = (addr_t)&(gprs->rbp);
381 if (reg->size == 1) {
382 reg->operand = (addr_t)&(gprs->rdx) + 1;
384 reg->operand = (addr_t)&(gprs->rsi);
388 if (reg->size == 1) {
389 reg->operand = (addr_t)&(gprs->rbx) + 1;
391 reg->operand = (addr_t)&(gprs->rdi);
395 PrintError("Invalid Reg Code (%d)\n", reg_code);
406 static inline int decode_cr(struct guest_info * core,
408 struct x86_operand * reg) {
410 struct v3_ctrl_regs * crs = &(core->ctrl_regs);
412 PrintDebug("\t Ctrl regs %d\n", reg_code);
416 reg->operand = (addr_t)&(crs->cr0);
419 reg->operand = (addr_t)&(crs->cr2);
422 reg->operand = (addr_t)&(crs->cr3);
425 reg->operand = (addr_t)&(crs->cr4);
429 PrintError("Invalid Reg Code (%d)\n", reg_code);
436 // This converts the displacement into the appropriate masked value
438 QUESTION: Are the register Values signed ?????
440 #define MASK_DISPLACEMENT(reg, mode) ({ \
442 if (mode == DISP8) { \
443 val = (sint8_t)(reg & 0xff); \
444 } else if (mode == DISP16) { \
445 val = (sint16_t)(reg & 0xffff); \
446 } else if (mode == DISP32) { \
447 val = (sint32_t)(reg & 0xffffffff); \
449 PrintError("Error invalid displacement size (%d)\n", mode); \
456 #define ADDR_MASK(val, length) ({ \
457 ullong_t mask = 0x0LL; \
460 mask = 0x00000000000fffffLL; \
463 mask = 0x00000000ffffffffLL; \
466 mask = 0xffffffffffffffffLL; \
474 static int decode_rm_operand16(struct guest_info * core,
475 uint8_t * modrm_instr,
476 struct x86_instr * instr,
477 struct x86_operand * operand,
478 uint8_t * reg_code) {
480 struct v3_gprs * gprs = &(core->vm_regs);
481 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
482 addr_t base_addr = 0;
483 modrm_mode_t mod_mode = 0;
484 uint8_t * instr_cursor = modrm_instr;
486 // PrintDebug("ModRM mod=%d\n", modrm->mod);
488 *reg_code = modrm->reg;
492 if (modrm->mod == 3) {
493 //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
494 operand->type = REG_OPERAND;
496 decode_gpr(core, modrm->rm, operand);
499 struct v3_segment * seg = NULL;
501 operand->type = MEM_OPERAND;
503 if (modrm->mod == 0) {
505 } else if (modrm->mod == 1) {
507 } else if (modrm->mod == 2) {
513 base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
516 base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
519 base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
522 base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
525 base_addr = gprs->rsi;
528 base_addr = gprs->rdi;
531 if (modrm->mod == 0) {
535 base_addr = gprs->rbp;
539 base_addr = gprs->rbx;
545 if (mod_mode == DISP8) {
546 base_addr += *(sint8_t *)instr_cursor;
548 } else if (mod_mode == DISP16) {
549 base_addr += *(sint16_t *)instr_cursor;
554 // get appropriate segment
555 if (instr->prefixes.cs_override) {
556 seg = &(core->segments.cs);
557 } else if (instr->prefixes.es_override) {
558 seg = &(core->segments.es);
559 } else if (instr->prefixes.ss_override) {
560 seg = &(core->segments.ss);
561 } else if (instr->prefixes.fs_override) {
562 seg = &(core->segments.fs);
563 } else if (instr->prefixes.gs_override) {
564 seg = &(core->segments.gs);
566 seg = &(core->segments.ds);
569 operand->operand = ADDR_MASK(get_addr_linear(core, base_addr, seg),
570 get_addr_width(core, instr));
574 return (instr_cursor - modrm_instr);
578 // returns num_bytes parsed
579 static int decode_rm_operand32(struct guest_info * core,
580 uint8_t * modrm_instr,
581 struct x86_instr * instr,
582 struct x86_operand * operand,
583 uint8_t * reg_code) {
585 struct v3_gprs * gprs = &(core->vm_regs);
586 uint8_t * instr_cursor = modrm_instr;
587 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
588 addr_t base_addr = 0;
589 modrm_mode_t mod_mode = 0;
590 uint_t has_sib_byte = 0;
593 *reg_code = modrm->reg;
597 if (modrm->mod == 3) {
598 operand->type = REG_OPERAND;
599 // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
601 decode_gpr(core, modrm->rm, operand);
604 struct v3_segment * seg = NULL;
606 operand->type = MEM_OPERAND;
608 if (modrm->mod == 0) {
610 } else if (modrm->mod == 1) {
612 } else if (modrm->mod == 2) {
618 base_addr = gprs->rax;
621 base_addr = gprs->rcx;
624 base_addr = gprs->rdx;
627 base_addr = gprs->rbx;
633 if (modrm->mod == 0) {
637 base_addr = gprs->rbp;
641 base_addr = gprs->rsi;
644 base_addr = gprs->rdi;
650 struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
651 int scale = 0x1 << sib->scale;
655 switch (sib->index) {
657 base_addr = gprs->rax;
660 base_addr = gprs->rcx;
663 base_addr = gprs->rdx;
666 base_addr = gprs->rbx;
672 base_addr = gprs->rbp;
675 base_addr = gprs->rsi;
678 base_addr = gprs->rdi;
687 base_addr += MASK_DISPLACEMENT(gprs->rax, mod_mode);
690 base_addr += MASK_DISPLACEMENT(gprs->rcx, mod_mode);
693 base_addr += MASK_DISPLACEMENT(gprs->rdx, mod_mode);
696 base_addr += MASK_DISPLACEMENT(gprs->rbx, mod_mode);
699 base_addr += MASK_DISPLACEMENT(gprs->rsp, mod_mode);
702 if (modrm->mod != 0) {
703 base_addr += MASK_DISPLACEMENT(gprs->rbp, mod_mode);
707 base_addr += MASK_DISPLACEMENT(gprs->rsi, mod_mode);
710 base_addr += MASK_DISPLACEMENT(gprs->rdi, mod_mode);
717 if (mod_mode == DISP8) {
718 base_addr += *(sint8_t *)instr_cursor;
720 } else if (mod_mode == DISP32) {
721 base_addr += *(sint32_t *)instr_cursor;
725 // get appropriate segment
726 if (instr->prefixes.cs_override) {
727 seg = &(core->segments.cs);
728 } else if (instr->prefixes.es_override) {
729 seg = &(core->segments.es);
730 } else if (instr->prefixes.ss_override) {
731 seg = &(core->segments.ss);
732 } else if (instr->prefixes.fs_override) {
733 seg = &(core->segments.fs);
734 } else if (instr->prefixes.gs_override) {
735 seg = &(core->segments.gs);
737 seg = &(core->segments.ds);
740 operand->operand = ADDR_MASK(get_addr_linear(core, base_addr, seg),
741 get_addr_width(core, instr));
745 return (instr_cursor - modrm_instr);
752 static int decode_rm_operand(struct guest_info * core,
753 uint8_t * instr_ptr, // input
754 struct x86_instr * instr,
755 struct x86_operand * operand,
756 uint8_t * reg_code) {
758 v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
761 return decode_rm_operand16(core, instr_ptr, instr, operand, reg_code);
762 } else if ((mode == PROTECTED) || (mode == PROTECTED_PAE)) {
763 return decode_rm_operand32(core, instr_ptr, instr, operand, reg_code);
765 PrintError("Invalid CPU_MODE (%d)\n", mode);
772 static inline op_form_t op_code_to_form_0f(uint8_t * instr, int * length) {
777 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[2]);
779 switch (modrm->reg) {
787 return INVALID_INSTR;
848 return INVALID_INSTR;
853 static op_form_t op_code_to_form(uint8_t * instr, int * length) {
877 return op_code_to_form_0f(instr, length);
917 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
919 switch (modrm->reg) {
933 return INVALID_INSTR;
937 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
939 switch (modrm->reg) {
953 return INVALID_INSTR;
957 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
959 switch (modrm->reg) {
973 return INVALID_INSTR;
1002 return MOV_MEM2AL_8;
1006 return MOV_AL2MEM_8;
1030 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1032 switch (modrm->reg) {
1038 return INVALID_INSTR;
1042 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1044 switch (modrm->reg) {
1050 return INVALID_INSTR;
1056 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1058 switch (modrm->reg) {
1064 return INVALID_INSTR;
1069 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1071 switch (modrm->reg) {
1077 return INVALID_INSTR;
1082 return INVALID_INSTR;
1088 static char * op_form_to_str(op_form_t form) {
1091 case LMSW: return "LMSW";
1092 case SMSW: return "SMSW";
1093 case CLTS: return "CLTS";
1094 case INVLPG: return "INVLPG";
1095 case MOV_CR2: return "MOV_CR2";
1096 case MOV_2CR: return "MOV_2CR";
1097 case MOV_DR2: return "MOV_DR2";
1098 case MOV_2DR: return "MOV_2DR";
1099 case MOV_SR2: return "MOV_SR2";
1100 case MOV_2SR: return "MOV_2SR";
1101 case MOV_MEM2_8: return "MOV_MEM2_8";
1102 case MOV_MEM2: return "MOV_MEM2";
1103 case MOV_2MEM_8: return "MOV_2MEM_8";
1104 case MOV_2MEM: return "MOV_2MEM";
1105 case MOV_MEM2AL_8: return "MOV_MEM2AL_8";
1106 case MOV_MEM2AX: return "MOV_MEM2AX";
1107 case MOV_AL2MEM_8: return "MOV_AL2MEM_8";
1108 case MOV_AX2MEM: return "MOV_AX2MEM";
1109 case MOV_IMM2_8: return "MOV_IMM2_8";
1110 case MOV_IMM2: return "MOV_IMM2";
1111 case MOVS_8: return "MOVS_8";
1112 case MOVS: return "MOVS";
1113 case MOVSX_8: return "MOVSX_8";
1114 case MOVSX: return "MOVSX";
1115 case MOVZX_8: return "MOVZX_8";
1116 case MOVZX: return "MOVZX";
1117 case HLT: return "HLT";
1118 case PUSHF: return "PUSHF";
1119 case POPF: return "POPF";
1120 case ADC_2MEM_8: return "ADC_2MEM_8";
1121 case ADC_2MEM: return "ADC_2MEM";
1122 case ADC_MEM2_8: return "ADC_MEM2_8";
1123 case ADC_MEM2: return "ADC_MEM2";
1124 case ADC_IMM2_8: return "ADC_IMM2_8";
1125 case ADC_IMM2: return "ADC_IMM2";
1126 case ADC_IMM2SX_8: return "ADC_IMM2SX_8";
1127 case ADD_IMM2_8: return "ADD_IMM2_8";
1128 case ADD_IMM2: return "ADD_IMM2";
1129 case ADD_IMM2SX_8: return "ADD_IMM2SX_8";
1130 case ADD_2MEM_8: return "ADD_2MEM_8";
1131 case ADD_2MEM: return "ADD_2MEM";
1132 case ADD_MEM2_8: return "ADD_MEM2_8";
1133 case ADD_MEM2: return "ADD_MEM2";
1134 case AND_MEM2_8: return "AND_MEM2_8";
1135 case AND_MEM2: return "AND_MEM2";
1136 case AND_2MEM_8: return "AND_2MEM_8";
1137 case AND_2MEM: return "AND_2MEM";
1138 case AND_IMM2_8: return "AND_IMM2_8";
1139 case AND_IMM2: return "AND_IMM2";
1140 case AND_IMM2SX_8: return "AND_IMM2SX_8";
1141 case OR_2MEM_8: return "OR_2MEM_8";
1142 case OR_2MEM: return "OR_2MEM";
1143 case OR_MEM2_8: return "OR_MEM2_8";
1144 case OR_MEM2: return "OR_MEM2";
1145 case OR_IMM2_8: return "OR_IMM2_8";
1146 case OR_IMM2: return "OR_IMM2";
1147 case OR_IMM2SX_8: return "OR_IMM2SX_8";
1148 case SUB_2MEM_8: return "SUB_2MEM_8";
1149 case SUB_2MEM: return "SUB_2MEM";
1150 case SUB_MEM2_8: return "SUB_MEM2_8";
1151 case SUB_MEM2: return "SUB_MEM2";
1152 case SUB_IMM2_8: return "SUB_IMM2_8";
1153 case SUB_IMM2: return "SUB_IMM2";
1154 case SUB_IMM2SX_8: return "SUB_IMM2SX_8";
1155 case XOR_2MEM_8: return "XOR_2MEM_8";
1156 case XOR_2MEM: return "XOR_2MEM";
1157 case XOR_MEM2_8: return "XOR_MEM2_8";
1158 case XOR_MEM2: return "XOR_MEM2";
1159 case XOR_IMM2_8: return "XOR_IMM2_8";
1160 case XOR_IMM2: return "XOR_IMM2";
1161 case XOR_IMM2SX_8: return "XOR_IMM2SX_8";
1162 case INC_8: return "INC_8";
1163 case INC: return "INC";
1164 case DEC_8: return "DEC_8";
1165 case DEC: return "DEC";
1166 case NEG_8: return "NEG_8";
1167 case NEG: return "NEG";
1168 case NOT_8: return "NOT_8";
1169 case NOT: return "NOT";
1170 case XCHG_8: return "XCHG_8";
1171 case XCHG: return "XCHG";
1172 case SETB: return "SETB";
1173 case SETBE: return "SETBE";
1174 case SETL: return "SETL";
1175 case SETLE: return "SETLE";
1176 case SETNB: return "SETNB";
1177 case SETNBE: return "SETNBE";
1178 case SETNL: return "SETNL";
1179 case SETNLE: return "SETNLE";
1180 case SETNO: return "SETNO";
1181 case SETNP: return "SETNP";
1182 case SETNS: return "SETNS";
1183 case SETNZ: return "SETNZ";
1184 case SETP: return "SETP";
1185 case SETS: return "SETS";
1186 case SETZ: return "SETZ";
1187 case SETO: return "SETO";
1188 case STOS_8: return "STOS_8";
1189 case STOS: return "STOS";
1193 return "INVALID_INSTR";