All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Trap and propagate divide errors when emulating DIV
@ 2010-08-24 11:10 Avi Kivity
  2010-08-24 11:10 ` [PATCH 1/3] x86: allow kernel exception fixup for divide errors (#DE) Avi Kivity
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Avi Kivity @ 2010-08-24 11:10 UTC (permalink / raw)
  To: x86, kvm, Marcelo Tosatti, linux-kernel

KVM recently started emulating DIV and IDIV.  However, those instructions
trap when given the right operands.  Since figuring out when to trap or not
is difficult, we just execute the instruction and see if the processor trapped
or not.

tip: please queue the first patch on fast-forward-only branch kvm.git can
     merge, or we can carry the patch in kvm.git with your ack.

Avi Kivity (3):
  x86: allow kernel exception fixup for divide errors (#DE)
  KVM: x86 emulator: add macros for executing instructions that may
    trap
  KVM: x86 emulator: trap and propagate #DE from DIV and IDIV

 arch/x86/kernel/traps.c |   10 +++++++-
 arch/x86/kvm/emulate.c  |   60 ++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 66 insertions(+), 4 deletions(-)


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/3] x86: allow kernel exception fixup for divide errors (#DE)
  2010-08-24 11:10 [PATCH 0/3] Trap and propagate divide errors when emulating DIV Avi Kivity
@ 2010-08-24 11:10 ` Avi Kivity
  2010-08-24 11:22   ` Brian Gerst
  2010-08-24 11:10 ` [PATCH 2/3] KVM: x86 emulator: add macros for executing instructions that may trap Avi Kivity
  2010-08-24 11:10 ` [PATCH 3/3] KVM: x86 emulator: trap and propagate #DE from DIV and IDIV Avi Kivity
  2 siblings, 1 reply; 8+ messages in thread
From: Avi Kivity @ 2010-08-24 11:10 UTC (permalink / raw)
  To: x86, kvm, Marcelo Tosatti, linux-kernel

KVM wants to emulate the DIV and IDIV instructions by executing them natively;
this can cause a #DE to be raised.

Allow the exception handling mechanism to process #DE exceptions so KVM can
catch and process them.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kernel/traps.c |   10 +++++++++-
 1 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 725ef4d..dd313cf 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -205,7 +205,8 @@ dotraplinkage void do_##name(struct pt_regs *regs, long error_code)	\
 	do_trap(trapnr, signr, str, regs, error_code, &info);		\
 }
 
-DO_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip)
+static DO_ERROR_INFO(0, SIGFPE, "divide error", divide_error_user,
+		     FPE_INTDIV, regs->ip)
 DO_ERROR(4, SIGSEGV, "overflow", overflow)
 DO_ERROR(5, SIGSEGV, "bounds", bounds)
 DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip)
@@ -217,6 +218,13 @@ DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
 #endif
 DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
 
+dotraplinkage void do_divide_error(struct pt_regs *regs, long error_code)
+{
+	if (!user_mode_vm(regs) && fixup_exception(regs))
+		return;
+	do_divide_error_user(regs, error_code);
+}
+
 #ifdef CONFIG_X86_64
 /* Runs on IST stack */
 dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code)
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/3] KVM: x86 emulator: add macros for executing instructions that may trap
  2010-08-24 11:10 [PATCH 0/3] Trap and propagate divide errors when emulating DIV Avi Kivity
  2010-08-24 11:10 ` [PATCH 1/3] x86: allow kernel exception fixup for divide errors (#DE) Avi Kivity
@ 2010-08-24 11:10 ` Avi Kivity
  2010-08-24 11:10 ` [PATCH 3/3] KVM: x86 emulator: trap and propagate #DE from DIV and IDIV Avi Kivity
  2 siblings, 0 replies; 8+ messages in thread
From: Avi Kivity @ 2010-08-24 11:10 UTC (permalink / raw)
  To: x86, kvm, Marcelo Tosatti, linux-kernel

Like DIV and IDIV.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/emulate.c |   43 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 808934c..f82e43a 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -331,6 +331,27 @@ struct group_dual {
 			  "a" (_rax), "d" (_rdx));			\
 	} while (0)
 
