diff options
author | Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> | 2009-04-07 16:34:16 -0400 |
---|---|---|
committer | Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> | 2009-04-07 16:34:16 -0400 |
commit | 38f4b8c0da01ae7cd9b93386842ce272d6fde9ab (patch) | |
tree | 3c8c52201aac038094bfea7efdd0984a8f62045e /arch/powerpc/kernel | |
parent | a811454027352c762e0d5bba1b1d8f7d26bf96ae (diff) | |
parent | 8e2c4f2844c0e8dcdfe312e5f2204854ca8532c6 (diff) |
Merge commit 'origin/master' into for-linus/xen/master
* commit 'origin/master': (4825 commits)
Fix build errors due to CONFIG_BRANCH_TRACER=y
parport: Use the PCI IRQ if offered
tty: jsm cleanups
Adjust path to gpio headers
KGDB_SERIAL_CONSOLE check for module
Change KCONFIG name
tty: Blackin CTS/RTS
Change hardware flow control from poll to interrupt driven
Add support for the MAX3100 SPI UART.
lanana: assign a device name and numbering for MAX3100
serqt: initial clean up pass for tty side
tty: Use the generic RS485 ioctl on CRIS
tty: Correct inline types for tty_driver_kref_get()
splice: fix deadlock in splicing to file
nilfs2: support nanosecond timestamp
nilfs2: introduce secondary super block
nilfs2: simplify handling of active state of segments
nilfs2: mark minor flag for checkpoint created by internal operation
nilfs2: clean up sketch file
nilfs2: super block operations fix endian bug
...
Conflicts:
arch/x86/include/asm/thread_info.h
arch/x86/lguest/boot.c
drivers/xen/manage.c
Diffstat (limited to 'arch/powerpc/kernel')
47 files changed, 997 insertions, 493 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 8d1a419df35d..71901fbda4a5 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -18,12 +18,10 @@ CFLAGS_REMOVE_cputable.o = -pg -mno-sched-epilog | |||
18 | CFLAGS_REMOVE_prom_init.o = -pg -mno-sched-epilog | 18 | CFLAGS_REMOVE_prom_init.o = -pg -mno-sched-epilog |
19 | CFLAGS_REMOVE_btext.o = -pg -mno-sched-epilog | 19 | CFLAGS_REMOVE_btext.o = -pg -mno-sched-epilog |
20 | CFLAGS_REMOVE_prom.o = -pg -mno-sched-epilog | 20 | CFLAGS_REMOVE_prom.o = -pg -mno-sched-epilog |
21 | 21 | # do not trace tracer code | |
22 | ifdef CONFIG_DYNAMIC_FTRACE | ||
23 | # dynamic ftrace setup. | ||
24 | CFLAGS_REMOVE_ftrace.o = -pg -mno-sched-epilog | 22 | CFLAGS_REMOVE_ftrace.o = -pg -mno-sched-epilog |
25 | endif | 23 | # timers used by tracing |
26 | 24 | CFLAGS_REMOVE_time.o = -pg -mno-sched-epilog | |
27 | endif | 25 | endif |
28 | 26 | ||
29 | obj-y := cputable.o ptrace.o syscalls.o \ | 27 | obj-y := cputable.o ptrace.o syscalls.o \ |
@@ -61,6 +59,7 @@ obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o \ | |||
61 | obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o | 59 | obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o |
62 | obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o | 60 | obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o |
63 | obj-$(CONFIG_44x) += cpu_setup_44x.o | 61 | obj-$(CONFIG_44x) += cpu_setup_44x.o |
62 | obj-$(CONFIG_FSL_BOOKE) += cpu_setup_fsl_booke.o dbell.o | ||
64 | 63 | ||
65 | extra-$(CONFIG_PPC_STD_MMU) := head_32.o | 64 | extra-$(CONFIG_PPC_STD_MMU) := head_32.o |
66 | extra-$(CONFIG_PPC64) := head_64.o | 65 | extra-$(CONFIG_PPC64) := head_64.o |
@@ -76,7 +75,7 @@ obj-y += time.o prom.o traps.o setup-common.o \ | |||
76 | obj-$(CONFIG_PPC32) += entry_32.o setup_32.o | 75 | obj-$(CONFIG_PPC32) += entry_32.o setup_32.o |
77 | obj-$(CONFIG_PPC64) += dma-iommu.o iommu.o | 76 | obj-$(CONFIG_PPC64) += dma-iommu.o iommu.o |
78 | obj-$(CONFIG_KGDB) += kgdb.o | 77 | obj-$(CONFIG_KGDB) += kgdb.o |
79 | obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o | 78 | obj-$(CONFIG_PPC_OF_BOOT_TRAMPOLINE) += prom_init.o |
80 | obj-$(CONFIG_MODULES) += ppc_ksyms.o | 79 | obj-$(CONFIG_MODULES) += ppc_ksyms.o |
81 | obj-$(CONFIG_BOOTX_TEXT) += btext.o | 80 | obj-$(CONFIG_BOOTX_TEXT) += btext.o |
82 | obj-$(CONFIG_SMP) += smp.o | 81 | obj-$(CONFIG_SMP) += smp.o |
@@ -94,6 +93,7 @@ obj-$(CONFIG_AUDIT) += audit.o | |||
94 | obj64-$(CONFIG_AUDIT) += compat_audit.o | 93 | obj64-$(CONFIG_AUDIT) += compat_audit.o |
95 | 94 | ||
96 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | 95 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o |
96 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o | ||
97 | 97 | ||
98 | obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o | 98 | obj-$(CONFIG_8XX_MINIMAL_FPEMU) += softemu8xx.o |
99 | 99 | ||
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index 73cb6a3229ae..5ffcfaa77d6a 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c | |||
@@ -187,7 +187,7 @@ static struct aligninfo aligninfo[128] = { | |||
187 | { 4, ST+F+S+U }, /* 11 1 1010: stfsux */ | 187 | { 4, ST+F+S+U }, /* 11 1 1010: stfsux */ |
188 | { 8, ST+F+U }, /* 11 1 1011: stfdux */ | 188 | { 8, ST+F+U }, /* 11 1 1011: stfdux */ |
189 | INVALID, /* 11 1 1100 */ | 189 | INVALID, /* 11 1 1100 */ |
190 | INVALID, /* 11 1 1101 */ | 190 | { 4, LD+F }, /* 11 1 1101: lfiwzx */ |
191 | INVALID, /* 11 1 1110 */ | 191 | INVALID, /* 11 1 1110 */ |
192 | INVALID, /* 11 1 1111 */ | 192 | INVALID, /* 11 1 1111 */ |
193 | }; | 193 | }; |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 42fe4da4e8ae..1e40bc053946 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -284,9 +284,6 @@ int main(void) | |||
284 | #endif /* ! CONFIG_PPC64 */ | 284 | #endif /* ! CONFIG_PPC64 */ |
285 | 285 | ||
286 | /* About the CPU features table */ | 286 | /* About the CPU features table */ |
287 | DEFINE(CPU_SPEC_ENTRY_SIZE, sizeof(struct cpu_spec)); | ||
288 | DEFINE(CPU_SPEC_PVR_MASK, offsetof(struct cpu_spec, pvr_mask)); | ||
289 | DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value)); | ||
290 | DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); | 287 | DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); |
291 | DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); | 288 | DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); |
292 | DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore)); | 289 | DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore)); |
diff --git a/arch/powerpc/kernel/cpu_setup_44x.S b/arch/powerpc/kernel/cpu_setup_44x.S index 10b4ab1008af..7d606f89a839 100644 --- a/arch/powerpc/kernel/cpu_setup_44x.S +++ b/arch/powerpc/kernel/cpu_setup_44x.S | |||
@@ -34,6 +34,7 @@ _GLOBAL(__setup_cpu_440grx) | |||
34 | blr | 34 | blr |
35 | _GLOBAL(__setup_cpu_460ex) | 35 | _GLOBAL(__setup_cpu_460ex) |
36 | _GLOBAL(__setup_cpu_460gt) | 36 | _GLOBAL(__setup_cpu_460gt) |
37 | _GLOBAL(__setup_cpu_460sx) | ||
37 | mflr r4 | 38 | mflr r4 |
38 | bl __init_fpu_44x | 39 | bl __init_fpu_44x |
39 | bl __fixup_440A_mcheck | 40 | bl __fixup_440A_mcheck |
diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S index 72d1d7395254..54f767e31a1a 100644 --- a/arch/powerpc/kernel/cpu_setup_6xx.S +++ b/arch/powerpc/kernel/cpu_setup_6xx.S | |||
@@ -15,9 +15,14 @@ | |||
15 | #include <asm/ppc_asm.h> | 15 | #include <asm/ppc_asm.h> |
16 | #include <asm/asm-offsets.h> | 16 | #include <asm/asm-offsets.h> |
17 | #include <asm/cache.h> | 17 | #include <asm/cache.h> |
18 | #include <asm/mmu.h> | ||
18 | 19 | ||
19 | _GLOBAL(__setup_cpu_603) | 20 | _GLOBAL(__setup_cpu_603) |
20 | mflr r4 | 21 | mflr r4 |
22 | BEGIN_MMU_FTR_SECTION | ||
23 | li r10,0 | ||
24 | mtspr SPRN_SPRG4,r10 /* init SW LRU tracking */ | ||
25 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU) | ||
21 | BEGIN_FTR_SECTION | 26 | BEGIN_FTR_SECTION |
22 | bl __init_fpu_registers | 27 | bl __init_fpu_registers |
23 | END_FTR_SECTION_IFCLR(CPU_FTR_FPU_UNAVAILABLE) | 28 | END_FTR_SECTION_IFCLR(CPU_FTR_FPU_UNAVAILABLE) |
diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S new file mode 100644 index 000000000000..eb4b9adcedb4 --- /dev/null +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * This file contains low level CPU setup functions. | ||
3 | * Kumar Gala <galak@kernel.crashing.org> | ||
4 | * Copyright 2009 Freescale Semiconductor, Inc. | ||
5 | * | ||
6 | * Based on cpu_setup_6xx code by | ||
7 | * Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version | ||
12 | * 2 of the License, or (at your option) any later version. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <asm/processor.h> | ||
17 | #include <asm/cputable.h> | ||
18 | #include <asm/ppc_asm.h> | ||
19 | |||
20 | _GLOBAL(__setup_cpu_e200) | ||
21 | /* enable dedicated debug exception handling resources (Debug APU) */ | ||
22 | mfspr r3,SPRN_HID0 | ||
23 | ori r3,r3,HID0_DAPUEN@l | ||
24 | mtspr SPRN_HID0,r3 | ||
25 | b __setup_e200_ivors | ||
26 | _GLOBAL(__setup_cpu_e500v1) | ||
27 | _GLOBAL(__setup_cpu_e500v2) | ||
28 | b __setup_e500_ivors | ||
29 | _GLOBAL(__setup_cpu_e500mc) | ||
30 | b __setup_e500mc_ivors | ||
31 | |||
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 923f87aff20a..cd1b687544f3 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -35,6 +35,10 @@ const char *powerpc_base_platform; | |||
35 | * and ppc64 | 35 | * and ppc64 |
36 | */ | 36 | */ |
37 | #ifdef CONFIG_PPC32 | 37 | #ifdef CONFIG_PPC32 |
38 | extern void __setup_cpu_e200(unsigned long offset, struct cpu_spec* spec); | ||
39 | extern void __setup_cpu_e500v1(unsigned long offset, struct cpu_spec* spec); | ||
40 | extern void __setup_cpu_e500v2(unsigned long offset, struct cpu_spec* spec); | ||
41 | extern void __setup_cpu_e500mc(unsigned long offset, struct cpu_spec* spec); | ||
38 | extern void __setup_cpu_440ep(unsigned long offset, struct cpu_spec* spec); | 42 | extern void __setup_cpu_440ep(unsigned long offset, struct cpu_spec* spec); |
39 | extern void __setup_cpu_440epx(unsigned long offset, struct cpu_spec* spec); | 43 | extern void __setup_cpu_440epx(unsigned long offset, struct cpu_spec* spec); |
40 | extern void __setup_cpu_440gx(unsigned long offset, struct cpu_spec* spec); | 44 | extern void __setup_cpu_440gx(unsigned long offset, struct cpu_spec* spec); |
@@ -43,6 +47,7 @@ extern void __setup_cpu_440spe(unsigned long offset, struct cpu_spec* spec); | |||
43 | extern void __setup_cpu_440x5(unsigned long offset, struct cpu_spec* spec); | 47 | extern void __setup_cpu_440x5(unsigned long offset, struct cpu_spec* spec); |
44 | extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec); | 48 | extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec); |
45 | extern void __setup_cpu_460gt(unsigned long offset, struct cpu_spec* spec); | 49 | extern void __setup_cpu_460gt(unsigned long offset, struct cpu_spec* spec); |
50 | extern void __setup_cpu_460sx(unsigned long offset, struct cpu_spec *spec); | ||
46 | extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec); | 51 | extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec); |
47 | extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec); | 52 | extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec); |
48 | extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec); | 53 | extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec); |
@@ -726,6 +731,8 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
726 | .cpu_setup = __setup_cpu_750, | 731 | .cpu_setup = __setup_cpu_750, |
727 | .machine_check = machine_check_generic, | 732 | .machine_check = machine_check_generic, |
728 | .platform = "ppc750", | 733 | .platform = "ppc750", |
734 | .oprofile_cpu_type = "ppc/750", | ||
735 | .oprofile_type = PPC_OPROFILE_G4, | ||
729 | }, | 736 | }, |
730 | { /* 750FX rev 2.0 must disable HID0[DPM] */ | 737 | { /* 750FX rev 2.0 must disable HID0[DPM] */ |
731 | .pvr_mask = 0xffffffff, | 738 | .pvr_mask = 0xffffffff, |
@@ -741,6 +748,8 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
741 | .cpu_setup = __setup_cpu_750, | 748 | .cpu_setup = __setup_cpu_750, |
742 | .machine_check = machine_check_generic, | 749 | .machine_check = machine_check_generic, |
743 | .platform = "ppc750", | 750 | .platform = "ppc750", |
751 | .oprofile_cpu_type = "ppc/750", | ||
752 | .oprofile_type = PPC_OPROFILE_G4, | ||
744 | }, | 753 | }, |
745 | { /* 750FX (All revs except 2.0) */ | 754 | { /* 750FX (All revs except 2.0) */ |
746 | .pvr_mask = 0xffff0000, | 755 | .pvr_mask = 0xffff0000, |
@@ -756,6 +765,8 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
756 | .cpu_setup = __setup_cpu_750fx, | 765 | .cpu_setup = __setup_cpu_750fx, |
757 | .machine_check = machine_check_generic, | 766 | .machine_check = machine_check_generic, |
758 | .platform = "ppc750", | 767 | .platform = "ppc750", |
768 | .oprofile_cpu_type = "ppc/750", | ||
769 | .oprofile_type = PPC_OPROFILE_G4, | ||
759 | }, | 770 | }, |
760 | { /* 750GX */ | 771 | { /* 750GX */ |
761 | .pvr_mask = 0xffff0000, | 772 | .pvr_mask = 0xffff0000, |
@@ -771,6 +782,8 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
771 | .cpu_setup = __setup_cpu_750fx, | 782 | .cpu_setup = __setup_cpu_750fx, |
772 | .machine_check = machine_check_generic, | 783 | .machine_check = machine_check_generic, |
773 | .platform = "ppc750", | 784 | .platform = "ppc750", |
785 | .oprofile_cpu_type = "ppc/750", | ||
786 | .oprofile_type = PPC_OPROFILE_G4, | ||
774 | }, | 787 | }, |
775 | { /* 740/750 (L2CR bit need fixup for 740) */ | 788 | { /* 740/750 (L2CR bit need fixup for 740) */ |
776 | .pvr_mask = 0xffff0000, | 789 | .pvr_mask = 0xffff0000, |
@@ -1077,7 +1090,8 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1077 | .cpu_name = "e300c2", | 1090 | .cpu_name = "e300c2", |
1078 | .cpu_features = CPU_FTRS_E300C2, | 1091 | .cpu_features = CPU_FTRS_E300C2, |
1079 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, | 1092 | .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, |
1080 | .mmu_features = MMU_FTR_USE_HIGH_BATS, | 1093 | .mmu_features = MMU_FTR_USE_HIGH_BATS | |
1094 | MMU_FTR_NEED_DTLB_SW_LRU, | ||
1081 | .icache_bsize = 32, | 1095 | .icache_bsize = 32, |
1082 | .dcache_bsize = 32, | 1096 | .dcache_bsize = 32, |
1083 | .cpu_setup = __setup_cpu_603, | 1097 | .cpu_setup = __setup_cpu_603, |
@@ -1090,7 +1104,8 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1090 | .cpu_name = "e300c3", | 1104 | .cpu_name = "e300c3", |
1091 | .cpu_features = CPU_FTRS_E300, | 1105 | .cpu_features = CPU_FTRS_E300, |
1092 | .cpu_user_features = COMMON_USER, | 1106 | .cpu_user_features = COMMON_USER, |
1093 | .mmu_features = MMU_FTR_USE_HIGH_BATS, | 1107 | .mmu_features = MMU_FTR_USE_HIGH_BATS | |
1108 | MMU_FTR_NEED_DTLB_SW_LRU, | ||
1094 | .icache_bsize = 32, | 1109 | .icache_bsize = 32, |
1095 | .dcache_bsize = 32, | 1110 | .dcache_bsize = 32, |
1096 | .cpu_setup = __setup_cpu_603, | 1111 | .cpu_setup = __setup_cpu_603, |
@@ -1105,7 +1120,8 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1105 | .cpu_name = "e300c4", | 1120 | .cpu_name = "e300c4", |
1106 | .cpu_features = CPU_FTRS_E300, | 1121 | .cpu_features = CPU_FTRS_E300, |
1107 | .cpu_user_features = COMMON_USER, | 1122 | .cpu_user_features = COMMON_USER, |
1108 | .mmu_features = MMU_FTR_USE_HIGH_BATS, | 1123 | .mmu_features = MMU_FTR_USE_HIGH_BATS | |
1124 | MMU_FTR_NEED_DTLB_SW_LRU, | ||
1109 | .icache_bsize = 32, | 1125 | .icache_bsize = 32, |
1110 | .dcache_bsize = 32, | 1126 | .dcache_bsize = 32, |
1111 | .cpu_setup = __setup_cpu_603, | 1127 | .cpu_setup = __setup_cpu_603, |
@@ -1634,6 +1650,19 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1634 | .machine_check = machine_check_440A, | 1650 | .machine_check = machine_check_440A, |
1635 | .platform = "ppc440", | 1651 | .platform = "ppc440", |
1636 | }, | 1652 | }, |
1653 | { /* 460SX */ | ||
1654 | .pvr_mask = 0xffffff00, | ||
1655 | .pvr_value = 0x13541800, | ||
1656 | .cpu_name = "460SX", | ||
1657 | .cpu_features = CPU_FTRS_44X, | ||
1658 | .cpu_user_features = COMMON_USER_BOOKE, | ||
1659 | .mmu_features = MMU_FTR_TYPE_44x, | ||
1660 | .icache_bsize = 32, | ||
1661 | .dcache_bsize = 32, | ||
1662 | .cpu_setup = __setup_cpu_460sx, | ||
1663 | .machine_check = machine_check_440A, | ||
1664 | .platform = "ppc440", | ||
1665 | }, | ||
1637 | { /* default match */ | 1666 | { /* default match */ |
1638 | .pvr_mask = 0x00000000, | 1667 | .pvr_mask = 0x00000000, |
1639 | .pvr_value = 0x00000000, | 1668 | .pvr_value = 0x00000000, |
@@ -1687,6 +1716,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1687 | PPC_FEATURE_UNIFIED_CACHE, | 1716 | PPC_FEATURE_UNIFIED_CACHE, |
1688 | .mmu_features = MMU_FTR_TYPE_FSL_E, | 1717 | .mmu_features = MMU_FTR_TYPE_FSL_E, |
1689 | .dcache_bsize = 32, | 1718 | .dcache_bsize = 32, |
1719 | .cpu_setup = __setup_cpu_e200, | ||
1690 | .machine_check = machine_check_e200, | 1720 | .machine_check = machine_check_e200, |
1691 | .platform = "ppc5554", | 1721 | .platform = "ppc5554", |
1692 | } | 1722 | } |
@@ -1706,6 +1736,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1706 | .num_pmcs = 4, | 1736 | .num_pmcs = 4, |
1707 | .oprofile_cpu_type = "ppc/e500", | 1737 | .oprofile_cpu_type = "ppc/e500", |
1708 | .oprofile_type = PPC_OPROFILE_FSL_EMB, | 1738 | .oprofile_type = PPC_OPROFILE_FSL_EMB, |
1739 | .cpu_setup = __setup_cpu_e500v1, | ||
1709 | .machine_check = machine_check_e500, | 1740 | .machine_check = machine_check_e500, |
1710 | .platform = "ppc8540", | 1741 | .platform = "ppc8540", |
1711 | }, | 1742 | }, |
@@ -1724,6 +1755,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1724 | .num_pmcs = 4, | 1755 | .num_pmcs = 4, |
1725 | .oprofile_cpu_type = "ppc/e500", | 1756 | .oprofile_cpu_type = "ppc/e500", |
1726 | .oprofile_type = PPC_OPROFILE_FSL_EMB, | 1757 | .oprofile_type = PPC_OPROFILE_FSL_EMB, |
1758 | .cpu_setup = __setup_cpu_e500v2, | ||
1727 | .machine_check = machine_check_e500, | 1759 | .machine_check = machine_check_e500, |
1728 | .platform = "ppc8548", | 1760 | .platform = "ppc8548", |
1729 | }, | 1761 | }, |
@@ -1733,12 +1765,14 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1733 | .cpu_name = "e500mc", | 1765 | .cpu_name = "e500mc", |
1734 | .cpu_features = CPU_FTRS_E500MC, | 1766 | .cpu_features = CPU_FTRS_E500MC, |
1735 | .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, | 1767 | .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, |
1736 | .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS, | 1768 | .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS | |
1769 | MMU_FTR_USE_TLBILX, | ||
1737 | .icache_bsize = 64, | 1770 | .icache_bsize = 64, |
1738 | .dcache_bsize = 64, | 1771 | .dcache_bsize = 64, |
1739 | .num_pmcs = 4, | 1772 | .num_pmcs = 4, |
1740 | .oprofile_cpu_type = "ppc/e500", /* xxx - galak, e500mc? */ | 1773 | .oprofile_cpu_type = "ppc/e500", /* xxx - galak, e500mc? */ |
1741 | .oprofile_type = PPC_OPROFILE_FSL_EMB, | 1774 | .oprofile_type = PPC_OPROFILE_FSL_EMB, |
1775 | .cpu_setup = __setup_cpu_e500mc, | ||
1742 | .machine_check = machine_check_e500, | 1776 | .machine_check = machine_check_e500, |
1743 | .platform = "ppce500mc", | 1777 | .platform = "ppce500mc", |
1744 | }, | 1778 | }, |
@@ -1762,74 +1796,84 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1762 | 1796 | ||
1763 | static struct cpu_spec the_cpu_spec; | 1797 | static struct cpu_spec the_cpu_spec; |
1764 | 1798 | ||
1765 | struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr) | 1799 | static void __init setup_cpu_spec(unsigned long offset, struct cpu_spec *s) |
1766 | { | 1800 | { |
1767 | struct cpu_spec *s = cpu_specs; | ||
1768 | struct cpu_spec *t = &the_cpu_spec; | 1801 | struct cpu_spec *t = &the_cpu_spec; |
1769 | int i; | 1802 | struct cpu_spec old; |
1770 | 1803 | ||
1771 | s = PTRRELOC(s); | ||
1772 | t = PTRRELOC(t); | 1804 | t = PTRRELOC(t); |
1805 | old = *t; | ||
1773 | 1806 | ||
1774 | for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) | 1807 | /* Copy everything, then do fixups */ |
1775 | if ((pvr & s->pvr_mask) == s->pvr_value) { | 1808 | *t = *s; |
1776 | /* | 1809 | |
1777 | * If we are overriding a previous value derived | 1810 | /* |
1778 | * from the real PVR with a new value obtained | 1811 | * If we are overriding a previous value derived from the real |
1779 | * using a logical PVR value, don't modify the | 1812 | * PVR with a new value obtained using a logical PVR value, |
1780 | * performance monitor fields. | 1813 | * don't modify the performance monitor fields. |
1781 | */ | 1814 | */ |
1782 | if (t->num_pmcs && !s->num_pmcs) { | 1815 | if (old.num_pmcs && !s->num_pmcs) { |
1783 | t->cpu_name = s->cpu_name; | 1816 | t->num_pmcs = old.num_pmcs; |
1784 | t->cpu_features = s->cpu_features; | 1817 | t->pmc_type = old.pmc_type; |
1785 | t->cpu_user_features = s->cpu_user_features; | 1818 | t->oprofile_type = old.oprofile_type; |
1786 | t->icache_bsize = s->icache_bsize; | 1819 | t->oprofile_mmcra_sihv = old.oprofile_mmcra_sihv; |
1787 | t->dcache_bsize = s->dcache_bsize; | 1820 | t->oprofile_mmcra_sipr = old.oprofile_mmcra_sipr; |
1788 | t->cpu_setup = s->cpu_setup; | 1821 | t->oprofile_mmcra_clear = old.oprofile_mmcra_clear; |
1789 | t->cpu_restore = s->cpu_restore; | 1822 | |
1790 | t->platform = s->platform; | 1823 | /* |
1791 | /* | 1824 | * If we have passed through this logic once before and |
1792 | * If we have passed through this logic once | 1825 | * have pulled the default case because the real PVR was |
1793 | * before and have pulled the default case | 1826 | * not found inside cpu_specs[], then we are possibly |
1794 | * because the real PVR was not found inside | 1827 | * running in compatibility mode. In that case, let the |
1795 | * cpu_specs[], then we are possibly running in | 1828 | * oprofiler know which set of compatibility counters to |
1796 | * compatibility mode. In that case, let the | 1829 | * pull from by making sure the oprofile_cpu_type string |
1797 | * oprofiler know which set of compatibility | 1830 | * is set to that of compatibility mode. If the |
1798 | * counters to pull from by making sure the | 1831 | * oprofile_cpu_type already has a value, then we are |
1799 | * oprofile_cpu_type string is set to that of | 1832 | * possibly overriding a real PVR with a logical one, |
1800 | * compatibility mode. If the oprofile_cpu_type | 1833 | * and, in that case, keep the current value for |
1801 | * already has a value, then we are possibly | 1834 | * oprofile_cpu_type. |
1802 | * overriding a real PVR with a logical one, and, | 1835 | */ |
1803 | * in that case, keep the current value for | 1836 | if (old.oprofile_cpu_type == NULL) |
1804 | * oprofile_cpu_type. | 1837 | t->oprofile_cpu_type = s->oprofile_cpu_type; |
1805 | */ | 1838 | } |
1806 | if (t->oprofile_cpu_type == NULL) | ||
1807 | t->oprofile_cpu_type = s->oprofile_cpu_type; | ||
1808 | } else | ||
1809 | *t = *s; | ||
1810 | *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec; | ||
1811 | 1839 | ||
1812 | /* | 1840 | *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec; |
1813 | * Set the base platform string once; assumes | 1841 | |
1814 | * we're called with real pvr first. | 1842 | /* |
1815 | */ | 1843 | * Set the base platform string once; assumes |
1816 | if (*PTRRELOC(&powerpc_base_platform) == NULL) | 1844 | * we're called with real pvr first. |
1817 | *PTRRELOC(&powerpc_base_platform) = t->platform; | 1845 | */ |
1846 | if (*PTRRELOC(&powerpc_base_platform) == NULL) | ||
1847 | *PTRRELOC(&powerpc_base_platform) = t->platform; | ||
1818 | 1848 | ||
1819 | #if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE) | 1849 | #if defined(CONFIG_PPC64) || defined(CONFIG_BOOKE) |
1820 | /* ppc64 and booke expect identify_cpu to also call | 1850 | /* ppc64 and booke expect identify_cpu to also call setup_cpu for |
1821 | * setup_cpu for that processor. I will consolidate | 1851 | * that processor. I will consolidate that at a later time, for now, |
1822 | * that at a later time, for now, just use #ifdef. | 1852 | * just use #ifdef. We also don't need to PTRRELOC the function |
1823 | * we also don't need to PTRRELOC the function pointer | 1853 | * pointer on ppc64 and booke as we are running at 0 in real mode |
1824 | * on ppc64 and booke as we are running at 0 in real | 1854 | * on ppc64 and reloc_offset is always 0 on booke. |
1825 | * mode on ppc64 and reloc_offset is always 0 on booke. | 1855 | */ |
1826 | */ | 1856 | if (s->cpu_setup) { |
1827 | if (s->cpu_setup) { | 1857 | s->cpu_setup(offset, s); |
1828 | s->cpu_setup(offset, s); | 1858 | } |
1829 | } | ||
1830 | #endif /* CONFIG_PPC64 || CONFIG_BOOKE */ | 1859 | #endif /* CONFIG_PPC64 || CONFIG_BOOKE */ |
1860 | } | ||
1861 | |||
1862 | struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr) | ||
1863 | { | ||
1864 | struct cpu_spec *s = cpu_specs; | ||
1865 | int i; | ||
1866 | |||
1867 | s = PTRRELOC(s); | ||
1868 | |||
1869 | for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) { | ||
1870 | if ((pvr & s->pvr_mask) == s->pvr_value) { | ||
1871 | setup_cpu_spec(offset, s); | ||
1831 | return s; | 1872 | return s; |
1832 | } | 1873 | } |
1874 | } | ||
1875 | |||
1833 | BUG(); | 1876 | BUG(); |
1877 | |||
1834 | return NULL; | 1878 | return NULL; |
1835 | } | 1879 | } |
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 19671aca6591..5fb667a60894 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c | |||
@@ -48,7 +48,7 @@ static void __init create_trampoline(unsigned long addr) | |||
48 | * branch to "addr" we jump to ("addr" + 32 MB). Although it requires | 48 | * branch to "addr" we jump to ("addr" + 32 MB). Although it requires |
49 | * two instructions it doesn't require any registers. | 49 | * two instructions it doesn't require any registers. |
50 | */ | 50 | */ |
51 | patch_instruction(p, PPC_NOP_INSTR); | 51 | patch_instruction(p, PPC_INST_NOP); |
52 | patch_branch(++p, addr + PHYSICAL_START, 0); | 52 | patch_branch(++p, addr + PHYSICAL_START, 0); |
53 | } | 53 | } |
54 | 54 | ||
diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c new file mode 100644 index 000000000000..1493734cd871 --- /dev/null +++ b/arch/powerpc/kernel/dbell.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Author: Kumar Gala <galak@kernel.crashing.org> | ||
3 | * | ||
4 | * Copyright 2009 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/stddef.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/smp.h> | ||
15 | #include <linux/threads.h> | ||
16 | |||
17 | #include <asm/dbell.h> | ||
18 | |||
19 | #ifdef CONFIG_SMP | ||
20 | unsigned long dbell_smp_message[NR_CPUS]; | ||
21 | |||
22 | void smp_dbell_message_pass(int target, int msg) | ||
23 | { | ||
24 | int i; | ||
25 | |||
26 | if(target < NR_CPUS) { | ||
27 | set_bit(msg, &dbell_smp_message[target]); | ||
28 | ppc_msgsnd(PPC_DBELL, 0, target); | ||
29 | } | ||
30 | else if(target == MSG_ALL_BUT_SELF) { | ||
31 | for_each_online_cpu(i) { | ||
32 | if (i == smp_processor_id()) | ||
33 | continue; | ||
34 | set_bit(msg, &dbell_smp_message[i]); | ||
35 | ppc_msgsnd(PPC_DBELL, 0, i); | ||
36 | } | ||
37 | } | ||
38 | else { /* target == MSG_ALL */ | ||
39 | for_each_online_cpu(i) | ||
40 | set_bit(msg, &dbell_smp_message[i]); | ||
41 | ppc_msgsnd(PPC_DBELL, PPC_DBELL_MSG_BRDCAST, 0); | ||
42 | } | ||
43 | } | ||
44 | #endif | ||
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c index 1c5c8a6fc129..53c7788cba78 100644 --- a/arch/powerpc/kernel/dma.c +++ b/arch/powerpc/kernel/dma.c | |||
@@ -94,7 +94,7 @@ static int dma_direct_dma_supported(struct device *dev, u64 mask) | |||
94 | * done via some global so platforms can set the limit in case | 94 | * done via some global so platforms can set the limit in case |
95 | * they have limited DMA windows | 95 | * they have limited DMA windows |
96 | */ | 96 | */ |
97 | return mask >= DMA_32BIT_MASK; | 97 | return mask >= DMA_BIT_MASK(32); |
98 | #else | 98 | #else |
99 | return 1; | 99 | return 1; |
100 | #endif | 100 | #endif |
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 6f7eb7e00c79..4dd38f129153 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -63,7 +63,7 @@ debug_transfer_to_handler: | |||
63 | 63 | ||
64 | .globl crit_transfer_to_handler | 64 | .globl crit_transfer_to_handler |
65 | crit_transfer_to_handler: | 65 | crit_transfer_to_handler: |
66 | #ifdef CONFIG_FSL_BOOKE | 66 | #ifdef CONFIG_PPC_BOOK3E_MMU |
67 | mfspr r0,SPRN_MAS0 | 67 | mfspr r0,SPRN_MAS0 |
68 | stw r0,MAS0(r11) | 68 | stw r0,MAS0(r11) |
69 | mfspr r0,SPRN_MAS1 | 69 | mfspr r0,SPRN_MAS1 |
@@ -78,7 +78,7 @@ crit_transfer_to_handler: | |||
78 | mfspr r0,SPRN_MAS7 | 78 | mfspr r0,SPRN_MAS7 |
79 | stw r0,MAS7(r11) | 79 | stw r0,MAS7(r11) |
80 | #endif /* CONFIG_PHYS_64BIT */ | 80 | #endif /* CONFIG_PHYS_64BIT */ |
81 | #endif /* CONFIG_FSL_BOOKE */ | 81 | #endif /* CONFIG_PPC_BOOK3E_MMU */ |
82 | #ifdef CONFIG_44x | 82 | #ifdef CONFIG_44x |
83 | mfspr r0,SPRN_MMUCR | 83 | mfspr r0,SPRN_MMUCR |
84 | stw r0,MMUCR(r11) | 84 | stw r0,MMUCR(r11) |
@@ -914,7 +914,7 @@ exc_exit_restart_end: | |||
914 | mtspr SPRN_##exc_lvl_srr0,r9; \ | 914 | mtspr SPRN_##exc_lvl_srr0,r9; \ |
915 | mtspr SPRN_##exc_lvl_srr1,r10; | 915 | mtspr SPRN_##exc_lvl_srr1,r10; |
916 | 916 | ||
917 | #if defined(CONFIG_FSL_BOOKE) | 917 | #if defined(CONFIG_PPC_BOOK3E_MMU) |
918 | #ifdef CONFIG_PHYS_64BIT | 918 | #ifdef CONFIG_PHYS_64BIT |
919 | #define RESTORE_MAS7 \ | 919 | #define RESTORE_MAS7 \ |
920 | lwz r11,MAS7(r1); \ | 920 | lwz r11,MAS7(r1); \ |
@@ -956,7 +956,7 @@ ret_from_crit_exc: | |||
956 | lwz r10,crit_srr1@l(r10); | 956 | lwz r10,crit_srr1@l(r10); |
957 | mtspr SPRN_SRR0,r9; | 957 | mtspr SPRN_SRR0,r9; |
958 | mtspr SPRN_SRR1,r10; | 958 | mtspr SPRN_SRR1,r10; |
959 | RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI) | 959 | RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, PPC_RFCI) |
960 | #endif /* CONFIG_40x */ | 960 | #endif /* CONFIG_40x */ |
961 | 961 | ||
962 | #ifdef CONFIG_BOOKE | 962 | #ifdef CONFIG_BOOKE |
@@ -967,7 +967,7 @@ ret_from_crit_exc: | |||
967 | stw r10,KSP_LIMIT(r9) | 967 | stw r10,KSP_LIMIT(r9) |
968 | RESTORE_xSRR(SRR0,SRR1); | 968 | RESTORE_xSRR(SRR0,SRR1); |
969 | RESTORE_MMU_REGS; | 969 | RESTORE_MMU_REGS; |
970 | RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI) | 970 | RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, PPC_RFCI) |
971 | 971 | ||
972 | .globl ret_from_debug_exc | 972 | .globl ret_from_debug_exc |
973 | ret_from_debug_exc: | 973 | ret_from_debug_exc: |
@@ -981,7 +981,7 @@ ret_from_debug_exc: | |||
981 | RESTORE_xSRR(SRR0,SRR1); | 981 | RESTORE_xSRR(SRR0,SRR1); |
982 | RESTORE_xSRR(CSRR0,CSRR1); | 982 | RESTORE_xSRR(CSRR0,CSRR1); |
983 | RESTORE_MMU_REGS; | 983 | RESTORE_MMU_REGS; |
984 | RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, RFDI) | 984 | RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, PPC_RFDI) |
985 | 985 | ||
986 | .globl ret_from_mcheck_exc | 986 | .globl ret_from_mcheck_exc |
987 | ret_from_mcheck_exc: | 987 | ret_from_mcheck_exc: |
@@ -992,7 +992,7 @@ ret_from_mcheck_exc: | |||
992 | RESTORE_xSRR(CSRR0,CSRR1); | 992 | RESTORE_xSRR(CSRR0,CSRR1); |
993 | RESTORE_xSRR(DSRR0,DSRR1); | 993 | RESTORE_xSRR(DSRR0,DSRR1); |
994 | RESTORE_MMU_REGS; | 994 | RESTORE_MMU_REGS; |
995 | RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, RFMCI) | 995 | RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, PPC_RFMCI) |
996 | #endif /* CONFIG_BOOKE */ | 996 | #endif /* CONFIG_BOOKE */ |
997 | 997 | ||
998 | /* | 998 | /* |
@@ -1176,59 +1176,27 @@ _GLOBAL(_mcount) | |||
1176 | bctr | 1176 | bctr |
1177 | 1177 | ||
1178 | _GLOBAL(ftrace_caller) | 1178 | _GLOBAL(ftrace_caller) |
1179 | /* Based off of objdump optput from glibc */ | 1179 | MCOUNT_SAVE_FRAME |
1180 | stwu r1,-48(r1) | 1180 | /* r3 ends up with link register */ |
1181 | stw r3, 12(r1) | ||
1182 | stw r4, 16(r1) | ||
1183 | stw r5, 20(r1) | ||
1184 | stw r6, 24(r1) | ||
1185 | mflr r3 | ||
1186 | lwz r4, 52(r1) | ||
1187 | mfcr r5 | ||
1188 | stw r7, 28(r1) | ||
1189 | stw r8, 32(r1) | ||
1190 | stw r9, 36(r1) | ||
1191 | stw r10,40(r1) | ||
1192 | stw r3, 44(r1) | ||
1193 | stw r5, 8(r1) | ||
1194 | subi r3, r3, MCOUNT_INSN_SIZE | 1181 | subi r3, r3, MCOUNT_INSN_SIZE |
1195 | .globl ftrace_call | 1182 | .globl ftrace_call |
1196 | ftrace_call: | 1183 | ftrace_call: |
1197 | bl ftrace_stub | 1184 | bl ftrace_stub |
1198 | nop | 1185 | nop |
1199 | lwz r6, 8(r1) | 1186 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
1200 | lwz r0, 44(r1) | 1187 | .globl ftrace_graph_call |
1201 | lwz r3, 12(r1) | 1188 | ftrace_graph_call: |
1202 | mtctr r0 | 1189 | b ftrace_graph_stub |
1203 | lwz r4, 16(r1) | 1190 | _GLOBAL(ftrace_graph_stub) |
1204 | mtcr r6 | 1191 | #endif |
1205 | lwz r5, 20(r1) | 1192 | MCOUNT_RESTORE_FRAME |
1206 | lwz r6, 24(r1) | 1193 | /* old link register ends up in ctr reg */ |
1207 | lwz r0, 52(r1) | ||
1208 | lwz r7, 28(r1) | ||
1209 | lwz r8, 32(r1) | ||
1210 | mtlr r0 | ||
1211 | lwz r9, 36(r1) | ||
1212 | lwz r10,40(r1) | ||
1213 | addi r1, r1, 48 | ||
1214 | bctr | 1194 | bctr |
1215 | #else | 1195 | #else |
1216 | _GLOBAL(mcount) | 1196 | _GLOBAL(mcount) |
1217 | _GLOBAL(_mcount) | 1197 | _GLOBAL(_mcount) |
1218 | stwu r1,-48(r1) | 1198 | |
1219 | stw r3, 12(r1) | 1199 | MCOUNT_SAVE_FRAME |
1220 | stw r4, 16(r1) | ||
1221 | stw r5, 20(r1) | ||
1222 | stw r6, 24(r1) | ||
1223 | mflr r3 | ||
1224 | lwz r4, 52(r1) | ||
1225 | mfcr r5 | ||
1226 | stw r7, 28(r1) | ||
1227 | stw r8, 32(r1) | ||
1228 | stw r9, 36(r1) | ||
1229 | stw r10,40(r1) | ||
1230 | stw r3, 44(r1) | ||
1231 | stw r5, 8(r1) | ||
1232 | 1200 | ||
1233 | subi r3, r3, MCOUNT_INSN_SIZE | 1201 | subi r3, r3, MCOUNT_INSN_SIZE |
1234 | LOAD_REG_ADDR(r5, ftrace_trace_function) | 1202 | LOAD_REG_ADDR(r5, ftrace_trace_function) |
@@ -1236,28 +1204,55 @@ _GLOBAL(_mcount) | |||
1236 | 1204 | ||
1237 | mtctr r5 | 1205 | mtctr r5 |
1238 | bctrl | 1206 | bctrl |
1239 | |||
1240 | nop | 1207 | nop |
1241 | 1208 | ||
1242 | lwz r6, 8(r1) | 1209 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
1243 | lwz r0, 44(r1) | 1210 | b ftrace_graph_caller |
1244 | lwz r3, 12(r1) | 1211 | #endif |
1245 | mtctr r0 | 1212 | MCOUNT_RESTORE_FRAME |
1246 | lwz r4, 16(r1) | ||
1247 | mtcr r6 | ||
1248 | lwz r5, 20(r1) | ||
1249 | lwz r6, 24(r1) | ||
1250 | lwz r0, 52(r1) | ||
1251 | lwz r7, 28(r1) | ||
1252 | lwz r8, 32(r1) | ||
1253 | mtlr r0 | ||
1254 | lwz r9, 36(r1) | ||
1255 | lwz r10,40(r1) | ||
1256 | addi r1, r1, 48 | ||
1257 | bctr | 1213 | bctr |
1258 | #endif | 1214 | #endif |
1259 | 1215 | ||
1260 | _GLOBAL(ftrace_stub) | 1216 | _GLOBAL(ftrace_stub) |
1261 | blr | 1217 | blr |
1262 | 1218 | ||
1219 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
1220 | _GLOBAL(ftrace_graph_caller) | ||
1221 | /* load r4 with local address */ | ||
1222 | lwz r4, 44(r1) | ||
1223 | subi r4, r4, MCOUNT_INSN_SIZE | ||
1224 | |||
1225 | /* get the parent address */ | ||
1226 | addi r3, r1, 52 | ||
1227 | |||
1228 | bl prepare_ftrace_return | ||
1229 | nop | ||
1230 | |||
1231 | MCOUNT_RESTORE_FRAME | ||
1232 | /* old link register ends up in ctr reg */ | ||
1233 | bctr | ||
1234 | |||
1235 | _GLOBAL(return_to_handler) | ||
1236 | /* need to save return values */ | ||
1237 | stwu r1, -32(r1) | ||
1238 | stw r3, 20(r1) | ||
1239 | stw r4, 16(r1) | ||
1240 | stw r31, 12(r1) | ||
1241 | mr r31, r1 | ||
1242 | |||
1243 | bl ftrace_return_to_handler | ||
1244 | nop | ||
1245 | |||
1246 | /* return value has real return address */ | ||
1247 | mtlr r3 | ||
1248 | |||
1249 | lwz r3, 20(r1) | ||
1250 | lwz r4, 16(r1) | ||
1251 | lwz r31,12(r1) | ||
1252 | lwz r1, 0(r1) | ||
1253 | |||
1254 | /* Jump back to real return address */ | ||
1255 | blr | ||
1256 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | ||
1257 | |||
1263 | #endif /* CONFIG_MCOUNT */ | 1258 | #endif /* CONFIG_MCOUNT */ |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 383ed6eb0085..abfc32330479 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -908,6 +908,12 @@ _GLOBAL(ftrace_caller) | |||
908 | ftrace_call: | 908 | ftrace_call: |
909 | bl ftrace_stub | 909 | bl ftrace_stub |
910 | nop | 910 | nop |
911 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
912 | .globl ftrace_graph_call | ||
913 | ftrace_graph_call: | ||
914 | b ftrace_graph_stub | ||
915 | _GLOBAL(ftrace_graph_stub) | ||
916 | #endif | ||
911 | ld r0, 128(r1) | 917 | ld r0, 128(r1) |
912 | mtlr r0 | 918 | mtlr r0 |
913 | addi r1, r1, 112 | 919 | addi r1, r1, 112 |
@@ -931,13 +937,90 @@ _GLOBAL(_mcount) | |||
931 | ld r5,0(r5) | 937 | ld r5,0(r5) |
932 | mtctr r5 | 938 | mtctr r5 |
933 | bctrl | 939 | bctrl |
934 | |||
935 | nop | 940 | nop |
941 | |||
942 | |||
943 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
944 | b ftrace_graph_caller | ||
945 | #endif | ||
936 | ld r0, 128(r1) | 946 | ld r0, 128(r1) |
937 | mtlr r0 | 947 | mtlr r0 |
938 | addi r1, r1, 112 | 948 | addi r1, r1, 112 |
939 | _GLOBAL(ftrace_stub) | 949 | _GLOBAL(ftrace_stub) |
940 | blr | 950 | blr |
941 | 951 | ||
942 | #endif | 952 | #endif /* CONFIG_DYNAMIC_FTRACE */ |
943 | #endif | 953 | |
954 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
955 | _GLOBAL(ftrace_graph_caller) | ||
956 | /* load r4 with local address */ | ||
957 | ld r4, 128(r1) | ||
958 | subi r4, r4, MCOUNT_INSN_SIZE | ||
959 | |||
960 | /* get the parent address */ | ||
961 | ld r11, 112(r1) | ||
962 | addi r3, r11, 16 | ||
963 | |||
964 | bl .prepare_ftrace_return | ||
965 | nop | ||
966 | |||
967 | ld r0, 128(r1) | ||
968 | mtlr r0 | ||
969 | addi r1, r1, 112 | ||
970 | blr | ||
971 | |||
972 | _GLOBAL(return_to_handler) | ||
973 | /* need to save return values */ | ||
974 | std r4, -24(r1) | ||
975 | std r3, -16(r1) | ||
976 | std r31, -8(r1) | ||
977 | mr r31, r1 | ||
978 | stdu r1, -112(r1) | ||
979 | |||
980 | bl .ftrace_return_to_handler | ||
981 | nop | ||
982 | |||
983 | /* return value has real return address */ | ||
984 | mtlr r3 | ||
985 | |||
986 | ld r1, 0(r1) | ||
987 | ld r4, -24(r1) | ||
988 | ld r3, -16(r1) | ||
989 | ld r31, -8(r1) | ||
990 | |||
991 | /* Jump back to real return address */ | ||
992 | blr | ||
993 | |||
994 | _GLOBAL(mod_return_to_handler) | ||
995 | /* need to save return values */ | ||
996 | std r4, -32(r1) | ||
997 | std r3, -24(r1) | ||
998 | /* save TOC */ | ||
999 | std r2, -16(r1) | ||
1000 | std r31, -8(r1) | ||
1001 | mr r31, r1 | ||
1002 | stdu r1, -112(r1) | ||
1003 | |||
1004 | /* | ||
1005 | * We are in a module using the module's TOC. | ||
1006 | * Switch to our TOC to run inside the core kernel. | ||
1007 | */ | ||
1008 | LOAD_REG_IMMEDIATE(r4,ftrace_return_to_handler) | ||
1009 | ld r2, 8(r4) | ||
1010 | |||
1011 | bl .ftrace_return_to_handler | ||
1012 | nop | ||
1013 | |||
1014 | /* return value has real return address */ | ||
1015 | mtlr r3 | ||
1016 | |||
1017 | ld r1, 0(r1) | ||
1018 | ld r4, -32(r1) | ||
1019 | ld r3, -24(r1) | ||
1020 | ld r2, -16(r1) | ||
1021 | ld r31, -8(r1) | ||
1022 | |||
1023 | /* Jump back to real return address */ | ||
1024 | blr | ||
1025 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | ||
1026 | #endif /* CONFIG_FUNCTION_TRACER */ | ||
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index a088c064ae40..2436df33c6f4 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S | |||
@@ -145,6 +145,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
145 | beq 1f | 145 | beq 1f |
146 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 146 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
147 | li r3,MSR_FP|MSR_FE0|MSR_FE1 | 147 | li r3,MSR_FP|MSR_FE0|MSR_FE1 |
148 | #ifdef CONFIG_VSX | ||
149 | BEGIN_FTR_SECTION | ||
150 | oris r3,r3,MSR_VSX@h | ||
151 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) | ||
152 | #endif | ||
148 | andc r4,r4,r3 /* disable FP for previous task */ | 153 | andc r4,r4,r3 /* disable FP for previous task */ |
149 | PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 154 | PPC_STL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
150 | 1: | 155 | 1: |
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index 60c60ccf5e3c..70e2a736be1f 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c | |||
@@ -5,6 +5,9 @@ | |||
5 | * | 5 | * |
6 | * Thanks goes out to P.A. Semi, Inc for supplying me with a PPC64 box. | 6 | * Thanks goes out to P.A. Semi, Inc for supplying me with a PPC64 box. |
7 | * | 7 | * |
8 | * Added function graph tracer code, taken from x86 that was written | ||
9 | * by Frederic Weisbecker, and ported to PPC by Steven Rostedt. | ||
10 | * | ||
8 | */ | 11 | */ |
9 | 12 | ||
10 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
@@ -20,14 +23,6 @@ | |||
20 | #include <asm/code-patching.h> | 23 | #include <asm/code-patching.h> |
21 | #include <asm/ftrace.h> | 24 | #include <asm/ftrace.h> |
22 | 25 | ||
23 | #if 0 | ||
24 | #define DEBUGP printk | ||
25 | #else | ||
26 | #define DEBUGP(fmt , ...) do { } while (0) | ||
27 | #endif | ||
28 | |||
29 | static unsigned int ftrace_nop = PPC_NOP_INSTR; | ||
30 | |||
31 | #ifdef CONFIG_PPC32 | 26 | #ifdef CONFIG_PPC32 |
32 | # define GET_ADDR(addr) addr | 27 | # define GET_ADDR(addr) addr |
33 | #else | 28 | #else |
@@ -35,37 +30,23 @@ static unsigned int ftrace_nop = PPC_NOP_INSTR; | |||
35 | # define GET_ADDR(addr) (*(unsigned long *)addr) | 30 | # define GET_ADDR(addr) (*(unsigned long *)addr) |
36 | #endif | 31 | #endif |
37 | 32 | ||
38 | 33 | #ifdef CONFIG_DYNAMIC_FTRACE | |
39 | static unsigned int ftrace_calc_offset(long ip, long addr) | 34 | static unsigned int ftrace_nop_replace(void) |
40 | { | 35 | { |
41 | return (int)(addr - ip); | 36 | return PPC_INST_NOP; |
42 | } | 37 | } |
43 | 38 | ||
44 | static unsigned char *ftrace_nop_replace(void) | 39 | static unsigned int |
40 | ftrace_call_replace(unsigned long ip, unsigned long addr, int link) | ||
45 | { | 41 | { |
46 | return (char *)&ftrace_nop; | 42 | unsigned int op; |
47 | } | ||
48 | |||
49 | static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) | ||
50 | { | ||
51 | static unsigned int op; | ||
52 | 43 | ||
53 | /* | ||
54 | * It would be nice to just use create_function_call, but that will | ||
55 | * update the code itself. Here we need to just return the | ||
56 | * instruction that is going to be modified, without modifying the | ||
57 | * code. | ||
58 | */ | ||
59 | addr = GET_ADDR(addr); | 44 | addr = GET_ADDR(addr); |
60 | 45 | ||
61 | /* Set to "bl addr" */ | 46 | /* if (link) set op to 'bl' else 'b' */ |
62 | op = 0x48000001 | (ftrace_calc_offset(ip, addr) & 0x03fffffc); | 47 | op = create_branch((unsigned int *)ip, addr, link ? 1 : 0); |
63 | 48 | ||
64 | /* | 49 | return op; |
65 | * No locking needed, this must be called via kstop_machine | ||
66 | * which in essence is like running on a uniprocessor machine. | ||
67 | */ | ||
68 | return (unsigned char *)&op; | ||
69 | } | 50 | } |
70 | 51 | ||
71 | #ifdef CONFIG_PPC64 | 52 | #ifdef CONFIG_PPC64 |
@@ -77,10 +58,9 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr) | |||
77 | #endif | 58 | #endif |
78 | 59 | ||
79 | static int | 60 | static int |
80 | ftrace_modify_code(unsigned long ip, unsigned char *old_code, | 61 | ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new) |
81 | unsigned char *new_code) | ||
82 | { | 62 | { |
83 | unsigned char replaced[MCOUNT_INSN_SIZE]; | 63 | unsigned int replaced; |
84 | 64 | ||
85 | /* | 65 | /* |
86 | * Note: Due to modules and __init, code can | 66 | * Note: Due to modules and __init, code can |
@@ -93,15 +73,15 @@ ftrace_modify_code(unsigned long ip, unsigned char *old_code, | |||
93 | */ | 73 | */ |
94 | 74 | ||
95 | /* read the text we want to modify */ | 75 | /* read the text we want to modify */ |
96 | if (probe_kernel_read(replaced, (void *)ip, MCOUNT_INSN_SIZE)) | 76 | if (probe_kernel_read(&replaced, (void *)ip, MCOUNT_INSN_SIZE)) |
97 | return -EFAULT; | 77 | return -EFAULT; |
98 | 78 | ||
99 | /* Make sure it is what we expect it to be */ | 79 | /* Make sure it is what we expect it to be */ |
100 | if (memcmp(replaced, old_code, MCOUNT_INSN_SIZE) != 0) | 80 | if (replaced != old) |
101 | return -EINVAL; | 81 | return -EINVAL; |
102 | 82 | ||
103 | /* replace the text with the new text */ | 83 | /* replace the text with the new text */ |
104 | if (probe_kernel_write((void *)ip, new_code, MCOUNT_INSN_SIZE)) | 84 | if (probe_kernel_write((void *)ip, &new, MCOUNT_INSN_SIZE)) |
105 | return -EPERM; | 85 | return -EPERM; |
106 | 86 | ||
107 | flush_icache_range(ip, ip + 8); | 87 | flush_icache_range(ip, ip + 8); |
@@ -119,6 +99,8 @@ static int test_24bit_addr(unsigned long ip, unsigned long addr) | |||
119 | return create_branch((unsigned int *)ip, addr, 0); | 99 | return create_branch((unsigned int *)ip, addr, 0); |
120 | } | 100 | } |
121 | 101 | ||
102 | #ifdef CONFIG_MODULES | ||
103 | |||
122 | static int is_bl_op(unsigned int op) | 104 | static int is_bl_op(unsigned int op) |
123 | { | 105 | { |
124 | return (op & 0xfc000003) == 0x48000001; | 106 | return (op & 0xfc000003) == 0x48000001; |
@@ -175,7 +157,7 @@ __ftrace_make_nop(struct module *mod, | |||
175 | * 0xe8, 0x4c, 0x00, 0x28, ld r2,40(r12) | 157 | * 0xe8, 0x4c, 0x00, 0x28, ld r2,40(r12) |
176 | */ | 158 | */ |
177 | 159 | ||
178 | DEBUGP("ip:%lx jumps to %lx r2: %lx", ip, tramp, mod->arch.toc); | 160 | pr_debug("ip:%lx jumps to %lx r2: %lx", ip, tramp, mod->arch.toc); |
179 | 161 | ||
180 | /* Find where the trampoline jumps to */ | 162 | /* Find where the trampoline jumps to */ |
181 | if (probe_kernel_read(jmp, (void *)tramp, sizeof(jmp))) { | 163 | if (probe_kernel_read(jmp, (void *)tramp, sizeof(jmp))) { |
@@ -183,7 +165,7 @@ __ftrace_make_nop(struct module *mod, | |||
183 | return -EFAULT; | 165 | return -EFAULT; |
184 | } | 166 | } |
185 | 167 | ||
186 | DEBUGP(" %08x %08x", jmp[0], jmp[1]); | 168 | pr_debug(" %08x %08x", jmp[0], jmp[1]); |
187 | 169 | ||
188 | /* verify that this is what we expect it to be */ | 170 | /* verify that this is what we expect it to be */ |
189 | if (((jmp[0] & 0xffff0000) != 0x3d820000) || | 171 | if (((jmp[0] & 0xffff0000) != 0x3d820000) || |
@@ -199,18 +181,18 @@ __ftrace_make_nop(struct module *mod, | |||
199 | offset = ((unsigned)((unsigned short)jmp[0]) << 16) + | 181 | offset = ((unsigned)((unsigned short)jmp[0]) << 16) + |
200 | (int)((short)jmp[1]); | 182 | (int)((short)jmp[1]); |
201 | 183 | ||
202 | DEBUGP(" %x ", offset); | 184 | pr_debug(" %x ", offset); |
203 | 185 | ||
204 | /* get the address this jumps too */ | 186 | /* get the address this jumps too */ |
205 | tramp = mod->arch.toc + offset + 32; | 187 | tramp = mod->arch.toc + offset + 32; |
206 | DEBUGP("toc: %lx", tramp); | 188 | pr_debug("toc: %lx", tramp); |
207 | 189 | ||
208 | if (probe_kernel_read(jmp, (void *)tramp, 8)) { | 190 | if (probe_kernel_read(jmp, (void *)tramp, 8)) { |
209 | printk(KERN_ERR "Failed to read %lx\n", tramp); | 191 | printk(KERN_ERR "Failed to read %lx\n", tramp); |
210 | return -EFAULT; | 192 | return -EFAULT; |
211 | } | 193 | } |
212 | 194 | ||
213 | DEBUGP(" %08x %08x\n", jmp[0], jmp[1]); | 195 | pr_debug(" %08x %08x\n", jmp[0], jmp[1]); |
214 | 196 | ||
215 | ptr = ((unsigned long)jmp[0] << 32) + jmp[1]; | 197 | ptr = ((unsigned long)jmp[0] << 32) + jmp[1]; |
216 | 198 | ||
@@ -287,7 +269,7 @@ __ftrace_make_nop(struct module *mod, | |||
287 | * 0x4e, 0x80, 0x04, 0x20 bctr | 269 | * 0x4e, 0x80, 0x04, 0x20 bctr |
288 | */ | 270 | */ |
289 | 271 | ||
290 | DEBUGP("ip:%lx jumps to %lx", ip, tramp); | 272 | pr_debug("ip:%lx jumps to %lx", ip, tramp); |
291 | 273 | ||
292 | /* Find where the trampoline jumps to */ | 274 | /* Find where the trampoline jumps to */ |
293 | if (probe_kernel_read(jmp, (void *)tramp, sizeof(jmp))) { | 275 | if (probe_kernel_read(jmp, (void *)tramp, sizeof(jmp))) { |
@@ -295,7 +277,7 @@ __ftrace_make_nop(struct module *mod, | |||
295 | return -EFAULT; | 277 | return -EFAULT; |
296 | } | 278 | } |
297 | 279 | ||
298 | DEBUGP(" %08x %08x ", jmp[0], jmp[1]); | 280 | pr_debug(" %08x %08x ", jmp[0], jmp[1]); |
299 | 281 | ||
300 | /* verify that this is what we expect it to be */ | 282 | /* verify that this is what we expect it to be */ |
301 | if (((jmp[0] & 0xffff0000) != 0x3d600000) || | 283 | if (((jmp[0] & 0xffff0000) != 0x3d600000) || |
@@ -311,7 +293,7 @@ __ftrace_make_nop(struct module *mod, | |||
311 | if (tramp & 0x8000) | 293 | if (tramp & 0x8000) |
312 | tramp -= 0x10000; | 294 | tramp -= 0x10000; |
313 | 295 | ||
314 | DEBUGP(" %x ", tramp); | 296 | pr_debug(" %lx ", tramp); |
315 | 297 | ||
316 | if (tramp != addr) { | 298 | if (tramp != addr) { |
317 | printk(KERN_ERR | 299 | printk(KERN_ERR |
@@ -320,7 +302,7 @@ __ftrace_make_nop(struct module *mod, | |||
320 | return -EINVAL; | 302 | return -EINVAL; |
321 | } | 303 | } |
322 | 304 | ||
323 | op = PPC_NOP_INSTR; | 305 | op = PPC_INST_NOP; |
324 | 306 | ||
325 | if (probe_kernel_write((void *)ip, &op, MCOUNT_INSN_SIZE)) | 307 | if (probe_kernel_write((void *)ip, &op, MCOUNT_INSN_SIZE)) |
326 | return -EPERM; | 308 | return -EPERM; |
@@ -330,12 +312,13 @@ __ftrace_make_nop(struct module *mod, | |||
330 | return 0; | 312 | return 0; |
331 | } | 313 | } |
332 | #endif /* PPC64 */ | 314 | #endif /* PPC64 */ |
315 | #endif /* CONFIG_MODULES */ | ||
333 | 316 | ||
334 | int ftrace_make_nop(struct module *mod, | 317 | int ftrace_make_nop(struct module *mod, |
335 | struct dyn_ftrace *rec, unsigned long addr) | 318 | struct dyn_ftrace *rec, unsigned long addr) |
336 | { | 319 | { |
337 | unsigned char *old, *new; | ||
338 | unsigned long ip = rec->ip; | 320 | unsigned long ip = rec->ip; |
321 | unsigned int old, new; | ||
339 | 322 | ||
340 | /* | 323 | /* |
341 | * If the calling address is more that 24 bits away, | 324 | * If the calling address is more that 24 bits away, |
@@ -344,11 +327,12 @@ int ftrace_make_nop(struct module *mod, | |||
344 | */ | 327 | */ |
345 | if (test_24bit_addr(ip, addr)) { | 328 | if (test_24bit_addr(ip, addr)) { |
346 | /* within range */ | 329 | /* within range */ |
347 | old = ftrace_call_replace(ip, addr); | 330 | old = ftrace_call_replace(ip, addr, 1); |
348 | new = ftrace_nop_replace(); | 331 | new = ftrace_nop_replace(); |
349 | return ftrace_modify_code(ip, old, new); | 332 | return ftrace_modify_code(ip, old, new); |
350 | } | 333 | } |
351 | 334 | ||
335 | #ifdef CONFIG_MODULES | ||
352 | /* | 336 | /* |
353 | * Out of range jumps are called from modules. | 337 | * Out of range jumps are called from modules. |
354 | * We should either already have a pointer to the module | 338 | * We should either already have a pointer to the module |
@@ -373,9 +357,13 @@ int ftrace_make_nop(struct module *mod, | |||
373 | mod = rec->arch.mod; | 357 | mod = rec->arch.mod; |
374 | 358 | ||
375 | return __ftrace_make_nop(mod, rec, addr); | 359 | return __ftrace_make_nop(mod, rec, addr); |
376 | 360 | #else | |
361 | /* We should not get here without modules */ | ||
362 | return -EINVAL; | ||
363 | #endif /* CONFIG_MODULES */ | ||
377 | } | 364 | } |
378 | 365 | ||
366 | #ifdef CONFIG_MODULES | ||
379 | #ifdef CONFIG_PPC64 | 367 | #ifdef CONFIG_PPC64 |
380 | static int | 368 | static int |
381 | __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | 369 | __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) |
@@ -392,7 +380,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
392 | * b +8; ld r2,40(r1) | 380 | * b +8; ld r2,40(r1) |
393 | */ | 381 | */ |
394 | if (((op[0] != 0x48000008) || (op[1] != 0xe8410028)) && | 382 | if (((op[0] != 0x48000008) || (op[1] != 0xe8410028)) && |
395 | ((op[0] != PPC_NOP_INSTR) || (op[1] != PPC_NOP_INSTR))) { | 383 | ((op[0] != PPC_INST_NOP) || (op[1] != PPC_INST_NOP))) { |
396 | printk(KERN_ERR "Expected NOPs but have %x %x\n", op[0], op[1]); | 384 | printk(KERN_ERR "Expected NOPs but have %x %x\n", op[0], op[1]); |
397 | return -EINVAL; | 385 | return -EINVAL; |
398 | } | 386 | } |
@@ -414,7 +402,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
414 | /* ld r2,40(r1) */ | 402 | /* ld r2,40(r1) */ |
415 | op[1] = 0xe8410028; | 403 | op[1] = 0xe8410028; |
416 | 404 | ||
417 | DEBUGP("write to %lx\n", rec->ip); | 405 | pr_debug("write to %lx\n", rec->ip); |
418 | 406 | ||
419 | if (probe_kernel_write((void *)ip, op, MCOUNT_INSN_SIZE * 2)) | 407 | if (probe_kernel_write((void *)ip, op, MCOUNT_INSN_SIZE * 2)) |
420 | return -EPERM; | 408 | return -EPERM; |
@@ -435,7 +423,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
435 | return -EFAULT; | 423 | return -EFAULT; |
436 | 424 | ||
437 | /* It should be pointing to a nop */ | 425 | /* It should be pointing to a nop */ |
438 | if (op != PPC_NOP_INSTR) { | 426 | if (op != PPC_INST_NOP) { |
439 | printk(KERN_ERR "Expected NOP but have %x\n", op); | 427 | printk(KERN_ERR "Expected NOP but have %x\n", op); |
440 | return -EINVAL; | 428 | return -EINVAL; |
441 | } | 429 | } |
@@ -454,7 +442,7 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
454 | return -EINVAL; | 442 | return -EINVAL; |
455 | } | 443 | } |
456 | 444 | ||
457 | DEBUGP("write to %lx\n", rec->ip); | 445 | pr_debug("write to %lx\n", rec->ip); |
458 | 446 | ||
459 | if (probe_kernel_write((void *)ip, &op, MCOUNT_INSN_SIZE)) | 447 | if (probe_kernel_write((void *)ip, &op, MCOUNT_INSN_SIZE)) |
460 | return -EPERM; | 448 | return -EPERM; |
@@ -464,11 +452,12 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
464 | return 0; | 452 | return 0; |
465 | } | 453 | } |
466 | #endif /* CONFIG_PPC64 */ | 454 | #endif /* CONFIG_PPC64 */ |
455 | #endif /* CONFIG_MODULES */ | ||
467 | 456 | ||
468 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | 457 | int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) |
469 | { | 458 | { |
470 | unsigned char *old, *new; | ||
471 | unsigned long ip = rec->ip; | 459 | unsigned long ip = rec->ip; |
460 | unsigned int old, new; | ||
472 | 461 | ||
473 | /* | 462 | /* |
474 | * If the calling address is more that 24 bits away, | 463 | * If the calling address is more that 24 bits away, |
@@ -478,10 +467,11 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
478 | if (test_24bit_addr(ip, addr)) { | 467 | if (test_24bit_addr(ip, addr)) { |
479 | /* within range */ | 468 | /* within range */ |
480 | old = ftrace_nop_replace(); | 469 | old = ftrace_nop_replace(); |
481 | new = ftrace_call_replace(ip, addr); | 470 | new = ftrace_call_replace(ip, addr, 1); |
482 | return ftrace_modify_code(ip, old, new); | 471 | return ftrace_modify_code(ip, old, new); |
483 | } | 472 | } |
484 | 473 | ||
474 | #ifdef CONFIG_MODULES | ||
485 | /* | 475 | /* |
486 | * Out of range jumps are called from modules. | 476 | * Out of range jumps are called from modules. |
487 | * Being that we are converting from nop, it had better | 477 | * Being that we are converting from nop, it had better |
@@ -493,16 +483,20 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
493 | } | 483 | } |
494 | 484 | ||
495 | return __ftrace_make_call(rec, addr); | 485 | return __ftrace_make_call(rec, addr); |
486 | #else | ||
487 | /* We should not get here without modules */ | ||
488 | return -EINVAL; | ||
489 | #endif /* CONFIG_MODULES */ | ||
496 | } | 490 | } |
497 | 491 | ||
498 | int ftrace_update_ftrace_func(ftrace_func_t func) | 492 | int ftrace_update_ftrace_func(ftrace_func_t func) |
499 | { | 493 | { |
500 | unsigned long ip = (unsigned long)(&ftrace_call); | 494 | unsigned long ip = (unsigned long)(&ftrace_call); |
501 | unsigned char old[MCOUNT_INSN_SIZE], *new; | 495 | unsigned int old, new; |
502 | int ret; | 496 | int ret; |
503 | 497 | ||
504 | memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE); | 498 | old = *(unsigned int *)&ftrace_call; |
505 | new = ftrace_call_replace(ip, (unsigned long)func); | 499 | new = ftrace_call_replace(ip, (unsigned long)func, 1); |
506 | ret = ftrace_modify_code(ip, old, new); | 500 | ret = ftrace_modify_code(ip, old, new); |
507 | 501 | ||
508 | return ret; | 502 | return ret; |
@@ -517,3 +511,111 @@ int __init ftrace_dyn_arch_init(void *data) | |||
517 | 511 | ||
518 | return 0; | 512 | return 0; |
519 | } | 513 | } |
514 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
515 | |||
516 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
517 | |||
518 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
519 | extern void ftrace_graph_call(void); | ||
520 | extern void ftrace_graph_stub(void); | ||
521 | |||
522 | int ftrace_enable_ftrace_graph_caller(void) | ||
523 | { | ||
524 | unsigned long ip = (unsigned long)(&ftrace_graph_call); | ||
525 | unsigned long addr = (unsigned long)(&ftrace_graph_caller); | ||
526 | unsigned long stub = (unsigned long)(&ftrace_graph_stub); | ||
527 | unsigned int old, new; | ||
528 | |||
529 | old = ftrace_call_replace(ip, stub, 0); | ||
530 | new = ftrace_call_replace(ip, addr, 0); | ||
531 | |||
532 | return ftrace_modify_code(ip, old, new); | ||
533 | } | ||
534 | |||
535 | int ftrace_disable_ftrace_graph_caller(void) | ||
536 | { | ||
537 | unsigned long ip = (unsigned long)(&ftrace_graph_call); | ||
538 | unsigned long addr = (unsigned long)(&ftrace_graph_caller); | ||
539 | unsigned long stub = (unsigned long)(&ftrace_graph_stub); | ||
540 | unsigned int old, new; | ||
541 | |||
542 | old = ftrace_call_replace(ip, addr, 0); | ||
543 | new = ftrace_call_replace(ip, stub, 0); | ||
544 | |||
545 | return ftrace_modify_code(ip, old, new); | ||
546 | } | ||
547 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
548 | |||
549 | #ifdef CONFIG_PPC64 | ||
550 | extern void mod_return_to_handler(void); | ||
551 | #endif | ||
552 | |||
553 | /* | ||
554 | * Hook the return address and push it in the stack of return addrs | ||
555 | * in current thread info. | ||
556 | */ | ||
557 | void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr) | ||
558 | { | ||
559 | unsigned long old; | ||
560 | int faulted; | ||
561 | struct ftrace_graph_ent trace; | ||
562 | unsigned long return_hooker = (unsigned long)&return_to_handler; | ||
563 | |||
564 | if (unlikely(atomic_read(¤t->tracing_graph_pause))) | ||
565 | return; | ||
566 | |||
567 | #ifdef CONFIG_PPC64 | ||
568 | /* non core kernel code needs to save and restore the TOC */ | ||
569 | if (REGION_ID(self_addr) != KERNEL_REGION_ID) | ||
570 | return_hooker = (unsigned long)&mod_return_to_handler; | ||
571 | #endif | ||
572 | |||
573 | return_hooker = GET_ADDR(return_hooker); | ||
574 | |||
575 | /* | ||
576 | * Protect against fault, even if it shouldn't | ||
577 | * happen. This tool is too much intrusive to | ||
578 | * ignore such a protection. | ||
579 | */ | ||
580 | asm volatile( | ||
581 | "1: " PPC_LL "%[old], 0(%[parent])\n" | ||
582 | "2: " PPC_STL "%[return_hooker], 0(%[parent])\n" | ||
583 | " li %[faulted], 0\n" | ||
584 | "3:\n" | ||
585 | |||
586 | ".section .fixup, \"ax\"\n" | ||
587 | "4: li %[faulted], 1\n" | ||
588 | " b 3b\n" | ||
589 | ".previous\n" | ||
590 | |||
591 | ".section __ex_table,\"a\"\n" | ||
592 | PPC_LONG_ALIGN "\n" | ||
593 | PPC_LONG "1b,4b\n" | ||
594 | PPC_LONG "2b,4b\n" | ||
595 | ".previous" | ||
596 | |||
597 | : [old] "=r" (old), [faulted] "=r" (faulted) | ||
598 | : [parent] "r" (parent), [return_hooker] "r" (return_hooker) | ||
599 | : "memory" | ||
600 | ); | ||
601 | |||
602 | if (unlikely(faulted)) { | ||
603 | ftrace_graph_stop(); | ||
604 | WARN_ON(1); | ||
605 | return; | ||
606 | } | ||
607 | |||
608 | if (ftrace_push_return_trace(old, self_addr, &trace.depth) == -EBUSY) { | ||
609 | *parent = old; | ||
610 | return; | ||
611 | } | ||
612 | |||
613 | trace.func = self_addr; | ||
614 | |||
615 | /* Only trace if the calling function expects to */ | ||
616 | if (!ftrace_graph_entry(&trace)) { | ||
617 | current->curr_ret_stack--; | ||
618 | *parent = old; | ||
619 | } | ||
620 | } | ||
621 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | ||
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index d794a637e421..54e68c11ae15 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S | |||
@@ -108,18 +108,21 @@ __start: | |||
108 | * because OF may have I/O devices mapped into that area | 108 | * because OF may have I/O devices mapped into that area |
109 | * (particularly on CHRP). | 109 | * (particularly on CHRP). |
110 | */ | 110 | */ |
111 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
112 | cmpwi 0,r5,0 | 111 | cmpwi 0,r5,0 |
113 | beq 1f | 112 | beq 1f |
114 | 113 | ||
114 | #ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE | ||
115 | /* find out where we are now */ | 115 | /* find out where we are now */ |
116 | bcl 20,31,$+4 | 116 | bcl 20,31,$+4 |
117 | 0: mflr r8 /* r8 = runtime addr here */ | 117 | 0: mflr r8 /* r8 = runtime addr here */ |
118 | addis r8,r8,(_stext - 0b)@ha | 118 | addis r8,r8,(_stext - 0b)@ha |
119 | addi r8,r8,(_stext - 0b)@l /* current runtime base addr */ | 119 | addi r8,r8,(_stext - 0b)@l /* current runtime base addr */ |
120 | bl prom_init | 120 | bl prom_init |
121 | #endif /* CONFIG_PPC_OF_BOOT_TRAMPOLINE */ | ||
122 | |||
123 | /* We never return. We also hit that trap if trying to boot | ||
124 | * from OF while CONFIG_PPC_OF_BOOT_TRAMPOLINE isn't selected */ | ||
121 | trap | 125 | trap |
122 | #endif | ||
123 | 126 | ||
124 | /* | 127 | /* |
125 | * Check for BootX signature when supporting PowerMac and branch to | 128 | * Check for BootX signature when supporting PowerMac and branch to |
@@ -472,12 +475,11 @@ SystemCall: | |||
472 | . = 0x1000 | 475 | . = 0x1000 |
473 | InstructionTLBMiss: | 476 | InstructionTLBMiss: |
474 | /* | 477 | /* |
475 | * r0: stored ctr | 478 | * r0: scratch |
476 | * r1: linux style pte ( later becomes ppc hardware pte ) | 479 | * r1: linux style pte ( later becomes ppc hardware pte ) |
477 | * r2: ptr to linux-style pte | 480 | * r2: ptr to linux-style pte |
478 | * r3: scratch | 481 | * r3: scratch |
479 | */ | 482 | */ |
480 | mfctr r0 | ||
481 | /* Get PTE (linux-style) and check access */ | 483 | /* Get PTE (linux-style) and check access */ |
482 | mfspr r3,SPRN_IMISS | 484 | mfspr r3,SPRN_IMISS |
483 | lis r1,PAGE_OFFSET@h /* check if kernel address */ | 485 | lis r1,PAGE_OFFSET@h /* check if kernel address */ |
@@ -496,28 +498,27 @@ InstructionTLBMiss: | |||
496 | rlwinm. r2,r2,0,0,19 /* extract address of pte page */ | 498 | rlwinm. r2,r2,0,0,19 /* extract address of pte page */ |
497 | beq- InstructionAddressInvalid /* return if no mapping */ | 499 | beq- InstructionAddressInvalid /* return if no mapping */ |
498 | rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ | 500 | rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ |
499 | lwz r3,0(r2) /* get linux-style pte */ | 501 | lwz r0,0(r2) /* get linux-style pte */ |
500 | andc. r1,r1,r3 /* check access & ~permission */ | 502 | andc. r1,r1,r0 /* check access & ~permission */ |
501 | bne- InstructionAddressInvalid /* return if access not permitted */ | 503 | bne- InstructionAddressInvalid /* return if access not permitted */ |
502 | ori r3,r3,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */ | 504 | ori r0,r0,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */ |
503 | /* | 505 | /* |
504 | * NOTE! We are assuming this is not an SMP system, otherwise | 506 | * NOTE! We are assuming this is not an SMP system, otherwise |
505 | * we would need to update the pte atomically with lwarx/stwcx. | 507 | * we would need to update the pte atomically with lwarx/stwcx. |
506 | */ | 508 | */ |
507 | stw r3,0(r2) /* update PTE (accessed bit) */ | 509 | stw r0,0(r2) /* update PTE (accessed bit) */ |
508 | /* Convert linux-style PTE to low word of PPC-style PTE */ | 510 | /* Convert linux-style PTE to low word of PPC-style PTE */ |
509 | rlwinm r1,r3,32-10,31,31 /* _PAGE_RW -> PP lsb */ | 511 | rlwinm r1,r0,32-10,31,31 /* _PAGE_RW -> PP lsb */ |
510 | rlwinm r2,r3,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */ | 512 | rlwinm r2,r0,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */ |
511 | and r1,r1,r2 /* writable if _RW and _DIRTY */ | 513 | and r1,r1,r2 /* writable if _RW and _DIRTY */ |
512 | rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ | 514 | rlwimi r0,r0,32-1,30,30 /* _PAGE_USER -> PP msb */ |
513 | rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */ | 515 | rlwimi r0,r0,32-1,31,31 /* _PAGE_USER -> PP lsb */ |
514 | ori r1,r1,0xe04 /* clear out reserved bits */ | 516 | ori r1,r1,0xe04 /* clear out reserved bits */ |
515 | andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ | 517 | andc r1,r0,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ |
516 | BEGIN_FTR_SECTION | 518 | BEGIN_FTR_SECTION |
517 | rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ | 519 | rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ |
518 | END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) | 520 | END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) |
519 | mtspr SPRN_RPA,r1 | 521 | mtspr SPRN_RPA,r1 |
520 | mfspr r3,SPRN_IMISS | ||
521 | tlbli r3 | 522 | tlbli r3 |
522 | mfspr r3,SPRN_SRR1 /* Need to restore CR0 */ | 523 | mfspr r3,SPRN_SRR1 /* Need to restore CR0 */ |
523 | mtcrf 0x80,r3 | 524 | mtcrf 0x80,r3 |
@@ -528,7 +529,6 @@ InstructionAddressInvalid: | |||
528 | 529 | ||
529 | addis r1,r1,0x2000 | 530 | addis r1,r1,0x2000 |
530 | mtspr SPRN_DSISR,r1 /* (shouldn't be needed) */ | 531 | mtspr SPRN_DSISR,r1 /* (shouldn't be needed) */ |
531 | mtctr r0 /* Restore CTR */ | ||
532 | andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */ | 532 | andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */ |
533 | or r2,r2,r1 | 533 | or r2,r2,r1 |
534 | mtspr SPRN_SRR1,r2 | 534 | mtspr SPRN_SRR1,r2 |
@@ -549,12 +549,11 @@ InstructionAddressInvalid: | |||
549 | . = 0x1100 | 549 | . = 0x1100 |
550 | DataLoadTLBMiss: | 550 | DataLoadTLBMiss: |
551 | /* | 551 | /* |
552 | * r0: stored ctr | 552 | * r0: scratch |
553 | * r1: linux style pte ( later becomes ppc hardware pte ) | 553 | * r1: linux style pte ( later becomes ppc hardware pte ) |
554 | * r2: ptr to linux-style pte | 554 | * r2: ptr to linux-style pte |
555 | * r3: scratch | 555 | * r3: scratch |
556 | */ | 556 | */ |
557 | mfctr r0 | ||
558 | /* Get PTE (linux-style) and check access */ | 557 | /* Get PTE (linux-style) and check access */ |
559 | mfspr r3,SPRN_DMISS | 558 | mfspr r3,SPRN_DMISS |
560 | lis r1,PAGE_OFFSET@h /* check if kernel address */ | 559 | lis r1,PAGE_OFFSET@h /* check if kernel address */ |
@@ -573,38 +572,48 @@ DataLoadTLBMiss: | |||
573 | rlwinm. r2,r2,0,0,19 /* extract address of pte page */ | 572 | rlwinm. r2,r2,0,0,19 /* extract address of pte page */ |
574 | beq- DataAddressInvalid /* return if no mapping */ | 573 | beq- DataAddressInvalid /* return if no mapping */ |
575 | rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ | 574 | rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ |
576 | lwz r3,0(r2) /* get linux-style pte */ | 575 | lwz r0,0(r2) /* get linux-style pte */ |
577 | andc. r1,r1,r3 /* check access & ~permission */ | 576 | andc. r1,r1,r0 /* check access & ~permission */ |
578 | bne- DataAddressInvalid /* return if access not permitted */ | 577 | bne- DataAddressInvalid /* return if access not permitted */ |
579 | ori r3,r3,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */ | 578 | ori r0,r0,_PAGE_ACCESSED /* set _PAGE_ACCESSED in pte */ |
580 | /* | 579 | /* |
581 | * NOTE! We are assuming this is not an SMP system, otherwise | 580 | * NOTE! We are assuming this is not an SMP system, otherwise |
582 | * we would need to update the pte atomically with lwarx/stwcx. | 581 | * we would need to update the pte atomically with lwarx/stwcx. |
583 | */ | 582 | */ |
584 | stw r3,0(r2) /* update PTE (accessed bit) */ | 583 | stw r0,0(r2) /* update PTE (accessed bit) */ |
585 | /* Convert linux-style PTE to low word of PPC-style PTE */ | 584 | /* Convert linux-style PTE to low word of PPC-style PTE */ |
586 | rlwinm r1,r3,32-10,31,31 /* _PAGE_RW -> PP lsb */ | 585 | rlwinm r1,r0,32-10,31,31 /* _PAGE_RW -> PP lsb */ |
587 | rlwinm r2,r3,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */ | 586 | rlwinm r2,r0,32-7,31,31 /* _PAGE_DIRTY -> PP lsb */ |
588 | and r1,r1,r2 /* writable if _RW and _DIRTY */ | 587 | and r1,r1,r2 /* writable if _RW and _DIRTY */ |
589 | rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ | 588 | rlwimi r0,r0,32-1,30,30 /* _PAGE_USER -> PP msb */ |
590 | rlwimi r3,r3,32-1,31,31 /* _PAGE_USER -> PP lsb */ | 589 | rlwimi r0,r0,32-1,31,31 /* _PAGE_USER -> PP lsb */ |
591 | ori r1,r1,0xe04 /* clear out reserved bits */ | 590 | ori r1,r1,0xe04 /* clear out reserved bits */ |
592 | andc r1,r3,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ | 591 | andc r1,r0,r1 /* PP = user? (rw&dirty? 2: 3): 0 */ |
593 | BEGIN_FTR_SECTION | 592 | BEGIN_FTR_SECTION |
594 | rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ | 593 | rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ |
595 | END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) | 594 | END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) |
596 | mtspr SPRN_RPA,r1 | 595 | mtspr SPRN_RPA,r1 |
597 | mfspr r3,SPRN_DMISS | 596 | mfspr r2,SPRN_SRR1 /* Need to restore CR0 */ |
597 | mtcrf 0x80,r2 | ||
598 | BEGIN_MMU_FTR_SECTION | ||
599 | li r0,1 | ||
600 | mfspr r1,SPRN_SPRG4 | ||
601 | rlwinm r2,r3,20,27,31 /* Get Address bits 15:19 */ | ||
602 | slw r0,r0,r2 | ||
603 | xor r1,r0,r1 | ||
604 | srw r0,r1,r2 | ||
605 | mtspr SPRN_SPRG4,r1 | ||
606 | mfspr r2,SPRN_SRR1 | ||
607 | rlwimi r2,r0,31-14,14,14 | ||
608 | mtspr SPRN_SRR1,r2 | ||
609 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU) | ||
598 | tlbld r3 | 610 | tlbld r3 |
599 | mfspr r3,SPRN_SRR1 /* Need to restore CR0 */ | ||
600 | mtcrf 0x80,r3 | ||
601 | rfi | 611 | rfi |
602 | DataAddressInvalid: | 612 | DataAddressInvalid: |
603 | mfspr r3,SPRN_SRR1 | 613 | mfspr r3,SPRN_SRR1 |
604 | rlwinm r1,r3,9,6,6 /* Get load/store bit */ | 614 | rlwinm r1,r3,9,6,6 /* Get load/store bit */ |
605 | addis r1,r1,0x2000 | 615 | addis r1,r1,0x2000 |
606 | mtspr SPRN_DSISR,r1 | 616 | mtspr SPRN_DSISR,r1 |
607 | mtctr r0 /* Restore CTR */ | ||
608 | andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */ | 617 | andi. r2,r3,0xFFFF /* Clear upper bits of SRR1 */ |
609 | mtspr SPRN_SRR1,r2 | 618 | mtspr SPRN_SRR1,r2 |
610 | mfspr r1,SPRN_DMISS /* Get failing address */ | 619 | mfspr r1,SPRN_DMISS /* Get failing address */ |
@@ -624,12 +633,11 @@ DataAddressInvalid: | |||
624 | . = 0x1200 | 633 | . = 0x1200 |
625 | DataStoreTLBMiss: | 634 | DataStoreTLBMiss: |
626 | /* | 635 | /* |
627 | * r0: stored ctr | 636 | * r0: scratch |
628 | * r1: linux style pte ( later becomes ppc hardware pte ) | 637 | * r1: linux style pte ( later becomes ppc hardware pte ) |
629 | * r2: ptr to linux-style pte | 638 | * r2: ptr to linux-style pte |
630 | * r3: scratch | 639 | * r3: scratch |
631 | */ | 640 | */ |
632 | mfctr r0 | ||
633 | /* Get PTE (linux-style) and check access */ | 641 | /* Get PTE (linux-style) and check access */ |
634 | mfspr r3,SPRN_DMISS | 642 | mfspr r3,SPRN_DMISS |
635 | lis r1,PAGE_OFFSET@h /* check if kernel address */ | 643 | lis r1,PAGE_OFFSET@h /* check if kernel address */ |
@@ -648,27 +656,38 @@ DataStoreTLBMiss: | |||
648 | rlwinm. r2,r2,0,0,19 /* extract address of pte page */ | 656 | rlwinm. r2,r2,0,0,19 /* extract address of pte page */ |
649 | beq- DataAddressInvalid /* return if no mapping */ | 657 | beq- DataAddressInvalid /* return if no mapping */ |
650 | rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ | 658 | rlwimi r2,r3,22,20,29 /* insert next 10 bits of address */ |
651 | lwz r3,0(r2) /* get linux-style pte */ | 659 | lwz r0,0(r2) /* get linux-style pte */ |
652 | andc. r1,r1,r3 /* check access & ~permission */ | 660 | andc. r1,r1,r0 /* check access & ~permission */ |
653 | bne- DataAddressInvalid /* return if access not permitted */ | 661 | bne- DataAddressInvalid /* return if access not permitted */ |
654 | ori r3,r3,_PAGE_ACCESSED|_PAGE_DIRTY | 662 | ori r0,r0,_PAGE_ACCESSED|_PAGE_DIRTY |
655 | /* | 663 | /* |
656 | * NOTE! We are assuming this is not an SMP system, otherwise | 664 | * NOTE! We are assuming this is not an SMP system, otherwise |
657 | * we would need to update the pte atomically with lwarx/stwcx. | 665 | * we would need to update the pte atomically with lwarx/stwcx. |
658 | */ | 666 | */ |
659 | stw r3,0(r2) /* update PTE (accessed/dirty bits) */ | 667 | stw r0,0(r2) /* update PTE (accessed/dirty bits) */ |
660 | /* Convert linux-style PTE to low word of PPC-style PTE */ | 668 | /* Convert linux-style PTE to low word of PPC-style PTE */ |
661 | rlwimi r3,r3,32-1,30,30 /* _PAGE_USER -> PP msb */ | 669 | rlwimi r0,r0,32-1,30,30 /* _PAGE_USER -> PP msb */ |
662 | li r1,0xe05 /* clear out reserved bits & PP lsb */ | 670 | li r1,0xe05 /* clear out reserved bits & PP lsb */ |
663 | andc r1,r3,r1 /* PP = user? 2: 0 */ | 671 | andc r1,r0,r1 /* PP = user? 2: 0 */ |
664 | BEGIN_FTR_SECTION | 672 | BEGIN_FTR_SECTION |
665 | rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ | 673 | rlwinm r1,r1,0,~_PAGE_COHERENT /* clear M (coherence not required) */ |
666 | END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) | 674 | END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) |
667 | mtspr SPRN_RPA,r1 | 675 | mtspr SPRN_RPA,r1 |
668 | mfspr r3,SPRN_DMISS | 676 | mfspr r2,SPRN_SRR1 /* Need to restore CR0 */ |
677 | mtcrf 0x80,r2 | ||
678 | BEGIN_MMU_FTR_SECTION | ||
679 | li r0,1 | ||
680 | mfspr r1,SPRN_SPRG4 | ||
681 | rlwinm r2,r3,20,27,31 /* Get Address bits 15:19 */ | ||
682 | slw r0,r0,r2 | ||
683 | xor r1,r0,r1 | ||
684 | srw r0,r1,r2 | ||
685 | mtspr SPRN_SPRG4,r1 | ||
686 | mfspr r2,SPRN_SRR1 | ||
687 | rlwimi r2,r0,31-14,14,14 | ||
688 | mtspr SPRN_SRR1,r2 | ||
689 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU) | ||
669 | tlbld r3 | 690 | tlbld r3 |
670 | mfspr r3,SPRN_SRR1 /* Need to restore CR0 */ | ||
671 | mtcrf 0x80,r3 | ||
672 | rfi | 691 | rfi |
673 | 692 | ||
674 | #ifndef CONFIG_ALTIVEC | 693 | #ifndef CONFIG_ALTIVEC |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index ebaedafc8e67..50ef505b8fb6 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -1360,6 +1360,7 @@ _GLOBAL(__start_initialization_multiplatform) | |||
1360 | b .__after_prom_start | 1360 | b .__after_prom_start |
1361 | 1361 | ||
1362 | _INIT_STATIC(__boot_from_prom) | 1362 | _INIT_STATIC(__boot_from_prom) |
1363 | #ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE | ||
1363 | /* Save parameters */ | 1364 | /* Save parameters */ |
1364 | mr r31,r3 | 1365 | mr r31,r3 |
1365 | mr r30,r4 | 1366 | mr r30,r4 |
@@ -1390,7 +1391,10 @@ _INIT_STATIC(__boot_from_prom) | |||
1390 | /* Do all of the interaction with OF client interface */ | 1391 | /* Do all of the interaction with OF client interface */ |
1391 | mr r8,r26 | 1392 | mr r8,r26 |
1392 | bl .prom_init | 1393 | bl .prom_init |
1393 | /* We never return */ | 1394 | #endif /* #CONFIG_PPC_OF_BOOT_TRAMPOLINE */ |
1395 | |||
1396 | /* We never return. We also hit that trap if trying to boot | ||
1397 | * from OF while CONFIG_PPC_OF_BOOT_TRAMPOLINE isn't selected */ | ||
1394 | trap | 1398 | trap |
1395 | 1399 | ||
1396 | _STATIC(__after_prom_start) | 1400 | _STATIC(__after_prom_start) |
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h index fce2df988504..95f39f1e68d4 100644 --- a/arch/powerpc/kernel/head_booke.h +++ b/arch/powerpc/kernel/head_booke.h | |||
@@ -10,6 +10,15 @@ | |||
10 | mtspr SPRN_IVOR##vector_number,r26; \ | 10 | mtspr SPRN_IVOR##vector_number,r26; \ |
11 | sync | 11 | sync |
12 | 12 | ||
13 | #if (THREAD_SHIFT < 15) | ||
14 | #define ALLOC_STACK_FRAME(reg, val) \ | ||
15 | addi reg,reg,val | ||
16 | #else | ||
17 | #define ALLOC_STACK_FRAME(reg, val) \ | ||
18 | addis reg,reg,val@ha; \ | ||
19 | addi reg,reg,val@l | ||
20 | #endif | ||
21 | |||
13 | #define NORMAL_EXCEPTION_PROLOG \ | 22 | #define NORMAL_EXCEPTION_PROLOG \ |
14 | mtspr SPRN_SPRG0,r10; /* save two registers to work with */\ | 23 | mtspr SPRN_SPRG0,r10; /* save two registers to work with */\ |
15 | mtspr SPRN_SPRG1,r11; \ | 24 | mtspr SPRN_SPRG1,r11; \ |
@@ -20,7 +29,7 @@ | |||
20 | beq 1f; \ | 29 | beq 1f; \ |
21 | mfspr r1,SPRN_SPRG3; /* if from user, start at top of */\ | 30 | mfspr r1,SPRN_SPRG3; /* if from user, start at top of */\ |
22 | lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\ | 31 | lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\ |
23 | addi r1,r1,THREAD_SIZE; \ | 32 | ALLOC_STACK_FRAME(r1, THREAD_SIZE); \ |
24 | 1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\ | 33 | 1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\ |
25 | mr r11,r1; \ | 34 | mr r11,r1; \ |
26 | stw r10,_CCR(r11); /* save various registers */\ | 35 | stw r10,_CCR(r11); /* save various registers */\ |
@@ -70,10 +79,10 @@ | |||
70 | 79 | ||
71 | /* only on e500mc/e200 */ | 80 | /* only on e500mc/e200 */ |
72 | #define DEBUG_STACK_BASE dbgirq_ctx | 81 | #define DEBUG_STACK_BASE dbgirq_ctx |
73 | #ifdef CONFIG_PPC_E500MC | 82 | #ifdef CONFIG_E200 |
74 | #define DEBUG_SPRG SPRN_SPRG9 | ||
75 | #else | ||
76 | #define DEBUG_SPRG SPRN_SPRG6W | 83 | #define DEBUG_SPRG SPRN_SPRG6W |
84 | #else | ||
85 | #define DEBUG_SPRG SPRN_SPRG9 | ||
77 | #endif | 86 | #endif |
78 | 87 | ||
79 | #define EXC_LVL_FRAME_OVERHEAD (THREAD_SIZE - INT_FRAME_SIZE - EXC_LVL_SIZE) | 88 | #define EXC_LVL_FRAME_OVERHEAD (THREAD_SIZE - INT_FRAME_SIZE - EXC_LVL_SIZE) |
@@ -279,7 +288,7 @@ label: | |||
279 | lwz r11,GPR11(r8); \ | 288 | lwz r11,GPR11(r8); \ |
280 | mfspr r8,DEBUG_SPRG; \ | 289 | mfspr r8,DEBUG_SPRG; \ |
281 | \ | 290 | \ |
282 | RFDI; \ | 291 | PPC_RFDI; \ |
283 | b .; \ | 292 | b .; \ |
284 | \ | 293 | \ |
285 | /* continue normal handling for a debug exception... */ \ | 294 | /* continue normal handling for a debug exception... */ \ |
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 36ffb3504a4f..4c22620d009b 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
@@ -103,10 +103,15 @@ invstr: mflr r6 /* Make it accessible */ | |||
103 | or r7,r7,r4 | 103 | or r7,r7,r4 |
104 | mtspr SPRN_MAS6,r7 | 104 | mtspr SPRN_MAS6,r7 |
105 | tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */ | 105 | tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */ |
106 | #ifndef CONFIG_E200 | ||
107 | mfspr r7,SPRN_MAS1 | 106 | mfspr r7,SPRN_MAS1 |
108 | andis. r7,r7,MAS1_VALID@h | 107 | andis. r7,r7,MAS1_VALID@h |
109 | bne match_TLB | 108 | bne match_TLB |
109 | |||
110 | mfspr r7,SPRN_MMUCFG | ||
111 | rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */ | ||
112 | cmpwi r7,3 | ||
113 | bne match_TLB /* skip if NPIDS != 3 */ | ||
114 | |||
110 | mfspr r7,SPRN_PID1 | 115 | mfspr r7,SPRN_PID1 |
111 | slwi r7,r7,16 | 116 | slwi r7,r7,16 |
112 | or r7,r7,r4 | 117 | or r7,r7,r4 |
@@ -120,7 +125,7 @@ invstr: mflr r6 /* Make it accessible */ | |||
120 | or r7,r7,r4 | 125 | or r7,r7,r4 |
121 | mtspr SPRN_MAS6,r7 | 126 | mtspr SPRN_MAS6,r7 |
122 | tlbsx 0,r6 /* Fall through, we had to match */ | 127 | tlbsx 0,r6 /* Fall through, we had to match */ |
123 | #endif | 128 | |
124 | match_TLB: | 129 | match_TLB: |
125 | mfspr r7,SPRN_MAS0 | 130 | mfspr r7,SPRN_MAS0 |
126 | rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */ | 131 | rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */ |
@@ -168,7 +173,7 @@ skpinv: addi r6,r6,1 /* Increment */ | |||
168 | 173 | ||
169 | /* grab and fixup the RPN */ | 174 | /* grab and fixup the RPN */ |
170 | mfspr r6,SPRN_MAS1 /* extract MAS1[SIZE] */ | 175 | mfspr r6,SPRN_MAS1 /* extract MAS1[SIZE] */ |
171 | rlwinm r6,r6,25,27,30 | 176 | rlwinm r6,r6,25,27,31 |
172 | li r8,-1 | 177 | li r8,-1 |
173 | addi r6,r6,10 | 178 | addi r6,r6,10 |
174 | slw r6,r8,r6 /* convert to mask */ | 179 | slw r6,r8,r6 /* convert to mask */ |
@@ -194,7 +199,7 @@ skpinv: addi r6,r6,1 /* Increment */ | |||
194 | xori r6,r4,1 /* Setup TMP mapping in the other Address space */ | 199 | xori r6,r4,1 /* Setup TMP mapping in the other Address space */ |
195 | slwi r6,r6,12 | 200 | slwi r6,r6,12 |
196 | oris r6,r6,(MAS1_VALID|MAS1_IPROT)@h | 201 | oris r6,r6,(MAS1_VALID|MAS1_IPROT)@h |
197 | ori r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_4K))@l | 202 | ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_4K))@l |
198 | mtspr SPRN_MAS1,r6 | 203 | mtspr SPRN_MAS1,r6 |
199 | mfspr r6,SPRN_MAS2 | 204 | mfspr r6,SPRN_MAS2 |
200 | li r7,0 /* temp EPN = 0 */ | 205 | li r7,0 /* temp EPN = 0 */ |
@@ -215,14 +220,19 @@ skpinv: addi r6,r6,1 /* Increment */ | |||
215 | 220 | ||
216 | /* 4. Clear out PIDs & Search info */ | 221 | /* 4. Clear out PIDs & Search info */ |
217 | li r6,0 | 222 | li r6,0 |
223 | mtspr SPRN_MAS6,r6 | ||
218 | mtspr SPRN_PID0,r6 | 224 | mtspr SPRN_PID0,r6 |
219 | #ifndef CONFIG_E200 | 225 | |
226 | mfspr r7,SPRN_MMUCFG | ||
227 | rlwinm r7,r7,21,28,31 /* extract MMUCFG[NPIDS] */ | ||
228 | cmpwi r7,3 | ||
229 | bne 2f /* skip if NPIDS != 3 */ | ||
230 | |||
220 | mtspr SPRN_PID1,r6 | 231 | mtspr SPRN_PID1,r6 |
221 | mtspr SPRN_PID2,r6 | 232 | mtspr SPRN_PID2,r6 |
222 | #endif | ||
223 | mtspr SPRN_MAS6,r6 | ||
224 | 233 | ||
225 | /* 5. Invalidate mapping we started in */ | 234 | /* 5. Invalidate mapping we started in */ |
235 | 2: | ||
226 | lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ | 236 | lis r7,0x1000 /* Set MAS0(TLBSEL) = 1 */ |
227 | rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */ | 237 | rlwimi r7,r3,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r3) */ |
228 | mtspr SPRN_MAS0,r7 | 238 | mtspr SPRN_MAS0,r7 |
@@ -247,10 +257,10 @@ skpinv: addi r6,r6,1 /* Increment */ | |||
247 | lis r6,0x1000 /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */ | 257 | lis r6,0x1000 /* Set MAS0(TLBSEL) = TLB1(1), ESEL = 0 */ |
248 | mtspr SPRN_MAS0,r6 | 258 | mtspr SPRN_MAS0,r6 |
249 | lis r6,(MAS1_VALID|MAS1_IPROT)@h | 259 | lis r6,(MAS1_VALID|MAS1_IPROT)@h |
250 | ori r6,r6,(MAS1_TSIZE(BOOKE_PAGESZ_64M))@l | 260 | ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_64M))@l |
251 | mtspr SPRN_MAS1,r6 | 261 | mtspr SPRN_MAS1,r6 |
252 | lis r6,MAS2_VAL(PAGE_OFFSET, BOOKE_PAGESZ_64M, M_IF_SMP)@h | 262 | lis r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@h |
253 | ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOKE_PAGESZ_64M, M_IF_SMP)@l | 263 | ori r6,r6,MAS2_VAL(PAGE_OFFSET, BOOK3E_PAGESZ_64M, M_IF_SMP)@l |
254 | mtspr SPRN_MAS2,r6 | 264 | mtspr SPRN_MAS2,r6 |
255 | mtspr SPRN_MAS3,r8 | 265 | mtspr SPRN_MAS3,r8 |
256 | tlbwe | 266 | tlbwe |
@@ -298,26 +308,14 @@ skpinv: addi r6,r6,1 /* Increment */ | |||
298 | SET_IVOR(12, WatchdogTimer); | 308 | SET_IVOR(12, WatchdogTimer); |
299 | SET_IVOR(13, DataTLBError); | 309 | SET_IVOR(13, DataTLBError); |
300 | SET_IVOR(14, InstructionTLBError); | 310 | SET_IVOR(14, InstructionTLBError); |
301 | SET_IVOR(15, DebugDebug); | ||
302 | #if defined(CONFIG_E500) && !defined(CONFIG_PPC_E500MC) | ||
303 | SET_IVOR(15, DebugCrit); | 311 | SET_IVOR(15, DebugCrit); |
304 | #endif | ||
305 | SET_IVOR(32, SPEUnavailable); | ||
306 | SET_IVOR(33, SPEFloatingPointData); | ||
307 | SET_IVOR(34, SPEFloatingPointRound); | ||
308 | #ifndef CONFIG_E200 | ||
309 | SET_IVOR(35, PerformanceMonitor); | ||
310 | #endif | ||
311 | #ifdef CONFIG_PPC_E500MC | ||
312 | SET_IVOR(36, Doorbell); | ||
313 | #endif | ||
314 | 312 | ||
315 | /* Establish the interrupt vector base */ | 313 | /* Establish the interrupt vector base */ |
316 | lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */ | 314 | lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */ |
317 | mtspr SPRN_IVPR,r4 | 315 | mtspr SPRN_IVPR,r4 |
318 | 316 | ||
319 | /* Setup the defaults for TLB entries */ | 317 | /* Setup the defaults for TLB entries */ |
320 | li r2,(MAS4_TSIZED(BOOKE_PAGESZ_4K))@l | 318 | li r2,(MAS4_TSIZED(BOOK3E_PAGESZ_4K))@l |
321 | #ifdef CONFIG_E200 | 319 | #ifdef CONFIG_E200 |
322 | oris r2,r2,MAS4_TLBSELD(1)@h | 320 | oris r2,r2,MAS4_TLBSELD(1)@h |
323 | #endif | 321 | #endif |
@@ -329,12 +327,6 @@ skpinv: addi r6,r6,1 /* Increment */ | |||
329 | oris r2,r2,HID0_DOZE@h | 327 | oris r2,r2,HID0_DOZE@h |
330 | mtspr SPRN_HID0, r2 | 328 | mtspr SPRN_HID0, r2 |
331 | #endif | 329 | #endif |
332 | #ifdef CONFIG_E200 | ||
333 | /* enable dedicated debug exception handling resources (Debug APU) */ | ||
334 | mfspr r2,SPRN_HID0 | ||
335 | ori r2,r2,HID0_DAPUEN@l | ||
336 | mtspr SPRN_HID0,r2 | ||
337 | #endif | ||
338 | 330 | ||
339 | #if !defined(CONFIG_BDI_SWITCH) | 331 | #if !defined(CONFIG_BDI_SWITCH) |
340 | /* | 332 | /* |
@@ -706,15 +698,13 @@ interrupt_base: | |||
706 | /* Performance Monitor */ | 698 | /* Performance Monitor */ |
707 | EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD) | 699 | EXCEPTION(0x2060, PerformanceMonitor, performance_monitor_exception, EXC_XFER_STD) |
708 | 700 | ||
709 | #ifdef CONFIG_PPC_E500MC | 701 | EXCEPTION(0x2070, Doorbell, doorbell_exception, EXC_XFER_STD) |
710 | EXCEPTION(0x2070, Doorbell, unknown_exception, EXC_XFER_STD) | 702 | |
711 | #endif | 703 | CRITICAL_EXCEPTION(0x2080, CriticalDoorbell, unknown_exception) |
712 | 704 | ||
713 | /* Debug Interrupt */ | 705 | /* Debug Interrupt */ |
714 | DEBUG_DEBUG_EXCEPTION | 706 | DEBUG_DEBUG_EXCEPTION |
715 | #if defined(CONFIG_E500) && !defined(CONFIG_PPC_E500MC) | ||
716 | DEBUG_CRIT_EXCEPTION | 707 | DEBUG_CRIT_EXCEPTION |
717 | #endif | ||
718 | 708 | ||
719 | /* | 709 | /* |
720 | * Local functions | 710 | * Local functions |
@@ -897,6 +887,47 @@ KernelSPE: | |||
897 | * Global functions | 887 | * Global functions |
898 | */ | 888 | */ |
899 | 889 | ||
890 | /* Adjust or setup IVORs for e200 */ | ||
891 | _GLOBAL(__setup_e200_ivors) | ||
892 | li r3,DebugDebug@l | ||
893 | mtspr SPRN_IVOR15,r3 | ||
894 | li r3,SPEUnavailable@l | ||
895 | mtspr SPRN_IVOR32,r3 | ||
896 | li r3,SPEFloatingPointData@l | ||
897 | mtspr SPRN_IVOR33,r3 | ||
898 | li r3,SPEFloatingPointRound@l | ||
899 | mtspr SPRN_IVOR34,r3 | ||
900 | sync | ||
901 | blr | ||
902 | |||
903 | /* Adjust or setup IVORs for e500v1/v2 */ | ||
904 | _GLOBAL(__setup_e500_ivors) | ||
905 | li r3,DebugCrit@l | ||
906 | mtspr SPRN_IVOR15,r3 | ||
907 | li r3,SPEUnavailable@l | ||
908 | mtspr SPRN_IVOR32,r3 | ||
909 | li r3,SPEFloatingPointData@l | ||
910 | mtspr SPRN_IVOR33,r3 | ||
911 | li r3,SPEFloatingPointRound@l | ||
912 | mtspr SPRN_IVOR34,r3 | ||
913 | li r3,PerformanceMonitor@l | ||
914 | mtspr SPRN_IVOR35,r3 | ||
915 | sync | ||
916 | blr | ||
917 | |||
918 | /* Adjust or setup IVORs for e500mc */ | ||
919 | _GLOBAL(__setup_e500mc_ivors) | ||
920 | li r3,DebugDebug@l | ||
921 | mtspr SPRN_IVOR15,r3 | ||
922 | li r3,PerformanceMonitor@l | ||
923 | mtspr SPRN_IVOR35,r3 | ||
924 | li r3,Doorbell@l | ||
925 | mtspr SPRN_IVOR36,r3 | ||
926 | li r3,CriticalDoorbell@l | ||
927 | mtspr SPRN_IVOR37,r3 | ||
928 | sync | ||
929 | blr | ||
930 | |||
900 | /* | 931 | /* |
901 | * extern void loadcam_entry(unsigned int index) | 932 | * extern void loadcam_entry(unsigned int index) |
902 | * | 933 | * |
@@ -1089,7 +1120,7 @@ __secondary_start: | |||
1089 | mtspr SPRN_SPRG3,r4 | 1120 | mtspr SPRN_SPRG3,r4 |
1090 | 1121 | ||
1091 | /* Setup the defaults for TLB entries */ | 1122 | /* Setup the defaults for TLB entries */ |
1092 | li r4,(MAS4_TSIZED(BOOKE_PAGESZ_4K))@l | 1123 | li r4,(MAS4_TSIZED(BOOK3E_PAGESZ_4K))@l |
1093 | mtspr SPRN_MAS4,r4 | 1124 | mtspr SPRN_MAS4,r4 |
1094 | 1125 | ||
1095 | /* Jump to start_secondary */ | 1126 | /* Jump to start_secondary */ |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 1b55ffdf0026..8c1a4966867e 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -171,7 +171,7 @@ int show_interrupts(struct seq_file *p, void *v) | |||
171 | { | 171 | { |
172 | int i = *(loff_t *)v, j; | 172 | int i = *(loff_t *)v, j; |
173 | struct irqaction *action; | 173 | struct irqaction *action; |
174 | irq_desc_t *desc; | 174 | struct irq_desc *desc; |
175 | unsigned long flags; | 175 | unsigned long flags; |
176 | 176 | ||
177 | if (i == 0) { | 177 | if (i == 0) { |
@@ -672,11 +672,13 @@ unsigned int irq_create_mapping(struct irq_host *host, | |||
672 | return NO_IRQ; | 672 | return NO_IRQ; |
673 | } | 673 | } |
674 | } | 674 | } |
675 | pr_debug("irq: -> obtained virq %d\n", virq); | ||
676 | 675 | ||
677 | if (irq_setup_virq(host, virq, hwirq)) | 676 | if (irq_setup_virq(host, virq, hwirq)) |
678 | return NO_IRQ; | 677 | return NO_IRQ; |
679 | 678 | ||
679 | printk(KERN_DEBUG "irq: irq %lu on host %s mapped to virtual irq %u\n", | ||
680 | hwirq, host->of_node ? host->of_node->full_name : "null", virq); | ||
681 | |||
680 | return virq; | 682 | return virq; |
681 | } | 683 | } |
682 | EXPORT_SYMBOL_GPL(irq_create_mapping); | 684 | EXPORT_SYMBOL_GPL(irq_create_mapping); |
@@ -1038,7 +1040,7 @@ arch_initcall(irq_late_init); | |||
1038 | static int virq_debug_show(struct seq_file *m, void *private) | 1040 | static int virq_debug_show(struct seq_file *m, void *private) |
1039 | { | 1041 | { |
1040 | unsigned long flags; | 1042 | unsigned long flags; |
1041 | irq_desc_t *desc; | 1043 | struct irq_desc *desc; |
1042 | const char *p; | 1044 | const char *p; |
1043 | char none[] = "none"; | 1045 | char none[] = "none"; |
1044 | int i; | 1046 | int i; |
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 182e0f642f36..78b3f7840ade 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
@@ -434,6 +434,21 @@ static void pseries_cmo_data(struct seq_file *m) | |||
434 | seq_printf(m, "cmo_page_size=%lu\n", cmo_get_page_size()); | 434 | seq_printf(m, "cmo_page_size=%lu\n", cmo_get_page_size()); |
435 | } | 435 | } |
436 | 436 | ||
437 | static void splpar_dispatch_data(struct seq_file *m) | ||
438 | { | ||
439 | int cpu; | ||
440 | unsigned long dispatches = 0; | ||
441 | unsigned long dispatch_dispersions = 0; | ||
442 | |||
443 | for_each_possible_cpu(cpu) { | ||
444 | dispatches += lppaca[cpu].yield_count; | ||
445 | dispatch_dispersions += lppaca[cpu].dispersion_count; | ||
446 | } | ||
447 | |||
448 | seq_printf(m, "dispatches=%lu\n", dispatches); | ||
449 | seq_printf(m, "dispatch_dispersions=%lu\n", dispatch_dispersions); | ||
450 | } | ||
451 | |||
437 | static int pseries_lparcfg_data(struct seq_file *m, void *v) | 452 | static int pseries_lparcfg_data(struct seq_file *m, void *v) |
438 | { | 453 | { |
439 | int partition_potential_processors; | 454 | int partition_potential_processors; |
@@ -460,6 +475,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) | |||
460 | parse_ppp_data(m); | 475 | parse_ppp_data(m); |
461 | parse_mpp_data(m); | 476 | parse_mpp_data(m); |
462 | pseries_cmo_data(m); | 477 | pseries_cmo_data(m); |
478 | splpar_dispatch_data(m); | ||
463 | 479 | ||
464 | seq_printf(m, "purr=%ld\n", get_purr()); | 480 | seq_printf(m, "purr=%ld\n", get_purr()); |
465 | } else { /* non SPLPAR case */ | 481 | } else { /* non SPLPAR case */ |
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 3053fe5c62f2..b9530b2395a2 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S | |||
@@ -495,7 +495,15 @@ _GLOBAL(giveup_altivec) | |||
495 | stvx vr0,r4,r3 | 495 | stvx vr0,r4,r3 |
496 | beq 1f | 496 | beq 1f |
497 | ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 497 | ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
498 | #ifdef CONFIG_VSX | ||
499 | BEGIN_FTR_SECTION | ||
500 | lis r3,(MSR_VEC|MSR_VSX)@h | ||
501 | FTR_SECTION_ELSE | ||
502 | lis r3,MSR_VEC@h | ||
503 | ALT_FTR_SECTION_END_IFSET(CPU_FTR_VSX) | ||
504 | #else | ||
498 | lis r3,MSR_VEC@h | 505 | lis r3,MSR_VEC@h |
506 | #endif | ||
499 | andc r4,r4,r3 /* disable FP for previous task */ | 507 | andc r4,r4,r3 /* disable FP for previous task */ |
500 | std r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 508 | std r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
501 | 1: | 509 | 1: |
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index 8992b031a7b6..8fbb12508bf3 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c | |||
@@ -329,7 +329,7 @@ static unsigned long stub_for_addr(Elf64_Shdr *sechdrs, | |||
329 | restore r2. */ | 329 | restore r2. */ |
330 | static int restore_r2(u32 *instruction, struct module *me) | 330 | static int restore_r2(u32 *instruction, struct module *me) |
331 | { | 331 | { |
332 | if (*instruction != PPC_NOP_INSTR) { | 332 | if (*instruction != PPC_INST_NOP) { |
333 | printk("%s: Expect noop after relocate, got %08x\n", | 333 | printk("%s: Expect noop after relocate, got %08x\n", |
334 | me->name, *instruction); | 334 | me->name, *instruction); |
335 | return 0; | 335 | return 0; |
diff --git a/arch/powerpc/kernel/msi.c b/arch/powerpc/kernel/msi.c index 3bb7d3dd28be..8bbc12d20f5c 100644 --- a/arch/powerpc/kernel/msi.c +++ b/arch/powerpc/kernel/msi.c | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/msi.h> | 11 | #include <linux/msi.h> |
12 | #include <linux/pci.h> | ||
12 | 13 | ||
13 | #include <asm/machdep.h> | 14 | #include <asm/machdep.h> |
14 | 15 | ||
@@ -19,6 +20,10 @@ int arch_msi_check_device(struct pci_dev* dev, int nvec, int type) | |||
19 | return -ENOSYS; | 20 | return -ENOSYS; |
20 | } | 21 | } |
21 | 22 | ||
23 | /* PowerPC doesn't support multiple MSI yet */ | ||
24 | if (type == PCI_CAP_ID_MSI && nvec > 1) | ||
25 | return 1; | ||
26 | |||
22 | if (ppc_md.msi_check_device) { | 27 | if (ppc_md.msi_check_device) { |
23 | pr_debug("msi: Using platform check routine.\n"); | 28 | pr_debug("msi: Using platform check routine.\n"); |
24 | return ppc_md.msi_check_device(dev, nvec, type); | 29 | return ppc_md.msi_check_device(dev, nvec, type); |
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index 3f37a6e62771..87df428e3588 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c | |||
@@ -76,7 +76,7 @@ struct of_device* of_platform_device_create(struct device_node *np, | |||
76 | return NULL; | 76 | return NULL; |
77 | 77 | ||
78 | dev->dma_mask = 0xffffffffUL; | 78 | dev->dma_mask = 0xffffffffUL; |
79 | dev->dev.coherent_dma_mask = DMA_32BIT_MASK; | 79 | dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); |
80 | 80 | ||
81 | dev->dev.bus = &of_platform_bus_type; | 81 | dev->dev.bus = &of_platform_bus_type; |
82 | 82 | ||
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 0f4181272311..9c69e7e145c5 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <asm/eeh.h> | 38 | #include <asm/eeh.h> |
39 | 39 | ||
40 | static DEFINE_SPINLOCK(hose_spinlock); | 40 | static DEFINE_SPINLOCK(hose_spinlock); |
41 | LIST_HEAD(hose_list); | ||
41 | 42 | ||
42 | /* XXX kill that some day ... */ | 43 | /* XXX kill that some day ... */ |
43 | static int global_phb_number; /* Global phb counter */ | 44 | static int global_phb_number; /* Global phb counter */ |
@@ -49,7 +50,7 @@ resource_size_t isa_mem_base; | |||
49 | unsigned int ppc_pci_flags = 0; | 50 | unsigned int ppc_pci_flags = 0; |
50 | 51 | ||
51 | 52 | ||
52 | static struct dma_mapping_ops *pci_dma_ops; | 53 | static struct dma_mapping_ops *pci_dma_ops = &dma_direct_ops; |
53 | 54 | ||
54 | void set_pci_dma_ops(struct dma_mapping_ops *dma_ops) | 55 | void set_pci_dma_ops(struct dma_mapping_ops *dma_ops) |
55 | { | 56 | { |
@@ -113,19 +114,24 @@ void pcibios_free_controller(struct pci_controller *phb) | |||
113 | kfree(phb); | 114 | kfree(phb); |
114 | } | 115 | } |
115 | 116 | ||
117 | static resource_size_t pcibios_io_size(const struct pci_controller *hose) | ||
118 | { | ||
119 | #ifdef CONFIG_PPC64 | ||
120 | return hose->pci_io_size; | ||
121 | #else | ||
122 | return hose->io_resource.end - hose->io_resource.start + 1; | ||
123 | #endif | ||
124 | } | ||
125 | |||
116 | int pcibios_vaddr_is_ioport(void __iomem *address) | 126 | int pcibios_vaddr_is_ioport(void __iomem *address) |
117 | { | 127 | { |
118 | int ret = 0; | 128 | int ret = 0; |
119 | struct pci_controller *hose; | 129 | struct pci_controller *hose; |
120 | unsigned long size; | 130 | resource_size_t size; |
121 | 131 | ||
122 | spin_lock(&hose_spinlock); | 132 | spin_lock(&hose_spinlock); |
123 | list_for_each_entry(hose, &hose_list, list_node) { | 133 | list_for_each_entry(hose, &hose_list, list_node) { |
124 | #ifdef CONFIG_PPC64 | 134 | size = pcibios_io_size(hose); |
125 | size = hose->pci_io_size; | ||
126 | #else | ||
127 | size = hose->io_resource.end - hose->io_resource.start + 1; | ||
128 | #endif | ||
129 | if (address >= hose->io_base_virt && | 135 | if (address >= hose->io_base_virt && |
130 | address < (hose->io_base_virt + size)) { | 136 | address < (hose->io_base_virt + size)) { |
131 | ret = 1; | 137 | ret = 1; |
@@ -136,6 +142,29 @@ int pcibios_vaddr_is_ioport(void __iomem *address) | |||
136 | return ret; | 142 | return ret; |
137 | } | 143 | } |
138 | 144 | ||
145 | unsigned long pci_address_to_pio(phys_addr_t address) | ||
146 | { | ||
147 | struct pci_controller *hose; | ||
148 | resource_size_t size; | ||
149 | unsigned long ret = ~0; | ||
150 | |||
151 | spin_lock(&hose_spinlock); | ||
152 | list_for_each_entry(hose, &hose_list, list_node) { | ||
153 | size = pcibios_io_size(hose); | ||
154 | if (address >= hose->io_base_phys && | ||
155 | address < (hose->io_base_phys + size)) { | ||
156 | unsigned long base = | ||
157 | (unsigned long)hose->io_base_virt - _IO_BASE; | ||
158 | ret = base + (address - hose->io_base_phys); | ||
159 | break; | ||
160 | } | ||
161 | } | ||
162 | spin_unlock(&hose_spinlock); | ||
163 | |||
164 | return ret; | ||
165 | } | ||
166 | EXPORT_SYMBOL_GPL(pci_address_to_pio); | ||
167 | |||
139 | /* | 168 | /* |
140 | * Return the domain number for this bus. | 169 | * Return the domain number for this bus. |
141 | */ | 170 | */ |
@@ -1453,7 +1482,7 @@ void __init pcibios_resource_survey(void) | |||
1453 | * we proceed to assigning things that were left unassigned | 1482 | * we proceed to assigning things that were left unassigned |
1454 | */ | 1483 | */ |
1455 | if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) { | 1484 | if (!(ppc_pci_flags & PPC_PCI_PROBE_ONLY)) { |
1456 | pr_debug("PCI: Assigning unassigned resouces...\n"); | 1485 | pr_debug("PCI: Assigning unassigned resources...\n"); |
1457 | pci_assign_unassigned_resources(); | 1486 | pci_assign_unassigned_resources(); |
1458 | } | 1487 | } |
1459 | 1488 | ||
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 132cd80afa21..d473634e39e3 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <asm/prom.h> | 20 | #include <asm/prom.h> |
21 | #include <asm/sections.h> | 21 | #include <asm/sections.h> |
22 | #include <asm/pci-bridge.h> | 22 | #include <asm/pci-bridge.h> |
23 | #include <asm/ppc-pci.h> | ||
23 | #include <asm/byteorder.h> | 24 | #include <asm/byteorder.h> |
24 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
25 | #include <asm/machdep.h> | 26 | #include <asm/machdep.h> |
@@ -43,8 +44,6 @@ static u8* pci_to_OF_bus_map; | |||
43 | */ | 44 | */ |
44 | static int pci_assign_all_buses; | 45 | static int pci_assign_all_buses; |
45 | 46 | ||
46 | LIST_HEAD(hose_list); | ||
47 | |||
48 | static int pci_bus_count; | 47 | static int pci_bus_count; |
49 | 48 | ||
50 | /* This will remain NULL for now, until isa-bridge.c is made common | 49 | /* This will remain NULL for now, until isa-bridge.c is made common |
@@ -219,16 +218,23 @@ scan_OF_pci_childs(struct device_node *parent, pci_OF_scan_iterator filter, void | |||
219 | static struct device_node *scan_OF_for_pci_dev(struct device_node *parent, | 218 | static struct device_node *scan_OF_for_pci_dev(struct device_node *parent, |
220 | unsigned int devfn) | 219 | unsigned int devfn) |
221 | { | 220 | { |
222 | struct device_node *np; | 221 | struct device_node *np, *cnp; |
223 | const u32 *reg; | 222 | const u32 *reg; |
224 | unsigned int psize; | 223 | unsigned int psize; |
225 | 224 | ||
226 | for_each_child_of_node(parent, np) { | 225 | for_each_child_of_node(parent, np) { |
227 | reg = of_get_property(np, "reg", &psize); | 226 | reg = of_get_property(np, "reg", &psize); |
228 | if (reg == NULL || psize < 4) | 227 | if (reg && psize >= 4 && ((reg[0] >> 8) & 0xff) == devfn) |
229 | continue; | ||
230 | if (((reg[0] >> 8) & 0xff) == devfn) | ||
231 | return np; | 228 | return np; |
229 | |||
230 | /* Note: some OFs create a parent node "multifunc-device" as | ||
231 | * a fake root for all functions of a multi-function device, | ||
232 | * we go down them as well. */ | ||
233 | if (!strcmp(np->name, "multifunc-device")) { | ||
234 | cnp = scan_OF_for_pci_dev(np, devfn); | ||
235 | if (cnp) | ||
236 | return cnp; | ||
237 | } | ||
232 | } | 238 | } |
233 | return NULL; | 239 | return NULL; |
234 | } | 240 | } |
@@ -491,24 +497,6 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) | |||
491 | return result; | 497 | return result; |
492 | } | 498 | } |
493 | 499 | ||
494 | unsigned long pci_address_to_pio(phys_addr_t address) | ||
495 | { | ||
496 | struct pci_controller *hose, *tmp; | ||
497 | |||
498 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | ||
499 | unsigned int size = hose->io_resource.end - | ||
500 | hose->io_resource.start + 1; | ||
501 | if (address >= hose->io_base_phys && | ||
502 | address < (hose->io_base_phys + size)) { | ||
503 | unsigned long base = | ||
504 | (unsigned long)hose->io_base_virt - _IO_BASE; | ||
505 | return base + (address - hose->io_base_phys); | ||
506 | } | ||
507 | } | ||
508 | return (unsigned int)-1; | ||
509 | } | ||
510 | EXPORT_SYMBOL(pci_address_to_pio); | ||
511 | |||
512 | /* | 500 | /* |
513 | * Null PCI config access functions, for the case when we can't | 501 | * Null PCI config access functions, for the case when we can't |
514 | * find a hose. | 502 | * find a hose. |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index ea8eda8c87cf..be574fc0d92f 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -43,8 +43,6 @@ unsigned long pci_probe_only = 1; | |||
43 | unsigned long pci_io_base = ISA_IO_BASE; | 43 | unsigned long pci_io_base = ISA_IO_BASE; |
44 | EXPORT_SYMBOL(pci_io_base); | 44 | EXPORT_SYMBOL(pci_io_base); |
45 | 45 | ||
46 | LIST_HEAD(hose_list); | ||
47 | |||
48 | static void fixup_broken_pcnet32(struct pci_dev* dev) | 46 | static void fixup_broken_pcnet32(struct pci_dev* dev) |
49 | { | 47 | { |
50 | if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { | 48 | if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { |
@@ -524,23 +522,6 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus) | |||
524 | } | 522 | } |
525 | EXPORT_SYMBOL_GPL(pcibios_map_io_space); | 523 | EXPORT_SYMBOL_GPL(pcibios_map_io_space); |
526 | 524 | ||
527 | unsigned long pci_address_to_pio(phys_addr_t address) | ||
528 | { | ||
529 | struct pci_controller *hose, *tmp; | ||
530 | |||
531 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | ||
532 | if (address >= hose->io_base_phys && | ||
533 | address < (hose->io_base_phys + hose->pci_io_size)) { | ||
534 | unsigned long base = | ||
535 | (unsigned long)hose->io_base_virt - _IO_BASE; | ||
536 | return base + (address - hose->io_base_phys); | ||
537 | } | ||
538 | } | ||
539 | return (unsigned int)-1; | ||
540 | } | ||
541 | EXPORT_SYMBOL_GPL(pci_address_to_pio); | ||
542 | |||
543 | |||
544 | #define IOBASE_BRIDGE_NUMBER 0 | 525 | #define IOBASE_BRIDGE_NUMBER 0 |
545 | #define IOBASE_MEMORY 1 | 526 | #define IOBASE_MEMORY 1 |
546 | #define IOBASE_IO 2 | 527 | #define IOBASE_IO 2 |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index fb7049c054c0..7b44a33f03c2 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -33,7 +33,10 @@ | |||
33 | #include <linux/mqueue.h> | 33 | #include <linux/mqueue.h> |
34 | #include <linux/hardirq.h> | 34 | #include <linux/hardirq.h> |
35 | #include <linux/utsname.h> | 35 | #include <linux/utsname.h> |
36 | #include <linux/ftrace.h> | ||
36 | #include <linux/kernel_stat.h> | 37 | #include <linux/kernel_stat.h> |
38 | #include <linux/personality.h> | ||
39 | #include <linux/random.h> | ||
37 | 40 | ||
38 | #include <asm/pgtable.h> | 41 | #include <asm/pgtable.h> |
39 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
@@ -595,7 +598,7 @@ void prepare_to_copy(struct task_struct *tsk) | |||
595 | /* | 598 | /* |
596 | * Copy a thread.. | 599 | * Copy a thread.. |
597 | */ | 600 | */ |
598 | int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, | 601 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
599 | unsigned long unused, struct task_struct *p, | 602 | unsigned long unused, struct task_struct *p, |
600 | struct pt_regs *regs) | 603 | struct pt_regs *regs) |
601 | { | 604 | { |
@@ -1008,6 +1011,14 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) | |||
1008 | unsigned long sp, ip, lr, newsp; | 1011 | unsigned long sp, ip, lr, newsp; |
1009 | int count = 0; | 1012 | int count = 0; |
1010 | int firstframe = 1; | 1013 | int firstframe = 1; |
1014 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
1015 | int curr_frame = current->curr_ret_stack; | ||
1016 | extern void return_to_handler(void); | ||
1017 | unsigned long addr = (unsigned long)return_to_handler; | ||
1018 | #ifdef CONFIG_PPC64 | ||
1019 | addr = *(unsigned long*)addr; | ||
1020 | #endif | ||
1021 | #endif | ||
1011 | 1022 | ||
1012 | sp = (unsigned long) stack; | 1023 | sp = (unsigned long) stack; |
1013 | if (tsk == NULL) | 1024 | if (tsk == NULL) |
@@ -1030,6 +1041,13 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) | |||
1030 | ip = stack[STACK_FRAME_LR_SAVE]; | 1041 | ip = stack[STACK_FRAME_LR_SAVE]; |
1031 | if (!firstframe || ip != lr) { | 1042 | if (!firstframe || ip != lr) { |
1032 | printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip); | 1043 | printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip); |
1044 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
1045 | if (ip == addr && curr_frame >= 0) { | ||
1046 | printk(" (%pS)", | ||
1047 | (void *)current->ret_stack[curr_frame].ret); | ||
1048 | curr_frame--; | ||
1049 | } | ||
1050 | #endif | ||
1033 | if (firstframe) | 1051 | if (firstframe) |
1034 | printk(" (unreliable)"); | 1052 | printk(" (unreliable)"); |
1035 | printk("\n"); | 1053 | printk("\n"); |
@@ -1122,3 +1140,43 @@ void thread_info_cache_init(void) | |||
1122 | } | 1140 | } |
1123 | 1141 | ||
1124 | #endif /* THREAD_SHIFT < PAGE_SHIFT */ | 1142 | #endif /* THREAD_SHIFT < PAGE_SHIFT */ |
1143 | |||
1144 | unsigned long arch_align_stack(unsigned long sp) | ||
1145 | { | ||
1146 | if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) | ||
1147 | sp -= get_random_int() & ~PAGE_MASK; | ||
1148 | return sp & ~0xf; | ||
1149 | } | ||
1150 | |||
1151 | static inline unsigned long brk_rnd(void) | ||
1152 | { | ||
1153 | unsigned long rnd = 0; | ||
1154 | |||
1155 | /* 8MB for 32bit, 1GB for 64bit */ | ||
1156 | if (is_32bit_task()) | ||
1157 | rnd = (long)(get_random_int() % (1<<(23-PAGE_SHIFT))); | ||
1158 | else | ||
1159 | rnd = (long)(get_random_int() % (1<<(30-PAGE_SHIFT))); | ||
1160 | |||
1161 | return rnd << PAGE_SHIFT; | ||
1162 | } | ||
1163 | |||
1164 | unsigned long arch_randomize_brk(struct mm_struct *mm) | ||
1165 | { | ||
1166 | unsigned long ret = PAGE_ALIGN(mm->brk + brk_rnd()); | ||
1167 | |||
1168 | if (ret < mm->brk) | ||
1169 | return mm->brk; | ||
1170 | |||
1171 | return ret; | ||
1172 | } | ||
1173 | |||
1174 | unsigned long randomize_et_dyn(unsigned long base) | ||
1175 | { | ||
1176 | unsigned long ret = PAGE_ALIGN(base + brk_rnd()); | ||
1177 | |||
1178 | if (ret < base) | ||
1179 | return base; | ||
1180 | |||
1181 | return ret; | ||
1182 | } | ||
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index f00f83109ab3..5ec6a9e23933 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -1075,11 +1075,6 @@ static void __init early_reserve_mem(void) | |||
1075 | DBG("reserving: %llx -> %llx\n", base, size); | 1075 | DBG("reserving: %llx -> %llx\n", base, size); |
1076 | lmb_reserve(base, size); | 1076 | lmb_reserve(base, size); |
1077 | } | 1077 | } |
1078 | |||
1079 | #if 0 | ||
1080 | DBG("memory reserved, lmbs :\n"); | ||
1081 | lmb_dump_all(); | ||
1082 | #endif | ||
1083 | } | 1078 | } |
1084 | 1079 | ||
1085 | #ifdef CONFIG_PHYP_DUMP | 1080 | #ifdef CONFIG_PHYP_DUMP |
@@ -1221,6 +1216,7 @@ void __init early_init_devtree(void *params) | |||
1221 | lmb_enforce_memory_limit(limit); | 1216 | lmb_enforce_memory_limit(limit); |
1222 | 1217 | ||
1223 | lmb_analyze(); | 1218 | lmb_analyze(); |
1219 | lmb_dump_all(); | ||
1224 | 1220 | ||
1225 | DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); | 1221 | DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); |
1226 | 1222 | ||
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 7f1b33d5e30d..2f0e64b53642 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -614,7 +614,7 @@ static unsigned char ibm_architecture_vec[] = { | |||
614 | W(0xffffffff), /* virt_base */ | 614 | W(0xffffffff), /* virt_base */ |
615 | W(0xffffffff), /* virt_size */ | 615 | W(0xffffffff), /* virt_size */ |
616 | W(0xffffffff), /* load_base */ | 616 | W(0xffffffff), /* load_base */ |
617 | W(64), /* 128MB min RMA */ | 617 | W(64), /* 64MB min RMA */ |
618 | W(0xffffffff), /* full client load */ | 618 | W(0xffffffff), /* full client load */ |
619 | 0, /* min RMA percentage of total RAM */ | 619 | 0, /* min RMA percentage of total RAM */ |
620 | 48, /* max log_2(hash table size) */ | 620 | 48, /* max log_2(hash table size) */ |
@@ -732,15 +732,17 @@ static void __init prom_send_capabilities(void) | |||
732 | root = call_prom("open", 1, 1, ADDR("/")); | 732 | root = call_prom("open", 1, 1, ADDR("/")); |
733 | if (root != 0) { | 733 | if (root != 0) { |
734 | /* try calling the ibm,client-architecture-support method */ | 734 | /* try calling the ibm,client-architecture-support method */ |
735 | prom_printf("Calling ibm,client-architecture..."); | ||
735 | if (call_prom_ret("call-method", 3, 2, &ret, | 736 | if (call_prom_ret("call-method", 3, 2, &ret, |
736 | ADDR("ibm,client-architecture-support"), | 737 | ADDR("ibm,client-architecture-support"), |
737 | root, | 738 | root, |
738 | ADDR(ibm_architecture_vec)) == 0) { | 739 | ADDR(ibm_architecture_vec)) == 0) { |
739 | /* the call exists... */ | 740 | /* the call exists... */ |
740 | if (ret) | 741 | if (ret) |
741 | prom_printf("WARNING: ibm,client-architecture" | 742 | prom_printf("\nWARNING: ibm,client-architecture" |
742 | "-support call FAILED!\n"); | 743 | "-support call FAILED!\n"); |
743 | call_prom("close", 1, 0, root); | 744 | call_prom("close", 1, 0, root); |
745 | prom_printf(" done\n"); | ||
744 | return; | 746 | return; |
745 | } | 747 | } |
746 | call_prom("close", 1, 0, root); | 748 | call_prom("close", 1, 0, root); |
@@ -1083,7 +1085,7 @@ static void __init prom_instantiate_rtas(void) | |||
1083 | return; | 1085 | return; |
1084 | } | 1086 | } |
1085 | 1087 | ||
1086 | prom_printf("instantiating rtas at 0x%x ...", base); | 1088 | prom_printf("instantiating rtas at 0x%x...", base); |
1087 | 1089 | ||
1088 | if (call_prom_ret("call-method", 3, 2, &entry, | 1090 | if (call_prom_ret("call-method", 3, 2, &entry, |
1089 | ADDR("instantiate-rtas"), | 1091 | ADDR("instantiate-rtas"), |
@@ -1495,7 +1497,7 @@ static int __init prom_find_machine_type(void) | |||
1495 | return PLATFORM_GENERIC; | 1497 | return PLATFORM_GENERIC; |
1496 | x = prom_getproplen(rtas, "ibm,hypertas-functions"); | 1498 | x = prom_getproplen(rtas, "ibm,hypertas-functions"); |
1497 | if (x != PROM_ERROR) { | 1499 | if (x != PROM_ERROR) { |
1498 | prom_printf("Hypertas detected, assuming LPAR !\n"); | 1500 | prom_debug("Hypertas detected, assuming LPAR !\n"); |
1499 | return PLATFORM_PSERIES_LPAR; | 1501 | return PLATFORM_PSERIES_LPAR; |
1500 | } | 1502 | } |
1501 | return PLATFORM_PSERIES; | 1503 | return PLATFORM_PSERIES; |
@@ -1544,7 +1546,7 @@ static void __init prom_check_displays(void) | |||
1544 | }; | 1546 | }; |
1545 | const unsigned char *clut; | 1547 | const unsigned char *clut; |
1546 | 1548 | ||
1547 | prom_printf("Looking for displays\n"); | 1549 | prom_debug("Looking for displays\n"); |
1548 | for (node = 0; prom_next_node(&node); ) { | 1550 | for (node = 0; prom_next_node(&node); ) { |
1549 | memset(type, 0, sizeof(type)); | 1551 | memset(type, 0, sizeof(type)); |
1550 | prom_getprop(node, "device_type", type, sizeof(type)); | 1552 | prom_getprop(node, "device_type", type, sizeof(type)); |
@@ -1562,7 +1564,7 @@ static void __init prom_check_displays(void) | |||
1562 | if (call_prom("package-to-path", 3, 1, node, path, | 1564 | if (call_prom("package-to-path", 3, 1, node, path, |
1563 | PROM_SCRATCH_SIZE-10) == PROM_ERROR) | 1565 | PROM_SCRATCH_SIZE-10) == PROM_ERROR) |
1564 | continue; | 1566 | continue; |
1565 | prom_printf("found display : %s, opening ... ", path); | 1567 | prom_printf("found display : %s, opening... ", path); |
1566 | 1568 | ||
1567 | ih = call_prom("open", 1, 1, path); | 1569 | ih = call_prom("open", 1, 1, path); |
1568 | if (ih == 0) { | 1570 | if (ih == 0) { |
@@ -2283,6 +2285,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2283 | */ | 2285 | */ |
2284 | prom_init_stdout(); | 2286 | prom_init_stdout(); |
2285 | 2287 | ||
2288 | prom_printf("Preparing to boot %s", RELOC(linux_banner)); | ||
2289 | |||
2286 | /* | 2290 | /* |
2287 | * Get default machine type. At this point, we do not differentiate | 2291 | * Get default machine type. At this point, we do not differentiate |
2288 | * between pSeries SMP and pSeries LPAR | 2292 | * between pSeries SMP and pSeries LPAR |
@@ -2385,7 +2389,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2385 | /* | 2389 | /* |
2386 | * Now finally create the flattened device-tree | 2390 | * Now finally create the flattened device-tree |
2387 | */ | 2391 | */ |
2388 | prom_printf("copying OF device tree ...\n"); | 2392 | prom_printf("copying OF device tree...\n"); |
2389 | flatten_device_tree(); | 2393 | flatten_device_tree(); |
2390 | 2394 | ||
2391 | /* | 2395 | /* |
@@ -2400,7 +2404,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2400 | * Call OF "quiesce" method to shut down pending DMA's from | 2404 | * Call OF "quiesce" method to shut down pending DMA's from |
2401 | * devices etc... | 2405 | * devices etc... |
2402 | */ | 2406 | */ |
2403 | prom_printf("Calling quiesce ...\n"); | 2407 | prom_printf("Calling quiesce...\n"); |
2404 | call_prom("quiesce", 0, 0); | 2408 | call_prom("quiesce", 0, 0); |
2405 | 2409 | ||
2406 | /* | 2410 | /* |
diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh index ea3a2ec03ffa..1ac136b128f0 100644 --- a/arch/powerpc/kernel/prom_init_check.sh +++ b/arch/powerpc/kernel/prom_init_check.sh | |||
@@ -20,7 +20,7 @@ WHITELIST="add_reloc_offset __bss_start __bss_stop copy_and_flush | |||
20 | _end enter_prom memcpy memset reloc_offset __secondary_hold | 20 | _end enter_prom memcpy memset reloc_offset __secondary_hold |
21 | __secondary_hold_acknowledge __secondary_hold_spinloop __start | 21 | __secondary_hold_acknowledge __secondary_hold_spinloop __start |
22 | strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224 | 22 | strcmp strcpy strlcpy strlen strncmp strstr logo_linux_clut224 |
23 | reloc_got2 kernstart_addr memstart_addr" | 23 | reloc_got2 kernstart_addr memstart_addr linux_banner" |
24 | 24 | ||
25 | NM="$1" | 25 | NM="$1" |
26 | OBJ="$2" | 26 | OBJ="$2" |
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index 197d49c790ad..297632cba047 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c | |||
@@ -67,7 +67,8 @@ static long compat_ptrace_old(struct task_struct *child, long request, | |||
67 | /* Macros to workout the correct index for the FPR in the thread struct */ | 67 | /* Macros to workout the correct index for the FPR in the thread struct */ |
68 | #define FPRNUMBER(i) (((i) - PT_FPR0) >> 1) | 68 | #define FPRNUMBER(i) (((i) - PT_FPR0) >> 1) |
69 | #define FPRHALF(i) (((i) - PT_FPR0) & 1) | 69 | #define FPRHALF(i) (((i) - PT_FPR0) & 1) |
70 | #define FPRINDEX(i) TS_FPRWIDTH * FPRNUMBER(i) + FPRHALF(i) | 70 | #define FPRINDEX(i) TS_FPRWIDTH * FPRNUMBER(i) * 2 + FPRHALF(i) |
71 | #define FPRINDEX_3264(i) (TS_FPRWIDTH * ((i) - PT_FPR0)) | ||
71 | 72 | ||
72 | long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | 73 | long compat_arch_ptrace(struct task_struct *child, compat_long_t request, |
73 | compat_ulong_t caddr, compat_ulong_t cdata) | 74 | compat_ulong_t caddr, compat_ulong_t cdata) |
@@ -168,8 +169,9 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
168 | CHECK_FULL_REGS(child->thread.regs); | 169 | CHECK_FULL_REGS(child->thread.regs); |
169 | if (numReg >= PT_FPR0) { | 170 | if (numReg >= PT_FPR0) { |
170 | flush_fp_to_thread(child); | 171 | flush_fp_to_thread(child); |
171 | tmp = ((unsigned long int *)child->thread.fpr) | 172 | /* get 64 bit FPR */ |
172 | [FPRINDEX(numReg)]; | 173 | tmp = ((u64 *)child->thread.fpr) |
174 | [FPRINDEX_3264(numReg)]; | ||
173 | } else { /* register within PT_REGS struct */ | 175 | } else { /* register within PT_REGS struct */ |
174 | tmp = ptrace_get_reg(child, numReg); | 176 | tmp = ptrace_get_reg(child, numReg); |
175 | } | 177 | } |
@@ -262,8 +264,13 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
262 | freg = (freg & 0xfffffffful) | (data << 32); | 264 | freg = (freg & 0xfffffffful) | (data << 32); |
263 | ret = ptrace_put_reg(child, numReg, freg); | 265 | ret = ptrace_put_reg(child, numReg, freg); |
264 | } else { | 266 | } else { |
267 | u64 *tmp; | ||
265 | flush_fp_to_thread(child); | 268 | flush_fp_to_thread(child); |
266 | ((unsigned int *)child->thread.regs)[index] = data; | 269 | /* get 64 bit FPR ... */ |
270 | tmp = &(((u64 *)child->thread.fpr) | ||
271 | [FPRINDEX_3264(numReg)]); | ||
272 | /* ... write the 32 bit part we want */ | ||
273 | ((u32 *)tmp)[index % 2] = data; | ||
267 | ret = 0; | 274 | ret = 0; |
268 | } | 275 | } |
269 | break; | 276 | break; |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index fdfe14c4bdef..ee4c7609b649 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -46,6 +46,7 @@ EXPORT_SYMBOL(rtas); | |||
46 | 46 | ||
47 | struct rtas_suspend_me_data { | 47 | struct rtas_suspend_me_data { |
48 | atomic_t working; /* number of cpus accessing this struct */ | 48 | atomic_t working; /* number of cpus accessing this struct */ |
49 | atomic_t done; | ||
49 | int token; /* ibm,suspend-me */ | 50 | int token; /* ibm,suspend-me */ |
50 | int error; | 51 | int error; |
51 | struct completion *complete; /* wait on this until working == 0 */ | 52 | struct completion *complete; /* wait on this until working == 0 */ |
@@ -689,7 +690,7 @@ static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; | |||
689 | #ifdef CONFIG_PPC_PSERIES | 690 | #ifdef CONFIG_PPC_PSERIES |
690 | static void rtas_percpu_suspend_me(void *info) | 691 | static void rtas_percpu_suspend_me(void *info) |
691 | { | 692 | { |
692 | long rc; | 693 | long rc = H_SUCCESS; |
693 | unsigned long msr_save; | 694 | unsigned long msr_save; |
694 | int cpu; | 695 | int cpu; |
695 | struct rtas_suspend_me_data *data = | 696 | struct rtas_suspend_me_data *data = |
@@ -701,7 +702,8 @@ static void rtas_percpu_suspend_me(void *info) | |||
701 | msr_save = mfmsr(); | 702 | msr_save = mfmsr(); |
702 | mtmsr(msr_save & ~(MSR_EE)); | 703 | mtmsr(msr_save & ~(MSR_EE)); |
703 | 704 | ||
704 | rc = plpar_hcall_norets(H_JOIN); | 705 | while (rc == H_SUCCESS && !atomic_read(&data->done)) |
706 | rc = plpar_hcall_norets(H_JOIN); | ||
705 | 707 | ||
706 | mtmsr(msr_save); | 708 | mtmsr(msr_save); |
707 | 709 | ||
@@ -724,6 +726,9 @@ static void rtas_percpu_suspend_me(void *info) | |||
724 | smp_processor_id(), rc); | 726 | smp_processor_id(), rc); |
725 | data->error = rc; | 727 | data->error = rc; |
726 | } | 728 | } |
729 | |||
730 | atomic_set(&data->done, 1); | ||
731 | |||
727 | /* This cpu did the suspend or got an error; in either case, | 732 | /* This cpu did the suspend or got an error; in either case, |
728 | * we need to prod all other other cpus out of join state. | 733 | * we need to prod all other other cpus out of join state. |
729 | * Extra prods are harmless. | 734 | * Extra prods are harmless. |
@@ -766,6 +771,7 @@ static int rtas_ibm_suspend_me(struct rtas_args *args) | |||
766 | } | 771 | } |
767 | 772 | ||
768 | atomic_set(&data.working, 0); | 773 | atomic_set(&data.working, 0); |
774 | atomic_set(&data.done, 0); | ||
769 | data.token = rtas_token("ibm,suspend-me"); | 775 | data.token = rtas_token("ibm,suspend-me"); |
770 | data.error = 0; | 776 | data.error = 0; |
771 | data.complete = &done; | 777 | data.complete = &done; |
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 149cb112cd1a..13011a96a977 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c | |||
@@ -669,7 +669,6 @@ static void remove_flash_pde(struct proc_dir_entry *dp) | |||
669 | { | 669 | { |
670 | if (dp) { | 670 | if (dp) { |
671 | kfree(dp->data); | 671 | kfree(dp->data); |
672 | dp->owner = NULL; | ||
673 | remove_proc_entry(dp->name, dp->parent); | 672 | remove_proc_entry(dp->name, dp->parent); |
674 | } | 673 | } |
675 | } | 674 | } |
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 705fc4bf3800..02fed27af7f6 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/debugfs.h> | 35 | #include <linux/debugfs.h> |
36 | #include <linux/percpu.h> | 36 | #include <linux/percpu.h> |
37 | #include <linux/lmb.h> | 37 | #include <linux/lmb.h> |
38 | #include <linux/of_platform.h> | ||
38 | #include <asm/io.h> | 39 | #include <asm/io.h> |
39 | #include <asm/prom.h> | 40 | #include <asm/prom.h> |
40 | #include <asm/processor.h> | 41 | #include <asm/processor.h> |
@@ -669,3 +670,37 @@ static int powerpc_debugfs_init(void) | |||
669 | } | 670 | } |
670 | arch_initcall(powerpc_debugfs_init); | 671 | arch_initcall(powerpc_debugfs_init); |
671 | #endif | 672 | #endif |
673 | |||
674 | static int ppc_dflt_bus_notify(struct notifier_block *nb, | ||
675 | unsigned long action, void *data) | ||
676 | { | ||
677 | struct device *dev = data; | ||
678 | |||
679 | /* We are only intereted in device addition */ | ||
680 | if (action != BUS_NOTIFY_ADD_DEVICE) | ||
681 | return 0; | ||
682 | |||
683 | set_dma_ops(dev, &dma_direct_ops); | ||
684 | |||
685 | return NOTIFY_DONE; | ||
686 | } | ||
687 | |||
688 | static struct notifier_block ppc_dflt_plat_bus_notifier = { | ||
689 | .notifier_call = ppc_dflt_bus_notify, | ||
690 | .priority = INT_MAX, | ||
691 | }; | ||
692 | |||
693 | static struct notifier_block ppc_dflt_of_bus_notifier = { | ||
694 | .notifier_call = ppc_dflt_bus_notify, | ||
695 | .priority = INT_MAX, | ||
696 | }; | ||
697 | |||
698 | static int __init setup_bus_notifier(void) | ||
699 | { | ||
700 | bus_register_notifier(&platform_bus_type, &ppc_dflt_plat_bus_notifier); | ||
701 | bus_register_notifier(&of_platform_bus_type, &ppc_dflt_of_bus_notifier); | ||
702 | |||
703 | return 0; | ||
704 | } | ||
705 | |||
706 | arch_initcall(setup_bus_notifier); | ||
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 2d34196bba8c..c410c606955d 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -202,8 +202,6 @@ void __init early_setup(unsigned long dt_ptr) | |||
202 | 202 | ||
203 | /* Fix up paca fields required for the boot cpu */ | 203 | /* Fix up paca fields required for the boot cpu */ |
204 | get_paca()->cpu_start = 1; | 204 | get_paca()->cpu_start = 1; |
205 | get_paca()->stab_real = __pa((u64)&initial_stab); | ||
206 | get_paca()->stab_addr = (u64)&initial_stab; | ||
207 | 205 | ||
208 | /* Probe the machine type */ | 206 | /* Probe the machine type */ |
209 | probe_machine(); | 207 | probe_machine(); |
@@ -212,20 +210,8 @@ void __init early_setup(unsigned long dt_ptr) | |||
212 | 210 | ||
213 | DBG("Found, Initializing memory management...\n"); | 211 | DBG("Found, Initializing memory management...\n"); |
214 | 212 | ||
215 | /* | 213 | /* Initialize the hash table or TLB handling */ |
216 | * Initialize the MMU Hash table and create the linear mapping | 214 | early_init_mmu(); |
217 | * of memory. Has to be done before stab/slb initialization as | ||
218 | * this is currently where the page size encoding is obtained | ||
219 | */ | ||
220 | htab_initialize(); | ||
221 | |||
222 | /* | ||
223 | * Initialize stab / SLB management except on iSeries | ||
224 | */ | ||
225 | if (cpu_has_feature(CPU_FTR_SLB)) | ||
226 | slb_initialize(); | ||
227 | else if (!firmware_has_feature(FW_FEATURE_ISERIES)) | ||
228 | stab_initialize(get_paca()->stab_real); | ||
229 | 215 | ||
230 | DBG(" <- early_setup()\n"); | 216 | DBG(" <- early_setup()\n"); |
231 | } | 217 | } |
@@ -233,22 +219,11 @@ void __init early_setup(unsigned long dt_ptr) | |||
233 | #ifdef CONFIG_SMP | 219 | #ifdef CONFIG_SMP |
234 | void early_setup_secondary(void) | 220 | void early_setup_secondary(void) |
235 | { | 221 | { |
236 | struct paca_struct *lpaca = get_paca(); | ||
237 | |||
238 | /* Mark interrupts enabled in PACA */ | 222 | /* Mark interrupts enabled in PACA */ |
239 | lpaca->soft_enabled = 0; | 223 | get_paca()->soft_enabled = 0; |
240 | 224 | ||
241 | /* Initialize hash table for that CPU */ | 225 | /* Initialize the hash table or TLB handling */ |
242 | htab_initialize_secondary(); | 226 | early_init_mmu_secondary(); |
243 | |||
244 | /* Initialize STAB/SLB. We use a virtual address as it works | ||
245 | * in real mode on pSeries and we want a virutal address on | ||
246 | * iSeries anyway | ||
247 | */ | ||
248 | if (cpu_has_feature(CPU_FTR_SLB)) | ||
249 | slb_initialize(); | ||
250 | else | ||
251 | stab_initialize(lpaca->stab_addr); | ||
252 | } | 227 | } |
253 | 228 | ||
254 | #endif /* CONFIG_SMP */ | 229 | #endif /* CONFIG_SMP */ |
@@ -578,13 +553,6 @@ void ppc64_boot_msg(unsigned int src, const char *msg) | |||
578 | printk("[boot]%04x %s\n", src, msg); | 553 | printk("[boot]%04x %s\n", src, msg); |
579 | } | 554 | } |
580 | 555 | ||
581 | /* Print a termination message (print only -- does not stop the kernel) */ | ||
582 | void ppc64_terminate_msg(unsigned int src, const char *msg) | ||
583 | { | ||
584 | ppc64_do_msg(PPC64_LINUX_FUNCTION|PPC64_TERM_MESSAGE|src, msg); | ||
585 | printk("[terminate]%04x %s\n", src, msg); | ||
586 | } | ||
587 | |||
588 | void cpu_die(void) | 556 | void cpu_die(void) |
589 | { | 557 | { |
590 | if (ppc_md.cpu_die) | 558 | if (ppc_md.cpu_die) |
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index a54405ebd7b0..00b5078da9a3 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
@@ -26,12 +26,12 @@ int show_unhandled_signals = 0; | |||
26 | * Allocate space for the signal frame | 26 | * Allocate space for the signal frame |
27 | */ | 27 | */ |
28 | void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | 28 | void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, |
29 | size_t frame_size) | 29 | size_t frame_size, int is_32) |
30 | { | 30 | { |
31 | unsigned long oldsp, newsp; | 31 | unsigned long oldsp, newsp; |
32 | 32 | ||
33 | /* Default to using normal stack */ | 33 | /* Default to using normal stack */ |
34 | oldsp = regs->gpr[1]; | 34 | oldsp = get_clean_sp(regs, is_32); |
35 | 35 | ||
36 | /* Check for alt stack */ | 36 | /* Check for alt stack */ |
37 | if ((ka->sa.sa_flags & SA_ONSTACK) && | 37 | if ((ka->sa.sa_flags & SA_ONSTACK) && |
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h index b427bf8e1d8f..6c0ddfc0603e 100644 --- a/arch/powerpc/kernel/signal.h +++ b/arch/powerpc/kernel/signal.h | |||
@@ -15,7 +15,7 @@ | |||
15 | extern void do_signal(struct pt_regs *regs, unsigned long thread_info_flags); | 15 | extern void do_signal(struct pt_regs *regs, unsigned long thread_info_flags); |
16 | 16 | ||
17 | extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | 17 | extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, |
18 | size_t frame_size); | 18 | size_t frame_size, int is_32); |
19 | extern void restore_sigmask(sigset_t *set); | 19 | extern void restore_sigmask(sigset_t *set); |
20 | 20 | ||
21 | extern int handle_signal32(unsigned long sig, struct k_sigaction *ka, | 21 | extern int handle_signal32(unsigned long sig, struct k_sigaction *ka, |
@@ -39,22 +39,12 @@ extern unsigned long copy_vsx_from_user(struct task_struct *task, | |||
39 | 39 | ||
40 | #ifdef CONFIG_PPC64 | 40 | #ifdef CONFIG_PPC64 |
41 | 41 | ||
42 | static inline int is_32bit_task(void) | ||
43 | { | ||
44 | return test_thread_flag(TIF_32BIT); | ||
45 | } | ||
46 | |||
47 | extern int handle_rt_signal64(int signr, struct k_sigaction *ka, | 42 | extern int handle_rt_signal64(int signr, struct k_sigaction *ka, |
48 | siginfo_t *info, sigset_t *set, | 43 | siginfo_t *info, sigset_t *set, |
49 | struct pt_regs *regs); | 44 | struct pt_regs *regs); |
50 | 45 | ||
51 | #else /* CONFIG_PPC64 */ | 46 | #else /* CONFIG_PPC64 */ |
52 | 47 | ||
53 | static inline int is_32bit_task(void) | ||
54 | { | ||
55 | return 1; | ||
56 | } | ||
57 | |||
58 | static inline int handle_rt_signal64(int signr, struct k_sigaction *ka, | 48 | static inline int handle_rt_signal64(int signr, struct k_sigaction *ka, |
59 | siginfo_t *info, sigset_t *set, | 49 | siginfo_t *info, sigset_t *set, |
60 | struct pt_regs *regs) | 50 | struct pt_regs *regs) |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index b13abf305996..d670429a1608 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -836,7 +836,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
836 | 836 | ||
837 | /* Set up Signal Frame */ | 837 | /* Set up Signal Frame */ |
838 | /* Put a Real Time Context onto stack */ | 838 | /* Put a Real Time Context onto stack */ |
839 | rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf)); | 839 | rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf), 1); |
840 | addr = rt_sf; | 840 | addr = rt_sf; |
841 | if (unlikely(rt_sf == NULL)) | 841 | if (unlikely(rt_sf == NULL)) |
842 | goto badframe; | 842 | goto badframe; |
@@ -1182,7 +1182,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1182 | unsigned long newsp = 0; | 1182 | unsigned long newsp = 0; |
1183 | 1183 | ||
1184 | /* Set up Signal Frame */ | 1184 | /* Set up Signal Frame */ |
1185 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 1185 | frame = get_sigframe(ka, regs, sizeof(*frame), 1); |
1186 | if (unlikely(frame == NULL)) | 1186 | if (unlikely(frame == NULL)) |
1187 | goto badframe; | 1187 | goto badframe; |
1188 | sc = (struct sigcontext __user *) &frame->sctx; | 1188 | sc = (struct sigcontext __user *) &frame->sctx; |
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index e132891d3cea..2fe6fc64b614 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
@@ -402,7 +402,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
402 | unsigned long newsp = 0; | 402 | unsigned long newsp = 0; |
403 | long err = 0; | 403 | long err = 0; |
404 | 404 | ||
405 | frame = get_sigframe(ka, regs, sizeof(*frame)); | 405 | frame = get_sigframe(ka, regs, sizeof(*frame), 0); |
406 | if (unlikely(frame == NULL)) | 406 | if (unlikely(frame == NULL)) |
407 | goto badframe; | 407 | goto badframe; |
408 | 408 | ||
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 4a2ee08af6a7..f41aec85aa49 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
@@ -134,44 +134,23 @@ void ppc_enable_pmcs(void) | |||
134 | } | 134 | } |
135 | EXPORT_SYMBOL(ppc_enable_pmcs); | 135 | EXPORT_SYMBOL(ppc_enable_pmcs); |
136 | 136 | ||
137 | #if defined(CONFIG_6xx) || defined(CONFIG_PPC64) | ||
138 | /* XXX convert to rusty's on_one_cpu */ | ||
139 | static unsigned long run_on_cpu(unsigned long cpu, | ||
140 | unsigned long (*func)(unsigned long), | ||
141 | unsigned long arg) | ||
142 | { | ||
143 | cpumask_t old_affinity = current->cpus_allowed; | ||
144 | unsigned long ret; | ||
145 | |||
146 | /* should return -EINVAL to userspace */ | ||
147 | if (set_cpus_allowed(current, cpumask_of_cpu(cpu))) | ||
148 | return 0; | ||
149 | |||
150 | ret = func(arg); | ||
151 | |||
152 | set_cpus_allowed(current, old_affinity); | ||
153 | |||
154 | return ret; | ||
155 | } | ||
156 | #endif | ||
157 | |||
158 | #define SYSFS_PMCSETUP(NAME, ADDRESS) \ | 137 | #define SYSFS_PMCSETUP(NAME, ADDRESS) \ |
159 | static unsigned long read_##NAME(unsigned long junk) \ | 138 | static void read_##NAME(void *val) \ |
160 | { \ | 139 | { \ |
161 | return mfspr(ADDRESS); \ | 140 | *(unsigned long *)val = mfspr(ADDRESS); \ |
162 | } \ | 141 | } \ |
163 | static unsigned long write_##NAME(unsigned long val) \ | 142 | static void write_##NAME(void *val) \ |
164 | { \ | 143 | { \ |
165 | ppc_enable_pmcs(); \ | 144 | ppc_enable_pmcs(); \ |
166 | mtspr(ADDRESS, val); \ | 145 | mtspr(ADDRESS, *(unsigned long *)val); \ |
167 | return 0; \ | ||
168 | } \ | 146 | } \ |
169 | static ssize_t show_##NAME(struct sys_device *dev, \ | 147 | static ssize_t show_##NAME(struct sys_device *dev, \ |
170 | struct sysdev_attribute *attr, \ | 148 | struct sysdev_attribute *attr, \ |
171 | char *buf) \ | 149 | char *buf) \ |
172 | { \ | 150 | { \ |
173 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); \ | 151 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); \ |
174 | unsigned long val = run_on_cpu(cpu->sysdev.id, read_##NAME, 0); \ | 152 | unsigned long val; \ |
153 | smp_call_function_single(cpu->sysdev.id, read_##NAME, &val, 1); \ | ||
175 | return sprintf(buf, "%lx\n", val); \ | 154 | return sprintf(buf, "%lx\n", val); \ |
176 | } \ | 155 | } \ |
177 | static ssize_t __used \ | 156 | static ssize_t __used \ |
@@ -183,7 +162,7 @@ static ssize_t __used \ | |||
183 | int ret = sscanf(buf, "%lx", &val); \ | 162 | int ret = sscanf(buf, "%lx", &val); \ |
184 | if (ret != 1) \ | 163 | if (ret != 1) \ |
185 | return -EINVAL; \ | 164 | return -EINVAL; \ |
186 | run_on_cpu(cpu->sysdev.id, write_##NAME, val); \ | 165 | smp_call_function_single(cpu->sysdev.id, write_##NAME, &val, 1); \ |
187 | return count; \ | 166 | return count; \ |
188 | } | 167 | } |
189 | 168 | ||
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index c9564031a2a9..926ea864e34f 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -1127,3 +1127,19 @@ void div128_by_32(u64 dividend_high, u64 dividend_low, | |||
1127 | dr->result_low = ((u64)y << 32) + z; | 1127 | dr->result_low = ((u64)y << 32) + z; |
1128 | 1128 | ||
1129 | } | 1129 | } |
1130 | |||
1131 | static int __init rtc_init(void) | ||
1132 | { | ||
1133 | struct platform_device *pdev; | ||
1134 | |||
1135 | if (!ppc_md.get_rtc_time) | ||
1136 | return -ENODEV; | ||
1137 | |||
1138 | pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0); | ||
1139 | if (IS_ERR(pdev)) | ||
1140 | return PTR_ERR(pdev); | ||
1141 | |||
1142 | return 0; | ||
1143 | } | ||
1144 | |||
1145 | module_init(rtc_init); | ||
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 5457e9575685..678fbff0d206 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -52,6 +52,10 @@ | |||
52 | #include <asm/processor.h> | 52 | #include <asm/processor.h> |
53 | #endif | 53 | #endif |
54 | #include <asm/kexec.h> | 54 | #include <asm/kexec.h> |
55 | #include <asm/ppc-opcode.h> | ||
56 | #ifdef CONFIG_FSL_BOOKE | ||
57 | #include <asm/dbell.h> | ||
58 | #endif | ||
55 | 59 | ||
56 | #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) | 60 | #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) |
57 | int (*__debugger)(struct pt_regs *regs); | 61 | int (*__debugger)(struct pt_regs *regs); |
@@ -637,29 +641,6 @@ static void parse_fpe(struct pt_regs *regs) | |||
637 | * bits is faster and easier. | 641 | * bits is faster and easier. |
638 | * | 642 | * |
639 | */ | 643 | */ |
640 | #define INST_MFSPR_PVR 0x7c1f42a6 | ||
641 | #define INST_MFSPR_PVR_MASK 0xfc1fffff | ||
642 | |||
643 | #define INST_DCBA 0x7c0005ec | ||
644 | #define INST_DCBA_MASK 0xfc0007fe | ||
645 | |||
646 | #define INST_MCRXR 0x7c000400 | ||
647 | #define INST_MCRXR_MASK 0xfc0007fe | ||
648 | |||
649 | #define INST_STRING 0x7c00042a | ||
650 | #define INST_STRING_MASK 0xfc0007fe | ||
651 | #define INST_STRING_GEN_MASK 0xfc00067e | ||
652 | #define INST_LSWI 0x7c0004aa | ||
653 | #define INST_LSWX 0x7c00042a | ||
654 | #define INST_STSWI 0x7c0005aa | ||
655 | #define INST_STSWX 0x7c00052a | ||
656 | |||
657 | #define INST_POPCNTB 0x7c0000f4 | ||
658 | #define INST_POPCNTB_MASK 0xfc0007fe | ||
659 | |||
660 | #define INST_ISEL 0x7c00001e | ||
661 | #define INST_ISEL_MASK 0xfc00003e | ||
662 | |||
663 | static int emulate_string_inst(struct pt_regs *regs, u32 instword) | 644 | static int emulate_string_inst(struct pt_regs *regs, u32 instword) |
664 | { | 645 | { |
665 | u8 rT = (instword >> 21) & 0x1f; | 646 | u8 rT = (instword >> 21) & 0x1f; |
@@ -670,20 +651,20 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword) | |||
670 | int pos = 0; | 651 | int pos = 0; |
671 | 652 | ||
672 | /* Early out if we are an invalid form of lswx */ | 653 | /* Early out if we are an invalid form of lswx */ |
673 | if ((instword & INST_STRING_MASK) == INST_LSWX) | 654 | if ((instword & PPC_INST_STRING_MASK) == PPC_INST_LSWX) |
674 | if ((rT == rA) || (rT == NB_RB)) | 655 | if ((rT == rA) || (rT == NB_RB)) |
675 | return -EINVAL; | 656 | return -EINVAL; |
676 | 657 | ||
677 | EA = (rA == 0) ? 0 : regs->gpr[rA]; | 658 | EA = (rA == 0) ? 0 : regs->gpr[rA]; |
678 | 659 | ||
679 | switch (instword & INST_STRING_MASK) { | 660 | switch (instword & PPC_INST_STRING_MASK) { |
680 | case INST_LSWX: | 661 | case PPC_INST_LSWX: |
681 | case INST_STSWX: | 662 | case PPC_INST_STSWX: |
682 | EA += NB_RB; | 663 | EA += NB_RB; |
683 | num_bytes = regs->xer & 0x7f; | 664 | num_bytes = regs->xer & 0x7f; |
684 | break; | 665 | break; |
685 | case INST_LSWI: | 666 | case PPC_INST_LSWI: |
686 | case INST_STSWI: | 667 | case PPC_INST_STSWI: |
687 | num_bytes = (NB_RB == 0) ? 32 : NB_RB; | 668 | num_bytes = (NB_RB == 0) ? 32 : NB_RB; |
688 | break; | 669 | break; |
689 | default: | 670 | default: |
@@ -695,9 +676,9 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword) | |||
695 | u8 val; | 676 | u8 val; |
696 | u32 shift = 8 * (3 - (pos & 0x3)); | 677 | u32 shift = 8 * (3 - (pos & 0x3)); |
697 | 678 | ||
698 | switch ((instword & INST_STRING_MASK)) { | 679 | switch ((instword & PPC_INST_STRING_MASK)) { |
699 | case INST_LSWX: | 680 | case PPC_INST_LSWX: |
700 | case INST_LSWI: | 681 | case PPC_INST_LSWI: |
701 | if (get_user(val, (u8 __user *)EA)) | 682 | if (get_user(val, (u8 __user *)EA)) |
702 | return -EFAULT; | 683 | return -EFAULT; |
703 | /* first time updating this reg, | 684 | /* first time updating this reg, |
@@ -706,8 +687,8 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword) | |||
706 | regs->gpr[rT] = 0; | 687 | regs->gpr[rT] = 0; |
707 | regs->gpr[rT] |= val << shift; | 688 | regs->gpr[rT] |= val << shift; |
708 | break; | 689 | break; |
709 | case INST_STSWI: | 690 | case PPC_INST_STSWI: |
710 | case INST_STSWX: | 691 | case PPC_INST_STSWX: |
711 | val = regs->gpr[rT] >> shift; | 692 | val = regs->gpr[rT] >> shift; |
712 | if (put_user(val, (u8 __user *)EA)) | 693 | if (put_user(val, (u8 __user *)EA)) |
713 | return -EFAULT; | 694 | return -EFAULT; |
@@ -775,18 +756,18 @@ static int emulate_instruction(struct pt_regs *regs) | |||
775 | return -EFAULT; | 756 | return -EFAULT; |
776 | 757 | ||
777 | /* Emulate the mfspr rD, PVR. */ | 758 | /* Emulate the mfspr rD, PVR. */ |
778 | if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) { | 759 | if ((instword & PPC_INST_MFSPR_PVR_MASK) == PPC_INST_MFSPR_PVR) { |
779 | rd = (instword >> 21) & 0x1f; | 760 | rd = (instword >> 21) & 0x1f; |
780 | regs->gpr[rd] = mfspr(SPRN_PVR); | 761 | regs->gpr[rd] = mfspr(SPRN_PVR); |
781 | return 0; | 762 | return 0; |
782 | } | 763 | } |
783 | 764 | ||
784 | /* Emulating the dcba insn is just a no-op. */ | 765 | /* Emulating the dcba insn is just a no-op. */ |
785 | if ((instword & INST_DCBA_MASK) == INST_DCBA) | 766 | if ((instword & PPC_INST_DCBA_MASK) == PPC_INST_DCBA) |
786 | return 0; | 767 | return 0; |
787 | 768 | ||
788 | /* Emulate the mcrxr insn. */ | 769 | /* Emulate the mcrxr insn. */ |
789 | if ((instword & INST_MCRXR_MASK) == INST_MCRXR) { | 770 | if ((instword & PPC_INST_MCRXR_MASK) == PPC_INST_MCRXR) { |
790 | int shift = (instword >> 21) & 0x1c; | 771 | int shift = (instword >> 21) & 0x1c; |
791 | unsigned long msk = 0xf0000000UL >> shift; | 772 | unsigned long msk = 0xf0000000UL >> shift; |
792 | 773 | ||
@@ -796,16 +777,16 @@ static int emulate_instruction(struct pt_regs *regs) | |||
796 | } | 777 | } |
797 | 778 | ||
798 | /* Emulate load/store string insn. */ | 779 | /* Emulate load/store string insn. */ |
799 | if ((instword & INST_STRING_GEN_MASK) == INST_STRING) | 780 | if ((instword & PPC_INST_STRING_GEN_MASK) == PPC_INST_STRING) |
800 | return emulate_string_inst(regs, instword); | 781 | return emulate_string_inst(regs, instword); |
801 | 782 | ||
802 | /* Emulate the popcntb (Population Count Bytes) instruction. */ | 783 | /* Emulate the popcntb (Population Count Bytes) instruction. */ |
803 | if ((instword & INST_POPCNTB_MASK) == INST_POPCNTB) { | 784 | if ((instword & PPC_INST_POPCNTB_MASK) == PPC_INST_POPCNTB) { |
804 | return emulate_popcntb_inst(regs, instword); | 785 | return emulate_popcntb_inst(regs, instword); |
805 | } | 786 | } |
806 | 787 | ||
807 | /* Emulate isel (Integer Select) instruction */ | 788 | /* Emulate isel (Integer Select) instruction */ |
808 | if ((instword & INST_ISEL_MASK) == INST_ISEL) { | 789 | if ((instword & PPC_INST_ISEL_MASK) == PPC_INST_ISEL) { |
809 | return emulate_isel(regs, instword); | 790 | return emulate_isel(regs, instword); |
810 | } | 791 | } |
811 | 792 | ||
@@ -1144,6 +1125,24 @@ void vsx_assist_exception(struct pt_regs *regs) | |||
1144 | #endif /* CONFIG_VSX */ | 1125 | #endif /* CONFIG_VSX */ |
1145 | 1126 | ||
1146 | #ifdef CONFIG_FSL_BOOKE | 1127 | #ifdef CONFIG_FSL_BOOKE |
1128 | |||
1129 | void doorbell_exception(struct pt_regs *regs) | ||
1130 | { | ||
1131 | #ifdef CONFIG_SMP | ||
1132 | int cpu = smp_processor_id(); | ||
1133 | int msg; | ||
1134 | |||
1135 | if (num_online_cpus() < 2) | ||
1136 | return; | ||
1137 | |||
1138 | for (msg = 0; msg < 4; msg++) | ||
1139 | if (test_and_clear_bit(msg, &dbell_smp_message[cpu])) | ||
1140 | smp_message_recv(msg); | ||
1141 | #else | ||
1142 | printk(KERN_WARNING "Received doorbell on non-smp system\n"); | ||
1143 | #endif | ||
1144 | } | ||
1145 | |||
1147 | void CacheLockingException(struct pt_regs *regs, unsigned long address, | 1146 | void CacheLockingException(struct pt_regs *regs, unsigned long address, |
1148 | unsigned long error_code) | 1147 | unsigned long error_code) |
1149 | { | 1148 | { |
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index 7d6c9bb8c77f..fc9af47e2128 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <asm/udbg.h> | 18 | #include <asm/udbg.h> |
19 | 19 | ||
20 | void (*udbg_putc)(char c); | 20 | void (*udbg_putc)(char c); |
21 | void (*udbg_flush)(void); | ||
21 | int (*udbg_getc)(void); | 22 | int (*udbg_getc)(void); |
22 | int (*udbg_getc_poll)(void); | 23 | int (*udbg_getc_poll)(void); |
23 | 24 | ||
@@ -76,6 +77,9 @@ void udbg_puts(const char *s) | |||
76 | while ((c = *s++) != '\0') | 77 | while ((c = *s++) != '\0') |
77 | udbg_putc(c); | 78 | udbg_putc(c); |
78 | } | 79 | } |
80 | |||
81 | if (udbg_flush) | ||
82 | udbg_flush(); | ||
79 | } | 83 | } |
80 | #if 0 | 84 | #if 0 |
81 | else { | 85 | else { |
@@ -98,6 +102,9 @@ int udbg_write(const char *s, int n) | |||
98 | } | 102 | } |
99 | } | 103 | } |
100 | 104 | ||
105 | if (udbg_flush) | ||
106 | udbg_flush(); | ||
107 | |||
101 | return n - remain; | 108 | return n - remain; |
102 | } | 109 | } |
103 | 110 | ||
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c index 7b7da8cfd5e8..0362a891e54e 100644 --- a/arch/powerpc/kernel/udbg_16550.c +++ b/arch/powerpc/kernel/udbg_16550.c | |||
@@ -48,14 +48,21 @@ struct NS16550 { | |||
48 | 48 | ||
49 | static struct NS16550 __iomem *udbg_comport; | 49 | static struct NS16550 __iomem *udbg_comport; |
50 | 50 | ||
51 | static void udbg_550_putc(char c) | 51 | static void udbg_550_flush(void) |
52 | { | 52 | { |
53 | if (udbg_comport) { | 53 | if (udbg_comport) { |
54 | while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0) | 54 | while ((in_8(&udbg_comport->lsr) & LSR_THRE) == 0) |
55 | /* wait for idle */; | 55 | /* wait for idle */; |
56 | out_8(&udbg_comport->thr, c); | 56 | } |
57 | } | ||
58 | |||
59 | static void udbg_550_putc(char c) | ||
60 | { | ||
61 | if (udbg_comport) { | ||
57 | if (c == '\n') | 62 | if (c == '\n') |
58 | udbg_550_putc('\r'); | 63 | udbg_550_putc('\r'); |
64 | udbg_550_flush(); | ||
65 | out_8(&udbg_comport->thr, c); | ||
59 | } | 66 | } |
60 | } | 67 | } |
61 | 68 | ||
@@ -108,6 +115,7 @@ void udbg_init_uart(void __iomem *comport, unsigned int speed, | |||
108 | /* Clear & enable FIFOs */ | 115 | /* Clear & enable FIFOs */ |
109 | out_8(&udbg_comport->fcr ,0x07); | 116 | out_8(&udbg_comport->fcr ,0x07); |
110 | udbg_putc = udbg_550_putc; | 117 | udbg_putc = udbg_550_putc; |
118 | udbg_flush = udbg_550_flush; | ||
111 | udbg_getc = udbg_550_getc; | 119 | udbg_getc = udbg_550_getc; |
112 | udbg_getc_poll = udbg_550_getc_poll; | 120 | udbg_getc_poll = udbg_550_getc_poll; |
113 | } | 121 | } |
@@ -149,14 +157,21 @@ unsigned int udbg_probe_uart_speed(void __iomem *comport, unsigned int clock) | |||
149 | } | 157 | } |
150 | 158 | ||
151 | #ifdef CONFIG_PPC_MAPLE | 159 | #ifdef CONFIG_PPC_MAPLE |
152 | void udbg_maple_real_putc(char c) | 160 | void udbg_maple_real_flush(void) |
153 | { | 161 | { |
154 | if (udbg_comport) { | 162 | if (udbg_comport) { |
155 | while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0) | 163 | while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0) |
156 | /* wait for idle */; | 164 | /* wait for idle */; |
157 | real_writeb(c, &udbg_comport->thr); eieio(); | 165 | } |
166 | } | ||
167 | |||
168 | void udbg_maple_real_putc(char c) | ||
169 | { | ||
170 | if (udbg_comport) { | ||
158 | if (c == '\n') | 171 | if (c == '\n') |
159 | udbg_maple_real_putc('\r'); | 172 | udbg_maple_real_putc('\r'); |
173 | udbg_maple_real_flush(); | ||
174 | real_writeb(c, &udbg_comport->thr); eieio(); | ||
160 | } | 175 | } |
161 | } | 176 | } |
162 | 177 | ||
@@ -165,20 +180,28 @@ void __init udbg_init_maple_realmode(void) | |||
165 | udbg_comport = (struct NS16550 __iomem *)0xf40003f8; | 180 | udbg_comport = (struct NS16550 __iomem *)0xf40003f8; |
166 | 181 | ||
167 | udbg_putc = udbg_maple_real_putc; | 182 | udbg_putc = udbg_maple_real_putc; |
183 | udbg_flush = udbg_maple_real_flush; | ||
168 | udbg_getc = NULL; | 184 | udbg_getc = NULL; |
169 | udbg_getc_poll = NULL; | 185 | udbg_getc_poll = NULL; |
170 | } | 186 | } |
171 | #endif /* CONFIG_PPC_MAPLE */ | 187 | #endif /* CONFIG_PPC_MAPLE */ |
172 | 188 | ||
173 | #ifdef CONFIG_PPC_PASEMI | 189 | #ifdef CONFIG_PPC_PASEMI |
174 | void udbg_pas_real_putc(char c) | 190 | void udbg_pas_real_flush(void) |
175 | { | 191 | { |
176 | if (udbg_comport) { | 192 | if (udbg_comport) { |
177 | while ((real_205_readb(&udbg_comport->lsr) & LSR_THRE) == 0) | 193 | while ((real_205_readb(&udbg_comport->lsr) & LSR_THRE) == 0) |
178 | /* wait for idle */; | 194 | /* wait for idle */; |
179 | real_205_writeb(c, &udbg_comport->thr); eieio(); | 195 | } |
196 | } | ||
197 | |||
198 | void udbg_pas_real_putc(char c) | ||
199 | { | ||
200 | if (udbg_comport) { | ||
180 | if (c == '\n') | 201 | if (c == '\n') |
181 | udbg_pas_real_putc('\r'); | 202 | udbg_pas_real_putc('\r'); |
203 | udbg_pas_real_flush(); | ||
204 | real_205_writeb(c, &udbg_comport->thr); eieio(); | ||
182 | } | 205 | } |
183 | } | 206 | } |
184 | 207 | ||
@@ -187,6 +210,7 @@ void udbg_init_pas_realmode(void) | |||
187 | udbg_comport = (struct NS16550 __iomem *)0xfcff03f8UL; | 210 | udbg_comport = (struct NS16550 __iomem *)0xfcff03f8UL; |
188 | 211 | ||
189 | udbg_putc = udbg_pas_real_putc; | 212 | udbg_putc = udbg_pas_real_putc; |
213 | udbg_flush = udbg_pas_real_flush; | ||
190 | udbg_getc = NULL; | 214 | udbg_getc = NULL; |
191 | udbg_getc_poll = NULL; | 215 | udbg_getc_poll = NULL; |
192 | } | 216 | } |
@@ -195,14 +219,21 @@ void udbg_init_pas_realmode(void) | |||
195 | #ifdef CONFIG_PPC_EARLY_DEBUG_44x | 219 | #ifdef CONFIG_PPC_EARLY_DEBUG_44x |
196 | #include <platforms/44x/44x.h> | 220 | #include <platforms/44x/44x.h> |
197 | 221 | ||
198 | static void udbg_44x_as1_putc(char c) | 222 | static int udbg_44x_as1_flush(void) |
199 | { | 223 | { |
200 | if (udbg_comport) { | 224 | if (udbg_comport) { |
201 | while ((as1_readb(&udbg_comport->lsr) & LSR_THRE) == 0) | 225 | while ((as1_readb(&udbg_comport->lsr) & LSR_THRE) == 0) |
202 | /* wait for idle */; | 226 | /* wait for idle */; |
203 | as1_writeb(c, &udbg_comport->thr); eieio(); | 227 | } |
228 | } | ||
229 | |||
230 | static void udbg_44x_as1_putc(char c) | ||
231 | { | ||
232 | if (udbg_comport) { | ||
204 | if (c == '\n') | 233 | if (c == '\n') |
205 | udbg_44x_as1_putc('\r'); | 234 | udbg_44x_as1_putc('\r'); |
235 | udbg_44x_as1_flush(); | ||
236 | as1_writeb(c, &udbg_comport->thr); eieio(); | ||
206 | } | 237 | } |
207 | } | 238 | } |
208 | 239 | ||
@@ -222,19 +253,27 @@ void __init udbg_init_44x_as1(void) | |||
222 | (struct NS16550 __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR; | 253 | (struct NS16550 __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR; |
223 | 254 | ||
224 | udbg_putc = udbg_44x_as1_putc; | 255 | udbg_putc = udbg_44x_as1_putc; |
256 | udbg_flush = udbg_44x_as1_flush; | ||
225 | udbg_getc = udbg_44x_as1_getc; | 257 | udbg_getc = udbg_44x_as1_getc; |
226 | } | 258 | } |
227 | #endif /* CONFIG_PPC_EARLY_DEBUG_44x */ | 259 | #endif /* CONFIG_PPC_EARLY_DEBUG_44x */ |
228 | 260 | ||
229 | #ifdef CONFIG_PPC_EARLY_DEBUG_40x | 261 | #ifdef CONFIG_PPC_EARLY_DEBUG_40x |
230 | static void udbg_40x_real_putc(char c) | 262 | static void udbg_40x_real_flush(void) |
231 | { | 263 | { |
232 | if (udbg_comport) { | 264 | if (udbg_comport) { |
233 | while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0) | 265 | while ((real_readb(&udbg_comport->lsr) & LSR_THRE) == 0) |
234 | /* wait for idle */; | 266 | /* wait for idle */; |
235 | real_writeb(c, &udbg_comport->thr); eieio(); | 267 | } |
268 | } | ||
269 | |||
270 | static void udbg_40x_real_putc(char c) | ||
271 | { | ||
272 | if (udbg_comport) { | ||
236 | if (c == '\n') | 273 | if (c == '\n') |
237 | udbg_40x_real_putc('\r'); | 274 | udbg_40x_real_putc('\r'); |
275 | udbg_40x_real_flush(); | ||
276 | real_writeb(c, &udbg_comport->thr); eieio(); | ||
238 | } | 277 | } |
239 | } | 278 | } |
240 | 279 | ||
@@ -254,6 +293,7 @@ void __init udbg_init_40x_realmode(void) | |||
254 | CONFIG_PPC_EARLY_DEBUG_40x_PHYSADDR; | 293 | CONFIG_PPC_EARLY_DEBUG_40x_PHYSADDR; |
255 | 294 | ||
256 | udbg_putc = udbg_40x_real_putc; | 295 | udbg_putc = udbg_40x_real_putc; |
296 | udbg_flush = udbg_40x_real_flush; | ||
257 | udbg_getc = udbg_40x_real_getc; | 297 | udbg_getc = udbg_40x_real_getc; |
258 | udbg_getc_poll = NULL; | 298 | udbg_getc_poll = NULL; |
259 | } | 299 | } |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index d3694498f3af..819e59f6f7c7 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
@@ -482,7 +482,7 @@ static void vio_cmo_balance(struct work_struct *work) | |||
482 | cmo->excess.size = cmo->entitled - cmo->reserve.size; | 482 | cmo->excess.size = cmo->entitled - cmo->reserve.size; |
483 | cmo->excess.free = cmo->excess.size - need; | 483 | cmo->excess.free = cmo->excess.size - need; |
484 | 484 | ||
485 | cancel_delayed_work(container_of(work, struct delayed_work, work)); | 485 | cancel_delayed_work(to_delayed_work(work)); |
486 | spin_unlock_irqrestore(&vio_cmo.lock, flags); | 486 | spin_unlock_irqrestore(&vio_cmo.lock, flags); |
487 | } | 487 | } |
488 | 488 | ||
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 67f07f453385..b9ef1644a722 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
@@ -58,6 +58,7 @@ SECTIONS | |||
58 | SCHED_TEXT | 58 | SCHED_TEXT |
59 | LOCK_TEXT | 59 | LOCK_TEXT |
60 | KPROBES_TEXT | 60 | KPROBES_TEXT |
61 | IRQENTRY_TEXT | ||
61 | 62 | ||
62 | #ifdef CONFIG_PPC32 | 63 | #ifdef CONFIG_PPC32 |
63 | *(.got1) | 64 | *(.got1) |