All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] The nested NMI modifies the place (instruction, flags and stack)
@ 2012-10-02  0:26 Salman Qazi
  2012-10-02  0:29 ` [PATCH] [PATCH] x86: Don't clobber top of pt_regs in nested NMI Salman Qazi
  0 siblings, 1 reply; 10+ messages in thread
From: Salman Qazi @ 2012-10-02  0:26 UTC (permalink / raw)
  To: Peter Zijlstra, LKML, Steven Rostedt, Thomas Gleixner,
	H. Peter Anvin, Linus Torvalds

that the first NMI will iret to.  However, the copy of registers
modified is exactly the one that is the part of pt_regs in
the first NMI.  This can change the behaviour of the first NMI.

In particular, Google's arch_trigger_all_cpu_backtrace handler
also prints regions of memory surrounding addresses appearing in
registers.  This results in handled exceptions, after which nested NMIs
start coming in.  These nested NMIs change the value of registers
in pt_regs.  This can cause the original NMI handler to produce
incorrect output.

We solve this problem by interchanging the position of the preserved
copy of the iret registers ("saved") and the copy subject to being
trampled by nested NMI ("copied").

Signed-off-by: Salman Qazi <sqazi@google.com>
---
 arch/x86/kernel/entry_64.S |   41 +++++++++++++++++++++++++++--------------
 1 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 44531ac..b5d6e43 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1739,9 +1739,10 @@ nested_nmi:
 
 1:
 	/* Set up the interrupted NMIs stack to jump to repeat_nmi */
-	leaq -6*8(%rsp), %rdx
+	leaq -1*8(%rsp), %rdx
 	movq %rdx, %rsp
-	CFI_ADJUST_CFA_OFFSET 6*8
+	CFI_ADJUST_CFA_OFFSET 1*8
+	leaq -10*8(%rsp), %rdx
 	pushq_cfi $__KERNEL_DS
 	pushq_cfi %rdx
 	pushfq_cfi
@@ -1749,8 +1750,8 @@ nested_nmi:
 	pushq_cfi $repeat_nmi
 
 	/* Put stack back */
-	addq $(11*8), %rsp
-	CFI_ADJUST_CFA_OFFSET -11*8
+	addq $(6*8), %rsp
+	CFI_ADJUST_CFA_OFFSET -6*8
 
 nested_nmi_out:
 	popq_cfi %rdx
@@ -1776,18 +1777,18 @@ first_nmi:
 	 * +-------------------------+
 	 * | NMI executing variable  |
 	 * +-------------------------+
-	 * | Saved SS                |
-	 * | Saved Return RSP        |
-	 * | Saved RFLAGS            |
-	 * | Saved CS                |
-	 * | Saved RIP               |
-	 * +-------------------------+
 	 * | copied SS               |
 	 * | copied Return RSP       |
 	 * | copied RFLAGS           |
 	 * | copied CS               |
 	 * | copied RIP              |
 	 * +-------------------------+
+	 * | Saved SS                |
+	 * | Saved Return RSP        |
+	 * | Saved RFLAGS            |
+	 * | Saved CS                |
+	 * | Saved RIP               |
+	 * +-------------------------+
 	 * | pt_regs                 |
 	 * +-------------------------+
 	 *
@@ -1803,9 +1804,14 @@ first_nmi:
 	/* Set the NMI executing variable on the stack. */
 	pushq_cfi $1
 
+	/*
+	 * Leave room for the "copied" frame
+	 */
+	subq $(5*8), %rsp
+
 	/* Copy the stack frame to the Saved frame */
 	.rept 5
-	pushq_cfi 6*8(%rsp)
+	pushq_cfi 11*8(%rsp)
 	.endr
 	CFI_DEF_CFA_OFFSET SS+8-RIP
 
@@ -1826,12 +1832,15 @@ repeat_nmi:
 	 * is benign for the non-repeat case, where 1 was pushed just above
 	 * to this very stack slot).
 	 */
-	movq $1, 5*8(%rsp)
+	movq $1, 10*8(%rsp)
 
 	/* Make another copy, this one may be modified by nested NMIs */
+	addq $(10*8), %rsp
 	.rept 5
-	pushq_cfi 4*8(%rsp)
+	pushq_cfi -6*8(%rsp)
 	.endr
+	subq $(5*8), %rsp
+
 	CFI_DEF_CFA_OFFSET SS+8-RIP
 end_repeat_nmi:
 
@@ -1882,8 +1891,12 @@ nmi_swapgs:
 	SWAPGS_UNSAFE_STACK
 nmi_restore:
 	RESTORE_ALL 8
+
+	/* Pop the extra iret frame */
+	addq $(5*8), %rsp
+
 	/* Clear the NMI executing stack variable */
-	movq $0, 10*8(%rsp)
+	movq $0, 5*8(%rsp)
 	jmp irq_return
 	CFI_ENDPROC
 END(nmi)


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

* [PATCH] [PATCH] x86: Don't clobber top of pt_regs in nested NMI
  2012-10-02  0:26 [PATCH] The nested NMI modifies the place (instruction, flags and stack) Salman Qazi
@ 2012-10-02  0:29 ` Salman Qazi
  2012-11-01  1:04   ` Steven Rostedt
  2012-11-02 19:37   ` [tip:x86/asm] " tip-bot for Salman Qazi
  0 siblings, 2 replies; 10+ messages in thread
