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 reg->operand = (addr_t)&(gprs->r8);
415 reg->operand = (addr_t)&(gprs->r9);
418 reg->operand = (addr_t)&(gprs->r10);
421 reg->operand = (addr_t)&(gprs->r11);
424 reg->operand = (addr_t)&(gprs->r12);
427 reg->operand = (addr_t)&(gprs->r13);
430 reg->operand = (addr_t)&(gprs->r14);
433 reg->operand = (addr_t)&(gprs->r15);
436 PrintError("Invalid Reg Code (%d)\n", reg_code);
447 static inline int decode_cr(struct guest_info * core,
449 struct x86_operand * reg) {
451 struct v3_ctrl_regs * crs = &(core->ctrl_regs);
453 PrintDebug("\t Ctrl regs %d\n", reg_code);
457 reg->operand = (addr_t)&(crs->cr0);
460 reg->operand = (addr_t)&(crs->cr2);
463 reg->operand = (addr_t)&(crs->cr3);
466 reg->operand = (addr_t)&(crs->cr4);
470 PrintError("Invalid Reg Code (%d)\n", reg_code);
477 // This converts the displacement into the appropriate masked value
479 QUESTION: Are the register Values signed ?????
481 #define MASK_DISPLACEMENT(reg, mode) ({ \
483 if (mode == DISP8) { \
484 val = (sint8_t)(reg & 0xff); \
485 } else if (mode == DISP16) { \
486 val = (sint16_t)(reg & 0xffff); \
487 } else if (mode == DISP32) { \
488 val = (sint32_t)(reg & 0xffffffff); \
490 PrintError("Error invalid displacement size (%d)\n", mode); \
497 #define ADDR_MASK(val, length) ({ \
498 ullong_t mask = 0x0LL; \
501 mask = 0x00000000000fffffLL; \
504 mask = 0x00000000ffffffffLL; \
507 mask = 0xffffffffffffffffLL; \
515 static int decode_rm_operand16(struct guest_info * core,
516 uint8_t * modrm_instr,
517 struct x86_instr * instr,
518 struct x86_operand * operand,
519 uint8_t * reg_code) {
521 struct v3_gprs * gprs = &(core->vm_regs);
522 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
523 addr_t base_addr = 0;
524 modrm_mode_t mod_mode = 0;
525 uint8_t * instr_cursor = modrm_instr;
527 // PrintDebug("ModRM mod=%d\n", modrm->mod);
529 *reg_code = modrm->reg;
533 if (modrm->mod == 3) {
534 //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
535 operand->type = REG_OPERAND;
537 decode_gpr(core, modrm->rm, operand);
540 struct v3_segment * seg = NULL;
542 operand->type = MEM_OPERAND;
544 if (modrm->mod == 0) {
546 } else if (modrm->mod == 1) {
548 } else if (modrm->mod == 2) {
554 base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
557 base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
560 base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
563 base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
566 base_addr = gprs->rsi;
569 base_addr = gprs->rdi;
572 if (modrm->mod == 0) {
576 base_addr = gprs->rbp;
580 base_addr = gprs->rbx;
586 if (mod_mode == DISP8) {
587 base_addr += *(sint8_t *)instr_cursor;
589 } else if (mod_mode == DISP16) {
590 base_addr += *(sint16_t *)instr_cursor;
595 // get appropriate segment
596 if (instr->prefixes.cs_override) {
597 seg = &(core->segments.cs);
598 } else if (instr->prefixes.es_override) {
599 seg = &(core->segments.es);
600 } else if (instr->prefixes.ss_override) {
601 seg = &(core->segments.ss);
602 } else if (instr->prefixes.fs_override) {
603 seg = &(core->segments.fs);
604 } else if (instr->prefixes.gs_override) {
605 seg = &(core->segments.gs);
607 seg = &(core->segments.ds);
610 operand->operand = ADDR_MASK(get_addr_linear(core, base_addr, seg),
611 get_addr_width(core, instr));
615 return (instr_cursor - modrm_instr);
619 // returns num_bytes parsed
620 static int decode_rm_operand32(struct guest_info * core,
621 uint8_t * modrm_instr,
622 struct x86_instr * instr,
623 struct x86_operand * operand,
624 uint8_t * reg_code) {
626 struct v3_gprs * gprs = &(core->vm_regs);
627 uint8_t * instr_cursor = modrm_instr;
628 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
629 addr_t base_addr = 0;
630 modrm_mode_t mod_mode = 0;
631 uint_t has_sib_byte = 0;
634 *reg_code = modrm->reg;
638 if (modrm->mod == 3) {
639 operand->type = REG_OPERAND;
640 // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
642 decode_gpr(core, modrm->rm, operand);
645 struct v3_segment * seg = NULL;
647 operand->type = MEM_OPERAND;
649 if (modrm->mod == 0) {
651 } else if (modrm->mod == 1) {
653 } else if (modrm->mod == 2) {
659 base_addr = gprs->rax;
662 base_addr = gprs->rcx;
665 base_addr = gprs->rdx;
668 base_addr = gprs->rbx;
674 if (modrm->mod == 0) {
678 base_addr = gprs->rbp;
682 base_addr = gprs->rsi;
685 base_addr = gprs->rdi;
691 struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
692 int scale = 0x1 << sib->scale;
696 switch (sib->index) {
698 base_addr = gprs->rax;
701 base_addr = gprs->rcx;
704 base_addr = gprs->rdx;
707 base_addr = gprs->rbx;
713 base_addr = gprs->rbp;
716 base_addr = gprs->rsi;
719 base_addr = gprs->rdi;
728 base_addr += MASK_DISPLACEMENT(gprs->rax, mod_mode);
731 base_addr += MASK_DISPLACEMENT(gprs->rcx, mod_mode);
734 base_addr += MASK_DISPLACEMENT(gprs->rdx, mod_mode);
737 base_addr += MASK_DISPLACEMENT(gprs->rbx, mod_mode);
740 base_addr += MASK_DISPLACEMENT(gprs->rsp, mod_mode);
743 if (modrm->mod != 0) {
744 base_addr += MASK_DISPLACEMENT(gprs->rbp, mod_mode);
748 base_addr += MASK_DISPLACEMENT(gprs->rsi, mod_mode);
751 base_addr += MASK_DISPLACEMENT(gprs->rdi, mod_mode);
758 if (mod_mode == DISP8) {
759 base_addr += *(sint8_t *)instr_cursor;
761 } else if (mod_mode == DISP32) {
762 base_addr += *(sint32_t *)instr_cursor;
766 // get appropriate segment
767 if (instr->prefixes.cs_override) {
768 seg = &(core->segments.cs);
769 } else if (instr->prefixes.es_override) {
770 seg = &(core->segments.es);
771 } else if (instr->prefixes.ss_override) {
772 seg = &(core->segments.ss);
773 } else if (instr->prefixes.fs_override) {
774 seg = &(core->segments.fs);
775 } else if (instr->prefixes.gs_override) {
776 seg = &(core->segments.gs);
778 seg = &(core->segments.ds);
781 operand->operand = ADDR_MASK(get_addr_linear(core, base_addr, seg),
782 get_addr_width(core, instr));
786 return (instr_cursor - modrm_instr);
790 int decode_rm_operand64(struct guest_info * core, uint8_t * modrm_instr,
791 struct x86_instr * instr, struct x86_operand * operand,
792 uint8_t * reg_code) {
794 struct v3_gprs * gprs = &(core->vm_regs);
795 uint8_t * instr_cursor = modrm_instr;
796 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
797 addr_t base_addr = 0;
798 modrm_mode_t mod_mode = 0;
799 uint_t has_sib_byte = 0;
804 *reg_code = modrm->reg;
805 *reg_code |= (instr->prefixes.rex_reg << 3);
807 if (modrm->mod == 3) {
808 uint8_t rm_val = modrm->rm;
810 rm_val |= (instr->prefixes.rex_rm << 3);
812 operand->type = REG_OPERAND;
813 // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
815 decode_gpr(core, rm_val, operand);
817 struct v3_segment * seg = NULL;
818 uint8_t rm_val = modrm->rm;
820 operand->type = MEM_OPERAND;
823 if (modrm->mod == 0) {
825 } else if (modrm->mod == 1) {
827 } else if (modrm->mod == 2) {
834 rm_val |= (instr->prefixes.rex_rm << 3);
838 base_addr = gprs->rax;
841 base_addr = gprs->rcx;
844 base_addr = gprs->rdx;
847 base_addr = gprs->rbx;
850 if (modrm->mod == 0) {
854 base_addr = gprs->rbp;
858 base_addr = gprs->rsi;
861 base_addr = gprs->rdi;
864 base_addr = gprs->r8;
867 base_addr = gprs->r9;
870 base_addr = gprs->r10;
873 base_addr = gprs->r11;
876 base_addr = gprs->r12;
879 base_addr = gprs->r13;
882 base_addr = gprs->r14;
885 base_addr = gprs->r15;
894 struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
895 int scale = 0x1 << sib->scale;
896 uint8_t index_val = sib->index;
897 uint8_t base_val = sib->base;
899 index_val |= (instr->prefixes.rex_sib_idx << 3);
900 base_val |= (instr->prefixes.rex_rm << 3);
906 base_addr = gprs->rax;
909 base_addr = gprs->rcx;
912 base_addr = gprs->rdx;
915 base_addr = gprs->rbx;
921 base_addr = gprs->rbp;
924 base_addr = gprs->rsi;
927 base_addr = gprs->rdi;
930 base_addr = gprs->r8;
933 base_addr = gprs->r9;
936 base_addr = gprs->r10;
939 base_addr = gprs->r11;
942 base_addr = gprs->r12;
945 base_addr = gprs->r13;
948 base_addr = gprs->r14;
951 base_addr = gprs->r15;
960 base_addr += MASK_DISPLACEMENT(gprs->rax, mod_mode);
963 base_addr += MASK_DISPLACEMENT(gprs->rcx, mod_mode);
966 base_addr += MASK_DISPLACEMENT(gprs->rdx, mod_mode);
969 base_addr += MASK_DISPLACEMENT(gprs->rbx, mod_mode);
972 base_addr += MASK_DISPLACEMENT(gprs->rsp, mod_mode);
975 if (modrm->mod != 0) {
976 base_addr += MASK_DISPLACEMENT(gprs->rbp, mod_mode);
980 base_addr += MASK_DISPLACEMENT(gprs->rsi, mod_mode);
983 base_addr += MASK_DISPLACEMENT(gprs->rdi, mod_mode);
986 base_addr += MASK_DISPLACEMENT(gprs->r8, mod_mode);
989 base_addr += MASK_DISPLACEMENT(gprs->r9, mod_mode);
992 base_addr += MASK_DISPLACEMENT(gprs->r10, mod_mode);
995 base_addr += MASK_DISPLACEMENT(gprs->r11, mod_mode);
998 base_addr += MASK_DISPLACEMENT(gprs->r12, mod_mode);
1001 base_addr += MASK_DISPLACEMENT(gprs->r13, mod_mode);
1004 base_addr += MASK_DISPLACEMENT(gprs->r14, mod_mode);
1007 base_addr += MASK_DISPLACEMENT(gprs->r15, mod_mode);
1014 if (mod_mode == DISP8) {
1015 base_addr += *(sint8_t *)instr_cursor;
1017 } else if (mod_mode == DISP32) {
1018 base_addr += *(sint32_t *)instr_cursor;
1024 Segments should be ignored
1025 // get appropriate segment
1026 if (instr->prefixes.cs_override) {
1027 seg = &(core->segments.cs);
1028 } else if (instr->prefixes.es_override) {
1029 seg = &(core->segments.es);
1030 } else if (instr->prefixes.ss_override) {
1031 seg = &(core->segments.ss);
1032 } else if (instr->prefixes.fs_override) {
1033 seg = &(core->segments.fs);
1034 } else if (instr->prefixes.gs_override) {
1035 seg = &(core->segments.gs);
1037 seg = &(core->segments.ds);
1041 operand->operand = ADDR_MASK(get_addr_linear(core, base_addr, seg),
1042 get_addr_width(core, instr));
1046 return (instr_cursor - modrm_instr);
1052 static int decode_rm_operand(struct guest_info * core,
1053 uint8_t * instr_ptr, // input
1055 struct x86_instr * instr,
1056 struct x86_operand * operand,
1057 uint8_t * reg_code) {
1059 v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
1061 operand->size = get_operand_width(core, instr, form);
1065 return decode_rm_operand16(core, instr_ptr, instr, operand, reg_code);
1067 if (instr->prefixes.rex_op_size) {
1068 return decode_rm_operand64(core, instr_ptr, instr, operand, reg_code);
1072 case LONG_32_COMPAT:
1073 return decode_rm_operand32(core, instr_ptr, instr, operand, reg_code);
1075 PrintError("Invalid CPU_MODE (%d)\n", mode);
1082 static inline op_form_t op_code_to_form_0f(uint8_t * instr, int * length) {
1087 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[2]);
1089 switch (modrm->reg) {
1097 return INVALID_INSTR;
1158 return INVALID_INSTR;
1163 static op_form_t op_code_to_form(uint8_t * instr, int * length) {
1187 return op_code_to_form_0f(instr, length);
1227 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1229 switch (modrm->reg) {
1243 return INVALID_INSTR;
1247 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1249 switch (modrm->reg) {
1263 return INVALID_INSTR;
1267 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1269 switch (modrm->reg) {
1271 return ADD_IMM2SX_8;
1275 return ADC_IMM2SX_8;
1277 return AND_IMM2SX_8;
1279 return SUB_IMM2SX_8;
1281 return XOR_IMM2SX_8;
1283 return INVALID_INSTR;
1312 return MOV_MEM2AL_8;
1316 return MOV_AL2MEM_8;
1340 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1342 switch (modrm->reg) {
1348 return INVALID_INSTR;
1352 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1354 switch (modrm->reg) {
1360 return INVALID_INSTR;
1366 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1368 switch (modrm->reg) {
1374 return INVALID_INSTR;
1379 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1381 switch (modrm->reg) {
1387 return INVALID_INSTR;
1392 return INVALID_INSTR;
1398 static char * op_form_to_str(op_form_t form) {
1401 case LMSW: return "LMSW";
1402 case SMSW: return "SMSW";
1403 case CLTS: return "CLTS";
1404 case INVLPG: return "INVLPG";
1405 case MOV_CR2: return "MOV_CR2";
1406 case MOV_2CR: return "MOV_2CR";
1407 case MOV_DR2: return "MOV_DR2";
1408 case MOV_2DR: return "MOV_2DR";
1409 case MOV_SR2: return "MOV_SR2";
1410 case MOV_2SR: return "MOV_2SR";
1411 case MOV_MEM2_8: return "MOV_MEM2_8";
1412 case MOV_MEM2: return "MOV_MEM2";
1413 case MOV_2MEM_8: return "MOV_2MEM_8";
1414 case MOV_2MEM: return "MOV_2MEM";
1415 case MOV_MEM2AL_8: return "MOV_MEM2AL_8";
1416 case MOV_MEM2AX: return "MOV_MEM2AX";
1417 case MOV_AL2MEM_8: return "MOV_AL2MEM_8";
1418 case MOV_AX2MEM: return "MOV_AX2MEM";
1419 case MOV_IMM2_8: return "MOV_IMM2_8";
1420 case MOV_IMM2: return "MOV_IMM2";
1421 case MOVS_8: return "MOVS_8";
1422 case MOVS: return "MOVS";
1423 case MOVSX_8: return "MOVSX_8";
1424 case MOVSX: return "MOVSX";
1425 case MOVZX_8: return "MOVZX_8";
1426 case MOVZX: return "MOVZX";
1427 case HLT: return "HLT";
1428 case PUSHF: return "PUSHF";
1429 case POPF: return "POPF";
1430 case ADC_2MEM_8: return "ADC_2MEM_8";
1431 case ADC_2MEM: return "ADC_2MEM";
1432 case ADC_MEM2_8: return "ADC_MEM2_8";
1433 case ADC_MEM2: return "ADC_MEM2";
1434 case ADC_IMM2_8: return "ADC_IMM2_8";
1435 case ADC_IMM2: return "ADC_IMM2";
1436 case ADC_IMM2SX_8: return "ADC_IMM2SX_8";
1437 case ADD_IMM2_8: return "ADD_IMM2_8";
1438 case ADD_IMM2: return "ADD_IMM2";
1439 case ADD_IMM2SX_8: return "ADD_IMM2SX_8";
1440 case ADD_2MEM_8: return "ADD_2MEM_8";
1441 case ADD_2MEM: return "ADD_2MEM";
1442 case ADD_MEM2_8: return "ADD_MEM2_8";
1443 case ADD_MEM2: return "ADD_MEM2";
1444 case AND_MEM2_8: return "AND_MEM2_8";
1445 case AND_MEM2: return "AND_MEM2";
1446 case AND_2MEM_8: return "AND_2MEM_8";
1447 case AND_2MEM: return "AND_2MEM";
1448 case AND_IMM2_8: return "AND_IMM2_8";
1449 case AND_IMM2: return "AND_IMM2";
1450 case AND_IMM2SX_8: return "AND_IMM2SX_8";
1451 case OR_2MEM_8: return "OR_2MEM_8";
1452 case OR_2MEM: return "OR_2MEM";
1453 case OR_MEM2_8: return "OR_MEM2_8";
1454 case OR_MEM2: return "OR_MEM2";
1455 case OR_IMM2_8: return "OR_IMM2_8";
1456 case OR_IMM2: return "OR_IMM2";
1457 case OR_IMM2SX_8: return "OR_IMM2SX_8";
1458 case SUB_2MEM_8: return "SUB_2MEM_8";
1459 case SUB_2MEM: return "SUB_2MEM";
1460 case SUB_MEM2_8: return "SUB_MEM2_8";
1461 case SUB_MEM2: return "SUB_MEM2";
1462 case SUB_IMM2_8: return "SUB_IMM2_8";
1463 case SUB_IMM2: return "SUB_IMM2";
1464 case SUB_IMM2SX_8: return "SUB_IMM2SX_8";
1465 case XOR_2MEM_8: return "XOR_2MEM_8";
1466 case XOR_2MEM: return "XOR_2MEM";
1467 case XOR_MEM2_8: return "XOR_MEM2_8";
1468 case XOR_MEM2: return "XOR_MEM2";
1469 case XOR_IMM2_8: return "XOR_IMM2_8";
1470 case XOR_IMM2: return "XOR_IMM2";
1471 case XOR_IMM2SX_8: return "XOR_IMM2SX_8";
1472 case INC_8: return "INC_8";
1473 case INC: return "INC";
1474 case DEC_8: return "DEC_8";
1475 case DEC: return "DEC";
1476 case NEG_8: return "NEG_8";
1477 case NEG: return "NEG";
1478 case NOT_8: return "NOT_8";
1479 case NOT: return "NOT";
1480 case XCHG_8: return "XCHG_8";
1481 case XCHG: return "XCHG";
1482 case SETB: return "SETB";
1483 case SETBE: return "SETBE";
1484 case SETL: return "SETL";
1485 case SETLE: return "SETLE";
1486 case SETNB: return "SETNB";
1487 case SETNBE: return "SETNBE";
1488 case SETNL: return "SETNL";
1489 case SETNLE: return "SETNLE";
1490 case SETNO: return "SETNO";
1491 case SETNP: return "SETNP";
1492 case SETNS: return "SETNS";
1493 case SETNZ: return "SETNZ";
1494 case SETP: return "SETP";
1495 case SETS: return "SETS";
1496 case SETZ: return "SETZ";
1497 case SETO: return "SETO";
1498 case STOS_8: return "STOS_8";
1499 case STOS: return "STOS";
1503 return "INVALID_INSTR";