aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/x86_emulate.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-11-22 07:16:12 -0500
committerAvi Kivity <avi@qumranet.com>2008-01-30 10:53:14 -0500
commitf21b8bf4cc4091b23669987124fd13f758abf6d6 (patch)
treea15405e027bc520727c9aa86e607a629b98924ac /drivers/kvm/x86_emulate.c
parent90e0a28f6b7241c7793f2ebd540c349580170446 (diff)
KVM: x86 emulator: address size and operand size overrides are sticky
Current implementation is to toggle, which is incorrect. Patch ported from corresponding Xen code. Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/x86_emulate.c')
-rw-r--r--drivers/kvm/x86_emulate.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/drivers/kvm/x86_emulate.c b/drivers/kvm/x86_emulate.c
index 9f8d59a49313..3be506ac01a3 100644
--- a/drivers/kvm/x86_emulate.c
+++ b/drivers/kvm/x86_emulate.c
@@ -758,6 +758,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
758 struct decode_cache *c = &ctxt->decode; 758 struct decode_cache *c = &ctxt->decode;
759 int rc = 0; 759 int rc = 0;
760 int mode = ctxt->mode; 760 int mode = ctxt->mode;
761 int def_op_bytes, def_ad_bytes;
761 762
762 /* Shadow copy of register state. Committed on successful emulation. */ 763 /* Shadow copy of register state. Committed on successful emulation. */
763 764
@@ -768,34 +769,38 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
768 switch (mode) { 769 switch (mode) {
769 case X86EMUL_MODE_REAL: 770 case X86EMUL_MODE_REAL:
770 case X86EMUL_MODE_PROT16: 771 case X86EMUL_MODE_PROT16:
771 c->op_bytes = c->ad_bytes = 2; 772 def_op_bytes = def_ad_bytes = 2;
772 break; 773 break;
773 case X86EMUL_MODE_PROT32: 774 case X86EMUL_MODE_PROT32:
774 c->op_bytes = c->ad_bytes = 4; 775 def_op_bytes = def_ad_bytes = 4;
775 break; 776 break;
776#ifdef CONFIG_X86_64 777#ifdef CONFIG_X86_64
777 case X86EMUL_MODE_PROT64: 778 case X86EMUL_MODE_PROT64:
778 c->op_bytes = 4; 779 def_op_bytes = 4;
779 c->ad_bytes = 8; 780 def_ad_bytes = 8;
780 break; 781 break;
781#endif 782#endif
782 default: 783 default:
783 return -1; 784 return -1;
784 } 785 }
785 786
787 c->op_bytes = def_op_bytes;
788 c->ad_bytes = def_ad_bytes;
789
786 /* Legacy prefixes. */ 790 /* Legacy prefixes. */
787 for (;;) { 791 for (;;) {
788 switch (c->b = insn_fetch(u8, 1, c->eip)) { 792 switch (c->b = insn_fetch(u8, 1, c->eip)) {
789 case 0x66: /* operand-size override */ 793 case 0x66: /* operand-size override */
790 c->op_bytes ^= 6; /* switch between 2/4 bytes */ 794 /* switch between 2/4 bytes */
795 c->op_bytes = def_op_bytes ^ 6;
791 break; 796 break;
792 case 0x67: /* address-size override */ 797 case 0x67: /* address-size override */
793 if (mode == X86EMUL_MODE_PROT64) 798 if (mode == X86EMUL_MODE_PROT64)
794 /* switch between 4/8 bytes */ 799 /* switch between 4/8 bytes */
795 c->ad_bytes ^= 12; 800 c->ad_bytes = def_ad_bytes ^ 12;
796 else 801 else
797 /* switch between 2/4 bytes */ 802 /* switch between 2/4 bytes */
798 c->ad_bytes ^= 6; 803 c->ad_bytes = def_ad_bytes ^ 6;
799 break; 804 break;
800 case 0x2e: /* CS override */ 805 case 0x2e: /* CS override */
801 c->override_base = &ctxt->cs_base; 806 c->override_base = &ctxt->cs_base;