aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/traps.c
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2006-01-11 16:43:00 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-11 22:01:13 -0500
commitb556b35e98ad2b9174a7a623d152cdf412d1a999 (patch)
tree10f99d70e719fba811dee85d2f3a82b26d7a4ce8 /arch/x86_64/kernel/traps.c
parented8388a5d9db0445322f86ee8381b0f04a2057ee (diff)
[PATCH] x86_64: Move int 3 handler to debug stack and allow to increase it.
This - switches the INT3 handler to run on an IST stack (to cope with breakpoints set by a kernel debugger on places where the kernel's %gs base hasn't been set up, yet); the IST stack used is shared with the INT1 handler's [AK: this also allows setting a kprobe on the interrupt/exception entry points] - allows nesting of INT1/INT3 handlers so that one can, with a kernel debugger, debug (at least) the user-mode portions of the INT1/INT3 handling; the nesting isn't actively enabled here since a kernel- debugger-free kernel doesn't need it Signed-Off-By: Jan Beulich <jbeulich@novell.com> Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/x86_64/kernel/traps.c')
-rw-r--r--arch/x86_64/kernel/traps.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index bd71ddac0dc5..1a9094dab682 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -121,19 +121,31 @@ int printk_address(unsigned long address)
121static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, 121static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
122 unsigned *usedp, const char **idp) 122 unsigned *usedp, const char **idp)
123{ 123{
124 static const char ids[N_EXCEPTION_STACKS][8] = { 124 static char ids[][8] = {
125 [DEBUG_STACK - 1] = "#DB", 125 [DEBUG_STACK - 1] = "#DB",
126 [NMI_STACK - 1] = "NMI", 126 [NMI_STACK - 1] = "NMI",
127 [DOUBLEFAULT_STACK - 1] = "#DF", 127 [DOUBLEFAULT_STACK - 1] = "#DF",
128 [STACKFAULT_STACK - 1] = "#SS", 128 [STACKFAULT_STACK - 1] = "#SS",
129 [MCE_STACK - 1] = "#MC", 129 [MCE_STACK - 1] = "#MC",
130#if DEBUG_STKSZ > EXCEPTION_STKSZ
131 [N_EXCEPTION_STACKS ... N_EXCEPTION_STACKS + DEBUG_STKSZ / EXCEPTION_STKSZ - 2] = "#DB[?]"
132#endif
130 }; 133 };
131 unsigned k; 134 unsigned k;
132 135
133 for (k = 0; k < N_EXCEPTION_STACKS; k++) { 136 for (k = 0; k < N_EXCEPTION_STACKS; k++) {
134 unsigned long end; 137 unsigned long end;
135 138
136 end = per_cpu(init_tss, cpu).ist[k]; 139 switch (k + 1) {
140#if DEBUG_STKSZ > EXCEPTION_STKSZ
141 case DEBUG_STACK:
142 end = cpu_pda[cpu].debugstack + DEBUG_STKSZ;
143 break;
144#endif
145 default:
146 end = per_cpu(init_tss, cpu).ist[k];
147 break;
148 }
137 if (stack >= end) 149 if (stack >= end)
138 continue; 150 continue;
139 if (stack >= end - EXCEPTION_STKSZ) { 151 if (stack >= end - EXCEPTION_STKSZ) {
@@ -143,6 +155,22 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack,
143 *idp = ids[k]; 155 *idp = ids[k];
144 return (unsigned long *)end; 156 return (unsigned long *)end;
145 } 157 }
158#if DEBUG_STKSZ > EXCEPTION_STKSZ
159 if (k == DEBUG_STACK - 1 && stack >= end - DEBUG_STKSZ) {
160 unsigned j = N_EXCEPTION_STACKS - 1;
161
162 do {
163 ++j;
164 end -= EXCEPTION_STKSZ;
165 ids[j][4] = '1' + (j - N_EXCEPTION_STACKS);
166 } while (stack < end - EXCEPTION_STKSZ);
167 if (*usedp & (1U << j))
168 break;
169 *usedp |= 1U << j;
170 *idp = ids[j];
171 return (unsigned long *)end;
172 }
173#endif
146 } 174 }
147 return NULL; 175 return NULL;
148} 176}
@@ -613,6 +641,7 @@ asmlinkage void default_do_nmi(struct pt_regs *regs)
613 io_check_error(reason, regs); 641 io_check_error(reason, regs);
614} 642}
615 643
644/* runs on IST stack. */
616asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code) 645asmlinkage void __kprobes do_int3(struct pt_regs * regs, long error_code)
617{ 646{
618 if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) { 647 if (notify_die(DIE_INT3, "int3", regs, error_code, 3, SIGTRAP) == NOTIFY_STOP) {
@@ -894,7 +923,7 @@ void __init trap_init(void)
894 set_intr_gate(0,&divide_error); 923 set_intr_gate(0,&divide_error);
895 set_intr_gate_ist(1,&debug,DEBUG_STACK); 924 set_intr_gate_ist(1,&debug,DEBUG_STACK);
896 set_intr_gate_ist(2,&nmi,NMI_STACK); 925 set_intr_gate_ist(2,&nmi,NMI_STACK);
897 set_system_gate(3,&int3); 926 set_system_gate_ist(3,&int3,DEBUG_STACK); /* int3 can be called from all */
898 set_system_gate(4,&overflow); /* int4 can be called from all */ 927 set_system_gate(4,&overflow); /* int4 can be called from all */
899 set_intr_gate(5,&bounds); 928 set_intr_gate(5,&bounds);
900 set_intr_gate(6,&invalid_op); 929 set_intr_gate(6,&invalid_op);