+#define __emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, _eflags, _suffix, _ex) \
+	do {								\
+		unsigned long _tmp;					\
+									\
+		__asm__ __volatile__ (					\
+			_PRE_EFLAGS("0", "5", "1")			\
+			"1: \n\t"					\
+			_op _suffix " %6; "				\
+			"2: \n\t"					\
+			_POST_EFLAGS("0", "5", "1")			\
+			".pushsection .fixup,\"ax\" \n\t"		\
+			"3: movb $1, %4 \n\t"				\
+			"jmp 2b \n\t"					\
+			".popsection \n\t"				\
+			_ASM_EXTABLE(1b, 3b)				\
+			: "=m" (_eflags), "=&r" (_tmp),			\
+			  "+a" (_rax), "+d" (_rdx), "+qm"(_ex)		\
+			: "i" (EFLAGS_MASK), "m" ((_src).val),		\
+			  "a" (_rax), "d" (_rdx));			\
+	} while (0)
+
 /* instruction has only one source operand, destination is implicit (e.g. mul, div, imul, idiv) */
 #define emulate_1op_rax_rdx(_op, _src, _rax, _rdx, _eflags)			\
 	do {									\
@@ -342,6 +363,28 @@ struct group_dual {
 		}							\
 	} while (0)
 
+#define emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, _eflags, _ex)	\
+	do {								\
+		switch((_src).bytes) {					\
+		case 1:							\
+			__emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx,	\
+						 _eflags, "b", _ex);	\
+			break;						\
+		case 2:							\
+			__emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
+						 _eflags, "w", _ex);	\
+			break;						\
+		case 4:							\
+			__emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
+						 _eflags, "l", _ex);	\
+			break;						\
+		case 8: ON64(						\
+			__emulate_1op_rax_rdx_ex(_op, _src, _rax, _rdx, \
+						 _eflags, "q", _ex));	\
+			break;						\
+		}							\
+	} while (0)
+
 /* Fetch next part of the instruction being emulated. */
 #define insn_fetch(_type, _size, _eip)                                  \
 ({	unsigned long _x;						\
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/3] KVM: x86 emulator: trap and propagate #DE from DIV and IDIV
  2010-08-24 11:10 [PATCH 0/3] Trap and propagate divide errors when emulating DIV Avi Kivity
  2010-08-24 11:10 ` [PATCH 1/3] x86: allow kernel exception fixup for divide errors (#DE) Avi Kivity
  2010-08-24 11:10 ` [PATCH 2/3] KVM: x86 emulator: add macros for executing instructions that may trap Avi Kivity
@ 2010-08-24 11:10 ` Avi Kivity
  2010-08-25 21:05   ` Marcelo Tosatti
  2 siblings, 1 reply; 8+ messages in thread
From: Avi Kivity @ 2010-08-24 11:10 UTC (permalink / raw)
  To: x86, kvm, Marcelo Tosatti, linux-kernel

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/kvm/emulate.c |   17 ++++++++++++++---
 1 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index f82e43a..a7e26d0 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -505,6 +505,12 @@ static void emulate_ts(struct x86_emulate_ctxt *ctxt, int err)
 	emulate_exception(ctxt, TS_VECTOR, err, true);
 }
 
+static int emulate_de(struct x86_emulate_ctxt *ctxt)
+{
+	emulate_exception(ctxt, DE_VECTOR, 0, false);
+	return X86EMUL_PROPAGATE_FAULT;
+}
+
 static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
 			      struct x86_emulate_ops *ops,
 			      unsigned long eip, u8 *dest)
