2015-02-26 06:18:58

by Wang Nan

[permalink] [raw]
Subject: [PATCH] x86, traps: install gates using IST after cpu_init().

X86_TRAP_NMI, X86_TRAP_DF and X86_TRAP_MC use their own stack. Those
stacks are invalid until cpu_init() installs TSS.

This patch moves setting of the 3 gates after cpu_init().

Signed-off-by: Wang Nan <[email protected]>
---

If I understand correctly, logically speaking the original code is
incorrect. However, there is no real bug caused by it for serval years.
I'm not sure whether this fix is practical or not. Fix them only for
logical correctness.

---
arch/x86/kernel/traps.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 4281988..cf7898e 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -962,7 +962,6 @@ void __init trap_init(void)
#endif

set_intr_gate(X86_TRAP_DE, divide_error);
- set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK);
/* int4 can be called from all */
set_system_intr_gate(X86_TRAP_OF, &overflow);
set_intr_gate(X86_TRAP_BR, bounds);
@@ -970,8 +969,6 @@ void __init trap_init(void)
set_intr_gate(X86_TRAP_NM, device_not_available);
#ifdef CONFIG_X86_32
set_task_gate(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS);
-#else
- set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK);
#endif
set_intr_gate(X86_TRAP_OLD_MF, coprocessor_segment_overrun);
set_intr_gate(X86_TRAP_TS, invalid_TSS);
@@ -981,9 +978,6 @@ void __init trap_init(void)
set_intr_gate(X86_TRAP_SPURIOUS, spurious_interrupt_bug);
set_intr_gate(X86_TRAP_MF, coprocessor_error);
set_intr_gate(X86_TRAP_AC, alignment_check);
-#ifdef CONFIG_X86_MCE
- set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK);
-#endif
set_intr_gate(X86_TRAP_XF, simd_coprocessor_error);

/* Reserve all the builtin and the syscall vector: */
@@ -1013,6 +1007,14 @@ void __init trap_init(void)
*/
cpu_init();

+ set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK);
+#ifndef CONFIG_X86_32
+ set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK);
+#endif
+#ifdef CONFIG_X86_MCE
+ set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK);
+#endif
+
/*
* X86_TRAP_DB and X86_TRAP_BP have been set
* in early_trap_init(). However, DEBUG_STACK works only after
--
1.8.4


2015-02-26 15:14:23

by Andy Lutomirski

[permalink] [raw]
Subject: Re: [PATCH] x86, traps: install gates using IST after cpu_init().

On Wed, Feb 25, 2015 at 10:15 PM, Wang Nan <[email protected]> wrote:
> X86_TRAP_NMI, X86_TRAP_DF and X86_TRAP_MC use their own stack. Those
> stacks are invalid until cpu_init() installs TSS.
>
> This patch moves setting of the 3 gates after cpu_init().
>
> Signed-off-by: Wang Nan <[email protected]>
> ---
>
> If I understand correctly, logically speaking the original code is
> incorrect. However, there is no real bug caused by it for serval years.
> I'm not sure whether this fix is practical or not. Fix them only for
> logical correctness.

Acked-by: Andy Lutomirski <[email protected]>

That being said, I'm pretty sure you're not fixing a bug here.
Delivery of an exception with no handler is every bit as fatal as
delivery of an exception with a non-working IST handler.

--Andy

2015-02-27 04:35:37

by Wang Nan

[permalink] [raw]
Subject: Re: [PATCH] x86, traps: install gates using IST after cpu_init().

On 2015/2/26 23:14, Andy Lutomirski wrote:
> On Wed, Feb 25, 2015 at 10:15 PM, Wang Nan <[email protected]> wrote:
>> X86_TRAP_NMI, X86_TRAP_DF and X86_TRAP_MC use their own stack. Those
>> stacks are invalid until cpu_init() installs TSS.
>>
>> This patch moves setting of the 3 gates after cpu_init().
>>
>> Signed-off-by: Wang Nan <[email protected]>
>> ---
>>
>> If I understand correctly, logically speaking the original code is
>> incorrect. However, there is no real bug caused by it for serval years.
>> I'm not sure whether this fix is practical or not. Fix them only for
>> logical correctness.
>
> Acked-by: Andy Lutomirski <[email protected]>
>
> That being said, I'm pretty sure you're not fixing a bug here.

Agree.

> Delivery of an exception with no handler is every bit as fatal as
> delivery of an exception with a non-working IST handler.
>

Just curious: in original code, what will happen if an NMI or MC raises after
'set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK);' and before cpu_init()?
In my opinion, at that time the interrupt handler is set but IST is not ready.

In addition, why it's never happened for real? Does it means NMI is possible
to be disabled?

Thank you!

> --Andy
>

2015-02-27 19:56:48

by Andy Lutomirski

[permalink] [raw]
Subject: Re: [PATCH] x86, traps: install gates using IST after cpu_init().

On Thu, Feb 26, 2015 at 8:34 PM, Wang Nan <[email protected]> wrote:
> On 2015/2/26 23:14, Andy Lutomirski wrote:
>> On Wed, Feb 25, 2015 at 10:15 PM, Wang Nan <[email protected]> wrote:
>>> X86_TRAP_NMI, X86_TRAP_DF and X86_TRAP_MC use their own stack. Those
>>> stacks are invalid until cpu_init() installs TSS.
>>>
>>> This patch moves setting of the 3 gates after cpu_init().
>>>
>>> Signed-off-by: Wang Nan <[email protected]>
>>> ---
>>>
>>> If I understand correctly, logically speaking the original code is
>>> incorrect. However, there is no real bug caused by it for serval years.
>>> I'm not sure whether this fix is practical or not. Fix them only for
>>> logical correctness.
>>
>> Acked-by: Andy Lutomirski <[email protected]>
>>
>> That being said, I'm pretty sure you're not fixing a bug here.
>
> Agree.
>
>> Delivery of an exception with no handler is every bit as fatal as
>> delivery of an exception with a non-working IST handler.
>>
>
> Just curious: in original code, what will happen if an NMI or MC raises after
> 'set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK);' and before cpu_init()?
> In my opinion, at that time the interrupt handler is set but IST is not ready.
>
> In addition, why it's never happened for real? Does it means NMI is possible
> to be disabled?

It means that no NMI sources are enabled (hopefully) that early. If
they were, we'd be doomed -- AFAIK it's impossible to maintain a
continuously valid IDT all the way through the transition from real
mode to long mode. (Maybe I'm wrong and there's some trick that would
work.)

--Andy

>
> Thank you!
>
>> --Andy
>>
>
>



--
Andy Lutomirski
AMA Capital Management, LLC