From: Salman Qazi @ 2012-10-02  0:29 UTC (permalink / raw)
  To: Peter Zijlstra, LKML, Steven Rostedt, Thomas Gleixner,
	H. Peter Anvin, Linus Torvalds

The nested NMI modifies the place (instruction, flags and stack)
that the first NMI will iret to.  However, the copy of registers
modified is exactly the one that is the part of pt_regs in
the first NMI.  This can change the behaviour of the first NMI.

In particular, Google's arch_trigger_all_cpu_backtrace handler
also prints regions of memory surrounding addresses appearing in
registers.  This results in handled exceptions, after which nested NMIs
start coming in.  These nested NMIs change the value of registers
in pt_regs.  This can cause the original NMI handler to produce
incorrect output.

We solve this problem by interchanging the position of the preserved
copy of the iret registers ("saved") and the copy subject to being
trampled by nested NMI ("copied").

Signed-off-by: Salman Qazi <sqazi@google.com>
---
 arch/x86/kernel/entry_64.S |   41 +++++++++++++++++++++++++++--------------
 1 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 44531ac..b5d6e43 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1739,9 +1739,10 @@ nested_nmi:
 
 1:
 	/* Set up the interrupted NMIs stack to jump to repeat_nmi */
-	leaq -6*8(%rsp), %rdx
+	leaq -1*8(%rsp), %rdx
 	movq %rdx, %rsp
-	CFI_ADJUST_CFA_OFFSET 6*8
+	CFI_ADJUST_CFA_OFFSET 1*8
+	leaq -10*8(%rsp), %rdx
 	pushq_cfi $__KERNEL_DS
 	pushq_cfi %rdx
 	pushfq_cfi
@@ -1749,8 +1750,8 @@ nested_nmi:
 	pushq_cfi $repeat_nmi
 
 	/* Put stack back */
-	addq $(11*8), %rsp
-	CFI_ADJUST_CFA_OFFSET -11*8
+	addq $(6*8), %rsp
+	CFI_ADJUST_CFA_OFFSET -6*8
 
 nested_nmi_out:
 	popq_cfi %rdx
@@ -1776,18 +1777,18 @@ first_nmi:
 	 * +-------------------------+
 	 * | NMI executing variable  |
 	 * +-------------------------+
-	 * | Saved SS                |
-	 * | Saved Return RSP        |
-	 * | Saved RFLAGS            |
-	 * | Saved CS                |
-	 * | Saved RIP               |
-	 * +-------------------------+
 	 * | copied SS               |
 	 * | copied Return RSP       |
 	 * | copied RFLAGS           |
 	 * | copied CS               |
 	 * | copied RIP              |
 	 * +-------------------------+
+	 * | Saved SS                |
+	 * | Saved Return RSP        |
+	 * | Saved RFLAGS            |
+	 * | Saved CS                |
+	 * | Saved RIP               |
+	 * +-------------------------+
 	 * | pt_regs                 |
 	 * +-------------------------+
 	 *