@@ -1459,6 +1465,7 @@ static inline int emulate_grp3(struct x86_emulate_ctxt *ctxt,
 	struct decode_cache *c = &ctxt->decode;
 	unsigned long *rax = &c->regs[VCPU_REGS_RAX];
 	unsigned long *rdx = &c->regs[VCPU_REGS_RDX];
+	u8 de = 0;
 
 	switch (c->modrm_reg) {
 	case 0 ... 1:	/* test */
@@ -1477,14 +1484,18 @@ static inline int emulate_grp3(struct x86_emulate_ctxt *ctxt,
 		emulate_1op_rax_rdx("imul", c->src, *rax, *rdx, ctxt->eflags);
 		break;
 	case 6: /* div */
-		emulate_1op_rax_rdx("div", c->src, *rax, *rdx, ctxt->eflags);
+		emulate_1op_rax_rdx_ex("div", c->src, *rax, *rdx,
+				       ctxt->eflags, de);
 		break;
 	case 7: /* idiv */
-		emulate_1op_rax_rdx("idiv", c->src, *rax, *rdx, ctxt->eflags);
+		emulate_1op_rax_rdx_ex("idiv", c->src, *rax, *rdx,
+				       ctxt->eflags, de);
 		break;
 	default:
 		return X86EMUL_UNHANDLEABLE;
 	}
+	if (de)
+		return emulate_de(ctxt);
 	return X86EMUL_CONTINUE;
 }
 
@@ -3363,7 +3374,7 @@ special_insn:
 		break;
 	case 0xf6 ... 0xf7:	/* Grp3 */
 		if (emulate_grp3(ctxt, ops) != X86EMUL_CONTINUE)
-			goto cannot_emulate;
+			goto done;
 		break;
 	case 0xf8: /* clc */
 		ctxt->eflags &= ~EFLG_CF;
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/3] x86: allow kernel exception fixup for divide errors (#DE)
  2010-08-24 11:10 ` [PATCH 1/3] x86: allow kernel exception fixup for divide errors (#DE) Avi Kivity
@ 2010-08-24 11:22   ` Brian Gerst
  2010-08-24 11:39     ` Avi Kivity
  0 siblings, 1 reply; 8+ messages in thread
From: Brian Gerst @ 2010-08-24 11:22 UTC (permalink / raw)
  To: Avi Kivity; +Cc: x86, kvm, Marcelo Tosatti, linux-kernel

On Tue, Aug 24, 2010 at 7:10 AM, Avi Kivity <avi@redhat.com> wrote:
> KVM wants to emulate the DIV and IDIV instructions by executing them natively;
> this can cause a #DE to be raised.
>
> Allow the exception handling mechanism to process #DE exceptions so KVM can
> catch and process them.
>
> Signed-off-by: Avi Kivity <avi@redhat.com>
> ---
>  arch/x86/kernel/traps.c |   10 +++++++++-
>  1 files changed, 9 insertions(+), 1 deletions(-)
>
> diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
> index 725ef4d..dd313cf 100644
> --- a/arch/x86/kernel/traps.c
> +++ b/arch/x86/kernel/traps.c
> @@ -205,7 +205,8 @@ dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \
>        do_trap(trapnr, signr, str, regs, error_code, &info);           \
>  }
>
> -DO_ERROR_INFO(0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->ip)
> +static DO_ERROR_INFO(0, SIGFPE, "divide error", divide_error_user,
> +                    FPE_INTDIV, regs->ip)
>  DO_ERROR(4, SIGSEGV, "overflow", overflow)
>  DO_ERROR(5, SIGSEGV, "bounds", bounds)
>  DO_ERROR_INFO(6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->ip)
> @@ -217,6 +218,13 @@ DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
>  #endif
>  DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
>
> +dotraplinkage void do_divide_error(struct pt_regs *regs, long error_code)
> +{
> +       if (!user_mode_vm(regs) && fixup_exception(regs))
> +               return;
> +       do_divide_error_user(regs, error_code);
> +}
> +
>  #ifdef CONFIG_X86_64
>  /* Runs on IST stack */
>  dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code)

Kernel mode exceptions should already be handled by do_trap().  This
is unnecessary.

--
Brian Gerst

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/3] x86: allow kernel exception fixup for divide errors (#DE)
  2010-08-24 11:22   ` Brian Gerst
@ 2010-08-24 11:39     ` Avi Kivity
  0 siblings, 0 replies; 8+ messages in thread
From: Avi Kivity @ 2010-08-24 11:39 UTC (permalink / raw)
  To: Brian Gerst; +Cc: x86, kvm, Marcelo Tosatti, linux-kernel

  On 08/24/2010 02:22 PM, Brian Gerst wrote:
>
>> +dotraplinkage void do_divide_error(struct pt_regs *regs, long error_code)
>> +{
>> +       if (!user_mode_vm(regs)&&  fixup_exception(regs))
>> +               return;
>> +       do_divide_error_user(regs, error_code);
>> +}
>> +
>>   #ifdef CONFIG_X86_64
>>   /* Runs on IST stack */
>>   dotraplinkage void do_stack_segment(struct pt_regs *regs, long error_code)
> Kernel mode exceptions should already be handled by do_trap().  This
> is unnecessary.

Correct.  Please ignore this patch.  I've verified that the other two 
work without it.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 3/3] KVM: x86 emulator: trap and propagate #DE from DIV and IDIV
  2010-08-24 11:10 ` [PATCH 3/3] KVM: x86 emulator: trap and propagate #DE from DIV and IDIV Avi Kivity
@ 2010-08-25 21:05   ` Marcelo Tosatti
  2010-08-26  8:23     ` Avi Kivity
  0 siblings, 1 reply; 8+ messages in thread
From: Marcelo Tosatti @ 2010-08-25 21:05 UTC (permalink / raw)
  To: Avi Kivity; +Cc: x86, kvm, linux-kernel

On Tue, Aug 24, 2010 at 02:10:29PM +0300, Avi Kivity wrote:
> Signed-off-by: Avi Kivity <avi@redhat.com>
> ---
>  arch/x86/kvm/emulate.c |   17 ++++++++++++++---
>  1 files changed, 14 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
> index f82e43a..a7e26d0 100644
> --- a/arch/x86/kvm/emulate.c
> +++ b/arch/x86/kvm/emulate.c
> @@ -505,6 +505,12 @@ static void emulate_ts(struct x86_emulate_ctxt *ctxt, int err)
>  	emulate_exception(ctxt, TS_VECTOR, err, true);
>  }
>  
> +static int emulate_de(struct x86_emulate_ctxt *ctxt)
> +{
> +	emulate_exception(ctxt, DE_VECTOR, 0, false);
> +	return X86EMUL_PROPAGATE_FAULT;
> +}
> +
>  static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
>  			      struct x86_emulate_ops *ops,
>  			      unsigned long eip, u8 *dest)
> @@ -1459,6 +1465,7 @@ static inline int emulate_grp3(struct x86_emulate_ctxt *ctxt,
>  	struct decode_cache *c = &ctxt->decode;
>  	unsigned long *rax = &c->regs[VCPU_REGS_RAX];
>  	unsigned long *rdx = &c->regs[VCPU_REGS_RDX];
> +	u8 de = 0;
>  
>  	switch (c->modrm_reg) {
>  	case 0 ... 1:	/* test */
> @@ -1477,14 +1484,18 @@ static inline int emulate_grp3(struct x86_emulate_ctxt *ctxt,
>  		emulate_1op_rax_rdx("imul", c->src, *rax, *rdx, ctxt->eflags);
>  		break;
>  	case 6: /* div */
> -		emulate_1op_rax_rdx("div", c->src, *rax, *rdx, ctxt->eflags);
> +		emulate_1op_rax_rdx_ex("div", c->src, *rax, *rdx,
> +				       ctxt->eflags, de);
>  		break;
>  	case 7: /* idiv */
> -		emulate_1op_rax_rdx("idiv", c->src, *rax, *rdx, ctxt->eflags);
> +		emulate_1op_rax_rdx_ex("idiv", c->src, *rax, *rdx,
> +				       ctxt->eflags, de);
>  		break;
>  	default:
>  		return X86EMUL_UNHANDLEABLE;
>  	}
> +	if (de)
> +		return emulate_de(ctxt);
>  	return X86EMUL_CONTINUE;
>  }
>  
> @@ -3363,7 +3374,7 @@ special_insn:
>  		break;
>  	case 0xf6 ... 0xf7:	/* Grp3 */
>  		if (emulate_grp3(ctxt, ops) != X86EMUL_CONTINUE)
> -			goto cannot_emulate;
> +			goto done;
>  		break;

Must assign rc to emulate_grp3() retval.


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 3/3] KVM: x86 emulator: trap and propagate #DE from DIV and IDIV
  2010-08-25 21:05   ` Marcelo Tosatti
@ 2010-08-26  8:23     ` Avi Kivity
  0 siblings, 0 replies; 8+ messages in thread
