diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-01-08 17:04:20 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-01-08 17:04:20 -0500 |
commit | 9993b364d2c42acc2949ddbc6371405e17829e32 (patch) | |
tree | b9eb8126c46f08cf09d513f77a48a53e941b7a92 | |
parent | 82062e7b50280bcf0feca70ac35a44f375602976 (diff) | |
parent | b11e1eca7ed9c0b5dab21a62c11acc711d9bdda0 (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:
kgdb: Fix kernel-doc format error in kgdb.h
blackfin,kgdb: Do not put PC in gdb_regs into retx.
blackfin,kgdb,probe_kernel: Cleanup probe_kernel_read/write
maccess,probe_kernel: Allow arch specific override probe_kernel_(read|write)
-rw-r--r-- | arch/blackfin/kernel/kgdb.c | 207 | ||||
-rw-r--r-- | arch/blackfin/mm/Makefile | 2 | ||||
-rw-r--r-- | arch/blackfin/mm/maccess.c | 97 | ||||
-rw-r--r-- | include/linux/kgdb.h | 7 | ||||
-rw-r--r-- | include/linux/uaccess.h | 4 | ||||
-rw-r--r-- | mm/maccess.c | 11 |
6 files changed, 114 insertions, 214 deletions
diff --git a/arch/blackfin/kernel/kgdb.c b/arch/blackfin/kernel/kgdb.c index f1036b6b9293..34c7c3ed2c9c 100644 --- a/arch/blackfin/kernel/kgdb.c +++ b/arch/blackfin/kernel/kgdb.c | |||
@@ -6,23 +6,9 @@ | |||
6 | * Licensed under the GPL-2 or later. | 6 | * Licensed under the GPL-2 or later. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/string.h> | ||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/sched.h> | ||
12 | #include <linux/smp.h> | ||
13 | #include <linux/spinlock.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/ptrace.h> /* for linux pt_regs struct */ | 9 | #include <linux/ptrace.h> /* for linux pt_regs struct */ |
16 | #include <linux/kgdb.h> | 10 | #include <linux/kgdb.h> |
17 | #include <linux/console.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/irq.h> | ||
21 | #include <linux/uaccess.h> | 11 | #include <linux/uaccess.h> |
22 | #include <asm/system.h> | ||
23 | #include <asm/traps.h> | ||
24 | #include <asm/blackfin.h> | ||
25 | #include <asm/dma.h> | ||
26 | 12 | ||
27 | void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) | 13 | void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs) |
28 | { | 14 | { |
@@ -147,7 +133,7 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs) | |||
147 | regs->lb1 = gdb_regs[BFIN_LB1]; | 133 | regs->lb1 = gdb_regs[BFIN_LB1]; |
148 | regs->usp = gdb_regs[BFIN_USP]; | 134 | regs->usp = gdb_regs[BFIN_USP]; |
149 | regs->syscfg = gdb_regs[BFIN_SYSCFG]; | 135 | regs->syscfg = gdb_regs[BFIN_SYSCFG]; |
150 | regs->retx = gdb_regs[BFIN_PC]; | 136 | regs->retx = gdb_regs[BFIN_RETX]; |
151 | regs->retn = gdb_regs[BFIN_RETN]; | 137 | regs->retn = gdb_regs[BFIN_RETN]; |
152 | regs->rete = gdb_regs[BFIN_RETE]; | 138 | regs->rete = gdb_regs[BFIN_RETE]; |
153 | regs->pc = gdb_regs[BFIN_PC]; | 139 | regs->pc = gdb_regs[BFIN_PC]; |
@@ -424,182 +410,6 @@ struct kgdb_arch arch_kgdb_ops = { | |||
424 | .correct_hw_break = bfin_correct_hw_break, | 410 | .correct_hw_break = bfin_correct_hw_break, |
425 | }; | 411 | }; |
426 | 412 | ||
427 | static int hex(char ch) | ||
428 | { | ||
429 | if ((ch >= 'a') && (ch <= 'f')) | ||
430 | return ch - 'a' + 10; | ||
431 | if ((ch >= '0') && (ch <= '9')) | ||
432 | return ch - '0'; | ||
433 | if ((ch >= 'A') && (ch <= 'F')) | ||
434 | return ch - 'A' + 10; | ||
435 | return -1; | ||
436 | } | ||
437 | |||
438 | static int validate_memory_access_address(unsigned long addr, int size) | ||
439 | { | ||
440 | if (size < 0 || addr == 0) | ||
441 | return -EFAULT; | ||
442 | return bfin_mem_access_type(addr, size); | ||
443 | } | ||
444 | |||
445 | static int bfin_probe_kernel_read(char *dst, char *src, int size) | ||
446 | { | ||
447 | unsigned long lsrc = (unsigned long)src; | ||
448 | int mem_type; | ||
449 | |||
450 | mem_type = validate_memory_access_address(lsrc, size); | ||
451 | if (mem_type < 0) | ||
452 | return mem_type; | ||
453 | |||
454 | if (lsrc >= SYSMMR_BASE) { | ||
455 | if (size == 2 && lsrc % 2 == 0) { | ||
456 | u16 mmr = bfin_read16(src); | ||
457 | memcpy(dst, &mmr, sizeof(mmr)); | ||
458 | return 0; | ||
459 | } else if (size == 4 && lsrc % 4 == 0) { | ||
460 | u32 mmr = bfin_read32(src); | ||
461 | memcpy(dst, &mmr, sizeof(mmr)); | ||
462 | return 0; | ||
463 | } | ||
464 | } else { | ||
465 | switch (mem_type) { | ||
466 | case BFIN_MEM_ACCESS_CORE: | ||
467 | case BFIN_MEM_ACCESS_CORE_ONLY: | ||
468 | return probe_kernel_read(dst, src, size); | ||
469 | /* XXX: should support IDMA here with SMP */ | ||
470 | case BFIN_MEM_ACCESS_DMA: | ||
471 | if (dma_memcpy(dst, src, size)) | ||
472 | return 0; | ||
473 | break; | ||
474 | case BFIN_MEM_ACCESS_ITEST: | ||
475 | if (isram_memcpy(dst, src, size)) | ||
476 | return 0; | ||
477 | break; | ||
478 | } | ||
479 | } | ||
480 | |||
481 | return -EFAULT; | ||
482 | } | ||
483 | |||
484 | static int bfin_probe_kernel_write(char *dst, char *src, int size) | ||
485 | { | ||
486 | unsigned long ldst = (unsigned long)dst; | ||
487 | int mem_type; | ||
488 | |||
489 | mem_type = validate_memory_access_address(ldst, size); | ||
490 | if (mem_type < 0) | ||
491 | return mem_type; | ||
492 | |||
493 | if (ldst >= SYSMMR_BASE) { | ||
494 | if (size == 2 && ldst % 2 == 0) { | ||
495 | u16 mmr; | ||
496 | memcpy(&mmr, src, sizeof(mmr)); | ||
497 | bfin_write16(dst, mmr); | ||
498 | return 0; | ||
499 | } else if (size == 4 && ldst % 4 == 0) { | ||
500 | u32 mmr; | ||
501 | memcpy(&mmr, src, sizeof(mmr)); | ||
502 | bfin_write32(dst, mmr); | ||
503 | return 0; | ||
504 | } | ||
505 | } else { | ||
506 | switch (mem_type) { | ||
507 | case BFIN_MEM_ACCESS_CORE: | ||
508 | case BFIN_MEM_ACCESS_CORE_ONLY: | ||
509 | return probe_kernel_write(dst, src, size); | ||
510 | /* XXX: should support IDMA here with SMP */ | ||
511 | case BFIN_MEM_ACCESS_DMA: | ||
512 | if (dma_memcpy(dst, src, size)) | ||
513 | return 0; | ||
514 | break; | ||
515 | case BFIN_MEM_ACCESS_ITEST: | ||
516 | if (isram_memcpy(dst, src, size)) | ||
517 | return 0; | ||
518 | break; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | return -EFAULT; | ||
523 | } | ||
524 | |||
525 | /* | ||
526 | * Convert the memory pointed to by mem into hex, placing result in buf. | ||
527 | * Return a pointer to the last char put in buf (null). May return an error. | ||
528 | */ | ||
529 | int kgdb_mem2hex(char *mem, char *buf, int count) | ||
530 | { | ||
531 | char *tmp; | ||
532 | int err; | ||
533 | |||
534 | /* | ||
535 | * We use the upper half of buf as an intermediate buffer for the | ||
536 | * raw memory copy. Hex conversion will work against this one. | ||
537 | */ | ||
538 | tmp = buf + count; | ||
539 | |||
540 | err = bfin_probe_kernel_read(tmp, mem, count); | ||
541 | if (!err) { | ||
542 | while (count > 0) { | ||
543 | buf = pack_hex_byte(buf, *tmp); | ||
544 | tmp++; | ||
545 | count--; | ||
546 | } | ||
547 | |||
548 | *buf = 0; | ||
549 | } | ||
550 | |||
551 | return err; | ||
552 | } | ||
553 | |||
554 | /* | ||
555 | * Copy the binary array pointed to by buf into mem. Fix $, #, and | ||
556 | * 0x7d escaped with 0x7d. Return a pointer to the character after | ||
557 | * the last byte written. | ||
558 | */ | ||
559 | int kgdb_ebin2mem(char *buf, char *mem, int count) | ||
560 | { | ||
561 | char *tmp_old, *tmp_new; | ||
562 | int size; | ||
563 | |||
564 | tmp_old = tmp_new = buf; | ||
565 | |||
566 | for (size = 0; size < count; ++size) { | ||
567 | if (*tmp_old == 0x7d) | ||
568 | *tmp_new = *(++tmp_old) ^ 0x20; | ||
569 | else | ||
570 | *tmp_new = *tmp_old; | ||
571 | tmp_new++; | ||
572 | tmp_old++; | ||
573 | } | ||
574 | |||
575 | return bfin_probe_kernel_write(mem, buf, count); | ||
576 | } | ||
577 | |||
578 | /* | ||
579 | * Convert the hex array pointed to by buf into binary to be placed in mem. | ||
580 | * Return a pointer to the character AFTER the last byte written. | ||
581 | * May return an error. | ||
582 | */ | ||
583 | int kgdb_hex2mem(char *buf, char *mem, int count) | ||
584 | { | ||
585 | char *tmp_raw, *tmp_hex; | ||
586 | |||
587 | /* | ||
588 | * We use the upper half of buf as an intermediate buffer for the | ||
589 | * raw memory that is converted from hex. | ||
590 | */ | ||
591 | tmp_raw = buf + count * 2; | ||
592 | |||
593 | tmp_hex = tmp_raw - 1; | ||
594 | while (tmp_hex >= buf) { | ||
595 | tmp_raw--; | ||
596 | *tmp_raw = hex(*tmp_hex--); | ||
597 | *tmp_raw |= hex(*tmp_hex--) << 4; | ||
598 | } | ||
599 | |||
600 | return bfin_probe_kernel_write(mem, tmp_raw, count); | ||
601 | } | ||
602 | |||
603 | #define IN_MEM(addr, size, l1_addr, l1_size) \ | 413 | #define IN_MEM(addr, size, l1_addr, l1_size) \ |
604 | ({ \ | 414 | ({ \ |
605 | unsigned long __addr = (unsigned long)(addr); \ | 415 | unsigned long __addr = (unsigned long)(addr); \ |
@@ -629,21 +439,6 @@ int kgdb_validate_break_address(unsigned long addr) | |||
629 | return -EFAULT; | 439 | return -EFAULT; |
630 | } | 440 | } |
631 | 441 | ||
632 | int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr) | ||
633 | { | ||
634 | int err = bfin_probe_kernel_read(saved_instr, (char *)addr, | ||
635 | BREAK_INSTR_SIZE); | ||
636 | if (err) | ||
637 | return err; | ||
638 | return bfin_probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr, | ||
639 | BREAK_INSTR_SIZE); | ||
640 | } | ||
641 | |||
642 | int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle) | ||
643 | { | ||
644 | return bfin_probe_kernel_write((char *)addr, bundle, BREAK_INSTR_SIZE); | ||
645 | } | ||
646 | |||
647 | int kgdb_arch_init(void) | 442 | int kgdb_arch_init(void) |
648 | { | 443 | { |
649 | kgdb_single_step = 0; | 444 | kgdb_single_step = 0; |
diff --git a/arch/blackfin/mm/Makefile b/arch/blackfin/mm/Makefile index d489f894f4b1..4c011b1f661f 100644 --- a/arch/blackfin/mm/Makefile +++ b/arch/blackfin/mm/Makefile | |||
@@ -2,4 +2,4 @@ | |||
2 | # arch/blackfin/mm/Makefile | 2 | # arch/blackfin/mm/Makefile |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := sram-alloc.o isram-driver.o init.o | 5 | obj-y := sram-alloc.o isram-driver.o init.o maccess.o |
diff --git a/arch/blackfin/mm/maccess.c b/arch/blackfin/mm/maccess.c new file mode 100644 index 000000000000..b71cebc1f8a3 --- /dev/null +++ b/arch/blackfin/mm/maccess.c | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * safe read and write memory routines callable while atomic | ||
3 | * | ||
4 | * Copyright 2005-2008 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/uaccess.h> | ||
10 | #include <asm/dma.h> | ||
11 | |||
12 | static int validate_memory_access_address(unsigned long addr, int size) | ||
13 | { | ||
14 | if (size < 0 || addr == 0) | ||
15 | return -EFAULT; | ||
16 | return bfin_mem_access_type(addr, size); | ||
17 | } | ||
18 | |||
19 | long probe_kernel_read(void *dst, void *src, size_t size) | ||
20 | { | ||
21 | unsigned long lsrc = (unsigned long)src; | ||
22 | int mem_type; | ||
23 | |||
24 | mem_type = validate_memory_access_address(lsrc, size); | ||
25 | if (mem_type < 0) | ||
26 | return mem_type; | ||
27 | |||
28 | if (lsrc >= SYSMMR_BASE) { | ||
29 | if (size == 2 && lsrc % 2 == 0) { | ||
30 | u16 mmr = bfin_read16(src); | ||
31 | memcpy(dst, &mmr, sizeof(mmr)); | ||
32 | return 0; | ||
33 | } else if (size == 4 && lsrc % 4 == 0) { | ||
34 | u32 mmr = bfin_read32(src); | ||
35 | memcpy(dst, &mmr, sizeof(mmr)); | ||
36 | return 0; | ||
37 | } | ||
38 | } else { | ||
39 | switch (mem_type) { | ||
40 | case BFIN_MEM_ACCESS_CORE: | ||
41 | case BFIN_MEM_ACCESS_CORE_ONLY: | ||
42 | return __probe_kernel_read(dst, src, size); | ||
43 | /* XXX: should support IDMA here with SMP */ | ||
44 | case BFIN_MEM_ACCESS_DMA: | ||
45 | if (dma_memcpy(dst, src, size)) | ||
46 | return 0; | ||
47 | break; | ||
48 | case BFIN_MEM_ACCESS_ITEST: | ||
49 | if (isram_memcpy(dst, src, size)) | ||
50 | return 0; | ||
51 | break; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | return -EFAULT; | ||
56 | } | ||
57 | |||
58 | long probe_kernel_write(void *dst, void *src, size_t size) | ||
59 | { | ||
60 | unsigned long ldst = (unsigned long)dst; | ||
61 | int mem_type; | ||
62 | |||
63 | mem_type = validate_memory_access_address(ldst, size); | ||
64 | if (mem_type < 0) | ||
65 | return mem_type; | ||
66 | |||
67 | if (ldst >= SYSMMR_BASE) { | ||
68 | if (size == 2 && ldst % 2 == 0) { | ||
69 | u16 mmr; | ||
70 | memcpy(&mmr, src, sizeof(mmr)); | ||
71 | bfin_write16(dst, mmr); | ||
72 | return 0; | ||
73 | } else if (size == 4 && ldst % 4 == 0) { | ||
74 | u32 mmr; | ||
75 | memcpy(&mmr, src, sizeof(mmr)); | ||
76 | bfin_write32(dst, mmr); | ||
77 | return 0; | ||
78 | } | ||
79 | } else { | ||
80 | switch (mem_type) { | ||
81 | case BFIN_MEM_ACCESS_CORE: | ||
82 | case BFIN_MEM_ACCESS_CORE_ONLY: | ||
83 | return __probe_kernel_write(dst, src, size); | ||
84 | /* XXX: should support IDMA here with SMP */ | ||
85 | case BFIN_MEM_ACCESS_DMA: | ||
86 | if (dma_memcpy(dst, src, size)) | ||
87 | return 0; | ||
88 | break; | ||
89 | case BFIN_MEM_ACCESS_ITEST: | ||
90 | if (isram_memcpy(dst, src, size)) | ||
91 | return 0; | ||
92 | break; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | return -EFAULT; | ||
97 | } | ||
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index 6adcc297e354..19ec41a183f5 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h | |||
@@ -29,8 +29,7 @@ struct pt_regs; | |||
29 | * | 29 | * |
30 | * On some architectures it is required to skip a breakpoint | 30 | * On some architectures it is required to skip a breakpoint |
31 | * exception when it occurs after a breakpoint has been removed. | 31 | * exception when it occurs after a breakpoint has been removed. |
32 | * This can be implemented in the architecture specific portion of | 32 | * This can be implemented in the architecture specific portion of kgdb. |
33 | * for kgdb. | ||
34 | */ | 33 | */ |
35 | extern int kgdb_skipexception(int exception, struct pt_regs *regs); | 34 | extern int kgdb_skipexception(int exception, struct pt_regs *regs); |
36 | 35 | ||
@@ -65,7 +64,7 @@ struct uart_port; | |||
65 | /** | 64 | /** |
66 | * kgdb_breakpoint - compiled in breakpoint | 65 | * kgdb_breakpoint - compiled in breakpoint |
67 | * | 66 | * |
68 | * This will be impelmented a static inline per architecture. This | 67 | * This will be implemented as a static inline per architecture. This |
69 | * function is called by the kgdb core to execute an architecture | 68 | * function is called by the kgdb core to execute an architecture |
70 | * specific trap to cause kgdb to enter the exception processing. | 69 | * specific trap to cause kgdb to enter the exception processing. |
71 | * | 70 | * |
@@ -190,7 +189,7 @@ kgdb_arch_handle_exception(int vector, int signo, int err_code, | |||
190 | * @flags: Current IRQ state | 189 | * @flags: Current IRQ state |
191 | * | 190 | * |
192 | * On SMP systems, we need to get the attention of the other CPUs | 191 | * On SMP systems, we need to get the attention of the other CPUs |
193 | * and get them be in a known state. This should do what is needed | 192 | * and get them into a known state. This should do what is needed |
194 | * to get the other CPUs to call kgdb_wait(). Note that on some arches, | 193 | * to get the other CPUs to call kgdb_wait(). Note that on some arches, |
195 | * the NMI approach is not used for rounding up all the CPUs. For example, | 194 | * the NMI approach is not used for rounding up all the CPUs. For example, |
196 | * in case of MIPS, smp_call_function() is used to roundup CPUs. In | 195 | * in case of MIPS, smp_call_function() is used to roundup CPUs. In |
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h index 6b58367d145e..d512d98dfb7d 100644 --- a/include/linux/uaccess.h +++ b/include/linux/uaccess.h | |||
@@ -94,6 +94,7 @@ static inline unsigned long __copy_from_user_nocache(void *to, | |||
94 | * happens, handle that and return -EFAULT. | 94 | * happens, handle that and return -EFAULT. |
95 | */ | 95 | */ |
96 | extern long probe_kernel_read(void *dst, void *src, size_t size); | 96 | extern long probe_kernel_read(void *dst, void *src, size_t size); |
97 | extern long __probe_kernel_read(void *dst, void *src, size_t size); | ||
97 | 98 | ||
98 | /* | 99 | /* |
99 | * probe_kernel_write(): safely attempt to write to a location | 100 | * probe_kernel_write(): safely attempt to write to a location |
@@ -104,6 +105,7 @@ extern long probe_kernel_read(void *dst, void *src, size_t size); | |||
104 | * Safely write to address @dst from the buffer at @src. If a kernel fault | 105 | * Safely write to address @dst from the buffer at @src. If a kernel fault |
105 | * happens, handle that and return -EFAULT. | 106 | * happens, handle that and return -EFAULT. |
106 | */ | 107 | */ |
107 | extern long probe_kernel_write(void *dst, void *src, size_t size); | 108 | extern long notrace probe_kernel_write(void *dst, void *src, size_t size); |
109 | extern long notrace __probe_kernel_write(void *dst, void *src, size_t size); | ||
108 | 110 | ||
109 | #endif /* __LINUX_UACCESS_H__ */ | 111 | #endif /* __LINUX_UACCESS_H__ */ |
diff --git a/mm/maccess.c b/mm/maccess.c index 9073695ff25f..4e348dbaecd7 100644 --- a/mm/maccess.c +++ b/mm/maccess.c | |||
@@ -14,7 +14,11 @@ | |||
14 | * Safely read from address @src to the buffer at @dst. If a kernel fault | 14 | * Safely read from address @src to the buffer at @dst. If a kernel fault |
15 | * happens, handle that and return -EFAULT. | 15 | * happens, handle that and return -EFAULT. |
16 | */ | 16 | */ |
17 | long probe_kernel_read(void *dst, void *src, size_t size) | 17 | |
18 | long __weak probe_kernel_read(void *dst, void *src, size_t size) | ||
19 | __attribute__((alias("__probe_kernel_read"))); | ||
20 | |||
21 | long __probe_kernel_read(void *dst, void *src, size_t size) | ||
18 | { | 22 | { |
19 | long ret; | 23 | long ret; |
20 | mm_segment_t old_fs = get_fs(); | 24 | mm_segment_t old_fs = get_fs(); |
@@ -39,7 +43,10 @@ EXPORT_SYMBOL_GPL(probe_kernel_read); | |||
39 | * Safely write to address @dst from the buffer at @src. If a kernel fault | 43 | * Safely write to address @dst from the buffer at @src. If a kernel fault |
40 | * happens, handle that and return -EFAULT. | 44 | * happens, handle that and return -EFAULT. |
41 | */ | 45 | */ |
42 | long notrace __weak probe_kernel_write(void *dst, void *src, size_t size) | 46 | long __weak probe_kernel_write(void *dst, void *src, size_t size) |
47 | __attribute__((alias("__probe_kernel_write"))); | ||
48 | |||
49 | long __probe_kernel_write(void *dst, void *src, size_t size) | ||
43 | { | 50 | { |
44 | long ret; | 51 | long ret; |
45 | mm_segment_t old_fs = get_fs(); | 52 | mm_segment_t old_fs = get_fs(); |