@@ -1803,9 +1804,14 @@ first_nmi:
 	/* Set the NMI executing variable on the stack. */
 	pushq_cfi $1
 
+	/*
+	 * Leave room for the "copied" frame
+	 */
+	subq $(5*8), %rsp
+
 	/* Copy the stack frame to the Saved frame */
 	.rept 5
-	pushq_cfi 6*8(%rsp)
+	pushq_cfi 11*8(%rsp)
 	.endr
 	CFI_DEF_CFA_OFFSET SS+8-RIP
 
@@ -1826,12 +1832,15 @@ repeat_nmi:
 	 * is benign for the non-repeat case, where 1 was pushed just above
 	 * to this very stack slot).
 	 */
-	movq $1, 5*8(%rsp)
+	movq $1, 10*8(%rsp)
 
 	/* Make another copy, this one may be modified by nested NMIs */
+	addq $(10*8), %rsp
 	.rept 5
-	pushq_cfi 4*8(%rsp)
+	pushq_cfi -6*8(%rsp)
 	.endr
+	subq $(5*8), %rsp
+
 	CFI_DEF_CFA_OFFSET SS+8-RIP
 end_repeat_nmi:
 
@@ -1882,8 +1891,12 @@ nmi_swapgs:
 	SWAPGS_UNSAFE_STACK
 nmi_restore:
 	RESTORE_ALL 8
+
+	/* Pop the extra iret frame */
+	addq $(5*8), %rsp
+
 	/* Clear the NMI executing stack variable */
-	movq $0, 10*8(%rsp)
+	movq $0, 5*8(%rsp)
 	jmp irq_return
 	CFI_ENDPROC
 END(nmi)


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

* Re: [PATCH] [PATCH] x86: Don't clobber top of pt_regs in nested NMI
  2012-10-02  0:29 ` [PATCH] [PATCH] x86: Don't clobber top of pt_regs in nested NMI Salman Qazi
@ 2012-11-01  1:04   ` Steven Rostedt
  2012-11-01 19:53     ` Jan Beulich
  2012-11-02 19:37   ` [tip:x86/asm] " tip-bot for Salman Qazi
  1 sibling, 1 reply; 10+ messages in thread
From: Steven Rostedt @ 2012-11-01  1:04 UTC (permalink / raw)
  To: Salman Qazi
  Cc: Peter Zijlstra, LKML, Thomas Gleixner, H. Peter Anvin,
	Linus Torvalds, Jan Beulich

On Mon, 2012-10-01 at 17:29 -0700, Salman Qazi wrote:
> The nested NMI modifies the place (instruction, flags and stack)
> that the first NMI will iret to.  However, the copy of registers
> modified is exactly the one that is the part of pt_regs in
> the first NMI.  This can change the behaviour of the first NMI.
> 
> In particular, Google's arch_trigger_all_cpu_backtrace handler
> also prints regions of memory surrounding addresses appearing in
> registers.  This results in handled exceptions, after which nested NMIs
> start coming in.  These nested NMIs change the value of registers
> in pt_regs.  This can cause the original NMI handler to produce
> incorrect output.
> 
> We solve this problem by interchanging the position of the preserved
> copy of the iret registers ("saved") and the copy subject to being
> trampled by nested NMI ("copied").
> 

I was all ready to push this forward, but on my last final review I
found some nits that prevent me from doing so.

