diff options
author | Laurent Vivier <Laurent.Vivier@bull.net> | 2007-09-24 05:10:56 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:52:49 -0500 |
commit | a01af5ec5163cdc51c00f6dcb22d7766199377cf (patch) | |
tree | 36ff10826f39b643736542957a980c37c4ad6fb1 /drivers/kvm/x86_emulate.c | |
parent | 05f086f87ef17da70d5f4e9b063e9ea31ab20f28 (diff) |
KVM: x86 emulator: Remove no_wb, use dst.type = OP_NONE instead
Remove no_wb, use dst.type = OP_NONE instead, idea stollen from xen-3.1
Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/x86_emulate.c')
-rw-r--r-- | drivers/kvm/x86_emulate.c | 76 |
1 files changed, 24 insertions, 52 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c index 76b813b6365c..6161e3f66585 100644 --- a/drivers/kvm/x86_emulate.c +++ b/drivers/kvm/x86_emulate.c | |||
@@ -1016,8 +1016,7 @@ done: | |||
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | static inline int emulate_grp45(struct x86_emulate_ctxt *ctxt, | 1018 | static inline int emulate_grp45(struct x86_emulate_ctxt *ctxt, |
1019 | struct x86_emulate_ops *ops, | 1019 | struct x86_emulate_ops *ops) |
1020 | int *no_wb) | ||
1021 | { | 1020 | { |
1022 | struct decode_cache *c = &ctxt->decode; | 1021 | struct decode_cache *c = &ctxt->decode; |
1023 | int rc; | 1022 | int rc; |
@@ -1055,7 +1054,7 @@ static inline int emulate_grp45(struct x86_emulate_ctxt *ctxt, | |||
1055 | c->dst.bytes, ctxt->vcpu); | 1054 | c->dst.bytes, ctxt->vcpu); |
1056 | if (rc != 0) | 1055 | if (rc != 0) |
1057 | return rc; | 1056 | return rc; |
1058 | *no_wb = 1; | 1057 | c->dst.type = OP_NONE; |
1059 | break; | 1058 | break; |
1060 | default: | 1059 | default: |
1061 | DPRINTF("Cannot emulate %02x\n", c->b); | 1060 | DPRINTF("Cannot emulate %02x\n", c->b); |
@@ -1137,6 +1136,10 @@ static inline int writeback(struct x86_emulate_ctxt *ctxt, | |||
1137 | ctxt->vcpu); | 1136 | ctxt->vcpu); |
1138 | if (rc != 0) | 1137 | if (rc != 0) |
1139 | return rc; | 1138 | return rc; |
1139 | break; | ||
1140 | case OP_NONE: | ||
1141 | /* no writeback */ | ||
1142 | break; | ||
1140 | default: | 1143 | default: |
1141 | break; | 1144 | break; |
1142 | } | 1145 | } |
@@ -1147,7 +1150,6 @@ int | |||
1147 | x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | 1150 | x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) |
1148 | { | 1151 | { |
1149 | unsigned long cr2 = ctxt->cr2; | 1152 | unsigned long cr2 = ctxt->cr2; |
1150 | int no_wb = 0; | ||
1151 | u64 msr_data; | 1153 | u64 msr_data; |
1152 | unsigned long saved_eip = 0; | 1154 | unsigned long saved_eip = 0; |
1153 | struct decode_cache *c = &ctxt->decode; | 1155 | struct decode_cache *c = &ctxt->decode; |
@@ -1344,18 +1346,16 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) | |||
1344 | goto done; | 1346 | goto done; |
1345 | break; | 1347 | break; |
1346 | case 0xfe ... 0xff: /* Grp4/Grp5 */ | 1348 | case 0xfe ... 0xff: /* Grp4/Grp5 */ |
1347 | rc = emulate_grp45(ctxt, ops, &no_wb); | 1349 | rc = emulate_grp45(ctxt, ops); |
1348 | if (rc != 0) | 1350 | if (rc != 0) |
1349 | goto done; | 1351 | goto done; |
1350 | break; | 1352 | break; |
1351 | } | 1353 | } |
1352 | 1354 | ||
1353 | writeback: | 1355 | writeback: |
1354 | if (!no_wb) { | 1356 | rc = writeback(ctxt, ops); |
1355 | rc = writeback(ctxt, ops); | 1357 | if (rc != 0) |
1356 | if (rc != 0) | 1358 | goto done; |
1357 | goto done; | ||
1358 | } | ||
1359 | 1359 | ||
1360 | /* Commit shadow register state. */ | 1360 | /* Commit shadow register state. */ |
1361 | memcpy(ctxt->vcpu->regs, c->regs, sizeof c->regs); | 1361 | memcpy(ctxt->vcpu->regs, c->regs, sizeof c->regs); |
@@ -1395,7 +1395,7 @@ special_insn: | |||
1395 | 1395 | ||
1396 | register_address_increment(c->regs[VCPU_REGS_RSP], | 1396 | register_address_increment(c->regs[VCPU_REGS_RSP], |
1397 | c->op_bytes); | 1397 | c->op_bytes); |
1398 | no_wb = 1; /* Disable writeback. */ | 1398 | c->dst.type = OP_NONE; /* Disable writeback. */ |
1399 | break; | 1399 | break; |
1400 | case 0x6a: /* push imm8 */ | 1400 | case 0x6a: /* push imm8 */ |
1401 | c->src.val = 0L; | 1401 | c->src.val = 0L; |
@@ -1538,7 +1538,7 @@ special_insn: | |||
1538 | case 0xe9: /* jmp rel */ | 1538 | case 0xe9: /* jmp rel */ |
1539 | case 0xeb: /* jmp rel short */ | 1539 | case 0xeb: /* jmp rel short */ |
1540 | JMP_REL(c->src.val); | 1540 | JMP_REL(c->src.val); |
1541 | no_wb = 1; /* Disable writeback. */ | 1541 | c->dst.type = OP_NONE; /* Disable writeback. */ |
1542 | break; | 1542 | break; |
1543 | 1543 | ||
1544 | 1544 | ||
@@ -1548,8 +1548,6 @@ special_insn: | |||
1548 | twobyte_insn: | 1548 | twobyte_insn: |
1549 | switch (c->b) { | 1549 | switch (c->b) { |
1550 | case 0x01: /* lgdt, lidt, lmsw */ | 1550 | case 0x01: /* lgdt, lidt, lmsw */ |
1551 | /* Disable writeback. */ | ||
1552 | no_wb = 1; | ||
1553 | switch (c->modrm_reg) { | 1551 | switch (c->modrm_reg) { |
1554 | u16 size; | 1552 | u16 size; |
1555 | unsigned long address; | 1553 | unsigned long address; |
@@ -1604,56 +1602,30 @@ twobyte_insn: | |||
1604 | default: | 1602 | default: |
1605 | goto cannot_emulate; | 1603 | goto cannot_emulate; |
1606 | } | 1604 | } |
1605 | /* Disable writeback. */ | ||
1606 | c->dst.type = OP_NONE; | ||
1607 | break; | 1607 | break; |
1608 | case 0x21: /* mov from dr to reg */ | 1608 | case 0x21: /* mov from dr to reg */ |
1609 | no_wb = 1; | ||
1610 | if (c->modrm_mod != 3) | 1609 | if (c->modrm_mod != 3) |
1611 | goto cannot_emulate; | 1610 | goto cannot_emulate; |
1612 | rc = emulator_get_dr(ctxt, c->modrm_reg, &c->regs[c->modrm_rm]); | 1611 | rc = emulator_get_dr(ctxt, c->modrm_reg, &c->regs[c->modrm_rm]); |
1612 | if (rc) | ||
1613 | goto cannot_emulate; | ||
1614 | c->dst.type = OP_NONE; /* no writeback */ | ||
1613 | break; | 1615 | break; |
1614 | case 0x23: /* mov from reg to dr */ | 1616 | case 0x23: /* mov from reg to dr */ |
1615 | no_wb = 1; | ||
1616 | if (c->modrm_mod != 3) | 1617 | if (c->modrm_mod != 3) |
1617 | goto cannot_emulate; | 1618 | goto cannot_emulate; |
1618 | rc = emulator_set_dr(ctxt, c->modrm_reg, | 1619 | rc = emulator_set_dr(ctxt, c->modrm_reg, |
1619 | c->regs[c->modrm_rm]); | 1620 | c->regs[c->modrm_rm]); |
1621 | if (rc) | ||
1622 | goto cannot_emulate; | ||
1623 | c->dst.type = OP_NONE; /* no writeback */ | ||
1620 | break; | 1624 | break; |
1621 | case 0x40 ... 0x4f: /* cmov */ | 1625 | case 0x40 ... 0x4f: /* cmov */ |
1622 | c->dst.val = c->dst.orig_val = c->src.val; | 1626 | c->dst.val = c->dst.orig_val = c->src.val; |
1623 | no_wb = 1; | 1627 | if (!test_cc(c->b, ctxt->eflags)) |
1624 | /* | 1628 | c->dst.type = OP_NONE; /* no writeback */ |
1625 | * First, assume we're decoding an even cmov opcode | ||
1626 | * (lsb == 0). | ||
1627 | */ | ||
1628 | switch ((c->b & 15) >> 1) { | ||
1629 | case 0: /* cmovo */ | ||
1630 | no_wb = (ctxt->eflags & EFLG_OF) ? 0 : 1; | ||
1631 | break; | ||
1632 | case 1: /* cmovb/cmovc/cmovnae */ | ||
1633 | no_wb = (ctxt->eflags & EFLG_CF) ? 0 : 1; | ||
1634 | break; | ||
1635 | case 2: /* cmovz/cmove */ | ||
1636 | no_wb = (ctxt->eflags & EFLG_ZF) ? 0 : 1; | ||
1637 | break; | ||
1638 | case 3: /* cmovbe/cmovna */ | ||
1639 | no_wb = (ctxt->eflags & (EFLG_CF | EFLG_ZF)) ? 0 : 1; | ||
1640 | break; | ||
1641 | case 4: /* cmovs */ | ||
1642 | no_wb = (ctxt->eflags & EFLG_SF) ? 0 : 1; | ||
1643 | break; | ||
1644 | case 5: /* cmovp/cmovpe */ | ||
1645 | no_wb = (ctxt->eflags & EFLG_PF) ? 0 : 1; | ||
1646 | break; | ||
1647 | case 7: /* cmovle/cmovng */ | ||
1648 | no_wb = (ctxt->eflags & EFLG_ZF) ? 0 : 1; | ||
1649 | /* fall through */ | ||
1650 | case 6: /* cmovl/cmovnge */ | ||
1651 | no_wb &= (!(ctxt->eflags & EFLG_SF) != | ||
1652 | !(ctxt->eflags & EFLG_OF)) ? 0 : 1; | ||
1653 | break; | ||
1654 | } | ||
1655 | /* Odd cmov opcodes (lsb == 1) have inverted sense. */ | ||
1656 | no_wb ^= c->b & 1; | ||
1657 | break; | 1629 | break; |
1658 | case 0xa3: | 1630 | case 0xa3: |
1659 | bt: /* bt */ | 1631 | bt: /* bt */ |
@@ -1727,8 +1699,6 @@ twobyte_insn: | |||
1727 | goto writeback; | 1699 | goto writeback; |
1728 | 1700 | ||
1729 | twobyte_special_insn: | 1701 | twobyte_special_insn: |
1730 | /* Disable writeback. */ | ||
1731 | no_wb = 1; | ||
1732 | switch (c->b) { | 1702 | switch (c->b) { |
1733 | case 0x06: | 1703 | case 0x06: |
1734 | emulate_clts(ctxt->vcpu); | 1704 | emulate_clts(ctxt->vcpu); |
@@ -1802,6 +1772,8 @@ twobyte_special_insn: | |||
1802 | goto done; | 1772 | goto done; |
1803 | break; | 1773 | break; |
1804 | } | 1774 | } |
1775 | /* Disable writeback. */ | ||
1776 | c->dst.type = OP_NONE; | ||
1805 | goto writeback; | 1777 | goto writeback; |
1806 | 1778 | ||
1807 | cannot_emulate: | 1779 | cannot_emulate: |