From: Avi Kivity @ 2010-08-26  8:23 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: x86, kvm, linux-kernel

  On 08/26/2010 12:05 AM, Marcelo Tosatti wrote:
>
>> @@ -3363,7 +3374,7 @@ special_insn:
>>   		break;
>>   	case 0xf6 ... 0xf7:	/* Grp3 */
>>   		if (emulate_grp3(ctxt, ops) != X86EMUL_CONTINUE)
>> -			goto cannot_emulate;
>> +			goto done;
>>   		break;
> Must assign rc to emulate_grp3() retval.

While there's not much difference between X86EMUL_PROPAGATE_FAULT and 
X86EMUL_CONTINUE, it's bad form to break things internally.  I'll fix 
and repost.

-- 
error compiling committee.c: too many arguments to function


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2010-08-26  8:23 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-24 11:10 [PATCH 0/3] Trap and propagate divide errors when emulating DIV Avi Kivity
2010-08-24 11:10 ` [PATCH 1/3] x86: allow kernel exception fixup for divide errors (#DE) Avi Kivity
2010-08-24 11:22   ` Brian Gerst
2010-08-24 11:39     ` Avi Kivity
2010-08-24 11:10 ` [PATCH 2/3] KVM: x86 emulator: add macros for executing instructions that may trap Avi Kivity
2010-08-24 11:10 ` [PATCH 3/3] KVM: x86 emulator: trap and propagate #DE from DIV and IDIV Avi Kivity
2010-08-25 21:05   ` Marcelo Tosatti
2010-08-26  8:23     ` Avi Kivity

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.