> Signed-off-by: Salman Qazi <sqazi@google.com>
> ---
>  arch/x86/kernel/entry_64.S |   41 +++++++++++++++++++++++++++--------------
>  1 files changed, 27 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
> index 44531ac..b5d6e43 100644
> --- a/arch/x86/kernel/entry_64.S
> +++ b/arch/x86/kernel/entry_64.S
> @@ -1739,9 +1739,10 @@ nested_nmi:
>  
>  1:
>  	/* Set up the interrupted NMIs stack to jump to repeat_nmi */
> -	leaq -6*8(%rsp), %rdx
> +	leaq -1*8(%rsp), %rdx
>  	movq %rdx, %rsp
> -	CFI_ADJUST_CFA_OFFSET 6*8
> +	CFI_ADJUST_CFA_OFFSET 1*8
> +	leaq -10*8(%rsp), %rdx
>  	pushq_cfi $__KERNEL_DS
>  	pushq_cfi %rdx
>  	pushfq_cfi
> @@ -1749,8 +1750,8 @@ nested_nmi:
>  	pushq_cfi $repeat_nmi
>  
>  	/* Put stack back */
> -	addq $(11*8), %rsp
> -	CFI_ADJUST_CFA_OFFSET -11*8
> +	addq $(6*8), %rsp
> +	CFI_ADJUST_CFA_OFFSET -6*8
>  
>  nested_nmi_out:
>  	popq_cfi %rdx
> @@ -1776,18 +1777,18 @@ first_nmi:
>  	 * +-------------------------+
>  	 * | NMI executing variable  |
>  	 * +-------------------------+
> -	 * | Saved SS                |
> -	 * | Saved Return RSP        |
> -	 * | Saved RFLAGS            |
> -	 * | Saved CS                |
> -	 * | Saved RIP               |
> -	 * +-------------------------+
>  	 * | copied SS               |
>  	 * | copied Return RSP       |
>  	 * | copied RFLAGS           |
>  	 * | copied CS               |
>  	 * | copied RIP              |
>  	 * +-------------------------+
> +	 * | Saved SS                |
> +	 * | Saved Return RSP        |
> +	 * | Saved RFLAGS            |
> +	 * | Saved CS                |
> +	 * | Saved RIP               |
> +	 * +-------------------------+
>  	 * | pt_regs                 |
>  	 * +-------------------------+
>  	 *
> @@ -1803,9 +1804,14 @@ first_nmi:
>  	/* Set the NMI executing variable on the stack. */
>  	pushq_cfi $1
>  
> +	/*
> +	 * Leave room for the "copied" frame
> +	 */
> +	subq $(5*8), %rsp
> +
>  	/* Copy the stack frame to the Saved frame */
>  	.rept 5
> -	pushq_cfi 6*8(%rsp)
> +	pushq_cfi 11*8(%rsp)
>  	.endr
>  	CFI_DEF_CFA_OFFSET SS+8-RIP
>  
> @@ -1826,12 +1832,15 @@ repeat_nmi:
>  	 * is benign for the non-repeat case, where 1 was pushed just above
>  	 * to this very stack slot).
>  	 */
> -	movq $1, 5*8(%rsp)
> +	movq $1, 10*8(%rsp)
>  
>  	/* Make another copy, this one may be modified by nested NMIs */
> +	addq $(10*8), %rsp

This breaks the CFI magic.

>  	.rept 5
> -	pushq_cfi 4*8(%rsp)
> +	pushq_cfi -6*8(%rsp)
>  	.endr
> +	subq $(5*8), %rsp

So does this.

This needs to be annotated correctly before I can push it out. But the
good news is, I stressed tested this change, and it all works out.

Jan, can you help out here?

-- Steve

> +
>  	CFI_DEF_CFA_OFFSET SS+8-RIP
>  end_repeat_nmi:
>  
> @@ -1882,8 +1891,12 @@ nmi_swapgs:
>  	SWAPGS_UNSAFE_STACK
>  nmi_restore:
>  	RESTORE_ALL 8
> +
> +	/* Pop the extra iret frame */
> +	addq $(5*8), %rsp
> +
>  	/* Clear the NMI executing stack variable */
> -	movq $0, 10*8(%rsp)
> +	movq $0, 5*8(%rsp)
>  	jmp irq_return
>  	CFI_ENDPROC
>  END(nmi)



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

* Re: [PATCH] [PATCH] x86: Don't clobber top of pt_regs in nested NMI
  2012-11-01  1:04   ` Steven Rostedt
@ 2012-11-01 19:53     ` Jan Beulich
  2012-11-01 20:37       ` Steven Rostedt
  2012-11-02 13:51       ` Steven Rostedt
  0 siblings, 2 replies; 10+ messages in thread
