aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-11-27 12:30:56 -0500
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:53:16 -0500
commit018a98db74d4cc8967cfc570197b14bcbdddb579 (patch)
treeeea371dd8c2c3060120501572da651c7bfc63f93
parent111de5d60c589bca02b49dce076ca588618e0d1c (diff)
KVM: x86 emulator: unify four switch statements into two
Unify the special instruction switch with the regular instruction switch, and the two byte special instruction switch with the regular two byte instruction switch. That makes it much easier to find an instruction or the place an instruction needs to be added in. Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r--drivers/kvm/x86_emulate.c342
1 files changed, 168 insertions, 174 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 499d1ad42bc4..3e3eba70d5ac 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -1294,6 +1294,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
1294 } 1294 }
1295 c->dst.orig_val = c->dst.val; 1295 c->dst.orig_val = c->dst.val;
1296 1296
1297special_insn:
1298
1297 if (c->twobyte) 1299 if (c->twobyte)
1298 goto twobyte_insn; 1300 goto twobyte_insn;
1299 1301
@@ -1378,6 +1380,52 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
1378 goto cannot_emulate; 1380 goto cannot_emulate;
1379 c->dst.val = (s32) c->src.val; 1381 c->dst.val = (s32) c->src.val;
1380 break; 1382 break;
1383 case 0x6a: /* push imm8 */
1384 c->src.val = 0L;
1385 c->src.val = insn_fetch(s8, 1, c->eip);
1386 emulate_push(ctxt);
1387 break;
1388 case 0x6c: /* insb */
1389 case 0x6d: /* insw/insd */
1390 if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
1391 1,
1392 (c->d & ByteOp) ? 1 : c->op_bytes,
1393 c->rep_prefix ?
1394 address_mask(c->regs[VCPU_REGS_RCX]) : 1,
1395 (ctxt->eflags & EFLG_DF),
1396 register_address(ctxt->es_base,
1397 c->regs[VCPU_REGS_RDI]),
1398 c->rep_prefix,
1399 c->regs[VCPU_REGS_RDX]) == 0) {
1400 c->eip = saved_eip;
1401 return -1;
1402 }
1403 return 0;
1404 case 0x6e: /* outsb */
1405 case 0x6f: /* outsw/outsd */
1406 if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
1407 0,
1408 (c->d & ByteOp) ? 1 : c->op_bytes,
1409 c->rep_prefix ?
1410 address_mask(c->regs[VCPU_REGS_RCX]) : 1,
1411 (ctxt->eflags & EFLG_DF),
1412 register_address(c->override_base ?
1413 *c->override_base :
1414 ctxt->ds_base,
1415 c->regs[VCPU_REGS_RSI]),
1416 c->rep_prefix,
1417 c->regs[VCPU_REGS_RDX]) == 0) {
1418 c->eip = saved_eip;
1419 return -1;
1420 }
1421 return 0;
1422 case 0x70 ... 0x7f: /* jcc (short) */ {
1423 int rel = insn_fetch(s8, 1, c->eip);
1424
1425 if (test_cc(c->b, ctxt->eflags))
1426 JMP_REL(rel);
1427 break;
1428 }
1381 case 0x80 ... 0x83: /* Grp1 */ 1429 case 0x80 ... 0x83: /* Grp1 */
1382 switch (c->modrm_reg) { 1430 switch (c->modrm_reg) {
1383 case 0: 1431 case 0:
@@ -1434,106 +1482,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
1434 if (rc != 0) 1482 if (rc != 0)
1435 goto done; 1483 goto done;
1436 break; 1484 break;
1437 case 0xa0 ... 0xa1: /* mov */
1438 c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX];
1439 c->dst.val = c->src.val;
1440 break;
1441 case 0xa2 ... 0xa3: /* mov */
1442 c->dst.val = (unsigned long)c->regs[VCPU_REGS_RAX];
1443 break;
1444 case 0xc0 ... 0xc1:
1445 emulate_grp2(ctxt);
1446 break;
1447 case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
1448 mov:
1449 c->dst.val = c->src.val;
1450 break;
1451 case 0xd0 ... 0xd1: /* Grp2 */
1452 c->src.val = 1;
1453 emulate_grp2(ctxt);
1454 break;
1455 case 0xd2 ... 0xd3: /* Grp2 */
1456 c->src.val = c->regs[VCPU_REGS_RCX];
1457 emulate_grp2(ctxt);
1458 break;
1459 case 0xf6 ... 0xf7: /* Grp3 */
1460 rc = emulate_grp3(ctxt, ops);
1461 if (rc != 0)
1462 goto done;
1463 break;
1464 case 0xfe ... 0xff: /* Grp4/Grp5 */
1465 rc = emulate_grp45(ctxt, ops);
1466 if (rc != 0)
1467 goto done;
1468 break;
1469 }
1470
1471writeback:
1472 rc = writeback(ctxt, ops);
1473 if (rc != 0)
1474 goto done;
1475
1476 /* Commit shadow register state. */
1477 memcpy(ctxt->vcpu->regs, c->regs, sizeof c->regs);
1478 ctxt->vcpu->rip = c->eip;
1479
1480done:
1481 if (rc == X86EMUL_UNHANDLEABLE) {
1482 c->eip = saved_eip;
1483 return -1;
1484 }
1485 return 0;
1486
1487special_insn:
1488 if (c->twobyte)
1489 goto twobyte_special_insn;
1490 switch (c->b) {
1491 case 0x6a: /* push imm8 */
1492 c->src.val = 0L;
1493 c->src.val = insn_fetch(s8, 1, c->eip);
1494 emulate_push(ctxt);
1495 break;
1496 case 0x6c: /* insb */
1497 case 0x6d: /* insw/insd */
1498 if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
1499 1,
1500 (c->d & ByteOp) ? 1 : c->op_bytes,
1501 c->rep_prefix ?
1502 address_mask(c->regs[VCPU_REGS_RCX]) : 1,
1503 (ctxt->eflags & EFLG_DF),
1504 register_address(ctxt->es_base,
1505 c->regs[VCPU_REGS_RDI]),
1506 c->rep_prefix,
1507 c->regs[VCPU_REGS_RDX]) == 0) {
1508 c->eip = saved_eip;
1509 return -1;
1510 }
1511 return 0;
1512 case 0x6e: /* outsb */
1513 case 0x6f: /* outsw/outsd */
1514 if (kvm_emulate_pio_string(ctxt->vcpu, NULL,
1515 0,
1516 (c->d & ByteOp) ? 1 : c->op_bytes,
1517 c->rep_prefix ?
1518 address_mask(c->regs[VCPU_REGS_RCX]) : 1,
1519 (ctxt->eflags & EFLG_DF),
1520 register_address(c->override_base ?
1521 *c->override_base :
1522 ctxt->ds_base,
1523 c->regs[VCPU_REGS_RSI]),
1524 c->rep_prefix,
1525 c->regs[VCPU_REGS_RDX]) == 0) {
1526 c->eip = saved_eip;
1527 return -1;
1528 }
1529 return 0;
1530 case 0x70 ... 0x7f: /* jcc (short) */ {
1531 int rel = insn_fetch(s8, 1, c->eip);
1532
1533 if (test_cc(c->b, ctxt->eflags))
1534 JMP_REL(rel);
1535 break;
1536 }
1537 case 0x9c: /* pushf */ 1485 case 0x9c: /* pushf */
1538 c->src.val = (unsigned long) ctxt->eflags; 1486 c->src.val = (unsigned long) ctxt->eflags;
1539 emulate_push(ctxt); 1487 emulate_push(ctxt);
@@ -1541,6 +1489,13 @@ special_insn:
1541 case 0x9d: /* popf */ 1489 case 0x9d: /* popf */
1542 c->dst.ptr = (unsigned long *) &ctxt->eflags; 1490 c->dst.ptr = (unsigned long *) &ctxt->eflags;
1543 goto pop_instruction; 1491 goto pop_instruction;
1492 case 0xa0 ... 0xa1: /* mov */
1493 c->dst.ptr = (unsigned long *)&c->regs[VCPU_REGS_RAX];
1494 c->dst.val = c->src.val;
1495 break;
1496 case 0xa2 ... 0xa3: /* mov */
1497 c->dst.val = (unsigned long)c->regs[VCPU_REGS_RAX];
1498 break;
1544 case 0xa4 ... 0xa5: /* movs */ 1499 case 0xa4 ... 0xa5: /* movs */
1545 c->dst.type = OP_MEM; 1500 c->dst.type = OP_MEM;
1546 c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; 1501 c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
@@ -1627,9 +1582,24 @@ special_insn:
1627 case 0xae ... 0xaf: /* scas */ 1582 case 0xae ... 0xaf: /* scas */
1628 DPRINTF("Urk! I don't handle SCAS.\n"); 1583 DPRINTF("Urk! I don't handle SCAS.\n");
1629 goto cannot_emulate; 1584 goto cannot_emulate;
1585 case 0xc0 ... 0xc1:
1586 emulate_grp2(ctxt);
1587 break;
1630 case 0xc3: /* ret */ 1588 case 0xc3: /* ret */
1631 c->dst.ptr = &c->eip; 1589 c->dst.ptr = &c->eip;
1632 goto pop_instruction; 1590 goto pop_instruction;
1591 case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */
1592 mov:
1593 c->dst.val = c->src.val;
1594 break;
1595 case 0xd0 ... 0xd1: /* Grp2 */
1596 c->src.val = 1;
1597 emulate_grp2(ctxt);
1598 break;
1599 case 0xd2 ... 0xd3: /* Grp2 */
1600 c->src.val = c->regs[VCPU_REGS_RCX];
1601 emulate_grp2(ctxt);
1602 break;
1633 case 0xe8: /* call (near) */ { 1603 case 0xe8: /* call (near) */ {
1634 long int rel; 1604 long int rel;
1635 switch (c->op_bytes) { 1605 switch (c->op_bytes) {
@@ -1662,6 +1632,11 @@ special_insn:
1662 ctxt->eflags ^= EFLG_CF; 1632 ctxt->eflags ^= EFLG_CF;
1663 c->dst.type = OP_NONE; /* Disable writeback. */ 1633 c->dst.type = OP_NONE; /* Disable writeback. */
1664 break; 1634 break;
1635 case 0xf6 ... 0xf7: /* Grp3 */
1636 rc = emulate_grp3(ctxt, ops);
1637 if (rc != 0)
1638 goto done;
1639 break;
1665 case 0xf8: /* clc */ 1640 case 0xf8: /* clc */
1666 ctxt->eflags &= ~EFLG_CF; 1641 ctxt->eflags &= ~EFLG_CF;
1667 c->dst.type = OP_NONE; /* Disable writeback. */ 1642 c->dst.type = OP_NONE; /* Disable writeback. */
@@ -1674,8 +1649,28 @@ special_insn:
1674 ctxt->eflags |= X86_EFLAGS_IF; 1649 ctxt->eflags |= X86_EFLAGS_IF;
1675 c->dst.type = OP_NONE; /* Disable writeback. */ 1650 c->dst.type = OP_NONE; /* Disable writeback. */
1676 break; 1651 break;
1652 case 0xfe ... 0xff: /* Grp4/Grp5 */
1653 rc = emulate_grp45(ctxt, ops);
1654 if (rc != 0)
1655 goto done;
1656 break;
1677 } 1657 }
1678 goto writeback; 1658
1659writeback:
1660 rc = writeback(ctxt, ops);
1661 if (rc != 0)
1662 goto done;
1663
1664 /* Commit shadow register state. */
1665 memcpy(ctxt->vcpu->regs, c->regs, sizeof c->regs);
1666 ctxt->vcpu->rip = c->eip;
1667
1668done:
1669 if (rc == X86EMUL_UNHANDLEABLE) {
1670 c->eip = saved_eip;
1671 return -1;
1672 }
1673 return 0;
1679 1674
1680twobyte_insn: 1675twobyte_insn:
1681 switch (c->b) { 1676 switch (c->b) {
@@ -1737,6 +1732,23 @@ twobyte_insn:
1737 /* Disable writeback. */ 1732 /* Disable writeback. */
1738 c->dst.type = OP_NONE; 1733 c->dst.type = OP_NONE;
1739 break; 1734 break;
1735 case 0x06:
1736 emulate_clts(ctxt->vcpu);
1737 c->dst.type = OP_NONE;
1738 break;
1739 case 0x08: /* invd */
1740 case 0x09: /* wbinvd */
1741 case 0x0d: /* GrpP (prefetch) */
1742 case 0x18: /* Grp16 (prefetch/nop) */
1743 c->dst.type = OP_NONE;
1744 break;
1745 case 0x20: /* mov cr, reg */
1746 if (c->modrm_mod != 3)
1747 goto cannot_emulate;
1748 c->regs[c->modrm_rm] =
1749 realmode_get_cr(ctxt->vcpu, c->modrm_reg);
1750 c->dst.type = OP_NONE; /* no writeback */
1751 break;
1740 case 0x21: /* mov from dr to reg */ 1752 case 0x21: /* mov from dr to reg */
1741 if (c->modrm_mod != 3) 1753 if (c->modrm_mod != 3)
1742 goto cannot_emulate; 1754 goto cannot_emulate;
@@ -1745,6 +1757,13 @@ twobyte_insn:
1745 goto cannot_emulate; 1757 goto cannot_emulate;
1746 c->dst.type = OP_NONE; /* no writeback */ 1758 c->dst.type = OP_NONE; /* no writeback */
1747 break; 1759 break;
1760 case 0x22: /* mov reg, cr */
1761 if (c->modrm_mod != 3)
1762 goto cannot_emulate;
1763 realmode_set_cr(ctxt->vcpu,
1764 c->modrm_reg, c->modrm_val, &ctxt->eflags);
1765 c->dst.type = OP_NONE;
1766 break;
1748 case 0x23: /* mov from reg to dr */ 1767 case 0x23: /* mov from reg to dr */
1749 if (c->modrm_mod != 3) 1768 if (c->modrm_mod != 3)
1750 goto cannot_emulate; 1769 goto cannot_emulate;
@@ -1754,11 +1773,58 @@ twobyte_insn:
1754 goto cannot_emulate; 1773 goto cannot_emulate;
1755 c->dst.type = OP_NONE; /* no writeback */ 1774 c->dst.type = OP_NONE; /* no writeback */
1756 break; 1775 break;
1776 case 0x30:
1777 /* wrmsr */
1778 msr_data = (u32)c->regs[VCPU_REGS_RAX]
1779 | ((u64)c->regs[VCPU_REGS_RDX] << 32);
1780 rc = kvm_set_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], msr_data);
1781 if (rc) {
1782 kvm_x86_ops->inject_gp(ctxt->vcpu, 0);
1783 c->eip = ctxt->vcpu->rip;
1784 }
1785 rc = X86EMUL_CONTINUE;
1786 c->dst.type = OP_NONE;
1787 break;
1788 case 0x32:
1789 /* rdmsr */
1790 rc = kvm_get_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], &msr_data);
1791 if (rc) {
1792 kvm_x86_ops->inject_gp(ctxt->vcpu, 0);
1793 c->eip = ctxt->vcpu->rip;
1794 } else {
1795 c->regs[VCPU_REGS_RAX] = (u32)msr_data;
1796 c->regs[VCPU_REGS_RDX] = msr_data >> 32;
1797 }
1798 rc = X86EMUL_CONTINUE;
1799 c->dst.type = OP_NONE;
1800 break;
1757 case 0x40 ... 0x4f: /* cmov */ 1801 case 0x40 ... 0x4f: /* cmov */
1758 c->dst.val = c->dst.orig_val = c->src.val; 1802 c->dst.val = c->dst.orig_val = c->src.val;
1759 if (!test_cc(c->b, ctxt->eflags)) 1803 if (!test_cc(c->b, ctxt->eflags))
1760 c->dst.type = OP_NONE; /* no writeback */ 1804 c->dst.type = OP_NONE; /* no writeback */
1761 break; 1805 break;
1806 case 0x80 ... 0x8f: /* jnz rel, etc*/ {
1807 long int rel;
1808
1809 switch (c->op_bytes) {
1810 case 2:
1811 rel = insn_fetch(s16, 2, c->eip);
1812 break;
1813 case 4:
1814 rel = insn_fetch(s32, 4, c->eip);
1815 break;
1816 case 8:
1817 rel = insn_fetch(s64, 8, c->eip);
1818 break;
1819 default:
1820 DPRINTF("jnz: Invalid op_bytes\n");
1821 goto cannot_emulate;
1822 }
1823 if (test_cc(c->b, ctxt->eflags))
1824 JMP_REL(rel);
1825 c->dst.type = OP_NONE;
1826 break;
1827 }
1762 case 0xa3: 1828 case 0xa3:
1763 bt: /* bt */ 1829 bt: /* bt */
1764 c->dst.type = OP_NONE; 1830 c->dst.type = OP_NONE;
@@ -1828,85 +1894,13 @@ twobyte_insn:
1828 c->dst.val = (c->op_bytes == 4) ? (u32) c->src.val : 1894 c->dst.val = (c->op_bytes == 4) ? (u32) c->src.val :
1829 (u64) c->src.val; 1895 (u64) c->src.val;
1830 break; 1896 break;
1831 }
1832 goto writeback;
1833
1834twobyte_special_insn:
1835 switch (c->b) {
1836 case 0x06:
1837 emulate_clts(ctxt->vcpu);
1838 break;
1839 case 0x08: /* invd */
1840 break;
1841 case 0x09: /* wbinvd */
1842 break;
1843 case 0x0d: /* GrpP (prefetch) */
1844 case 0x18: /* Grp16 (prefetch/nop) */
1845 break;
1846 case 0x20: /* mov cr, reg */
1847 if (c->modrm_mod != 3)
1848 goto cannot_emulate;
1849 c->regs[c->modrm_rm] =
1850 realmode_get_cr(ctxt->vcpu, c->modrm_reg);
1851 break;
1852 case 0x22: /* mov reg, cr */
1853 if (c->modrm_mod != 3)
1854 goto cannot_emulate;
1855 realmode_set_cr(ctxt->vcpu,
1856 c->modrm_reg, c->modrm_val, &ctxt->eflags);
1857 break;
1858 case 0x30:
1859 /* wrmsr */
1860 msr_data = (u32)c->regs[VCPU_REGS_RAX]
1861 | ((u64)c->regs[VCPU_REGS_RDX] << 32);
1862 rc = kvm_set_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], msr_data);
1863 if (rc) {
1864 kvm_x86_ops->inject_gp(ctxt->vcpu, 0);
1865 c->eip = ctxt->vcpu->rip;
1866 }
1867 rc = X86EMUL_CONTINUE;
1868 break;
1869 case 0x32:
1870 /* rdmsr */
1871 rc = kvm_get_msr(ctxt->vcpu, c->regs[VCPU_REGS_RCX], &msr_data);
1872 if (rc) {
1873 kvm_x86_ops->inject_gp(ctxt->vcpu, 0);
1874 c->eip = ctxt->vcpu->rip;
1875 } else {
1876 c->regs[VCPU_REGS_RAX] = (u32)msr_data;
1877 c->regs[VCPU_REGS_RDX] = msr_data >> 32;
1878 }
1879 rc = X86EMUL_CONTINUE;
1880 break;
1881 case 0x80 ... 0x8f: /* jnz rel, etc*/ {
1882 long int rel;
1883
1884 switch (c->op_bytes) {
1885 case 2:
1886 rel = insn_fetch(s16, 2, c->eip);
1887 break;
1888 case 4:
1889 rel = insn_fetch(s32, 4, c->eip);
1890 break;
1891 case 8:
1892 rel = insn_fetch(s64, 8, c->eip);
1893 break;
1894 default:
1895 DPRINTF("jnz: Invalid op_bytes\n");
1896 goto cannot_emulate;
1897 }
1898 if (test_cc(c->b, ctxt->eflags))
1899 JMP_REL(rel);
1900 break;
1901 }
1902 case 0xc7: /* Grp9 (cmpxchg8b) */ 1897 case 0xc7: /* Grp9 (cmpxchg8b) */
1903 rc = emulate_grp9(ctxt, ops, memop); 1898 rc = emulate_grp9(ctxt, ops, memop);
1904 if (rc != 0) 1899 if (rc != 0)
1905 goto done; 1900 goto done;
1901 c->dst.type = OP_NONE;
1906 break; 1902 break;
1907 } 1903 }
1908 /* Disable writeback. */
1909 c->dst.type = OP_NONE;
1910 goto writeback; 1904 goto writeback;
1911 1905
1912cannot_emulate: 1906cannot_emulate: