diff options
author | Avi Kivity <avi@qumranet.com> | 2007-11-22 07:16:12 -0500 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-01-30 10:53:14 -0500 |
commit | f21b8bf4cc4091b23669987124fd13f758abf6d6 (patch) | |
tree | a15405e027bc520727c9aa86e607a629b98924ac /drivers | |
parent | 90e0a28f6b7241c7793f2ebd540c349580170446 (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')
-rw-r--r-- | drivers/kvm/x86_emulate.c | 19 |
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; |