From: Jan Beulich @ 2012-11-01 19:53 UTC (permalink / raw)
  To: rostedt, sqazi; +Cc: peterz, tglx, torvalds, hpa, linux-kernel

>>> Steven Rostedt <rostedt@goodmis.org> 11/01/12 2:04 AM >>>
>On Mon, 2012-10-01 at 17:29 -0700, Salman Qazi wrote:
>> @@ -1826,12 +1832,15 @@ repeat_nmi:
>>       * is benign for the non-repeat case, where 1 was pushed just above
>>       * to this very stack slot).
>>       */
>> -    movq $1, 5*8(%rsp)
>> +    movq $1, 10*8(%rsp)
>>  
>>      /* Make another copy, this one may be modified by nested NMIs */
>> +    addq $(10*8), %rsp
>
>This breaks the CFI magic.
>
>>      .rept 5
>> -    pushq_cfi 4*8(%rsp)
>> +    pushq_cfi -6*8(%rsp)
>>      .endr
>> +    subq $(5*8), %rsp
>
>So does this.
>
>This needs to be annotated correctly before I can push it out. But the
>good news is, I stressed tested this change, and it all works out.
>
>Jan, can you help out here?

There doesn't appear to be anything special about these adjustments, so I
don't see what help would be required here - it ought to be the normal use
of CFI_ADJUST_CFA_OFFSET that needs adding.

Jan


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

* Re: [PATCH] [PATCH] x86: Don't clobber top of pt_regs in nested NMI
  2012-11-01 19:53     ` Jan Beulich
@ 2012-11-01 20:37       ` Steven Rostedt
  2012-11-02 13:51       ` Steven Rostedt
  1 sibling, 0 replies; 10+ messages in thread
From: Steven Rostedt @ 2012-11-01 20:37 UTC (permalink / raw)
  To: Jan Beulich; +Cc: sqazi, peterz, tglx, torvalds, hpa, linux-kernel

On Thu, 2012-11-01 at 19:53 +0000, Jan Beulich wrote:
> >>> Steven Rostedt <rostedt@goodmis.org> 11/01/12 2:04 AM >>>
> >On Mon, 2012-10-01 at 17:29 -0700, Salman Qazi wrote:
> >> @@ -1826,12 +1832,15 @@ repeat_nmi:
> >>       * is benign for the non-repeat case, where 1 was pushed just above
> >>       * to this very stack slot).
> >>       */
> >> -    movq $1, 5*8(%rsp)
> >> +    movq $1, 10*8(%rsp)
> >>  
> >>      /* Make another copy, this one may be modified by nested NMIs */
> >> +    addq $(10*8), %rsp
> >
> >This breaks the CFI magic.
> >
> >>      .rept 5
> >> -    pushq_cfi 4*8(%rsp)
> >> +    pushq_cfi -6*8(%rsp)
> >>      .endr
> >> +    subq $(5*8), %rsp
> >
> >So does this.
> >
> >This needs to be annotated correctly before I can push it out. But the
> >good news is, I stressed tested this change, and it all works out.
> >
> >Jan, can you help out here?
> 
> There doesn't appear to be anything special about these adjustments, so I
> don't see what help would be required here - it ought to be the normal use
> of CFI_ADJUST_CFA_OFFSET that needs adding.

Even the simple CFI adjustments look like magic to me :-)  OK, I'll
update the patch and send it out. I'll Cc you in case I screw up even
the most simple case ;-)

-- Steve



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

* Re: [PATCH] [PATCH] x86: Don't clobber top of pt_regs in nested NMI
  2012-11-01 19:53     ` Jan Beulich
  2012-11-01 20:37       ` Steven Rostedt
@ 2012-11-02 13:51       ` Steven Rostedt
  2012-11-02 13:53         ` Steven Rostedt
  1 sibling, 1 reply; 10+ messages in thread
From: Steven Rostedt @ 2012-11-02 13:51 UTC (permalink / raw)
  To: Jan Beulich; +Cc: sqazi, peterz, tglx, torvalds, hpa, linux-kernel

On Thu, 2012-11-01 at 19:53 +0000, Jan Beulich wrote:

> There doesn't appear to be anything special about these adjustments, so I
> don't see what help would be required here - it ought to be the normal use
> of CFI_ADJUST_CFA_OFFSET that needs adding.

This change look fine to you?

diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 52edf92..7ba5342 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1796,10 +1796,12 @@ repeat_nmi:
 
 	/* Make another copy, this one may be modified by nested NMIs */
 	addq $(10*8), %rsp
+	CFI_ADJUST_CFA_OFFSET -10*8
 	.rept 5
 	pushq_cfi -6*8(%rsp)
 	.endr
 	subq $(5*8), %rsp
+	CFI_ADJUST_CFA_OFFSET 5*8
 
 	CFI_DEF_CFA_OFFSET SS+8-RIP
 end_repeat_nmi:


-- Steve



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

* Re: [PATCH] [PATCH] x86: Don't clobber top of pt_regs in nested NMI
  2012-11-02 13:51       ` Steven Rostedt
@ 2012-11-02 13:53         ` Steven Rostedt
  2012-11-02 14:09           ` Jan Beulich
  0 siblings, 1 reply; 10+ messages in thread
From: Steven Rostedt @ 2012-11-02 13:53 UTC (permalink / raw)
  To: Jan Beulich; +Cc: sqazi, peterz, tglx, torvalds, hpa, linux-kernel

On Fri, 2012-11-02 at 09:51 -0400, Steven Rostedt wrote:
> On Thu, 2012-11-01 at 19:53 +0000, Jan Beulich wrote:
> 
> > There doesn't appear to be anything special about these adjustments, so I
> > don't see what help would be required here - it ought to be the normal use
> > of CFI_ADJUST_CFA_OFFSET that needs adding.
> 
> This change look fine to you?
> 
> diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
> index 52edf92..7ba5342 100644
> --- a/arch/x86/kernel/entry_64.S
> +++ b/arch/x86/kernel/entry_64.S
> @@ -1796,10 +1796,12 @@ repeat_nmi:
>  
>  	/* Make another copy, this one may be modified by nested NMIs */
>  	addq $(10*8), %rsp
> +	CFI_ADJUST_CFA_OFFSET -10*8
>  	.rept 5
>  	pushq_cfi -6*8(%rsp)
>  	.endr
>  	subq $(5*8), %rsp
> +	CFI_ADJUST_CFA_OFFSET 5*8
>  
>  	CFI_DEF_CFA_OFFSET SS+8-RIP
>  end_repeat_nmi:
> 

Is that second one even needed? Or will the CFI_DEF_CFA_OFFSET SS+8-RIP
fix it?

-- Steve



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

* Re: [PATCH] [PATCH] x86: Don't clobber top of pt_regs in nested NMI
  2012-11-02 13:53         ` Steven Rostedt
@ 2012-11-02 14:09           ` Jan Beulich
  2012-11-02 14:11             ` Steven Rostedt
  0 siblings, 1 reply; 10+ messages in thread
From: Jan Beulich @ 2012-11-02 14:09 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: sqazi, peterz, tglx, torvalds, hpa, linux-kernel

>>> On 02.11.12 at 14:53, Steven Rostedt <rostedt@goodmis.org> wrote:
> On Fri, 2012-11-02 at 09:51 -0400, Steven Rostedt wrote:
>> On Thu, 2012-11-01 at 19:53 +0000, Jan Beulich wrote:
>> 
>> > There doesn't appear to be anything special about these adjustments, so I
>> > don't see what help would be required here - it ought to be the normal use
>> > of CFI_ADJUST_CFA_OFFSET that needs adding.
>> 
>> This change look fine to you?
>> 
>> diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
>> index 52edf92..7ba5342 100644
>> --- a/arch/x86/kernel/entry_64.S
>> +++ b/arch/x86/kernel/entry_64.S
>> @@ -1796,10 +1796,12 @@ repeat_nmi:
>>  
>>  	/* Make another copy, this one may be modified by nested NMIs */
>>  	addq $(10*8), %rsp
>> +	CFI_ADJUST_CFA_OFFSET -10*8
>>  	.rept 5
>>  	pushq_cfi -6*8(%rsp)
>>  	.endr
>>  	subq $(5*8), %rsp
>> +	CFI_ADJUST_CFA_OFFSET 5*8
>>  
>>  	CFI_DEF_CFA_OFFSET SS+8-RIP
>>  end_repeat_nmi:
>> 
> 
> Is that second one even needed? Or will the CFI_DEF_CFA_OFFSET SS+8-RIP
> fix it?

Yes it will (as long as no intervening instructions get added; that's
to say that I'd recommend removing the blank line to make clear
that instruction and annotation belong together).

Jan


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

* Re: [PATCH] [PATCH] x86: Don't clobber top of pt_regs in nested NMI
  2012-11-02 14:09           ` Jan Beulich
