From mboxrd@z Thu Jan 1 00:00:00 1970 From: Mohammed Gamal Subject: [PATCH] x86 emulator: Add call near absolute (opcode 0xff rm/2) Date: Wed, 20 Aug 2008 05:11:45 +0300 Message-ID: <20080820021145.GA7541@mohd-laptop> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Cc: avi@qumranet.com, riel@surriel.com To: kvm@vger.kernel.org Return-path: Received: from wr-out-0506.google.com ([64.233.184.226]:57777 "EHLO wr-out-0506.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751526AbYHTCLy (ORCPT ); Tue, 19 Aug 2008 22:11:54 -0400 Received: by wr-out-0506.google.com with SMTP id 69so230199wri.5 for ; Tue, 19 Aug 2008 19:11:53 -0700 (PDT) Content-Disposition: inline Sender: kvm-owner@vger.kernel.org List-ID: This adds the near call with absolute address instruction. Signed-off-by: Mohammed Gamal --- arch/x86/kvm/x86_emulate.c | 55 +++++++++++++++++++++++++++++-------------- 1 files changed, 37 insertions(+), 18 deletions(-) diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c index b97e80e..1707056 100644 --- a/arch/x86/kvm/x86_emulate.c +++ b/arch/x86/kvm/x86_emulate.c @@ -1080,6 +1080,37 @@ static inline void emulate_push(struct x86_emulate_ctxt *ctxt) c->regs[VCPU_REGS_RSP]); } +static int emulate_near_call(struct x86_emulate_ctxt *ctxt, + struct x86_emulate_ops *ops, + bool absolute) +{ + struct decode_cache *c = &ctxt->decode; + long int offset; + int rc = 0; + + switch (c->op_bytes) { + case 2: + offset = insn_fetch(s16, 2, c->eip); + break; + case 4: + offset = insn_fetch(s32, 4, c->eip); + break; + default: + DPRINTF("Call: Invalid op_bytes\n"); + rc = 1; + goto done; + } + c->src.val = (unsigned long) c->eip; + if (absolute) + c->eip = offset; + else + jmp_rel(c, offset); + c->op_bytes = c->ad_bytes; + emulate_push(ctxt); +done: + return rc; +} + static inline int emulate_grp1a(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) { @@ -1162,6 +1193,8 @@ static inline int emulate_grp45(struct x86_emulate_ctxt *ctxt, case 1: /* dec */ emulate_1op("dec", c->dst, ctxt->eflags); break; + case 2: /* call near abs */ + return emulate_near_call(ctxt, ops, 1); case 4: /* jmp abs */ c->eip = c->src.val; break; @@ -1710,25 +1743,11 @@ special_insn: port = insn_fetch(u8, 1, c->eip); io_direction = 0; goto do_io; - case 0xe8: /* call (near) */ { - long int rel; - switch (c->op_bytes) { - case 2: - rel = insn_fetch(s16, 2, c->eip); - break; - case 4: - rel = insn_fetch(s32, 4, c->eip); - break; - default: - DPRINTF("Call: Invalid op_bytes\n"); - goto cannot_emulate; - } - c->src.val = (unsigned long) c->eip; - jmp_rel(c, rel); - c->op_bytes = c->ad_bytes; - emulate_push(ctxt); + case 0xe8: /* call (near) */ + rc = emulate_near_call(ctxt, ops, 0); + if (rc != 0) + goto done; break; - } case 0xe9: /* jmp rel */ goto jmp; case 0xea: /* jmp far */ { -- 1.5.4.3