diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/emulate.c | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index d9ebf6939e49..d6e2477feb18 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -1687,6 +1687,23 @@ static inline int emulate_iret(struct x86_emulate_ctxt *ctxt, | |||
1687 | } | 1687 | } |
1688 | } | 1688 | } |
1689 | 1689 | ||
1690 | static int em_jmp_far(struct x86_emulate_ctxt *ctxt) | ||
1691 | { | ||
1692 | struct decode_cache *c = &ctxt->decode; | ||
1693 | int rc; | ||
1694 | unsigned short sel; | ||
1695 | |||
1696 | memcpy(&sel, c->src.valptr + c->op_bytes, 2); | ||
1697 | |||
1698 | rc = load_segment_descriptor(ctxt, ctxt->ops, sel, VCPU_SREG_CS); | ||
1699 | if (rc != X86EMUL_CONTINUE) | ||
1700 | return rc; | ||
1701 | |||
1702 | c->eip = 0; | ||
1703 | memcpy(&c->eip, c->src.valptr, c->op_bytes); | ||
1704 | return X86EMUL_CONTINUE; | ||
1705 | } | ||
1706 | |||
1690 | static int em_grp1a(struct x86_emulate_ctxt *ctxt) | 1707 | static int em_grp1a(struct x86_emulate_ctxt *ctxt) |
1691 | { | 1708 | { |
1692 | struct decode_cache *c = &ctxt->decode; | 1709 | struct decode_cache *c = &ctxt->decode; |
@@ -1786,6 +1803,9 @@ static int em_grp45(struct x86_emulate_ctxt *ctxt) | |||
1786 | case 4: /* jmp abs */ | 1803 | case 4: /* jmp abs */ |
1787 | c->eip = c->src.val; | 1804 | c->eip = c->src.val; |
1788 | break; | 1805 | break; |
1806 | case 5: /* jmp far */ | ||
1807 | rc = em_jmp_far(ctxt); | ||
1808 | break; | ||
1789 | case 6: /* push */ | 1809 | case 6: /* push */ |
1790 | rc = em_push(ctxt); | 1810 | rc = em_push(ctxt); |
1791 | break; | 1811 | break; |
@@ -3997,19 +4017,9 @@ special_insn: | |||
3997 | } | 4017 | } |
3998 | case 0xe9: /* jmp rel */ | 4018 | case 0xe9: /* jmp rel */ |
3999 | goto jmp; | 4019 | goto jmp; |
4000 | case 0xea: { /* jmp far */ | 4020 | case 0xea: /* jmp far */ |
4001 | unsigned short sel; | 4021 | rc = em_jmp_far(ctxt); |
4002 | jump_far: | ||
4003 | memcpy(&sel, c->src.valptr + c->op_bytes, 2); | ||
4004 | |||
4005 | rc = load_segment_descriptor(ctxt, ops, sel, VCPU_SREG_CS); | ||
4006 | if (rc != X86EMUL_CONTINUE) | ||
4007 | goto done; | ||
4008 | |||
4009 | c->eip = 0; | ||
4010 | memcpy(&c->eip, c->src.valptr, c->op_bytes); | ||
4011 | break; | 4022 | break; |
4012 | } | ||
4013 | case 0xeb: | 4023 | case 0xeb: |
4014 | jmp: /* jmp rel short */ | 4024 | jmp: /* jmp rel short */ |
4015 | jmp_rel(c, c->src.val); | 4025 | jmp_rel(c, c->src.val); |
@@ -4073,8 +4083,6 @@ special_insn: | |||
4073 | rc = em_grp45(ctxt); | 4083 | rc = em_grp45(ctxt); |
4074 | break; | 4084 | break; |
4075 | case 0xff: /* Grp5 */ | 4085 | case 0xff: /* Grp5 */ |
4076 | if (c->modrm_reg == 5) | ||
4077 | goto jump_far; | ||
4078 | rc = em_grp45(ctxt); | 4086 | rc = em_grp45(ctxt); |
4079 | break; | 4087 | break; |
4080 | default: | 4088 | default: |