@ 2012-11-02 14:11             ` Steven Rostedt
  0 siblings, 0 replies; 10+ messages in thread
From: Steven Rostedt @ 2012-11-02 14:11 UTC (permalink / raw)
  To: Jan Beulich; +Cc: sqazi, peterz, tglx, torvalds, hpa, linux-kernel

On Fri, 2012-11-02 at 14:09 +0000, Jan Beulich wrote:

> >>  	subq $(5*8), %rsp
> >> +	CFI_ADJUST_CFA_OFFSET 5*8
> >>  
> >>  	CFI_DEF_CFA_OFFSET SS+8-RIP
> >>  end_repeat_nmi:
> >> 
> > 
> > Is that second one even needed? Or will the CFI_DEF_CFA_OFFSET SS+8-RIP
> > fix it?
> 
> Yes it will (as long as no intervening instructions get added; that's
> to say that I'd recommend removing the blank line to make clear
> that instruction and annotation belong together).

OK, will do.

Thanks!

-- Steve



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

* [tip:x86/asm] x86: Don't clobber top of pt_regs in nested NMI
  2012-10-02  0:29 ` [PATCH] [PATCH] x86: Don't clobber top of pt_regs in nested NMI Salman Qazi
  2012-11-01  1:04   ` Steven Rostedt
@ 2012-11-02 19:37   ` tip-bot for Salman Qazi
  1 sibling, 0 replies; 10+ messages in thread
From: tip-bot for Salman Qazi @ 2012-11-02 19:37 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: linux-kernel, hpa, mingo, rostedt, sqazi, tglx

Commit-ID:  28696f434fef0efa97534b59986ad33b9c4df7f8
Gitweb:     http://git.kernel.org/tip/28696f434fef0efa97534b59986ad33b9c4df7f8
Author:     Salman Qazi <sqazi@google.com>
AuthorDate: Mon, 1 Oct 2012 17:29:25 -0700
Committer:  Steven Rostedt <rostedt@goodmis.org>
CommitDate: Fri, 2 Nov 2012 11:29:36 -0400

x86: Don't clobber top of pt_regs in nested NMI

The nested NMI modifies the place (instruction, flags and stack)
that the first NMI will iret to.  However, the copy of registers
modified is exactly the one that is the part of pt_regs in
the first NMI.  This can change the behaviour of the first NMI.

In particular, Google's arch_trigger_all_cpu_backtrace handler
also prints regions of memory surrounding addresses appearing in
registers.  This results in handled exceptions, after which nested NMIs
start coming in.  These nested NMIs change the value of registers
in pt_regs.  This can cause the original NMI handler to produce
incorrect output.

We solve this problem by interchanging the position of the preserved
copy of the iret registers ("saved") and the copy subject to being
trampled by nested NMI ("copied").

Link: http://lkml.kernel.org/r/20121002002919.27236.14388.stgit@dungbeetle.mtv.corp.google.com

Signed-off-by: Salman Qazi <sqazi@google.com>
[ Added a needed CFI_ADJUST_CFA_OFFSET ]
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 arch/x86/kernel/entry_64.S |   41 +++++++++++++++++++++++++++--------------
 1 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index b51b2c7..811795d 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1699,9 +1699,10 @@ nested_nmi:
 
 1:
 	/* Set up the interrupted NMIs stack to jump to repeat_nmi */
-	leaq -6*8(%rsp), %rdx
+	leaq -1*8(%rsp), %rdx
 	movq %rdx, %rsp
