diff options
Diffstat (limited to 'kernel/debug/debug_core.c')
| -rw-r--r-- | kernel/debug/debug_core.c | 54 |
1 files changed, 24 insertions, 30 deletions
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c index 3f88a45e6f0a..0557f24c6bca 100644 --- a/kernel/debug/debug_core.c +++ b/kernel/debug/debug_core.c | |||
| @@ -53,7 +53,6 @@ | |||
| 53 | #include <asm/cacheflush.h> | 53 | #include <asm/cacheflush.h> |
| 54 | #include <asm/byteorder.h> | 54 | #include <asm/byteorder.h> |
| 55 | #include <linux/atomic.h> | 55 | #include <linux/atomic.h> |
| 56 | #include <asm/system.h> | ||
| 57 | 56 | ||
| 58 | #include "debug_core.h" | 57 | #include "debug_core.h" |
| 59 | 58 | ||
| @@ -161,37 +160,39 @@ early_param("nokgdbroundup", opt_nokgdbroundup); | |||
| 161 | * Weak aliases for breakpoint management, | 160 | * Weak aliases for breakpoint management, |
| 162 | * can be overriden by architectures when needed: | 161 | * can be overriden by architectures when needed: |
| 163 | */ | 162 | */ |
| 164 | int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) | 163 | int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt) |
| 165 | { | 164 | { |
| 166 | int err; | 165 | int err; |
| 167 | 166 | ||
| 168 | err = probe_kernel_read(saved_instr, (char *)addr, BREAK_INSTR_SIZE); | 167 | err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr, |
| 168 | BREAK_INSTR_SIZE); | ||
| 169 | if (err) | 169 | if (err) |
| 170 | return err; | 170 | return err; |
| 171 | 171 | err = probe_kernel_write((char *)bpt->bpt_addr, | |
| 172 | return probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr, | 172 | arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE); |
| 173 | BREAK_INSTR_SIZE); | 173 | return err; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle) | 176 | int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt) |
| 177 | { | 177 | { |
| 178 | return probe_kernel_write((char *)addr, | 178 | return probe_kernel_write((char *)bpt->bpt_addr, |
| 179 | (char *)bundle, BREAK_INSTR_SIZE); | 179 | (char *)bpt->saved_instr, BREAK_INSTR_SIZE); |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | int __weak kgdb_validate_break_address(unsigned long addr) | 182 | int __weak kgdb_validate_break_address(unsigned long addr) |
| 183 | { | 183 | { |
| 184 | char tmp_variable[BREAK_INSTR_SIZE]; | 184 | struct kgdb_bkpt tmp; |
| 185 | int err; | 185 | int err; |
| 186 | /* Validate setting the breakpoint and then removing it. In the | 186 | /* Validate setting the breakpoint and then removing it. If the |
| 187 | * remove fails, the kernel needs to emit a bad message because we | 187 | * remove fails, the kernel needs to emit a bad message because we |
| 188 | * are deep trouble not being able to put things back the way we | 188 | * are deep trouble not being able to put things back the way we |
| 189 | * found them. | 189 | * found them. |
| 190 | */ | 190 | */ |
| 191 | err = kgdb_arch_set_breakpoint(addr, tmp_variable); | 191 | tmp.bpt_addr = addr; |
| 192 | err = kgdb_arch_set_breakpoint(&tmp); | ||
| 192 | if (err) | 193 | if (err) |
| 193 | return err; | 194 | return err; |
| 194 | err = kgdb_arch_remove_breakpoint(addr, tmp_variable); | 195 | err = kgdb_arch_remove_breakpoint(&tmp); |
| 195 | if (err) | 196 | if (err) |
| 196 | printk(KERN_ERR "KGDB: Critical breakpoint error, kernel " | 197 | printk(KERN_ERR "KGDB: Critical breakpoint error, kernel " |
| 197 | "memory destroyed at: %lx", addr); | 198 | "memory destroyed at: %lx", addr); |
| @@ -235,7 +236,6 @@ static void kgdb_flush_swbreak_addr(unsigned long addr) | |||
| 235 | */ | 236 | */ |
| 236 | int dbg_activate_sw_breakpoints(void) | 237 | int dbg_activate_sw_breakpoints(void) |
| 237 | { | 238 | { |
| 238 | unsigned long addr; | ||
| 239 | int error; | 239 | int error; |
| 240 | int ret = 0; | 240 | int ret = 0; |
| 241 | int i; | 241 | int i; |
| @@ -244,16 +244,15 @@ int dbg_activate_sw_breakpoints(void) | |||
| 244 | if (kgdb_break[i].state != BP_SET) | 244 | if (kgdb_break[i].state != BP_SET) |
| 245 | continue; | 245 | continue; |
| 246 | 246 | ||
| 247 | addr = kgdb_break[i].bpt_addr; | 247 | error = kgdb_arch_set_breakpoint(&kgdb_break[i]); |
| 248 | error = kgdb_arch_set_breakpoint(addr, | ||
| 249 | kgdb_break[i].saved_instr); | ||
| 250 | if (error) { | 248 | if (error) { |
| 251 | ret = error; | 249 | ret = error; |
| 252 | printk(KERN_INFO "KGDB: BP install failed: %lx", addr); | 250 | printk(KERN_INFO "KGDB: BP install failed: %lx", |
| 251 | kgdb_break[i].bpt_addr); | ||
| 253 | continue; | 252 | continue; |
| 254 | } | 253 | } |
| 255 | 254 | ||
| 256 | kgdb_flush_swbreak_addr(addr); | 255 | kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr); |
| 257 | kgdb_break[i].state = BP_ACTIVE; | 256 | kgdb_break[i].state = BP_ACTIVE; |
| 258 | } | 257 | } |
| 259 | return ret; | 258 | return ret; |
| @@ -302,7 +301,6 @@ int dbg_set_sw_break(unsigned long addr) | |||
| 302 | 301 | ||
| 303 | int dbg_deactivate_sw_breakpoints(void) | 302 | int dbg_deactivate_sw_breakpoints(void) |
| 304 | { | 303 | { |
| 305 | unsigned long addr; | ||
| 306 | int error; | 304 | int error; |
| 307 | int ret = 0; | 305 | int ret = 0; |
| 308 | int i; | 306 | int i; |
| @@ -310,15 +308,14 @@ int dbg_deactivate_sw_breakpoints(void) | |||
| 310 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { | 308 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { |
| 311 | if (kgdb_break[i].state != BP_ACTIVE) | 309 | if (kgdb_break[i].state != BP_ACTIVE) |
| 312 | continue; | 310 | continue; |
| 313 | addr = kgdb_break[i].bpt_addr; | 311 | error = kgdb_arch_remove_breakpoint(&kgdb_break[i]); |
| 314 | error = kgdb_arch_remove_breakpoint(addr, | ||
| 315 | kgdb_break[i].saved_instr); | ||
| 316 | if (error) { | 312 | if (error) { |
| 317 | printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr); | 313 | printk(KERN_INFO "KGDB: BP remove failed: %lx\n", |
| 314 | kgdb_break[i].bpt_addr); | ||
| 318 | ret = error; | 315 | ret = error; |
| 319 | } | 316 | } |
| 320 | 317 | ||
| 321 | kgdb_flush_swbreak_addr(addr); | 318 | kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr); |
| 322 | kgdb_break[i].state = BP_SET; | 319 | kgdb_break[i].state = BP_SET; |
| 323 | } | 320 | } |
| 324 | return ret; | 321 | return ret; |
| @@ -352,7 +349,6 @@ int kgdb_isremovedbreak(unsigned long addr) | |||
| 352 | 349 | ||
| 353 | int dbg_remove_all_break(void) | 350 | int dbg_remove_all_break(void) |
| 354 | { | 351 | { |
| 355 | unsigned long addr; | ||
| 356 | int error; | 352 | int error; |
| 357 | int i; | 353 | int i; |
| 358 | 354 | ||
| @@ -360,12 +356,10 @@ int dbg_remove_all_break(void) | |||
| 360 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { | 356 | for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) { |
| 361 | if (kgdb_break[i].state != BP_ACTIVE) | 357 | if (kgdb_break[i].state != BP_ACTIVE) |
| 362 | goto setundefined; | 358 | goto setundefined; |
| 363 | addr = kgdb_break[i].bpt_addr; | 359 | error = kgdb_arch_remove_breakpoint(&kgdb_break[i]); |
| 364 | error = kgdb_arch_remove_breakpoint(addr, | ||
| 365 | kgdb_break[i].saved_instr); | ||
| 366 | if (error) | 360 | if (error) |
| 367 | printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n", | 361 | printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n", |
| 368 | addr); | 362 | kgdb_break[i].bpt_addr); |
| 369 | setundefined: | 363 | setundefined: |
| 370 | kgdb_break[i].state = BP_UNDEFINED; | 364 | kgdb_break[i].state = BP_UNDEFINED; |
| 371 | } | 365 | } |
