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>
22 /* .... Giant fucking switch tables */
137 static int get_addr_width(struct guest_info * info, struct x86_instr * instr) {
139 switch (v3_get_vm_cpu_mode(info)) {
141 return (instr->prefixes.addr_size) ? 4 : 2;
147 if (info->segments.cs.db) {
148 return (instr->prefixes.addr_size) ? 2 : 4;
150 return (instr->prefixes.addr_size) ? 4 : 2;
153 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
158 static int get_operand_width(struct guest_info * info, struct x86_instr * instr,
258 switch (v3_get_vm_cpu_mode(info)) {
260 return (instr->prefixes.op_size) ? 4 : 2;
262 if (instr->prefixes.rex_op_size) {
268 if (info->segments.cs.db) {
270 return (instr->prefixes.op_size) ? 2 : 4;
272 return (instr->prefixes.op_size) ? 4 : 2;
275 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
280 switch (v3_get_vm_cpu_mode(info)) {
282 PrintError("Invalid instruction given operating mode (%d)\n", form);
291 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
297 switch (v3_get_vm_cpu_mode(info)) {
307 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
315 switch (v3_get_vm_cpu_mode(info)) {
325 PrintError("Unsupported CPU mode: %d\n", info->cpu_mode);
332 PrintError("Unsupported instruction form %d\n", form);
341 typedef enum {INVALID_ADDR_TYPE, REG, DISP0, DISP8, DISP16, DISP32} modrm_mode_t;
342 typedef enum {INVALID_REG_SIZE, REG64, REG32, REG16, REG8} reg_size_t;
349 } __attribute__((packed));
356 } __attribute__((packed));
363 static inline int decode_gpr(struct guest_info * core,
365 struct x86_operand * reg) {
367 struct v3_gprs * gprs = &(core->vm_regs);
371 reg->operand = (addr_t)&(gprs->rax);
374 reg->operand = (addr_t)&(gprs->rcx);
377 reg->operand = (addr_t)&(gprs->rdx);
380 reg->operand = (addr_t)&(gprs->rbx);
383 if (reg->size == 1) {
384 reg->operand = (addr_t)&(gprs->rax) + 1;
386 reg->operand = (addr_t)&(gprs->rsp);
390 if (reg->size == 1) {
391 reg->operand = (addr_t)&(gprs->rcx) + 1;
393 reg->operand = (addr_t)&(gprs->rbp);
397 if (reg->size == 1) {
398 reg->operand = (addr_t)&(gprs->rdx) + 1;
400 reg->operand = (addr_t)&(gprs->rsi);
404 if (reg->size == 1) {
405 reg->operand = (addr_t)&(gprs->rbx) + 1;
407 reg->operand = (addr_t)&(gprs->rdi);
411 reg->operand = (addr_t)&(gprs->r8);
414 reg->operand = (addr_t)&(gprs->r9);
417 reg->operand = (addr_t)&(gprs->r10);
420 reg->operand = (addr_t)&(gprs->r11);
423 reg->operand = (addr_t)&(gprs->r12);
426 reg->operand = (addr_t)&(gprs->r13);
429 reg->operand = (addr_t)&(gprs->r14);
432 reg->operand = (addr_t)&(gprs->r15);
435 PrintError("Invalid Reg Code (%d)\n", reg_code);
446 static inline int decode_cr(struct guest_info * core,
448 struct x86_operand * reg) {
450 struct v3_ctrl_regs * crs = &(core->ctrl_regs);
452 // PrintDebug("\t Ctrl regs %d\n", reg_code);
456 reg->operand = (addr_t)&(crs->cr0);
459 reg->operand = (addr_t)&(crs->cr2);
462 reg->operand = (addr_t)&(crs->cr3);
465 reg->operand = (addr_t)&(crs->cr4);
469 PrintError("Invalid Reg Code (%d)\n", reg_code);
476 // This converts the displacement into the appropriate masked value
478 QUESTION: Are the register Values signed ?????
480 #define MASK_DISPLACEMENT(reg, mode) ({ \
482 if (mode == DISP8) { \
483 val = (sint8_t)(reg & 0xff); \
484 } else if (mode == DISP16) { \
485 val = (sint16_t)(reg & 0xffff); \
486 } else if (mode == DISP32) { \
487 val = (sint32_t)(reg & 0xffffffff); \
489 PrintError("Error invalid displacement size (%d)\n", mode); \
496 #define ADDR_MASK(val, length) ({ \
497 ullong_t mask = 0x0LL; \
500 mask = 0x00000000000fffffLL; \
503 mask = 0x00000000ffffffffLL; \
506 mask = 0xffffffffffffffffLL; \
514 static int decode_rm_operand16(struct guest_info * core,
515 uint8_t * modrm_instr,
516 struct x86_instr * instr,
517 struct x86_operand * operand,
518 uint8_t * reg_code) {
520 struct v3_gprs * gprs = &(core->vm_regs);
521 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
522 addr_t base_addr = 0;
523 modrm_mode_t mod_mode = 0;
524 uint8_t * instr_cursor = modrm_instr;
526 // PrintDebug("ModRM mod=%d\n", modrm->mod);
528 *reg_code = modrm->reg;
532 if (modrm->mod == 3) {
533 //PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
534 operand->type = REG_OPERAND;
536 decode_gpr(core, modrm->rm, operand);
539 struct v3_segment * seg = NULL;
541 operand->type = MEM_OPERAND;
543 if (modrm->mod == 0) {
545 } else if (modrm->mod == 1) {
547 } else if (modrm->mod == 2) {
553 base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
556 base_addr = gprs->rbx + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
559 base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rsi, mod_mode);
562 base_addr = gprs->rbp + MASK_DISPLACEMENT(gprs->rdi, mod_mode);
565 base_addr = gprs->rsi;
568 base_addr = gprs->rdi;
571 if (modrm->mod == 0) {
575 base_addr = gprs->rbp;
579 base_addr = gprs->rbx;
585 if (mod_mode == DISP8) {
586 base_addr += *(sint8_t *)instr_cursor;
588 } else if (mod_mode == DISP16) {
589 base_addr += *(sint16_t *)instr_cursor;
594 // get appropriate segment
595 if (instr->prefixes.cs_override) {
596 seg = &(core->segments.cs);
597 } else if (instr->prefixes.es_override) {
598 seg = &(core->segments.es);
599 } else if (instr->prefixes.ss_override) {
600 seg = &(core->segments.ss);
601 } else if (instr->prefixes.fs_override) {
602 seg = &(core->segments.fs);
603 } else if (instr->prefixes.gs_override) {
604 seg = &(core->segments.gs);
606 seg = &(core->segments.ds);
609 operand->operand = ADDR_MASK(get_addr_linear(core, base_addr, seg),
610 get_addr_width(core, instr));
614 return (instr_cursor - modrm_instr);
618 // returns num_bytes parsed
619 static int decode_rm_operand32(struct guest_info * core,
620 uint8_t * modrm_instr,
621 struct x86_instr * instr,
622 struct x86_operand * operand,
623 uint8_t * reg_code) {
625 struct v3_gprs * gprs = &(core->vm_regs);
626 uint8_t * instr_cursor = modrm_instr;
627 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
628 addr_t base_addr = 0;
629 modrm_mode_t mod_mode = 0;
630 uint_t has_sib_byte = 0;
633 *reg_code = modrm->reg;
637 if (modrm->mod == 3) {
638 operand->type = REG_OPERAND;
639 // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
641 decode_gpr(core, modrm->rm, operand);
644 struct v3_segment * seg = NULL;
646 operand->type = MEM_OPERAND;
648 if (modrm->mod == 0) {
650 } else if (modrm->mod == 1) {
652 } else if (modrm->mod == 2) {
658 base_addr = gprs->rax;
661 base_addr = gprs->rcx;
664 base_addr = gprs->rdx;
667 base_addr = gprs->rbx;
673 if (modrm->mod == 0) {
677 base_addr = gprs->rbp;
681 base_addr = gprs->rsi;
684 base_addr = gprs->rdi;
690 struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
691 int scale = 0x1 << sib->scale;
695 switch (sib->index) {
697 base_addr = gprs->rax;
700 base_addr = gprs->rcx;
703 base_addr = gprs->rdx;
706 base_addr = gprs->rbx;
712 base_addr = gprs->rbp;
715 base_addr = gprs->rsi;
718 base_addr = gprs->rdi;
727 base_addr += MASK_DISPLACEMENT(gprs->rax, mod_mode);
730 base_addr += MASK_DISPLACEMENT(gprs->rcx, mod_mode);
733 base_addr += MASK_DISPLACEMENT(gprs->rdx, mod_mode);
736 base_addr += MASK_DISPLACEMENT(gprs->rbx, mod_mode);
739 base_addr += MASK_DISPLACEMENT(gprs->rsp, mod_mode);
742 if (modrm->mod != 0) {
743 base_addr += MASK_DISPLACEMENT(gprs->rbp, mod_mode);
747 base_addr += MASK_DISPLACEMENT(gprs->rsi, mod_mode);
750 base_addr += MASK_DISPLACEMENT(gprs->rdi, mod_mode);
757 if (mod_mode == DISP8) {
758 base_addr += *(sint8_t *)instr_cursor;
760 } else if (mod_mode == DISP32) {
761 base_addr += *(sint32_t *)instr_cursor;
765 // get appropriate segment
766 if (instr->prefixes.cs_override) {
767 seg = &(core->segments.cs);
768 } else if (instr->prefixes.es_override) {
769 seg = &(core->segments.es);
770 } else if (instr->prefixes.ss_override) {
771 seg = &(core->segments.ss);
772 } else if (instr->prefixes.fs_override) {
773 seg = &(core->segments.fs);
774 } else if (instr->prefixes.gs_override) {
775 seg = &(core->segments.gs);
777 seg = &(core->segments.ds);
780 operand->operand = ADDR_MASK(get_addr_linear(core, base_addr, seg),
781 get_addr_width(core, instr));
785 return (instr_cursor - modrm_instr);
789 int decode_rm_operand64(struct guest_info * core, uint8_t * modrm_instr,
790 struct x86_instr * instr, struct x86_operand * operand,
791 uint8_t * reg_code) {
793 struct v3_gprs * gprs = &(core->vm_regs);
794 uint8_t * instr_cursor = modrm_instr;
795 struct modrm_byte * modrm = (struct modrm_byte *)modrm_instr;
796 addr_t base_addr = 0;
797 modrm_mode_t mod_mode = 0;
798 uint_t has_sib_byte = 0;
803 *reg_code = modrm->reg;
804 *reg_code |= (instr->prefixes.rex_reg << 3);
806 if (modrm->mod == 3) {
807 uint8_t rm_val = modrm->rm;
809 rm_val |= (instr->prefixes.rex_rm << 3);
811 operand->type = REG_OPERAND;
812 // PrintDebug("first operand = Register (RM=%d)\n",modrm->rm);
814 decode_gpr(core, rm_val, operand);
816 struct v3_segment * seg = NULL;
817 uint8_t rm_val = modrm->rm;
819 operand->type = MEM_OPERAND;
822 if (modrm->mod == 0) {
824 } else if (modrm->mod == 1) {
826 } else if (modrm->mod == 2) {
833 rm_val |= (instr->prefixes.rex_rm << 3);
837 base_addr = gprs->rax;
840 base_addr = gprs->rcx;
843 base_addr = gprs->rdx;
846 base_addr = gprs->rbx;
849 if (modrm->mod == 0) {
853 base_addr = gprs->rbp;
857 base_addr = gprs->rsi;
860 base_addr = gprs->rdi;
863 base_addr = gprs->r8;
866 base_addr = gprs->r9;
869 base_addr = gprs->r10;
872 base_addr = gprs->r11;
875 base_addr = gprs->r12;
878 base_addr = gprs->r13;
881 base_addr = gprs->r14;
884 base_addr = gprs->r15;
893 struct sib_byte * sib = (struct sib_byte *)(instr_cursor);
894 int scale = 0x1 << sib->scale;
895 uint8_t index_val = sib->index;
896 uint8_t base_val = sib->base;
898 index_val |= (instr->prefixes.rex_sib_idx << 3);
899 base_val |= (instr->prefixes.rex_rm << 3);
905 base_addr = gprs->rax;
908 base_addr = gprs->rcx;
911 base_addr = gprs->rdx;
914 base_addr = gprs->rbx;
920 base_addr = gprs->rbp;
923 base_addr = gprs->rsi;
926 base_addr = gprs->rdi;
929 base_addr = gprs->r8;
932 base_addr = gprs->r9;
935 base_addr = gprs->r10;
938 base_addr = gprs->r11;
941 base_addr = gprs->r12;
944 base_addr = gprs->r13;
947 base_addr = gprs->r14;
950 base_addr = gprs->r15;
959 base_addr += MASK_DISPLACEMENT(gprs->rax, mod_mode);
962 base_addr += MASK_DISPLACEMENT(gprs->rcx, mod_mode);
965 base_addr += MASK_DISPLACEMENT(gprs->rdx, mod_mode);
968 base_addr += MASK_DISPLACEMENT(gprs->rbx, mod_mode);
971 base_addr += MASK_DISPLACEMENT(gprs->rsp, mod_mode);
974 if (modrm->mod != 0) {
975 base_addr += MASK_DISPLACEMENT(gprs->rbp, mod_mode);
979 base_addr += MASK_DISPLACEMENT(gprs->rsi, mod_mode);
982 base_addr += MASK_DISPLACEMENT(gprs->rdi, mod_mode);
985 base_addr += MASK_DISPLACEMENT(gprs->r8, mod_mode);
988 base_addr += MASK_DISPLACEMENT(gprs->r9, mod_mode);
991 base_addr += MASK_DISPLACEMENT(gprs->r10, mod_mode);
994 base_addr += MASK_DISPLACEMENT(gprs->r11, mod_mode);
997 base_addr += MASK_DISPLACEMENT(gprs->r12, mod_mode);
1000 base_addr += MASK_DISPLACEMENT(gprs->r13, mod_mode);
1003 base_addr += MASK_DISPLACEMENT(gprs->r14, mod_mode);
1006 base_addr += MASK_DISPLACEMENT(gprs->r15, mod_mode);
1013 if (mod_mode == DISP8) {
1014 base_addr += *(sint8_t *)instr_cursor;
1016 } else if (mod_mode == DISP32) {
1017 base_addr += *(sint32_t *)instr_cursor;
1023 Segments should be ignored
1024 // get appropriate segment
1025 if (instr->prefixes.cs_override) {
1026 seg = &(core->segments.cs);
1027 } else if (instr->prefixes.es_override) {
1028 seg = &(core->segments.es);
1029 } else if (instr->prefixes.ss_override) {
1030 seg = &(core->segments.ss);
1031 } else if (instr->prefixes.fs_override) {
1032 seg = &(core->segments.fs);
1033 } else if (instr->prefixes.gs_override) {
1034 seg = &(core->segments.gs);
1036 seg = &(core->segments.ds);
1040 operand->operand = ADDR_MASK(get_addr_linear(core, base_addr, seg),
1041 get_addr_width(core, instr));
1045 return (instr_cursor - modrm_instr);
1051 static int decode_rm_operand(struct guest_info * core,
1052 uint8_t * instr_ptr, // input
1054 struct x86_instr * instr,
1055 struct x86_operand * operand,
1056 uint8_t * reg_code) {
1058 v3_cpu_mode_t mode = v3_get_vm_cpu_mode(core);
1060 operand->size = get_operand_width(core, instr, form);
1064 return decode_rm_operand16(core, instr_ptr, instr, operand, reg_code);
1066 if (instr->prefixes.rex_op_size) {
1067 return decode_rm_operand64(core, instr_ptr, instr, operand, reg_code);
1071 case LONG_32_COMPAT:
1072 return decode_rm_operand32(core, instr_ptr, instr, operand, reg_code);
1074 PrintError("Invalid CPU_MODE (%d)\n", mode);
1081 static inline op_form_t op_code_to_form_0f(uint8_t * instr, int * length) {
1086 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[2]);
1088 switch (modrm->reg) {
1096 return INVALID_INSTR;
1157 return INVALID_INSTR;
1162 static op_form_t op_code_to_form(uint8_t * instr, int * length) {
1186 return op_code_to_form_0f(instr, length);
1226 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1228 switch (modrm->reg) {
1242 return INVALID_INSTR;
1246 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1248 switch (modrm->reg) {
1262 return INVALID_INSTR;
1266 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1268 switch (modrm->reg) {
1270 return ADD_IMM2SX_8;
1274 return ADC_IMM2SX_8;
1276 return AND_IMM2SX_8;
1278 return SUB_IMM2SX_8;
1280 return XOR_IMM2SX_8;
1282 return INVALID_INSTR;
1311 return MOV_MEM2AL_8;
1315 return MOV_AL2MEM_8;
1339 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1341 switch (modrm->reg) {
1347 return INVALID_INSTR;
1351 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1353 switch (modrm->reg) {
1359 return INVALID_INSTR;
1365 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1367 switch (modrm->reg) {
1373 return INVALID_INSTR;
1378 struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
1380 switch (modrm->reg) {
1386 return INVALID_INSTR;
1391 return INVALID_INSTR;
1397 static char * op_form_to_str(op_form_t form) {
1400 case LMSW: return "LMSW";
1401 case SMSW: return "SMSW";
1402 case CLTS: return "CLTS";
1403 case INVLPG: return "INVLPG";
1404 case MOV_CR2: return "MOV_CR2";
1405 case MOV_2CR: return "MOV_2CR";
1406 case MOV_DR2: return "MOV_DR2";
1407 case MOV_2DR: return "MOV_2DR";
1408 case MOV_SR2: return "MOV_SR2";
1409 case MOV_2SR: return "MOV_2SR";
1410 case MOV_MEM2_8: return "MOV_MEM2_8";
1411 case MOV_MEM2: return "MOV_MEM2";
1412 case MOV_2MEM_8: return "MOV_2MEM_8";
1413 case MOV_2MEM: return "MOV_2MEM";
1414 case MOV_MEM2AL_8: return "MOV_MEM2AL_8";
1415 case MOV_MEM2AX: return "MOV_MEM2AX";
1416 case MOV_AL2MEM_8: return "MOV_AL2MEM_8";
1417 case MOV_AX2MEM: return "MOV_AX2MEM";
1418 case MOV_IMM2_8: return "MOV_IMM2_8";
1419 case MOV_IMM2: return "MOV_IMM2";
1420 case MOVS_8: return "MOVS_8";
1421 case MOVS: return "MOVS";
1422 case MOVSX_8: return "MOVSX_8";
1423 case MOVSX: return "MOVSX";
1424 case MOVZX_8: return "MOVZX_8";
1425 case MOVZX: return "MOVZX";
1426 case HLT: return "HLT";
1427 case PUSHF: return "PUSHF";
1428 case POPF: return "POPF";
1429 case ADC_2MEM_8: return "ADC_2MEM_8";
1430 case ADC_2MEM: return "ADC_2MEM";
1431 case ADC_MEM2_8: return "ADC_MEM2_8";
1432 case ADC_MEM2: return "ADC_MEM2";
1433 case ADC_IMM2_8: return "ADC_IMM2_8";
1434 case ADC_IMM2: return "ADC_IMM2";
1435 case ADC_IMM2SX_8: return "ADC_IMM2SX_8";
1436 case ADD_IMM2_8: return "ADD_IMM2_8";
1437 case ADD_IMM2: return "ADD_IMM2";
1438 case ADD_IMM2SX_8: return "ADD_IMM2SX_8";
1439 case ADD_2MEM_8: return "ADD_2MEM_8";
1440 case ADD_2MEM: return "ADD_2MEM";
1441 case ADD_MEM2_8: return "ADD_MEM2_8";
1442 case ADD_MEM2: return "ADD_MEM2";
1443 case AND_MEM2_8: return "AND_MEM2_8";
1444 case AND_MEM2: return "AND_MEM2";
1445 case AND_2MEM_8: return "AND_2MEM_8";
1446 case AND_2MEM: return "AND_2MEM";
1447 case AND_IMM2_8: return "AND_IMM2_8";
1448 case AND_IMM2: return "AND_IMM2";
1449 case AND_IMM2SX_8: return "AND_IMM2SX_8";
1450 case OR_2MEM_8: return "OR_2MEM_8";
1451 case OR_2MEM: return "OR_2MEM";
1452 case OR_MEM2_8: return "OR_MEM2_8";
1453 case OR_MEM2: return "OR_MEM2";
1454 case OR_IMM2_8: return "OR_IMM2_8";
1455 case OR_IMM2: return "OR_IMM2";
1456 case OR_IMM2SX_8: return "OR_IMM2SX_8";
1457 case SUB_2MEM_8: return "SUB_2MEM_8";
1458 case SUB_2MEM: return "SUB_2MEM";
1459 case SUB_MEM2_8: return "SUB_MEM2_8";
1460 case SUB_MEM2: return "SUB_MEM2";
1461 case SUB_IMM2_8: return "SUB_IMM2_8";
1462 case SUB_IMM2: return "SUB_IMM2";
1463 case SUB_IMM2SX_8: return "SUB_IMM2SX_8";
1464 case XOR_2MEM_8: return "XOR_2MEM_8";
1465 case XOR_2MEM: return "XOR_2MEM";
1466 case XOR_MEM2_8: return "XOR_MEM2_8";
1467 case XOR_MEM2: return "XOR_MEM2";
1468 case XOR_IMM2_8: return "XOR_IMM2_8";
1469 case XOR_IMM2: return "XOR_IMM2";
1470 case XOR_IMM2SX_8: return "XOR_IMM2SX_8";
1471 case INC_8: return "INC_8";
1472 case INC: return "INC";
1473 case DEC_8: return "DEC_8";
1474 case DEC: return "DEC";
1475 case NEG_8: return "NEG_8";
1476 case NEG: return "NEG";
1477 case NOT_8: return "NOT_8";
1478 case NOT: return "NOT";
1479 case XCHG_8: return "XCHG_8";
1480 case XCHG: return "XCHG";
1481 case SETB: return "SETB";
1482 case SETBE: return "SETBE";
1483 case SETL: return "SETL";
1484 case SETLE: return "SETLE";
1485 case SETNB: return "SETNB";
1486 case SETNBE: return "SETNBE";
1487 case SETNL: return "SETNL";
1488 case SETNLE: return "SETNLE";
1489 case SETNO: return "SETNO";
1490 case SETNP: return "SETNP";
1491 case SETNS: return "SETNS";
1492 case SETNZ: return "SETNZ";
1493 case SETP: return "SETP";
1494 case SETS: return "SETS";
1495 case SETZ: return "SETZ";
1496 case SETO: return "SETO";
1497 case STOS_8: return "STOS_8";
1498 case STOS: return "STOS";
1502 return "INVALID_INSTR";