-	CFI_ADJUST_CFA_OFFSET 6*8
+	CFI_ADJUST_CFA_OFFSET 1*8
+	leaq -10*8(%rsp), %rdx
 	pushq_cfi $__KERNEL_DS
 	pushq_cfi %rdx
 	pushfq_cfi
@@ -1709,8 +1710,8 @@ nested_nmi:
 	pushq_cfi $repeat_nmi
 
 	/* Put stack back */
-	addq $(11*8), %rsp
-	CFI_ADJUST_CFA_OFFSET -11*8
+	addq $(6*8), %rsp
+	CFI_ADJUST_CFA_OFFSET -6*8
 
 nested_nmi_out:
 	popq_cfi %rdx
@@ -1736,18 +1737,18 @@ first_nmi:
 	 * +-------------------------+
 	 * | NMI executing variable  |
 	 * +-------------------------+
-	 * | Saved SS                |
-	 * | Saved Return RSP        |
-	 * | Saved RFLAGS            |
-	 * | Saved CS                |
-	 * | Saved RIP               |
-	 * +-------------------------+
 	 * | copied SS               |
 	 * | copied Return RSP       |
 	 * | copied RFLAGS           |
 	 * | copied CS               |
 	 * | copied RIP              |
 	 * +-------------------------+
+	 * | Saved SS                |
+	 * | Saved Return RSP        |
+	 * | Saved RFLAGS            |
+	 * | Saved CS                |
+	 * | Saved RIP               |
+	 * +-------------------------+
 	 * | pt_regs                 |
 	 * +-------------------------+
 	 *
@@ -1763,9 +1764,14 @@ first_nmi:
 	/* Set the NMI executing variable on the stack. */
 	pushq_cfi $1
 
+	/*
+	 * Leave room for the "copied" frame
+	 */
+	subq $(5*8), %rsp
+
 	/* Copy the stack frame to the Saved frame */
 	.rept 5
-	pushq_cfi 6*8(%rsp)
+	pushq_cfi 11*8(%rsp)
 	.endr
 	CFI_DEF_CFA_OFFSET SS+8-RIP
 
@@ -1786,12 +1792,15 @@ repeat_nmi:
 	 * is benign for the non-repeat case, where 1 was pushed just above
 	 * to this very stack slot).
 	 */
-	movq $1, 5*8(%rsp)
+	movq $1, 10*8(%rsp)
 
 	/* Make another copy, this one may be modified by nested NMIs */
+	addq $(10*8), %rsp
+	CFI_ADJUST_CFA_OFFSET -10*8
 	.rept 5
-	pushq_cfi 4*8(%rsp)
+	pushq_cfi -6*8(%rsp)
 	.endr
+	subq $(5*8), %rsp
 	CFI_DEF_CFA_OFFSET SS+8-RIP
 end_repeat_nmi:
 
@@ -1842,8 +1851,12 @@ nmi_swapgs:
 	SWAPGS_UNSAFE_STACK
 nmi_restore:
 	RESTORE_ALL 8
+
+	/* Pop the extra iret frame */
+	addq $(5*8), %rsp
+
 	/* Clear the NMI executing stack variable */
-	movq $0, 10*8(%rsp)
+	movq $0, 5*8(%rsp)
 	jmp irq_return
 	CFI_ENDPROC
 END(nmi)

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

end of thread, other threads:[~2012-11-02 19:37 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-02  0:26 [PATCH] The nested NMI modifies the place (instruction, flags and stack) Salman Qazi
2012-10-02  0:29 ` [PATCH] [PATCH] x86: Don't clobber top of pt_regs in nested NMI Salman Qazi
2012-11-01  1:04   ` Steven Rostedt
2012-11-01 19:53     ` Jan Beulich
2012-11-01 20:37       ` Steven Rostedt
2012-11-02 13:51       ` Steven Rostedt
2012-11-02 13:53         ` Steven Rostedt
2012-11-02 14:09           ` Jan Beulich
2012-11-02 14:11             ` Steven Rostedt
2012-11-02 19:37   ` [tip:x86/asm] " tip-bot for Salman Qazi

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.