diff options
author | Jason Wessel <jason.wessel@windriver.com> | 2009-12-11 09:43:16 -0500 |
---|---|---|
committer | Jason Wessel <jason.wessel@windriver.com> | 2009-12-11 09:43:16 -0500 |
commit | cf6f196d112a6f6757b1ca3cce0b576f7abee479 (patch) | |
tree | 977a9e18167112af168ce49f95b5d26fe1bec46d /arch | |
parent | 59d309f9c8ef0bd01bf93cc0e758f1d810417bdb (diff) |
kgdb,i386: Fix corner case access to ss with NMI watch dog exception
It is possible for the user_mode_vm(regs) check to return true on the
i368 arch for a non master kgdb cpu or when the master kgdb cpu
handles the NMI watch dog exception.
The solution is simply to select the correct gdb_ss location
based on the check to user_mode_vm(regs).
CC: Ingo Molnar <mingo@elte.hu>
Acked-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/kgdb.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index f93d015753ce..aefae46aa646 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c | |||
@@ -86,9 +86,15 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) | |||
86 | gdb_regs[GDB_DS] = regs->ds; | 86 | gdb_regs[GDB_DS] = regs->ds; |
87 | gdb_regs[GDB_ES] = regs->es; | 87 | gdb_regs[GDB_ES] = regs->es; |
88 | gdb_regs[GDB_CS] = regs->cs; | 88 | gdb_regs[GDB_CS] = regs->cs; |
89 | gdb_regs[GDB_SS] = __KERNEL_DS; | ||
90 | gdb_regs[GDB_FS] = 0xFFFF; | 89 | gdb_regs[GDB_FS] = 0xFFFF; |
91 | gdb_regs[GDB_GS] = 0xFFFF; | 90 | gdb_regs[GDB_GS] = 0xFFFF; |
91 | if (user_mode_vm(regs)) { | ||
92 | gdb_regs[GDB_SS] = regs->ss; | ||
93 | gdb_regs[GDB_SP] = regs->sp; | ||
94 | } else { | ||
95 | gdb_regs[GDB_SS] = __KERNEL_DS; | ||
96 | gdb_regs[GDB_SP] = kernel_stack_pointer(regs); | ||
97 | } | ||
92 | #else | 98 | #else |
93 | gdb_regs[GDB_R8] = regs->r8; | 99 | gdb_regs[GDB_R8] = regs->r8; |
94 | gdb_regs[GDB_R9] = regs->r9; | 100 | gdb_regs[GDB_R9] = regs->r9; |
@@ -101,8 +107,8 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) | |||
101 | gdb_regs32[GDB_PS] = regs->flags; | 107 | gdb_regs32[GDB_PS] = regs->flags; |
102 | gdb_regs32[GDB_CS] = regs->cs; | 108 | gdb_regs32[GDB_CS] = regs->cs; |
103 | gdb_regs32[GDB_SS] = regs->ss; | 109 | gdb_regs32[GDB_SS] = regs->ss; |
104 | #endif | ||
105 | gdb_regs[GDB_SP] = kernel_stack_pointer(regs); | 110 | gdb_regs[GDB_SP] = kernel_stack_pointer(regs); |
111 | #endif | ||
106 | } | 112 | } |
107 | 113 | ||
108 | /** | 114 | /** |