diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-09-29 11:30:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-09-29 11:30:11 -0400 |
commit | 929675d58c5b4883050804f2b48de2293803862d (patch) | |
tree | 038755ae54815d19d12873dcb9ac4662c8345ccd | |
parent | 66120005e65eed8a05b14a36ab448bdec42f0d6b (diff) | |
parent | 0dca0fd2bfeb99738708d6c9117994ebf398e72c (diff) |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jwessel/linux-2.6-kgdb:
kgdboc,tty: Fix tty polling search to use name correctly
kgdb, x86_64: fix PS CS SS registers in gdb serial
kgdb, x86_64: gdb serial has BX and DX reversed
kgdb, x86, arm, mips, powerpc: ignore user space single stepping
kgdb: could not write to the last of valid memory with kgdb
-rw-r--r-- | arch/arm/kernel/kgdb.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/kgdb.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/kgdb.c | 5 | ||||
-rw-r--r-- | arch/x86/kernel/kgdb.c | 43 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 14 | ||||
-rw-r--r-- | include/asm-x86/kgdb.h | 24 | ||||
-rw-r--r-- | kernel/kgdb.c | 10 |
7 files changed, 63 insertions, 38 deletions
diff --git a/arch/arm/kernel/kgdb.c b/arch/arm/kernel/kgdb.c index aaffaecffcd1..ba8ccfede964 100644 --- a/arch/arm/kernel/kgdb.c +++ b/arch/arm/kernel/kgdb.c | |||
@@ -111,8 +111,6 @@ int kgdb_arch_handle_exception(int exception_vector, int signo, | |||
111 | case 'D': | 111 | case 'D': |
112 | case 'k': | 112 | case 'k': |
113 | case 'c': | 113 | case 'c': |
114 | kgdb_contthread = NULL; | ||
115 | |||
116 | /* | 114 | /* |
117 | * Try to read optional parameter, pc unchanged if no parm. | 115 | * Try to read optional parameter, pc unchanged if no parm. |
118 | * If this was a compiled breakpoint, we need to move | 116 | * If this was a compiled breakpoint, we need to move |
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c index 8f6d58ede33c..6e152c80cd4a 100644 --- a/arch/mips/kernel/kgdb.c +++ b/arch/mips/kernel/kgdb.c | |||
@@ -236,8 +236,7 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code, | |||
236 | 236 | ||
237 | atomic_set(&kgdb_cpu_doing_single_step, -1); | 237 | atomic_set(&kgdb_cpu_doing_single_step, -1); |
238 | if (remcom_in_buffer[0] == 's') | 238 | if (remcom_in_buffer[0] == 's') |
239 | if (kgdb_contthread) | 239 | atomic_set(&kgdb_cpu_doing_single_step, cpu); |
240 | atomic_set(&kgdb_cpu_doing_single_step, cpu); | ||
241 | 240 | ||
242 | return 0; | 241 | return 0; |
243 | } | 242 | } |
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c index b4fdf2f2743c..fe8f71dd0b3f 100644 --- a/arch/powerpc/kernel/kgdb.c +++ b/arch/powerpc/kernel/kgdb.c | |||
@@ -347,9 +347,8 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code, | |||
347 | linux_regs->msr |= MSR_SE; | 347 | linux_regs->msr |= MSR_SE; |
348 | #endif | 348 | #endif |
349 | kgdb_single_step = 1; | 349 | kgdb_single_step = 1; |
350 | if (kgdb_contthread) | 350 | atomic_set(&kgdb_cpu_doing_single_step, |
351 | atomic_set(&kgdb_cpu_doing_single_step, | 351 | raw_smp_processor_id()); |
352 | raw_smp_processor_id()); | ||
353 | } | 352 | } |
354 | return 0; | 353 | return 0; |
355 | } | 354 | } |
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index f47f0eb886b8..8282a2139681 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c | |||
@@ -69,6 +69,9 @@ static int gdb_x86vector = -1; | |||
69 | */ | 69 | */ |
70 | void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) | 70 | void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) |
71 | { | 71 | { |
72 | #ifndef CONFIG_X86_32 | ||
73 | u32 *gdb_regs32 = (u32 *)gdb_regs; | ||
74 | #endif | ||
72 | gdb_regs[GDB_AX] = regs->ax; | 75 | gdb_regs[GDB_AX] = regs->ax; |
73 | gdb_regs[GDB_BX] = regs->bx; | 76 | gdb_regs[GDB_BX] = regs->bx; |
74 | gdb_regs[GDB_CX] = regs->cx; | 77 | gdb_regs[GDB_CX] = regs->cx; |
@@ -76,9 +79,9 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) | |||
76 | gdb_regs[GDB_SI] = regs->si; | 79 | gdb_regs[GDB_SI] = regs->si; |
77 | gdb_regs[GDB_DI] = regs->di; | 80 | gdb_regs[GDB_DI] = regs->di; |
78 | gdb_regs[GDB_BP] = regs->bp; | 81 | gdb_regs[GDB_BP] = regs->bp; |
79 | gdb_regs[GDB_PS] = regs->flags; | ||
80 | gdb_regs[GDB_PC] = regs->ip; | 82 | gdb_regs[GDB_PC] = regs->ip; |
81 | #ifdef CONFIG_X86_32 | 83 | #ifdef CONFIG_X86_32 |
84 | gdb_regs[GDB_PS] = regs->flags; | ||
82 | gdb_regs[GDB_DS] = regs->ds; | 85 | gdb_regs[GDB_DS] = regs->ds; |
83 | gdb_regs[GDB_ES] = regs->es; | 86 | gdb_regs[GDB_ES] = regs->es; |
84 | gdb_regs[GDB_CS] = regs->cs; | 87 | gdb_regs[GDB_CS] = regs->cs; |
@@ -94,6 +97,9 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) | |||
94 | gdb_regs[GDB_R13] = regs->r13; | 97 | gdb_regs[GDB_R13] = regs->r13; |
95 | gdb_regs[GDB_R14] = regs->r14; | 98 | gdb_regs[GDB_R14] = regs->r14; |
96 | gdb_regs[GDB_R15] = regs->r15; | 99 | gdb_regs[GDB_R15] = regs->r15; |
100 | gdb_regs32[GDB_PS] = regs->flags; | ||
101 | gdb_regs32[GDB_CS] = regs->cs; | ||
102 | gdb_regs32[GDB_SS] = regs->ss; | ||
97 | #endif | 103 | #endif |
98 | gdb_regs[GDB_SP] = regs->sp; | 104 | gdb_regs[GDB_SP] = regs->sp; |
99 | } | 105 | } |
@@ -112,6 +118,9 @@ void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) | |||
112 | */ | 118 | */ |
113 | void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) | 119 | void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) |
114 | { | 120 | { |
121 | #ifndef CONFIG_X86_32 | ||
122 | u32 *gdb_regs32 = (u32 *)gdb_regs; | ||
123 | #endif | ||
115 | gdb_regs[GDB_AX] = 0; | 124 | gdb_regs[GDB_AX] = 0; |
116 | gdb_regs[GDB_BX] = 0; | 125 | gdb_regs[GDB_BX] = 0; |
117 | gdb_regs[GDB_CX] = 0; | 126 | gdb_regs[GDB_CX] = 0; |
@@ -129,8 +138,10 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) | |||
129 | gdb_regs[GDB_FS] = 0xFFFF; | 138 | gdb_regs[GDB_FS] = 0xFFFF; |
130 | gdb_regs[GDB_GS] = 0xFFFF; | 139 | gdb_regs[GDB_GS] = 0xFFFF; |
131 | #else | 140 | #else |
132 | gdb_regs[GDB_PS] = *(unsigned long *)(p->thread.sp + 8); | 141 | gdb_regs32[GDB_PS] = *(unsigned long *)(p->thread.sp + 8); |
133 | gdb_regs[GDB_PC] = 0; | 142 | gdb_regs32[GDB_CS] = __KERNEL_CS; |
143 | gdb_regs32[GDB_SS] = __KERNEL_DS; | ||
144 | gdb_regs[GDB_PC] = p->thread.ip; | ||
134 | gdb_regs[GDB_R8] = 0; | 145 | gdb_regs[GDB_R8] = 0; |
135 | gdb_regs[GDB_R9] = 0; | 146 | gdb_regs[GDB_R9] = 0; |
136 | gdb_regs[GDB_R10] = 0; | 147 | gdb_regs[GDB_R10] = 0; |
@@ -153,6 +164,9 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) | |||
153 | */ | 164 | */ |
154 | void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) | 165 | void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) |
155 | { | 166 | { |
167 | #ifndef CONFIG_X86_32 | ||
168 | u32 *gdb_regs32 = (u32 *)gdb_regs; | ||
169 | #endif | ||
156 | regs->ax = gdb_regs[GDB_AX]; | 170 | regs->ax = gdb_regs[GDB_AX]; |
157 | regs->bx = gdb_regs[GDB_BX]; | 171 | regs->bx = gdb_regs[GDB_BX]; |
158 | regs->cx = gdb_regs[GDB_CX]; | 172 | regs->cx = gdb_regs[GDB_CX]; |
@@ -160,9 +174,9 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) | |||
160 | regs->si = gdb_regs[GDB_SI]; | 174 | regs->si = gdb_regs[GDB_SI]; |
161 | regs->di = gdb_regs[GDB_DI]; | 175 | regs->di = gdb_regs[GDB_DI]; |
162 | regs->bp = gdb_regs[GDB_BP]; | 176 | regs->bp = gdb_regs[GDB_BP]; |
163 | regs->flags = gdb_regs[GDB_PS]; | ||
164 | regs->ip = gdb_regs[GDB_PC]; | 177 | regs->ip = gdb_regs[GDB_PC]; |
165 | #ifdef CONFIG_X86_32 | 178 | #ifdef CONFIG_X86_32 |
179 | regs->flags = gdb_regs[GDB_PS]; | ||
166 | regs->ds = gdb_regs[GDB_DS]; | 180 | regs->ds = gdb_regs[GDB_DS]; |
167 | regs->es = gdb_regs[GDB_ES]; | 181 | regs->es = gdb_regs[GDB_ES]; |
168 | regs->cs = gdb_regs[GDB_CS]; | 182 | regs->cs = gdb_regs[GDB_CS]; |
@@ -175,6 +189,9 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) | |||
175 | regs->r13 = gdb_regs[GDB_R13]; | 189 | regs->r13 = gdb_regs[GDB_R13]; |
176 | regs->r14 = gdb_regs[GDB_R14]; | 190 | regs->r14 = gdb_regs[GDB_R14]; |
177 | regs->r15 = gdb_regs[GDB_R15]; | 191 | regs->r15 = gdb_regs[GDB_R15]; |
192 | regs->flags = gdb_regs32[GDB_PS]; | ||
193 | regs->cs = gdb_regs32[GDB_CS]; | ||
194 | regs->ss = gdb_regs32[GDB_SS]; | ||
178 | #endif | 195 | #endif |
179 | } | 196 | } |
180 | 197 | ||
@@ -378,10 +395,8 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, | |||
378 | if (remcomInBuffer[0] == 's') { | 395 | if (remcomInBuffer[0] == 's') { |
379 | linux_regs->flags |= X86_EFLAGS_TF; | 396 | linux_regs->flags |= X86_EFLAGS_TF; |
380 | kgdb_single_step = 1; | 397 | kgdb_single_step = 1; |
381 | if (kgdb_contthread) { | 398 | atomic_set(&kgdb_cpu_doing_single_step, |
382 | atomic_set(&kgdb_cpu_doing_single_step, | 399 | raw_smp_processor_id()); |
383 | raw_smp_processor_id()); | ||
384 | } | ||
385 | } | 400 | } |
386 | 401 | ||
387 | get_debugreg(dr6, 6); | 402 | get_debugreg(dr6, 6); |
@@ -466,9 +481,15 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd) | |||
466 | 481 | ||
467 | case DIE_DEBUG: | 482 | case DIE_DEBUG: |
468 | if (atomic_read(&kgdb_cpu_doing_single_step) == | 483 | if (atomic_read(&kgdb_cpu_doing_single_step) == |
469 | raw_smp_processor_id() && | 484 | raw_smp_processor_id()) { |
470 | user_mode(regs)) | 485 | if (user_mode(regs)) |
471 | return single_step_cont(regs, args); | 486 | return single_step_cont(regs, args); |
487 | break; | ||
488 | } else if (test_thread_flag(TIF_SINGLESTEP)) | ||
489 | /* This means a user thread is single stepping | ||
490 | * a system call which should be ignored | ||
491 | */ | ||
492 | return NOTIFY_DONE; | ||
472 | /* fall through */ | 493 | /* fall through */ |
473 | default: | 494 | default: |
474 | if (user_mode(regs)) | 495 | if (user_mode(regs)) |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index daeb8f766971..e4dce8709541 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -695,13 +695,23 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) | |||
695 | { | 695 | { |
696 | struct tty_driver *p, *res = NULL; | 696 | struct tty_driver *p, *res = NULL; |
697 | int tty_line = 0; | 697 | int tty_line = 0; |
698 | int len; | ||
698 | char *str; | 699 | char *str; |
699 | 700 | ||
701 | for (str = name; *str; str++) | ||
702 | if ((*str >= '0' && *str <= '9') || *str == ',') | ||
703 | break; | ||
704 | if (!*str) | ||
705 | return NULL; | ||
706 | |||
707 | len = str - name; | ||
708 | tty_line = simple_strtoul(str, &str, 10); | ||
709 | |||
700 | mutex_lock(&tty_mutex); | 710 | mutex_lock(&tty_mutex); |
701 | /* Search through the tty devices to look for a match */ | 711 | /* Search through the tty devices to look for a match */ |
702 | list_for_each_entry(p, &tty_drivers, tty_drivers) { | 712 | list_for_each_entry(p, &tty_drivers, tty_drivers) { |
703 | str = name + strlen(p->name); | 713 | if (strncmp(name, p->name, len) != 0) |
704 | tty_line = simple_strtoul(str, &str, 10); | 714 | continue; |
705 | if (*str == ',') | 715 | if (*str == ',') |
706 | str++; | 716 | str++; |
707 | if (*str == '\0') | 717 | if (*str == '\0') |
diff --git a/include/asm-x86/kgdb.h b/include/asm-x86/kgdb.h index 484c47554f3b..94d63db10365 100644 --- a/include/asm-x86/kgdb.h +++ b/include/asm-x86/kgdb.h | |||
@@ -39,12 +39,13 @@ enum regnames { | |||
39 | GDB_FS, /* 14 */ | 39 | GDB_FS, /* 14 */ |
40 | GDB_GS, /* 15 */ | 40 | GDB_GS, /* 15 */ |
41 | }; | 41 | }; |
42 | #define NUMREGBYTES ((GDB_GS+1)*4) | ||
42 | #else /* ! CONFIG_X86_32 */ | 43 | #else /* ! CONFIG_X86_32 */ |
43 | enum regnames { | 44 | enum regnames64 { |
44 | GDB_AX, /* 0 */ | 45 | GDB_AX, /* 0 */ |
45 | GDB_DX, /* 1 */ | 46 | GDB_BX, /* 1 */ |
46 | GDB_CX, /* 2 */ | 47 | GDB_CX, /* 2 */ |
47 | GDB_BX, /* 3 */ | 48 | GDB_DX, /* 3 */ |
48 | GDB_SI, /* 4 */ | 49 | GDB_SI, /* 4 */ |
49 | GDB_DI, /* 5 */ | 50 | GDB_DI, /* 5 */ |
50 | GDB_BP, /* 6 */ | 51 | GDB_BP, /* 6 */ |
@@ -58,18 +59,15 @@ enum regnames { | |||
58 | GDB_R14, /* 14 */ | 59 | GDB_R14, /* 14 */ |
59 | GDB_R15, /* 15 */ | 60 | GDB_R15, /* 15 */ |
60 | GDB_PC, /* 16 */ | 61 | GDB_PC, /* 16 */ |
61 | GDB_PS, /* 17 */ | ||
62 | }; | 62 | }; |
63 | #endif /* CONFIG_X86_32 */ | ||
64 | 63 | ||
65 | /* | 64 | enum regnames32 { |
66 | * Number of bytes of registers: | 65 | GDB_PS = 34, |
67 | */ | 66 | GDB_CS, |
68 | #ifdef CONFIG_X86_32 | 67 | GDB_SS, |
69 | # define NUMREGBYTES 64 | 68 | }; |
70 | #else | 69 | #define NUMREGBYTES ((GDB_SS+1)*4) |
71 | # define NUMREGBYTES ((GDB_PS+1)*8) | 70 | #endif /* CONFIG_X86_32 */ |
72 | #endif | ||
73 | 71 | ||
74 | static inline void arch_kgdb_breakpoint(void) | 72 | static inline void arch_kgdb_breakpoint(void) |
75 | { | 73 | { |
diff --git a/kernel/kgdb.c b/kernel/kgdb.c index eaa21fc9ad1d..25d955dbb989 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c | |||
@@ -488,7 +488,7 @@ static int write_mem_msg(int binary) | |||
488 | if (err) | 488 | if (err) |
489 | return err; | 489 | return err; |
490 | if (CACHE_FLUSH_IS_SAFE) | 490 | if (CACHE_FLUSH_IS_SAFE) |
491 | flush_icache_range(addr, addr + length + 1); | 491 | flush_icache_range(addr, addr + length); |
492 | return 0; | 492 | return 0; |
493 | } | 493 | } |
494 | 494 | ||
@@ -1462,7 +1462,7 @@ acquirelock: | |||
1462 | * Get the passive CPU lock which will hold all the non-primary | 1462 | * Get the passive CPU lock which will hold all the non-primary |
1463 | * CPU in a spin state while the debugger is active | 1463 | * CPU in a spin state while the debugger is active |
1464 | */ | 1464 | */ |
1465 | if (!kgdb_single_step || !kgdb_contthread) { | 1465 | if (!kgdb_single_step) { |
1466 | for (i = 0; i < NR_CPUS; i++) | 1466 | for (i = 0; i < NR_CPUS; i++) |
1467 | atomic_set(&passive_cpu_wait[i], 1); | 1467 | atomic_set(&passive_cpu_wait[i], 1); |
1468 | } | 1468 | } |
@@ -1475,7 +1475,7 @@ acquirelock: | |||
1475 | 1475 | ||
1476 | #ifdef CONFIG_SMP | 1476 | #ifdef CONFIG_SMP |
1477 | /* Signal the other CPUs to enter kgdb_wait() */ | 1477 | /* Signal the other CPUs to enter kgdb_wait() */ |
1478 | if ((!kgdb_single_step || !kgdb_contthread) && kgdb_do_roundup) | 1478 | if ((!kgdb_single_step) && kgdb_do_roundup) |
1479 | kgdb_roundup_cpus(flags); | 1479 | kgdb_roundup_cpus(flags); |
1480 | #endif | 1480 | #endif |
1481 | 1481 | ||
@@ -1494,7 +1494,7 @@ acquirelock: | |||
1494 | kgdb_post_primary_code(ks->linux_regs, ks->ex_vector, ks->err_code); | 1494 | kgdb_post_primary_code(ks->linux_regs, ks->ex_vector, ks->err_code); |
1495 | kgdb_deactivate_sw_breakpoints(); | 1495 | kgdb_deactivate_sw_breakpoints(); |
1496 | kgdb_single_step = 0; | 1496 | kgdb_single_step = 0; |
1497 | kgdb_contthread = NULL; | 1497 | kgdb_contthread = current; |
1498 | exception_level = 0; | 1498 | exception_level = 0; |
1499 | 1499 | ||
1500 | /* Talk to debugger with gdbserial protocol */ | 1500 | /* Talk to debugger with gdbserial protocol */ |
@@ -1508,7 +1508,7 @@ acquirelock: | |||
1508 | kgdb_info[ks->cpu].task = NULL; | 1508 | kgdb_info[ks->cpu].task = NULL; |
1509 | atomic_set(&cpu_in_kgdb[ks->cpu], 0); | 1509 | atomic_set(&cpu_in_kgdb[ks->cpu], 0); |
1510 | 1510 | ||
1511 | if (!kgdb_single_step || !kgdb_contthread) { | 1511 | if (!kgdb_single_step) { |
1512 | for (i = NR_CPUS-1; i >= 0; i--) | 1512 | for (i = NR_CPUS-1; i >= 0; i--) |
1513 | atomic_set(&passive_cpu_wait[i], 0); | 1513 | atomic_set(&passive_cpu_wait[i], 0); |
1514 | /* | 1514 | /* |