diff options
author | Dmitry Torokhov <dtor_core@ameritech.net> | 2006-04-02 00:08:05 -0500 |
---|---|---|
committer | Dmitry Torokhov <dtor_core@ameritech.net> | 2006-04-02 00:08:05 -0500 |
commit | 95d465fd750897ab32462a6702fbfe1b122cbbc0 (patch) | |
tree | 65c38b2f11c51bb6932e44dd6c92f15b0091abfe /arch/powerpc | |
parent | 642fde17dceceb56c7ba2762733ac688666ae657 (diff) | |
parent | 683aa4012f53b2ada0f430487e05d37b0d94e90a (diff) |
Manual merge with Linus.
Conflicts:
arch/powerpc/kernel/setup-common.c
drivers/input/keyboard/hil_kbd.c
drivers/input/mouse/hil_ptr.c
Diffstat (limited to 'arch/powerpc')
228 files changed, 11996 insertions, 2144 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index a834f9e0bbb3..2cdc35ce8045 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -37,6 +37,10 @@ config RWSEM_XCHGADD_ALGORITHM | |||
37 | bool | 37 | bool |
38 | default y | 38 | default y |
39 | 39 | ||
40 | config GENERIC_HWEIGHT | ||
41 | bool | ||
42 | default y | ||
43 | |||
40 | config GENERIC_CALIBRATE_DELAY | 44 | config GENERIC_CALIBRATE_DELAY |
41 | bool | 45 | bool |
42 | default y | 46 | default y |
@@ -127,6 +131,12 @@ config PPC_83xx | |||
127 | select 83xx | 131 | select 83xx |
128 | select PPC_FPU | 132 | select PPC_FPU |
129 | 133 | ||
134 | config PPC_85xx | ||
135 | bool "Freescale 85xx" | ||
136 | select E500 | ||
137 | select FSL_SOC | ||
138 | select 85xx | ||
139 | |||
130 | config 40x | 140 | config 40x |
131 | bool "AMCC 40x" | 141 | bool "AMCC 40x" |
132 | 142 | ||
@@ -139,8 +149,6 @@ config 8xx | |||
139 | config E200 | 149 | config E200 |
140 | bool "Freescale e200" | 150 | bool "Freescale e200" |
141 | 151 | ||
142 | config E500 | ||
143 | bool "Freescale e500" | ||
144 | endchoice | 152 | endchoice |
145 | 153 | ||
146 | config POWER4_ONLY | 154 | config POWER4_ONLY |
@@ -168,6 +176,13 @@ config 6xx | |||
168 | config 83xx | 176 | config 83xx |
169 | bool | 177 | bool |
170 | 178 | ||
179 | # this is temp to handle compat with arch=ppc | ||
180 | config 85xx | ||
181 | bool | ||
182 | |||
183 | config E500 | ||
184 | bool | ||
185 | |||
171 | config PPC_FPU | 186 | config PPC_FPU |
172 | bool | 187 | bool |
173 | default y if PPC64 | 188 | default y if PPC64 |
@@ -217,6 +232,7 @@ config ALTIVEC | |||
217 | config SPE | 232 | config SPE |
218 | bool "SPE Support" | 233 | bool "SPE Support" |
219 | depends on E200 || E500 | 234 | depends on E200 || E500 |
235 | default y | ||
220 | ---help--- | 236 | ---help--- |
221 | This option enables kernel support for the Signal Processing | 237 | This option enables kernel support for the Signal Processing |
222 | Extensions (SPE) to the PowerPC processor. The kernel currently | 238 | Extensions (SPE) to the PowerPC processor. The kernel currently |
@@ -238,6 +254,21 @@ config PPC_STD_MMU_32 | |||
238 | def_bool y | 254 | def_bool y |
239 | depends on PPC_STD_MMU && PPC32 | 255 | depends on PPC_STD_MMU && PPC32 |
240 | 256 | ||
257 | config VIRT_CPU_ACCOUNTING | ||
258 | bool "Deterministic task and CPU time accounting" | ||
259 | depends on PPC64 | ||
260 | default y | ||
261 | help | ||
262 | Select this option to enable more accurate task and CPU time | ||
263 | accounting. This is done by reading a CPU counter on each | ||
264 | kernel entry and exit and on transitions within the kernel | ||
265 | between system, softirq and hardirq state, so there is a | ||
266 | small performance impact. This also enables accounting of | ||
267 | stolen time on logically-partitioned systems running on | ||
268 | IBM POWER5-based machines. | ||
269 | |||
270 | If in doubt, say Y here. | ||
271 | |||
241 | config SMP | 272 | config SMP |
242 | depends on PPC_STD_MMU | 273 | depends on PPC_STD_MMU |
243 | bool "Symmetric multi-processing support" | 274 | bool "Symmetric multi-processing support" |
@@ -460,7 +491,7 @@ config PPC601_SYNC_FIX | |||
460 | If in doubt, say Y here. | 491 | If in doubt, say Y here. |
461 | 492 | ||
462 | config TAU | 493 | config TAU |
463 | bool "Thermal Management Support" | 494 | bool "On-chip CPU temperature sensor support" |
464 | depends on 6xx | 495 | depends on 6xx |
465 | help | 496 | help |
466 | G3 and G4 processors have an on-chip temperature sensor called the | 497 | G3 and G4 processors have an on-chip temperature sensor called the |
@@ -469,7 +500,7 @@ config TAU | |||
469 | on-die temperature in /proc/cpuinfo if the cpu supports it. | 500 | on-die temperature in /proc/cpuinfo if the cpu supports it. |
470 | 501 | ||
471 | Unfortunately, on some chip revisions, this sensor is very inaccurate | 502 | Unfortunately, on some chip revisions, this sensor is very inaccurate |
472 | and in some cases, does not work at all, so don't assume the cpu | 503 | and in many cases, does not work at all, so don't assume the cpu |
473 | temp is actually what /proc/cpuinfo says it is. | 504 | temp is actually what /proc/cpuinfo says it is. |
474 | 505 | ||
475 | config TAU_INT | 506 | config TAU_INT |
@@ -580,7 +611,7 @@ config KEXEC | |||
580 | strongly in flux, so no good recommendation can be made. | 611 | strongly in flux, so no good recommendation can be made. |
581 | 612 | ||
582 | config CRASH_DUMP | 613 | config CRASH_DUMP |
583 | bool "kernel crash dumps (EXPERIMENTAL)" | 614 | bool "Build a kdump crash kernel (EXPERIMENTAL)" |
584 | depends on PPC_MULTIPLATFORM && PPC64 && EXPERIMENTAL | 615 | depends on PPC_MULTIPLATFORM && PPC64 && EXPERIMENTAL |
585 | help | 616 | help |
586 | Build a kernel suitable for use as a kdump capture kernel. | 617 | Build a kernel suitable for use as a kdump capture kernel. |
@@ -734,13 +765,12 @@ config GENERIC_ISA_DMA | |||
734 | 765 | ||
735 | config PPC_I8259 | 766 | config PPC_I8259 |
736 | bool | 767 | bool |
737 | default y if 85xx | ||
738 | default n | 768 | default n |
739 | 769 | ||
740 | config PPC_INDIRECT_PCI | 770 | config PPC_INDIRECT_PCI |
741 | bool | 771 | bool |
742 | depends on PCI | 772 | depends on PCI |
743 | default y if 40x || 44x || 85xx | 773 | default y if 40x || 44x |
744 | default n | 774 | default n |
745 | 775 | ||
746 | config EISA | 776 | config EISA |
@@ -757,8 +787,8 @@ config MCA | |||
757 | bool | 787 | bool |
758 | 788 | ||
759 | config PCI | 789 | config PCI |
760 | bool "PCI support" if 40x || CPM2 || PPC_83xx || 85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) | 790 | bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) |
761 | default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !85xx | 791 | default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !PPC_85xx |
762 | default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS | 792 | default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS |
763 | default PCI_QSPAN if !4xx && !CPM2 && 8xx | 793 | default PCI_QSPAN if !4xx && !CPM2 && 8xx |
764 | help | 794 | help |
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 9254806f7032..8d48e9e7162a 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug | |||
@@ -110,11 +110,6 @@ config SERIAL_TEXT_DEBUG | |||
110 | depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \ | 110 | depends on 4xx || LOPEC || MV64X60 || PPLUS || PRPMC800 || \ |
111 | PPC_GEN550 || PPC_MPC52xx | 111 | PPC_GEN550 || PPC_MPC52xx |
112 | 112 | ||
113 | config PPC_OCP | ||
114 | bool | ||
115 | depends on IBM_OCP || XILINX_OCP | ||
116 | default y | ||
117 | |||
118 | choice | 113 | choice |
119 | prompt "Early debugging (dangerous)" | 114 | prompt "Early debugging (dangerous)" |
120 | bool | 115 | bool |
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 5500ab55d042..6ec84d37a337 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile | |||
@@ -129,13 +129,8 @@ core-y += arch/powerpc/kernel/ \ | |||
129 | arch/powerpc/lib/ \ | 129 | arch/powerpc/lib/ \ |
130 | arch/powerpc/sysdev/ \ | 130 | arch/powerpc/sysdev/ \ |
131 | arch/powerpc/platforms/ | 131 | arch/powerpc/platforms/ |
132 | core-$(CONFIG_PPC32) += arch/ppc/kernel/ | 132 | core-$(CONFIG_MATH_EMULATION) += arch/powerpc/math-emu/ |
133 | core-$(CONFIG_MATH_EMULATION) += arch/ppc/math-emu/ | ||
134 | core-$(CONFIG_XMON) += arch/powerpc/xmon/ | 133 | core-$(CONFIG_XMON) += arch/powerpc/xmon/ |
135 | core-$(CONFIG_APUS) += arch/ppc/amiga/ | ||
136 | drivers-$(CONFIG_8xx) += arch/ppc/8xx_io/ | ||
137 | drivers-$(CONFIG_4xx) += arch/ppc/4xx_io/ | ||
138 | drivers-$(CONFIG_CPM2) += arch/ppc/8260_io/ | ||
139 | 134 | ||
140 | drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ | 135 | drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ |
141 | 136 | ||
@@ -148,9 +143,9 @@ all: $(KBUILD_IMAGE) | |||
148 | 143 | ||
149 | CPPFLAGS_vmlinux.lds := -Upowerpc | 144 | CPPFLAGS_vmlinux.lds := -Upowerpc |
150 | 145 | ||
151 | BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage | 146 | BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm uImage vmlinux.bin |
152 | 147 | ||
153 | .PHONY: $(BOOT_TARGETS) | 148 | PHONY += $(BOOT_TARGETS) |
154 | 149 | ||
155 | boot := arch/$(ARCH)/boot | 150 | boot := arch/$(ARCH)/boot |
156 | 151 | ||
diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S index e0192c26037b..70e65b13e033 100644 --- a/arch/powerpc/boot/crt0.S +++ b/arch/powerpc/boot/crt0.S | |||
@@ -45,7 +45,8 @@ _zimage_start: | |||
45 | bdnz 2b | 45 | bdnz 2b |
46 | 46 | ||
47 | /* Do a cache flush for our text, in case OF didn't */ | 47 | /* Do a cache flush for our text, in case OF didn't */ |
48 | 3: lis r9,_start@h | 48 | 3: lis r9,_start@ha |
49 | addi r9,r9,_start@l | ||
49 | add r9,r0,r9 | 50 | add r9,r0,r9 |
50 | lis r8,_etext@ha | 51 | lis r8,_etext@ha |
51 | addi r8,r8,_etext@l | 52 | addi r8,r8,_etext@l |
@@ -53,7 +54,7 @@ _zimage_start: | |||
53 | 4: dcbf r0,r9 | 54 | 4: dcbf r0,r9 |
54 | icbi r0,r9 | 55 | icbi r0,r9 |
55 | addi r9,r9,0x20 | 56 | addi r9,r9,0x20 |
56 | cmplwi 0,r9,8 | 57 | cmplw cr0,r9,r8 |
57 | blt 4b | 58 | blt 4b |
58 | sync | 59 | sync |
59 | isync | 60 | isync |
diff --git a/arch/powerpc/boot/install.sh b/arch/powerpc/boot/install.sh index eacce9590816..b002bfd56786 100644 --- a/arch/powerpc/boot/install.sh +++ b/arch/powerpc/boot/install.sh | |||
@@ -1,7 +1,5 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | # | 2 | # |
3 | # arch/ppc64/boot/install.sh | ||
4 | # | ||
5 | # This file is subject to the terms and conditions of the GNU General Public | 3 | # This file is subject to the terms and conditions of the GNU General Public |
6 | # License. See the file "COPYING" in the main directory of this archive | 4 | # License. See the file "COPYING" in the main directory of this archive |
7 | # for more details. | 5 | # for more details. |
diff --git a/arch/powerpc/boot/main.c b/arch/powerpc/boot/main.c index 55ec59867250..816446f0e497 100644 --- a/arch/powerpc/boot/main.c +++ b/arch/powerpc/boot/main.c | |||
@@ -152,7 +152,7 @@ static int is_elf64(void *hdr) | |||
152 | elf64ph = (Elf64_Phdr *)((unsigned long)elf64 + | 152 | elf64ph = (Elf64_Phdr *)((unsigned long)elf64 + |
153 | (unsigned long)elf64->e_phoff); | 153 | (unsigned long)elf64->e_phoff); |
154 | for (i = 0; i < (unsigned int)elf64->e_phnum; i++, elf64ph++) | 154 | for (i = 0; i < (unsigned int)elf64->e_phnum; i++, elf64ph++) |
155 | if (elf64ph->p_type == PT_LOAD && elf64ph->p_offset != 0) | 155 | if (elf64ph->p_type == PT_LOAD) |
156 | break; | 156 | break; |
157 | if (i >= (unsigned int)elf64->e_phnum) | 157 | if (i >= (unsigned int)elf64->e_phnum) |
158 | return 0; | 158 | return 0; |
@@ -193,7 +193,7 @@ static int is_elf32(void *hdr) | |||
193 | elf32 = (Elf32_Ehdr *)elfheader; | 193 | elf32 = (Elf32_Ehdr *)elfheader; |
194 | elf32ph = (Elf32_Phdr *) ((unsigned long)elf32 + elf32->e_phoff); | 194 | elf32ph = (Elf32_Phdr *) ((unsigned long)elf32 + elf32->e_phoff); |
195 | for (i = 0; i < elf32->e_phnum; i++, elf32ph++) | 195 | for (i = 0; i < elf32->e_phnum; i++, elf32ph++) |
196 | if (elf32ph->p_type == PT_LOAD && elf32ph->p_offset != 0) | 196 | if (elf32ph->p_type == PT_LOAD) |
197 | break; | 197 | break; |
198 | if (i >= elf32->e_phnum) | 198 | if (i >= elf32->e_phnum) |
199 | return 0; | 199 | return 0; |
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig index 063b84f2cbea..fe22e54ab2b0 100644 --- a/arch/powerpc/configs/cell_defconfig +++ b/arch/powerpc/configs/cell_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.15-rc5 | 3 | # Linux kernel version: 2.6.16 |
4 | # Tue Dec 20 15:59:26 2005 | 4 | # Thu Mar 23 20:48:09 2006 |
5 | # | 5 | # |
6 | CONFIG_PPC64=y | 6 | CONFIG_PPC64=y |
7 | CONFIG_64BIT=y | 7 | CONFIG_64BIT=y |
@@ -16,6 +16,10 @@ CONFIG_COMPAT=y | |||
16 | CONFIG_SYSVIPC_COMPAT=y | 16 | CONFIG_SYSVIPC_COMPAT=y |
17 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y | 17 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y |
18 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y | 18 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y |
19 | CONFIG_PPC_OF=y | ||
20 | CONFIG_PPC_UDBG_16550=y | ||
21 | # CONFIG_GENERIC_TBSYNC is not set | ||
22 | # CONFIG_DEFAULT_UIMAGE is not set | ||
19 | 23 | ||
20 | # | 24 | # |
21 | # Processor support | 25 | # Processor support |
@@ -26,6 +30,7 @@ CONFIG_POWER4=y | |||
26 | CONFIG_PPC_FPU=y | 30 | CONFIG_PPC_FPU=y |
27 | CONFIG_ALTIVEC=y | 31 | CONFIG_ALTIVEC=y |
28 | CONFIG_PPC_STD_MMU=y | 32 | CONFIG_PPC_STD_MMU=y |
33 | CONFIG_VIRT_CPU_ACCOUNTING=y | ||
29 | CONFIG_SMP=y | 34 | CONFIG_SMP=y |
30 | CONFIG_NR_CPUS=4 | 35 | CONFIG_NR_CPUS=4 |
31 | 36 | ||
@@ -33,7 +38,6 @@ CONFIG_NR_CPUS=4 | |||
33 | # Code maturity level options | 38 | # Code maturity level options |
34 | # | 39 | # |
35 | CONFIG_EXPERIMENTAL=y | 40 | CONFIG_EXPERIMENTAL=y |
36 | CONFIG_CLEAN_COMPILE=y | ||
37 | CONFIG_LOCK_KERNEL=y | 41 | CONFIG_LOCK_KERNEL=y |
38 | CONFIG_INIT_ENV_ARG_LIMIT=32 | 42 | CONFIG_INIT_ENV_ARG_LIMIT=32 |
39 | 43 | ||
@@ -48,9 +52,8 @@ CONFIG_SYSVIPC=y | |||
48 | # CONFIG_BSD_PROCESS_ACCT is not set | 52 | # CONFIG_BSD_PROCESS_ACCT is not set |
49 | CONFIG_SYSCTL=y | 53 | CONFIG_SYSCTL=y |
50 | # CONFIG_AUDIT is not set | 54 | # CONFIG_AUDIT is not set |
51 | CONFIG_HOTPLUG=y | 55 | CONFIG_IKCONFIG=y |
52 | CONFIG_KOBJECT_UEVENT=y | 56 | CONFIG_IKCONFIG_PROC=y |
53 | # CONFIG_IKCONFIG is not set | ||
54 | # CONFIG_CPUSETS is not set | 57 | # CONFIG_CPUSETS is not set |
55 | CONFIG_INITRAMFS_SOURCE="" | 58 | CONFIG_INITRAMFS_SOURCE="" |
56 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | 59 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y |
@@ -58,8 +61,10 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y | |||
58 | CONFIG_KALLSYMS=y | 61 | CONFIG_KALLSYMS=y |
59 | # CONFIG_KALLSYMS_ALL is not set | 62 | # CONFIG_KALLSYMS_ALL is not set |
60 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | 63 | # CONFIG_KALLSYMS_EXTRA_PASS is not set |
64 | CONFIG_HOTPLUG=y | ||
61 | CONFIG_PRINTK=y | 65 | CONFIG_PRINTK=y |
62 | CONFIG_BUG=y | 66 | CONFIG_BUG=y |
67 | CONFIG_ELF_CORE=y | ||
63 | CONFIG_BASE_FULL=y | 68 | CONFIG_BASE_FULL=y |
64 | CONFIG_FUTEX=y | 69 | CONFIG_FUTEX=y |
65 | CONFIG_EPOLL=y | 70 | CONFIG_EPOLL=y |
@@ -68,8 +73,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0 | |||
68 | CONFIG_CC_ALIGN_LABELS=0 | 73 | CONFIG_CC_ALIGN_LABELS=0 |
69 | CONFIG_CC_ALIGN_LOOPS=0 | 74 | CONFIG_CC_ALIGN_LOOPS=0 |
70 | CONFIG_CC_ALIGN_JUMPS=0 | 75 | CONFIG_CC_ALIGN_JUMPS=0 |
76 | CONFIG_SLAB=y | ||
71 | # CONFIG_TINY_SHMEM is not set | 77 | # CONFIG_TINY_SHMEM is not set |
72 | CONFIG_BASE_SMALL=0 | 78 | CONFIG_BASE_SMALL=0 |
79 | # CONFIG_SLOB is not set | ||
73 | 80 | ||
74 | # | 81 | # |
75 | # Loadable module support | 82 | # Loadable module support |
@@ -80,7 +87,7 @@ CONFIG_MODULE_UNLOAD=y | |||
80 | CONFIG_OBSOLETE_MODPARM=y | 87 | CONFIG_OBSOLETE_MODPARM=y |
81 | # CONFIG_MODVERSIONS is not set | 88 | # CONFIG_MODVERSIONS is not set |
82 | # CONFIG_MODULE_SRCVERSION_ALL is not set | 89 | # CONFIG_MODULE_SRCVERSION_ALL is not set |
83 | # CONFIG_KMOD is not set | 90 | CONFIG_KMOD=y |
84 | CONFIG_STOP_MACHINE=y | 91 | CONFIG_STOP_MACHINE=y |
85 | 92 | ||
86 | # | 93 | # |
@@ -111,7 +118,6 @@ CONFIG_PPC_MULTIPLATFORM=y | |||
111 | # CONFIG_PPC_PMAC is not set | 118 | # CONFIG_PPC_PMAC is not set |
112 | # CONFIG_PPC_MAPLE is not set | 119 | # CONFIG_PPC_MAPLE is not set |
113 | CONFIG_PPC_CELL=y | 120 | CONFIG_PPC_CELL=y |
114 | CONFIG_PPC_OF=y | ||
115 | # CONFIG_U3_DART is not set | 121 | # CONFIG_U3_DART is not set |
116 | CONFIG_PPC_RTAS=y | 122 | CONFIG_PPC_RTAS=y |
117 | # CONFIG_RTAS_ERROR_LOGGING is not set | 123 | # CONFIG_RTAS_ERROR_LOGGING is not set |
@@ -120,11 +126,16 @@ CONFIG_RTAS_FLASH=y | |||
120 | CONFIG_MMIO_NVRAM=y | 126 | CONFIG_MMIO_NVRAM=y |
121 | CONFIG_CELL_IIC=y | 127 | CONFIG_CELL_IIC=y |
122 | # CONFIG_PPC_MPC106 is not set | 128 | # CONFIG_PPC_MPC106 is not set |
123 | # CONFIG_GENERIC_TBSYNC is not set | ||
124 | # CONFIG_CPU_FREQ is not set | 129 | # CONFIG_CPU_FREQ is not set |
125 | # CONFIG_WANT_EARLY_SERIAL is not set | 130 | # CONFIG_WANT_EARLY_SERIAL is not set |
126 | 131 | ||
127 | # | 132 | # |
133 | # Cell Broadband Engine options | ||
134 | # | ||
135 | CONFIG_SPU_FS=m | ||
136 | CONFIG_SPUFS_MMAP=y | ||
137 | |||
138 | # | ||
128 | # Kernel options | 139 | # Kernel options |
129 | # | 140 | # |
130 | # CONFIG_HZ_100 is not set | 141 | # CONFIG_HZ_100 is not set |
@@ -136,23 +147,27 @@ CONFIG_PREEMPT_NONE=y | |||
136 | # CONFIG_PREEMPT is not set | 147 | # CONFIG_PREEMPT is not set |
137 | CONFIG_PREEMPT_BKL=y | 148 | CONFIG_PREEMPT_BKL=y |
138 | CONFIG_BINFMT_ELF=y | 149 | CONFIG_BINFMT_ELF=y |
139 | # CONFIG_BINFMT_MISC is not set | 150 | CONFIG_BINFMT_MISC=m |
140 | CONFIG_FORCE_MAX_ZONEORDER=13 | 151 | CONFIG_FORCE_MAX_ZONEORDER=13 |
141 | # CONFIG_IOMMU_VMERGE is not set | 152 | # CONFIG_IOMMU_VMERGE is not set |
142 | CONFIG_KEXEC=y | 153 | CONFIG_KEXEC=y |
154 | # CONFIG_CRASH_DUMP is not set | ||
143 | CONFIG_IRQ_ALL_CPUS=y | 155 | CONFIG_IRQ_ALL_CPUS=y |
144 | # CONFIG_NUMA is not set | 156 | # CONFIG_NUMA is not set |
145 | CONFIG_ARCH_SELECT_MEMORY_MODEL=y | 157 | CONFIG_ARCH_SELECT_MEMORY_MODEL=y |
146 | CONFIG_ARCH_FLATMEM_ENABLE=y | 158 | CONFIG_ARCH_FLATMEM_ENABLE=y |
147 | CONFIG_ARCH_SPARSEMEM_ENABLE=y | 159 | CONFIG_ARCH_SPARSEMEM_ENABLE=y |
148 | CONFIG_SELECT_MEMORY_MODEL=y | 160 | CONFIG_SELECT_MEMORY_MODEL=y |
149 | CONFIG_FLATMEM_MANUAL=y | 161 | # CONFIG_FLATMEM_MANUAL is not set |
150 | # CONFIG_DISCONTIGMEM_MANUAL is not set | 162 | # CONFIG_DISCONTIGMEM_MANUAL is not set |
151 | # CONFIG_SPARSEMEM_MANUAL is not set | 163 | CONFIG_SPARSEMEM_MANUAL=y |
152 | CONFIG_FLATMEM=y | 164 | CONFIG_SPARSEMEM=y |
153 | CONFIG_FLAT_NODE_MEM_MAP=y | 165 | CONFIG_HAVE_MEMORY_PRESENT=y |
154 | # CONFIG_SPARSEMEM_STATIC is not set | 166 | # CONFIG_SPARSEMEM_STATIC is not set |
167 | CONFIG_SPARSEMEM_EXTREME=y | ||
168 | # CONFIG_MEMORY_HOTPLUG is not set | ||
155 | CONFIG_SPLIT_PTLOCK_CPUS=4 | 169 | CONFIG_SPLIT_PTLOCK_CPUS=4 |
170 | CONFIG_MIGRATION=y | ||
156 | # CONFIG_PPC_64K_PAGES is not set | 171 | # CONFIG_PPC_64K_PAGES is not set |
157 | CONFIG_SCHED_SMT=y | 172 | CONFIG_SCHED_SMT=y |
158 | CONFIG_PROC_DEVICETREE=y | 173 | CONFIG_PROC_DEVICETREE=y |
@@ -191,6 +206,7 @@ CONFIG_NET=y | |||
191 | # | 206 | # |
192 | # Networking options | 207 | # Networking options |
193 | # | 208 | # |
209 | # CONFIG_NETDEBUG is not set | ||
194 | CONFIG_PACKET=y | 210 | CONFIG_PACKET=y |
195 | # CONFIG_PACKET_MMAP is not set | 211 | # CONFIG_PACKET_MMAP is not set |
196 | CONFIG_UNIX=y | 212 | CONFIG_UNIX=y |
@@ -222,6 +238,7 @@ CONFIG_TCP_CONG_BIC=y | |||
222 | # CONFIG_IP_VS is not set | 238 | # CONFIG_IP_VS is not set |
223 | CONFIG_IPV6=y | 239 | CONFIG_IPV6=y |
224 | # CONFIG_IPV6_PRIVACY is not set | 240 | # CONFIG_IPV6_PRIVACY is not set |
241 | # CONFIG_IPV6_ROUTER_PREF is not set | ||
225 | CONFIG_INET6_AH=m | 242 | CONFIG_INET6_AH=m |
226 | CONFIG_INET6_ESP=m | 243 | CONFIG_INET6_ESP=m |
227 | CONFIG_INET6_IPCOMP=m | 244 | CONFIG_INET6_IPCOMP=m |
@@ -234,6 +251,7 @@ CONFIG_NETFILTER=y | |||
234 | # Core Netfilter Configuration | 251 | # Core Netfilter Configuration |
235 | # | 252 | # |
236 | # CONFIG_NETFILTER_NETLINK is not set | 253 | # CONFIG_NETFILTER_NETLINK is not set |
254 | # CONFIG_NETFILTER_XTABLES is not set | ||
237 | 255 | ||
238 | # | 256 | # |
239 | # IP: Netfilter Configuration | 257 | # IP: Netfilter Configuration |
@@ -249,69 +267,13 @@ CONFIG_IP_NF_IRC=m | |||
249 | CONFIG_IP_NF_TFTP=m | 267 | CONFIG_IP_NF_TFTP=m |
250 | CONFIG_IP_NF_AMANDA=m | 268 | CONFIG_IP_NF_AMANDA=m |
251 | # CONFIG_IP_NF_PPTP is not set | 269 | # CONFIG_IP_NF_PPTP is not set |
270 | # CONFIG_IP_NF_H323 is not set | ||
252 | CONFIG_IP_NF_QUEUE=m | 271 | CONFIG_IP_NF_QUEUE=m |
253 | CONFIG_IP_NF_IPTABLES=m | ||
254 | CONFIG_IP_NF_MATCH_LIMIT=m | ||
255 | CONFIG_IP_NF_MATCH_IPRANGE=m | ||
256 | CONFIG_IP_NF_MATCH_MAC=m | ||
257 | CONFIG_IP_NF_MATCH_PKTTYPE=m | ||
258 | CONFIG_IP_NF_MATCH_MARK=m | ||
259 | CONFIG_IP_NF_MATCH_MULTIPORT=m | ||
260 | CONFIG_IP_NF_MATCH_TOS=m | ||
261 | CONFIG_IP_NF_MATCH_RECENT=m | ||
262 | CONFIG_IP_NF_MATCH_ECN=m | ||
263 | CONFIG_IP_NF_MATCH_DSCP=m | ||
264 | CONFIG_IP_NF_MATCH_AH_ESP=m | ||
265 | CONFIG_IP_NF_MATCH_LENGTH=m | ||
266 | CONFIG_IP_NF_MATCH_TTL=m | ||
267 | CONFIG_IP_NF_MATCH_TCPMSS=m | ||
268 | CONFIG_IP_NF_MATCH_HELPER=m | ||
269 | CONFIG_IP_NF_MATCH_STATE=m | ||
270 | CONFIG_IP_NF_MATCH_CONNTRACK=m | ||
271 | CONFIG_IP_NF_MATCH_OWNER=m | ||
272 | CONFIG_IP_NF_MATCH_ADDRTYPE=m | ||
273 | CONFIG_IP_NF_MATCH_REALM=m | ||
274 | CONFIG_IP_NF_MATCH_SCTP=m | ||
275 | # CONFIG_IP_NF_MATCH_DCCP is not set | ||
276 | CONFIG_IP_NF_MATCH_COMMENT=m | ||
277 | CONFIG_IP_NF_MATCH_HASHLIMIT=m | ||
278 | CONFIG_IP_NF_MATCH_STRING=m | ||
279 | CONFIG_IP_NF_FILTER=m | ||
280 | CONFIG_IP_NF_TARGET_REJECT=m | ||
281 | CONFIG_IP_NF_TARGET_LOG=m | ||
282 | CONFIG_IP_NF_TARGET_ULOG=m | ||
283 | CONFIG_IP_NF_TARGET_TCPMSS=m | ||
284 | CONFIG_IP_NF_TARGET_NFQUEUE=m | ||
285 | CONFIG_IP_NF_NAT=m | ||
286 | CONFIG_IP_NF_NAT_NEEDED=y | ||
287 | CONFIG_IP_NF_TARGET_MASQUERADE=m | ||
288 | CONFIG_IP_NF_TARGET_REDIRECT=m | ||
289 | CONFIG_IP_NF_TARGET_NETMAP=m | ||
290 | CONFIG_IP_NF_TARGET_SAME=m | ||
291 | CONFIG_IP_NF_NAT_SNMP_BASIC=m | ||
292 | CONFIG_IP_NF_NAT_IRC=m | ||
293 | CONFIG_IP_NF_NAT_FTP=m | ||
294 | CONFIG_IP_NF_NAT_TFTP=m | ||
295 | CONFIG_IP_NF_NAT_AMANDA=m | ||
296 | CONFIG_IP_NF_MANGLE=m | ||
297 | CONFIG_IP_NF_TARGET_TOS=m | ||
298 | CONFIG_IP_NF_TARGET_ECN=m | ||
299 | CONFIG_IP_NF_TARGET_DSCP=m | ||
300 | CONFIG_IP_NF_TARGET_MARK=m | ||
301 | CONFIG_IP_NF_TARGET_CLASSIFY=m | ||
302 | CONFIG_IP_NF_TARGET_TTL=m | ||
303 | CONFIG_IP_NF_RAW=m | ||
304 | CONFIG_IP_NF_TARGET_NOTRACK=m | ||
305 | CONFIG_IP_NF_ARPTABLES=m | ||
306 | CONFIG_IP_NF_ARPFILTER=m | ||
307 | CONFIG_IP_NF_ARP_MANGLE=m | ||
308 | 272 | ||
309 | # | 273 | # |
310 | # IPv6: Netfilter Configuration (EXPERIMENTAL) | 274 | # IPv6: Netfilter Configuration (EXPERIMENTAL) |
311 | # | 275 | # |
312 | # CONFIG_IP6_NF_QUEUE is not set | 276 | # CONFIG_IP6_NF_QUEUE is not set |
313 | # CONFIG_IP6_NF_IPTABLES is not set | ||
314 | # CONFIG_IP6_NF_TARGET_NFQUEUE is not set | ||
315 | 277 | ||
316 | # | 278 | # |
317 | # DCCP Configuration (EXPERIMENTAL) | 279 | # DCCP Configuration (EXPERIMENTAL) |
@@ -322,6 +284,11 @@ CONFIG_IP_NF_ARP_MANGLE=m | |||
322 | # SCTP Configuration (EXPERIMENTAL) | 284 | # SCTP Configuration (EXPERIMENTAL) |
323 | # | 285 | # |
324 | # CONFIG_IP_SCTP is not set | 286 | # CONFIG_IP_SCTP is not set |
287 | |||
288 | # | ||
289 | # TIPC Configuration (EXPERIMENTAL) | ||
290 | # | ||
291 | # CONFIG_TIPC is not set | ||
325 | # CONFIG_ATM is not set | 292 | # CONFIG_ATM is not set |
326 | # CONFIG_BRIDGE is not set | 293 | # CONFIG_BRIDGE is not set |
327 | # CONFIG_VLAN_8021Q is not set | 294 | # CONFIG_VLAN_8021Q is not set |
@@ -339,7 +306,6 @@ CONFIG_IP_NF_ARP_MANGLE=m | |||
339 | # QoS and/or fair queueing | 306 | # QoS and/or fair queueing |
340 | # | 307 | # |
341 | # CONFIG_NET_SCHED is not set | 308 | # CONFIG_NET_SCHED is not set |
342 | CONFIG_NET_CLS_ROUTE=y | ||
343 | 309 | ||
344 | # | 310 | # |
345 | # Network testing | 311 | # Network testing |
@@ -392,7 +358,7 @@ CONFIG_FW_LOADER=y | |||
392 | # CONFIG_BLK_DEV_COW_COMMON is not set | 358 | # CONFIG_BLK_DEV_COW_COMMON is not set |
393 | CONFIG_BLK_DEV_LOOP=y | 359 | CONFIG_BLK_DEV_LOOP=y |
394 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set | 360 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set |
395 | CONFIG_BLK_DEV_NBD=y | 361 | # CONFIG_BLK_DEV_NBD is not set |
396 | # CONFIG_BLK_DEV_SX8 is not set | 362 | # CONFIG_BLK_DEV_SX8 is not set |
397 | CONFIG_BLK_DEV_RAM=y | 363 | CONFIG_BLK_DEV_RAM=y |
398 | CONFIG_BLK_DEV_RAM_COUNT=16 | 364 | CONFIG_BLK_DEV_RAM_COUNT=16 |
@@ -468,7 +434,23 @@ CONFIG_IDEDMA_AUTO=y | |||
468 | # | 434 | # |
469 | # Multi-device support (RAID and LVM) | 435 | # Multi-device support (RAID and LVM) |
470 | # | 436 | # |
471 | # CONFIG_MD is not set | 437 | CONFIG_MD=y |
438 | CONFIG_BLK_DEV_MD=m | ||
439 | CONFIG_MD_LINEAR=m | ||
440 | CONFIG_MD_RAID0=m | ||
441 | CONFIG_MD_RAID1=m | ||
442 | # CONFIG_MD_RAID10 is not set | ||
443 | # CONFIG_MD_RAID5 is not set | ||
444 | # CONFIG_MD_RAID6 is not set | ||
445 | # CONFIG_MD_MULTIPATH is not set | ||
446 | # CONFIG_MD_FAULTY is not set | ||
447 | CONFIG_BLK_DEV_DM=m | ||
448 | CONFIG_DM_CRYPT=m | ||
449 | CONFIG_DM_SNAPSHOT=m | ||
450 | CONFIG_DM_MIRROR=m | ||
451 | CONFIG_DM_ZERO=m | ||
452 | CONFIG_DM_MULTIPATH=m | ||
453 | # CONFIG_DM_MULTIPATH_EMC is not set | ||
472 | 454 | ||
473 | # | 455 | # |
474 | # Fusion MPT device support | 456 | # Fusion MPT device support |
@@ -532,7 +514,7 @@ CONFIG_MII=y | |||
532 | # CONFIG_ACENIC is not set | 514 | # CONFIG_ACENIC is not set |
533 | # CONFIG_DL2K is not set | 515 | # CONFIG_DL2K is not set |
534 | CONFIG_E1000=m | 516 | CONFIG_E1000=m |
535 | # CONFIG_E1000_NAPI is not set | 517 | CONFIG_E1000_NAPI=y |
536 | # CONFIG_E1000_DISABLE_PACKET_SPLIT is not set | 518 | # CONFIG_E1000_DISABLE_PACKET_SPLIT is not set |
537 | # CONFIG_NS83820 is not set | 519 | # CONFIG_NS83820 is not set |
538 | # CONFIG_HAMACHI is not set | 520 | # CONFIG_HAMACHI is not set |
@@ -540,9 +522,11 @@ CONFIG_E1000=m | |||
540 | # CONFIG_R8169 is not set | 522 | # CONFIG_R8169 is not set |
541 | # CONFIG_SIS190 is not set | 523 | # CONFIG_SIS190 is not set |
542 | CONFIG_SKGE=m | 524 | CONFIG_SKGE=m |
525 | # CONFIG_SKY2 is not set | ||
543 | # CONFIG_SK98LIN is not set | 526 | # CONFIG_SK98LIN is not set |
544 | # CONFIG_TIGON3 is not set | 527 | # CONFIG_TIGON3 is not set |
545 | # CONFIG_BNX2 is not set | 528 | # CONFIG_BNX2 is not set |
529 | CONFIG_SPIDER_NET=m | ||
546 | # CONFIG_MV643XX_ETH is not set | 530 | # CONFIG_MV643XX_ETH is not set |
547 | 531 | ||
548 | # | 532 | # |
@@ -628,13 +612,16 @@ CONFIG_VT=y | |||
628 | CONFIG_VT_CONSOLE=y | 612 | CONFIG_VT_CONSOLE=y |
629 | CONFIG_HW_CONSOLE=y | 613 | CONFIG_HW_CONSOLE=y |
630 | CONFIG_SERIAL_NONSTANDARD=y | 614 | CONFIG_SERIAL_NONSTANDARD=y |
615 | # CONFIG_COMPUTONE is not set | ||
631 | # CONFIG_ROCKETPORT is not set | 616 | # CONFIG_ROCKETPORT is not set |
632 | # CONFIG_CYCLADES is not set | 617 | # CONFIG_CYCLADES is not set |
633 | # CONFIG_DIGIEPCA is not set | 618 | # CONFIG_DIGIEPCA is not set |
619 | # CONFIG_MOXA_INTELLIO is not set | ||
634 | # CONFIG_MOXA_SMARTIO is not set | 620 | # CONFIG_MOXA_SMARTIO is not set |
635 | # CONFIG_ISI is not set | 621 | # CONFIG_ISI is not set |
636 | # CONFIG_SYNCLINK is not set | 622 | # CONFIG_SYNCLINK is not set |
637 | # CONFIG_SYNCLINKMP is not set | 623 | # CONFIG_SYNCLINKMP is not set |
624 | # CONFIG_SYNCLINK_GT is not set | ||
638 | # CONFIG_N_HDLC is not set | 625 | # CONFIG_N_HDLC is not set |
639 | # CONFIG_SPECIALIX is not set | 626 | # CONFIG_SPECIALIX is not set |
640 | # CONFIG_SX is not set | 627 | # CONFIG_SX is not set |
@@ -646,6 +633,7 @@ CONFIG_SERIAL_NONSTANDARD=y | |||
646 | CONFIG_SERIAL_8250=y | 633 | CONFIG_SERIAL_8250=y |
647 | CONFIG_SERIAL_8250_CONSOLE=y | 634 | CONFIG_SERIAL_8250_CONSOLE=y |
648 | CONFIG_SERIAL_8250_NR_UARTS=4 | 635 | CONFIG_SERIAL_8250_NR_UARTS=4 |
636 | CONFIG_SERIAL_8250_RUNTIME_UARTS=4 | ||
649 | # CONFIG_SERIAL_8250_EXTENDED is not set | 637 | # CONFIG_SERIAL_8250_EXTENDED is not set |
650 | 638 | ||
651 | # | 639 | # |
@@ -656,6 +644,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y | |||
656 | # CONFIG_SERIAL_JSM is not set | 644 | # CONFIG_SERIAL_JSM is not set |
657 | CONFIG_UNIX98_PTYS=y | 645 | CONFIG_UNIX98_PTYS=y |
658 | # CONFIG_LEGACY_PTYS is not set | 646 | # CONFIG_LEGACY_PTYS is not set |
647 | CONFIG_HVC_DRIVER=y | ||
648 | CONFIG_HVC_RTAS=y | ||
659 | 649 | ||
660 | # | 650 | # |
661 | # IPMI | 651 | # IPMI |
@@ -672,14 +662,13 @@ CONFIG_WATCHDOG=y | |||
672 | # Watchdog Device Drivers | 662 | # Watchdog Device Drivers |
673 | # | 663 | # |
674 | # CONFIG_SOFT_WATCHDOG is not set | 664 | # CONFIG_SOFT_WATCHDOG is not set |
675 | # CONFIG_WATCHDOG_RTAS is not set | 665 | CONFIG_WATCHDOG_RTAS=y |
676 | 666 | ||
677 | # | 667 | # |
678 | # PCI-based Watchdog Cards | 668 | # PCI-based Watchdog Cards |
679 | # | 669 | # |
680 | # CONFIG_PCIPCWATCHDOG is not set | 670 | # CONFIG_PCIPCWATCHDOG is not set |
681 | # CONFIG_WDTPCI is not set | 671 | # CONFIG_WDTPCI is not set |
682 | # CONFIG_RTC is not set | ||
683 | CONFIG_GEN_RTC=y | 672 | CONFIG_GEN_RTC=y |
684 | # CONFIG_GEN_RTC_X is not set | 673 | # CONFIG_GEN_RTC_X is not set |
685 | # CONFIG_DTLK is not set | 674 | # CONFIG_DTLK is not set |
@@ -756,6 +745,12 @@ CONFIG_I2C_ALGOBIT=y | |||
756 | # CONFIG_I2C_DEBUG_CHIP is not set | 745 | # CONFIG_I2C_DEBUG_CHIP is not set |
757 | 746 | ||
758 | # | 747 | # |
748 | # SPI support | ||
749 | # | ||
750 | # CONFIG_SPI is not set | ||
751 | # CONFIG_SPI_MASTER is not set | ||
752 | |||
753 | # | ||
759 | # Dallas's 1-wire bus | 754 | # Dallas's 1-wire bus |
760 | # | 755 | # |
761 | # CONFIG_W1 is not set | 756 | # CONFIG_W1 is not set |
@@ -805,6 +800,7 @@ CONFIG_DUMMY_CONSOLE=y | |||
805 | # | 800 | # |
806 | CONFIG_USB_ARCH_HAS_HCD=y | 801 | CONFIG_USB_ARCH_HAS_HCD=y |
807 | CONFIG_USB_ARCH_HAS_OHCI=y | 802 | CONFIG_USB_ARCH_HAS_OHCI=y |
803 | CONFIG_USB_ARCH_HAS_EHCI=y | ||
808 | # CONFIG_USB is not set | 804 | # CONFIG_USB is not set |
809 | 805 | ||
810 | # | 806 | # |
@@ -824,10 +820,17 @@ CONFIG_USB_ARCH_HAS_OHCI=y | |||
824 | # | 820 | # |
825 | # InfiniBand support | 821 | # InfiniBand support |
826 | # | 822 | # |
827 | # CONFIG_INFINIBAND is not set | 823 | CONFIG_INFINIBAND=y |
824 | CONFIG_INFINIBAND_USER_MAD=m | ||
825 | CONFIG_INFINIBAND_USER_ACCESS=m | ||
826 | CONFIG_INFINIBAND_MTHCA=m | ||
827 | CONFIG_INFINIBAND_MTHCA_DEBUG=y | ||
828 | CONFIG_INFINIBAND_IPOIB=m | ||
829 | CONFIG_INFINIBAND_IPOIB_DEBUG=y | ||
830 | CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y | ||
828 | 831 | ||
829 | # | 832 | # |
830 | # SN Devices | 833 | # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) |
831 | # | 834 | # |
832 | 835 | ||
833 | # | 836 | # |
@@ -847,6 +850,7 @@ CONFIG_FS_MBCACHE=y | |||
847 | # CONFIG_JFS_FS is not set | 850 | # CONFIG_JFS_FS is not set |
848 | CONFIG_FS_POSIX_ACL=y | 851 | CONFIG_FS_POSIX_ACL=y |
849 | # CONFIG_XFS_FS is not set | 852 | # CONFIG_XFS_FS is not set |
853 | # CONFIG_OCFS2_FS is not set | ||
850 | # CONFIG_MINIX_FS is not set | 854 | # CONFIG_MINIX_FS is not set |
851 | # CONFIG_ROMFS_FS is not set | 855 | # CONFIG_ROMFS_FS is not set |
852 | CONFIG_INOTIFY=y | 856 | CONFIG_INOTIFY=y |
@@ -886,6 +890,7 @@ CONFIG_HUGETLBFS=y | |||
886 | CONFIG_HUGETLB_PAGE=y | 890 | CONFIG_HUGETLB_PAGE=y |
887 | CONFIG_RAMFS=y | 891 | CONFIG_RAMFS=y |
888 | # CONFIG_RELAYFS_FS is not set | 892 | # CONFIG_RELAYFS_FS is not set |
893 | # CONFIG_CONFIGFS_FS is not set | ||
889 | 894 | ||
890 | # | 895 | # |
891 | # Miscellaneous filesystems | 896 | # Miscellaneous filesystems |
@@ -951,6 +956,7 @@ CONFIG_MSDOS_PARTITION=y | |||
951 | # CONFIG_SGI_PARTITION is not set | 956 | # CONFIG_SGI_PARTITION is not set |
952 | # CONFIG_ULTRIX_PARTITION is not set | 957 | # CONFIG_ULTRIX_PARTITION is not set |
953 | # CONFIG_SUN_PARTITION is not set | 958 | # CONFIG_SUN_PARTITION is not set |
959 | # CONFIG_KARMA_PARTITION is not set | ||
954 | CONFIG_EFI_PARTITION=y | 960 | CONFIG_EFI_PARTITION=y |
955 | 961 | ||
956 | # | 962 | # |
@@ -1006,10 +1012,6 @@ CONFIG_CRC32=y | |||
1006 | # CONFIG_LIBCRC32C is not set | 1012 | # CONFIG_LIBCRC32C is not set |
1007 | CONFIG_ZLIB_INFLATE=m | 1013 | CONFIG_ZLIB_INFLATE=m |
1008 | CONFIG_ZLIB_DEFLATE=m | 1014 | CONFIG_ZLIB_DEFLATE=m |
1009 | CONFIG_TEXTSEARCH=y | ||
1010 | CONFIG_TEXTSEARCH_KMP=m | ||
1011 | CONFIG_TEXTSEARCH_BM=m | ||
1012 | CONFIG_TEXTSEARCH_FSM=m | ||
1013 | 1015 | ||
1014 | # | 1016 | # |
1015 | # Instrumentation Support | 1017 | # Instrumentation Support |
@@ -1021,18 +1023,20 @@ CONFIG_TEXTSEARCH_FSM=m | |||
1021 | # Kernel hacking | 1023 | # Kernel hacking |
1022 | # | 1024 | # |
1023 | # CONFIG_PRINTK_TIME is not set | 1025 | # CONFIG_PRINTK_TIME is not set |
1024 | CONFIG_DEBUG_KERNEL=y | ||
1025 | CONFIG_MAGIC_SYSRQ=y | 1026 | CONFIG_MAGIC_SYSRQ=y |
1027 | CONFIG_DEBUG_KERNEL=y | ||
1026 | CONFIG_LOG_BUF_SHIFT=15 | 1028 | CONFIG_LOG_BUF_SHIFT=15 |
1027 | CONFIG_DETECT_SOFTLOCKUP=y | 1029 | CONFIG_DETECT_SOFTLOCKUP=y |
1028 | # CONFIG_SCHEDSTATS is not set | 1030 | # CONFIG_SCHEDSTATS is not set |
1029 | # CONFIG_DEBUG_SLAB is not set | 1031 | # CONFIG_DEBUG_SLAB is not set |
1032 | CONFIG_DEBUG_MUTEXES=y | ||
1030 | # CONFIG_DEBUG_SPINLOCK is not set | 1033 | # CONFIG_DEBUG_SPINLOCK is not set |
1031 | CONFIG_DEBUG_SPINLOCK_SLEEP=y | 1034 | CONFIG_DEBUG_SPINLOCK_SLEEP=y |
1032 | # CONFIG_DEBUG_KOBJECT is not set | 1035 | # CONFIG_DEBUG_KOBJECT is not set |
1033 | # CONFIG_DEBUG_INFO is not set | 1036 | # CONFIG_DEBUG_INFO is not set |
1034 | CONFIG_DEBUG_FS=y | 1037 | CONFIG_DEBUG_FS=y |
1035 | # CONFIG_DEBUG_VM is not set | 1038 | # CONFIG_DEBUG_VM is not set |
1039 | # CONFIG_FORCED_INLINING is not set | ||
1036 | # CONFIG_RCU_TORTURE_TEST is not set | 1040 | # CONFIG_RCU_TORTURE_TEST is not set |
1037 | # CONFIG_DEBUG_STACKOVERFLOW is not set | 1041 | # CONFIG_DEBUG_STACKOVERFLOW is not set |
1038 | # CONFIG_DEBUG_STACK_USAGE is not set | 1042 | # CONFIG_DEBUG_STACK_USAGE is not set |
@@ -1040,6 +1044,11 @@ CONFIG_DEBUGGER=y | |||
1040 | # CONFIG_XMON is not set | 1044 | # CONFIG_XMON is not set |
1041 | CONFIG_IRQSTACKS=y | 1045 | CONFIG_IRQSTACKS=y |
1042 | # CONFIG_BOOTX_TEXT is not set | 1046 | # CONFIG_BOOTX_TEXT is not set |
1047 | # CONFIG_PPC_EARLY_DEBUG_LPAR is not set | ||
1048 | # CONFIG_PPC_EARLY_DEBUG_G5 is not set | ||
1049 | # CONFIG_PPC_EARLY_DEBUG_RTAS is not set | ||
1050 | # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set | ||
1051 | # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set | ||
1043 | 1052 | ||
1044 | # | 1053 | # |
1045 | # Security options | 1054 | # Security options |
diff --git a/arch/powerpc/configs/iseries_defconfig b/arch/powerpc/configs/iseries_defconfig index c775027947f9..1816a46742f6 100644 --- a/arch/powerpc/configs/iseries_defconfig +++ b/arch/powerpc/configs/iseries_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.15-rc5 | 3 | # Linux kernel version: 2.6.16-rc6 |
4 | # Tue Dec 20 15:59:32 2005 | 4 | # Wed Mar 15 16:19:52 2006 |
5 | # | 5 | # |
6 | CONFIG_PPC64=y | 6 | CONFIG_PPC64=y |
7 | CONFIG_64BIT=y | 7 | CONFIG_64BIT=y |
@@ -16,6 +16,10 @@ CONFIG_COMPAT=y | |||
16 | CONFIG_SYSVIPC_COMPAT=y | 16 | CONFIG_SYSVIPC_COMPAT=y |
17 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y | 17 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y |
18 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y | 18 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y |
19 | CONFIG_PPC_OF=y | ||
20 | # CONFIG_PPC_UDBG_16550 is not set | ||
21 | # CONFIG_GENERIC_TBSYNC is not set | ||
22 | # CONFIG_DEFAULT_UIMAGE is not set | ||
19 | 23 | ||
20 | # | 24 | # |
21 | # Processor support | 25 | # Processor support |
@@ -33,7 +37,6 @@ CONFIG_NR_CPUS=32 | |||
33 | # Code maturity level options | 37 | # Code maturity level options |
34 | # | 38 | # |
35 | CONFIG_EXPERIMENTAL=y | 39 | CONFIG_EXPERIMENTAL=y |
36 | CONFIG_CLEAN_COMPILE=y | ||
37 | CONFIG_LOCK_KERNEL=y | 40 | CONFIG_LOCK_KERNEL=y |
38 | CONFIG_INIT_ENV_ARG_LIMIT=32 | 41 | CONFIG_INIT_ENV_ARG_LIMIT=32 |
39 | 42 | ||
@@ -49,8 +52,6 @@ CONFIG_POSIX_MQUEUE=y | |||
49 | CONFIG_SYSCTL=y | 52 | CONFIG_SYSCTL=y |
50 | CONFIG_AUDIT=y | 53 | CONFIG_AUDIT=y |
51 | CONFIG_AUDITSYSCALL=y | 54 | CONFIG_AUDITSYSCALL=y |
52 | CONFIG_HOTPLUG=y | ||
53 | CONFIG_KOBJECT_UEVENT=y | ||
54 | CONFIG_IKCONFIG=y | 55 | CONFIG_IKCONFIG=y |
55 | CONFIG_IKCONFIG_PROC=y | 56 | CONFIG_IKCONFIG_PROC=y |
56 | # CONFIG_CPUSETS is not set | 57 | # CONFIG_CPUSETS is not set |
@@ -60,8 +61,10 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y | |||
60 | CONFIG_KALLSYMS=y | 61 | CONFIG_KALLSYMS=y |
61 | # CONFIG_KALLSYMS_ALL is not set | 62 | # CONFIG_KALLSYMS_ALL is not set |
62 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | 63 | # CONFIG_KALLSYMS_EXTRA_PASS is not set |
64 | CONFIG_HOTPLUG=y | ||
63 | CONFIG_PRINTK=y | 65 | CONFIG_PRINTK=y |
64 | CONFIG_BUG=y | 66 | CONFIG_BUG=y |
67 | CONFIG_ELF_CORE=y | ||
65 | CONFIG_BASE_FULL=y | 68 | CONFIG_BASE_FULL=y |
66 | CONFIG_FUTEX=y | 69 | CONFIG_FUTEX=y |
67 | CONFIG_EPOLL=y | 70 | CONFIG_EPOLL=y |
@@ -70,8 +73,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0 | |||
70 | CONFIG_CC_ALIGN_LABELS=0 | 73 | CONFIG_CC_ALIGN_LABELS=0 |
71 | CONFIG_CC_ALIGN_LOOPS=0 | 74 | CONFIG_CC_ALIGN_LOOPS=0 |
72 | CONFIG_CC_ALIGN_JUMPS=0 | 75 | CONFIG_CC_ALIGN_JUMPS=0 |
76 | CONFIG_SLAB=y | ||
73 | # CONFIG_TINY_SHMEM is not set | 77 | # CONFIG_TINY_SHMEM is not set |
74 | CONFIG_BASE_SMALL=0 | 78 | CONFIG_BASE_SMALL=0 |
79 | # CONFIG_SLOB is not set | ||
75 | 80 | ||
76 | # | 81 | # |
77 | # Loadable module support | 82 | # Loadable module support |
@@ -113,7 +118,6 @@ CONFIG_PPC_ISERIES=y | |||
113 | # CONFIG_MMIO_NVRAM is not set | 118 | # CONFIG_MMIO_NVRAM is not set |
114 | CONFIG_IBMVIO=y | 119 | CONFIG_IBMVIO=y |
115 | # CONFIG_PPC_MPC106 is not set | 120 | # CONFIG_PPC_MPC106 is not set |
116 | # CONFIG_GENERIC_TBSYNC is not set | ||
117 | # CONFIG_CPU_FREQ is not set | 121 | # CONFIG_CPU_FREQ is not set |
118 | # CONFIG_WANT_EARLY_SERIAL is not set | 122 | # CONFIG_WANT_EARLY_SERIAL is not set |
119 | 123 | ||
@@ -183,6 +187,7 @@ CONFIG_NET=y | |||
183 | # | 187 | # |
184 | # Networking options | 188 | # Networking options |
185 | # | 189 | # |
190 | # CONFIG_NETDEBUG is not set | ||
186 | CONFIG_PACKET=y | 191 | CONFIG_PACKET=y |
187 | # CONFIG_PACKET_MMAP is not set | 192 | # CONFIG_PACKET_MMAP is not set |
188 | CONFIG_UNIX=y | 193 | CONFIG_UNIX=y |
@@ -220,6 +225,28 @@ CONFIG_NETFILTER=y | |||
220 | # Core Netfilter Configuration | 225 | # Core Netfilter Configuration |
221 | # | 226 | # |
222 | # CONFIG_NETFILTER_NETLINK is not set | 227 | # CONFIG_NETFILTER_NETLINK is not set |
228 | CONFIG_NETFILTER_XTABLES=m | ||
229 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | ||
230 | CONFIG_NETFILTER_XT_TARGET_CONNMARK=m | ||
231 | CONFIG_NETFILTER_XT_TARGET_MARK=m | ||
232 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | ||
233 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m | ||
234 | CONFIG_NETFILTER_XT_MATCH_COMMENT=m | ||
235 | CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m | ||
236 | CONFIG_NETFILTER_XT_MATCH_CONNMARK=m | ||
237 | CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m | ||
238 | # CONFIG_NETFILTER_XT_MATCH_DCCP is not set | ||
239 | CONFIG_NETFILTER_XT_MATCH_HELPER=m | ||
240 | CONFIG_NETFILTER_XT_MATCH_LENGTH=m | ||
241 | CONFIG_NETFILTER_XT_MATCH_LIMIT=m | ||
242 | CONFIG_NETFILTER_XT_MATCH_MAC=m | ||
243 | CONFIG_NETFILTER_XT_MATCH_MARK=m | ||
244 | CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m | ||
245 | CONFIG_NETFILTER_XT_MATCH_REALM=m | ||
246 | CONFIG_NETFILTER_XT_MATCH_SCTP=m | ||
247 | CONFIG_NETFILTER_XT_MATCH_STATE=m | ||
248 | CONFIG_NETFILTER_XT_MATCH_STRING=m | ||
249 | CONFIG_NETFILTER_XT_MATCH_TCPMSS=m | ||
223 | 250 | ||
224 | # | 251 | # |
225 | # IP: Netfilter Configuration | 252 | # IP: Netfilter Configuration |
@@ -237,39 +264,23 @@ CONFIG_IP_NF_AMANDA=m | |||
237 | # CONFIG_IP_NF_PPTP is not set | 264 | # CONFIG_IP_NF_PPTP is not set |
238 | CONFIG_IP_NF_QUEUE=m | 265 | CONFIG_IP_NF_QUEUE=m |
239 | CONFIG_IP_NF_IPTABLES=m | 266 | CONFIG_IP_NF_IPTABLES=m |
240 | CONFIG_IP_NF_MATCH_LIMIT=m | ||
241 | CONFIG_IP_NF_MATCH_IPRANGE=m | 267 | CONFIG_IP_NF_MATCH_IPRANGE=m |
242 | CONFIG_IP_NF_MATCH_MAC=m | ||
243 | CONFIG_IP_NF_MATCH_PKTTYPE=m | ||
244 | CONFIG_IP_NF_MATCH_MARK=m | ||
245 | CONFIG_IP_NF_MATCH_MULTIPORT=m | 268 | CONFIG_IP_NF_MATCH_MULTIPORT=m |
246 | CONFIG_IP_NF_MATCH_TOS=m | 269 | CONFIG_IP_NF_MATCH_TOS=m |
247 | CONFIG_IP_NF_MATCH_RECENT=m | 270 | CONFIG_IP_NF_MATCH_RECENT=m |
248 | CONFIG_IP_NF_MATCH_ECN=m | 271 | CONFIG_IP_NF_MATCH_ECN=m |
249 | CONFIG_IP_NF_MATCH_DSCP=m | 272 | CONFIG_IP_NF_MATCH_DSCP=m |
250 | CONFIG_IP_NF_MATCH_AH_ESP=m | 273 | CONFIG_IP_NF_MATCH_AH_ESP=m |
251 | CONFIG_IP_NF_MATCH_LENGTH=m | ||
252 | CONFIG_IP_NF_MATCH_TTL=m | 274 | CONFIG_IP_NF_MATCH_TTL=m |
253 | CONFIG_IP_NF_MATCH_TCPMSS=m | ||
254 | CONFIG_IP_NF_MATCH_HELPER=m | ||
255 | CONFIG_IP_NF_MATCH_STATE=m | ||
256 | CONFIG_IP_NF_MATCH_CONNTRACK=m | ||
257 | CONFIG_IP_NF_MATCH_OWNER=m | 275 | CONFIG_IP_NF_MATCH_OWNER=m |
258 | CONFIG_IP_NF_MATCH_ADDRTYPE=m | 276 | CONFIG_IP_NF_MATCH_ADDRTYPE=m |
259 | CONFIG_IP_NF_MATCH_REALM=m | ||
260 | CONFIG_IP_NF_MATCH_SCTP=m | ||
261 | # CONFIG_IP_NF_MATCH_DCCP is not set | ||
262 | CONFIG_IP_NF_MATCH_COMMENT=m | ||
263 | CONFIG_IP_NF_MATCH_CONNMARK=m | ||
264 | CONFIG_IP_NF_MATCH_CONNBYTES=m | ||
265 | CONFIG_IP_NF_MATCH_HASHLIMIT=m | 277 | CONFIG_IP_NF_MATCH_HASHLIMIT=m |
266 | CONFIG_IP_NF_MATCH_STRING=m | 278 | CONFIG_IP_NF_MATCH_POLICY=m |
267 | CONFIG_IP_NF_FILTER=m | 279 | CONFIG_IP_NF_FILTER=m |
268 | CONFIG_IP_NF_TARGET_REJECT=m | 280 | CONFIG_IP_NF_TARGET_REJECT=m |
269 | CONFIG_IP_NF_TARGET_LOG=m | 281 | CONFIG_IP_NF_TARGET_LOG=m |
270 | CONFIG_IP_NF_TARGET_ULOG=m | 282 | CONFIG_IP_NF_TARGET_ULOG=m |
271 | CONFIG_IP_NF_TARGET_TCPMSS=m | 283 | CONFIG_IP_NF_TARGET_TCPMSS=m |
272 | CONFIG_IP_NF_TARGET_NFQUEUE=m | ||
273 | CONFIG_IP_NF_NAT=m | 284 | CONFIG_IP_NF_NAT=m |
274 | CONFIG_IP_NF_NAT_NEEDED=y | 285 | CONFIG_IP_NF_NAT_NEEDED=y |
275 | CONFIG_IP_NF_TARGET_MASQUERADE=m | 286 | CONFIG_IP_NF_TARGET_MASQUERADE=m |
@@ -285,13 +296,9 @@ CONFIG_IP_NF_MANGLE=m | |||
285 | CONFIG_IP_NF_TARGET_TOS=m | 296 | CONFIG_IP_NF_TARGET_TOS=m |
286 | CONFIG_IP_NF_TARGET_ECN=m | 297 | CONFIG_IP_NF_TARGET_ECN=m |
287 | CONFIG_IP_NF_TARGET_DSCP=m | 298 | CONFIG_IP_NF_TARGET_DSCP=m |
288 | CONFIG_IP_NF_TARGET_MARK=m | ||
289 | CONFIG_IP_NF_TARGET_CLASSIFY=m | ||
290 | CONFIG_IP_NF_TARGET_TTL=m | 299 | CONFIG_IP_NF_TARGET_TTL=m |
291 | CONFIG_IP_NF_TARGET_CONNMARK=m | ||
292 | CONFIG_IP_NF_TARGET_CLUSTERIP=m | 300 | CONFIG_IP_NF_TARGET_CLUSTERIP=m |
293 | CONFIG_IP_NF_RAW=m | 301 | CONFIG_IP_NF_RAW=m |
294 | CONFIG_IP_NF_TARGET_NOTRACK=m | ||
295 | CONFIG_IP_NF_ARPTABLES=m | 302 | CONFIG_IP_NF_ARPTABLES=m |
296 | CONFIG_IP_NF_ARPFILTER=m | 303 | CONFIG_IP_NF_ARPFILTER=m |
297 | CONFIG_IP_NF_ARP_MANGLE=m | 304 | CONFIG_IP_NF_ARP_MANGLE=m |
@@ -305,6 +312,11 @@ CONFIG_IP_NF_ARP_MANGLE=m | |||
305 | # SCTP Configuration (EXPERIMENTAL) | 312 | # SCTP Configuration (EXPERIMENTAL) |
306 | # | 313 | # |
307 | # CONFIG_IP_SCTP is not set | 314 | # CONFIG_IP_SCTP is not set |
315 | |||
316 | # | ||
317 | # TIPC Configuration (EXPERIMENTAL) | ||
318 | # | ||
319 | # CONFIG_TIPC is not set | ||
308 | # CONFIG_ATM is not set | 320 | # CONFIG_ATM is not set |
309 | # CONFIG_BRIDGE is not set | 321 | # CONFIG_BRIDGE is not set |
310 | # CONFIG_VLAN_8021Q is not set | 322 | # CONFIG_VLAN_8021Q is not set |
@@ -451,13 +463,7 @@ CONFIG_SCSI_IBMVSCSI=m | |||
451 | # CONFIG_SCSI_IPR is not set | 463 | # CONFIG_SCSI_IPR is not set |
452 | # CONFIG_SCSI_QLOGIC_FC is not set | 464 | # CONFIG_SCSI_QLOGIC_FC is not set |
453 | # CONFIG_SCSI_QLOGIC_1280 is not set | 465 | # CONFIG_SCSI_QLOGIC_1280 is not set |
454 | CONFIG_SCSI_QLA2XXX=y | 466 | # CONFIG_SCSI_QLA_FC is not set |
455 | # CONFIG_SCSI_QLA21XX is not set | ||
456 | # CONFIG_SCSI_QLA22XX is not set | ||
457 | # CONFIG_SCSI_QLA2300 is not set | ||
458 | # CONFIG_SCSI_QLA2322 is not set | ||
459 | # CONFIG_SCSI_QLA6312 is not set | ||
460 | # CONFIG_SCSI_QLA24XX is not set | ||
461 | # CONFIG_SCSI_LPFC is not set | 467 | # CONFIG_SCSI_LPFC is not set |
462 | # CONFIG_SCSI_DC395x is not set | 468 | # CONFIG_SCSI_DC395x is not set |
463 | # CONFIG_SCSI_DC390T is not set | 469 | # CONFIG_SCSI_DC390T is not set |
@@ -574,6 +580,7 @@ CONFIG_E1000=m | |||
574 | # CONFIG_R8169 is not set | 580 | # CONFIG_R8169 is not set |
575 | # CONFIG_SIS190 is not set | 581 | # CONFIG_SIS190 is not set |
576 | # CONFIG_SKGE is not set | 582 | # CONFIG_SKGE is not set |
583 | # CONFIG_SKY2 is not set | ||
577 | # CONFIG_SK98LIN is not set | 584 | # CONFIG_SK98LIN is not set |
578 | # CONFIG_VIA_VELOCITY is not set | 585 | # CONFIG_VIA_VELOCITY is not set |
579 | # CONFIG_TIGON3 is not set | 586 | # CONFIG_TIGON3 is not set |
@@ -723,6 +730,12 @@ CONFIG_MAX_RAW_DEVS=256 | |||
723 | # CONFIG_I2C is not set | 730 | # CONFIG_I2C is not set |
724 | 731 | ||
725 | # | 732 | # |
733 | # SPI support | ||
734 | # | ||
735 | # CONFIG_SPI is not set | ||
736 | # CONFIG_SPI_MASTER is not set | ||
737 | |||
738 | # | ||
726 | # Dallas's 1-wire bus | 739 | # Dallas's 1-wire bus |
727 | # | 740 | # |
728 | # CONFIG_W1 is not set | 741 | # CONFIG_W1 is not set |
@@ -788,7 +801,7 @@ CONFIG_USB_ARCH_HAS_OHCI=y | |||
788 | # CONFIG_INFINIBAND is not set | 801 | # CONFIG_INFINIBAND is not set |
789 | 802 | ||
790 | # | 803 | # |
791 | # SN Devices | 804 | # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) |
792 | # | 805 | # |
793 | 806 | ||
794 | # | 807 | # |
@@ -825,6 +838,7 @@ CONFIG_XFS_EXPORT=y | |||
825 | CONFIG_XFS_SECURITY=y | 838 | CONFIG_XFS_SECURITY=y |
826 | CONFIG_XFS_POSIX_ACL=y | 839 | CONFIG_XFS_POSIX_ACL=y |
827 | # CONFIG_XFS_RT is not set | 840 | # CONFIG_XFS_RT is not set |
841 | # CONFIG_OCFS2_FS is not set | ||
828 | # CONFIG_MINIX_FS is not set | 842 | # CONFIG_MINIX_FS is not set |
829 | # CONFIG_ROMFS_FS is not set | 843 | # CONFIG_ROMFS_FS is not set |
830 | CONFIG_INOTIFY=y | 844 | CONFIG_INOTIFY=y |
@@ -865,6 +879,7 @@ CONFIG_TMPFS=y | |||
865 | # CONFIG_HUGETLB_PAGE is not set | 879 | # CONFIG_HUGETLB_PAGE is not set |
866 | CONFIG_RAMFS=y | 880 | CONFIG_RAMFS=y |
867 | # CONFIG_RELAYFS_FS is not set | 881 | # CONFIG_RELAYFS_FS is not set |
882 | # CONFIG_CONFIGFS_FS is not set | ||
868 | 883 | ||
869 | # | 884 | # |
870 | # Miscellaneous filesystems | 885 | # Miscellaneous filesystems |
@@ -993,31 +1008,36 @@ CONFIG_TEXTSEARCH_FSM=m | |||
993 | # | 1008 | # |
994 | # Instrumentation Support | 1009 | # Instrumentation Support |
995 | # | 1010 | # |
996 | CONFIG_PROFILING=y | ||
997 | CONFIG_OPROFILE=y | ||
998 | # CONFIG_KPROBES is not set | 1011 | # CONFIG_KPROBES is not set |
999 | 1012 | ||
1000 | # | 1013 | # |
1001 | # Kernel hacking | 1014 | # Kernel hacking |
1002 | # | 1015 | # |
1003 | # CONFIG_PRINTK_TIME is not set | 1016 | # CONFIG_PRINTK_TIME is not set |
1004 | CONFIG_DEBUG_KERNEL=y | ||
1005 | CONFIG_MAGIC_SYSRQ=y | 1017 | CONFIG_MAGIC_SYSRQ=y |
1018 | CONFIG_DEBUG_KERNEL=y | ||
1006 | CONFIG_LOG_BUF_SHIFT=17 | 1019 | CONFIG_LOG_BUF_SHIFT=17 |
1007 | CONFIG_DETECT_SOFTLOCKUP=y | 1020 | CONFIG_DETECT_SOFTLOCKUP=y |
1008 | # CONFIG_SCHEDSTATS is not set | 1021 | # CONFIG_SCHEDSTATS is not set |
1009 | # CONFIG_DEBUG_SLAB is not set | 1022 | # CONFIG_DEBUG_SLAB is not set |
1023 | # CONFIG_DEBUG_MUTEXES is not set | ||
1010 | # CONFIG_DEBUG_SPINLOCK is not set | 1024 | # CONFIG_DEBUG_SPINLOCK is not set |
1011 | # CONFIG_DEBUG_SPINLOCK_SLEEP is not set | 1025 | # CONFIG_DEBUG_SPINLOCK_SLEEP is not set |
1012 | # CONFIG_DEBUG_KOBJECT is not set | 1026 | # CONFIG_DEBUG_KOBJECT is not set |
1013 | # CONFIG_DEBUG_INFO is not set | 1027 | # CONFIG_DEBUG_INFO is not set |
1014 | CONFIG_DEBUG_FS=y | 1028 | CONFIG_DEBUG_FS=y |
1015 | # CONFIG_DEBUG_VM is not set | 1029 | # CONFIG_DEBUG_VM is not set |
1030 | # CONFIG_FORCED_INLINING is not set | ||
1016 | # CONFIG_RCU_TORTURE_TEST is not set | 1031 | # CONFIG_RCU_TORTURE_TEST is not set |
1017 | CONFIG_DEBUG_STACKOVERFLOW=y | 1032 | CONFIG_DEBUG_STACKOVERFLOW=y |
1018 | CONFIG_DEBUG_STACK_USAGE=y | 1033 | CONFIG_DEBUG_STACK_USAGE=y |
1019 | # CONFIG_DEBUGGER is not set | 1034 | # CONFIG_DEBUGGER is not set |
1020 | CONFIG_IRQSTACKS=y | 1035 | CONFIG_IRQSTACKS=y |
1036 | # CONFIG_PPC_EARLY_DEBUG_LPAR is not set | ||
1037 | # CONFIG_PPC_EARLY_DEBUG_G5 is not set | ||
1038 | # CONFIG_PPC_EARLY_DEBUG_RTAS is not set | ||
1039 | # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set | ||
1040 | # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set | ||
1021 | 1041 | ||
1022 | # | 1042 | # |
1023 | # Security options | 1043 | # Security options |
diff --git a/arch/powerpc/configs/maple_defconfig b/arch/powerpc/configs/maple_defconfig index 68194c03f6d1..80a0db43aeb7 100644 --- a/arch/powerpc/configs/maple_defconfig +++ b/arch/powerpc/configs/maple_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.15-rc5 | 3 | # Linux kernel version: 2.6.16-rc6 |
4 | # Tue Dec 20 15:59:36 2005 | 4 | # Wed Mar 15 16:19:54 2006 |
5 | # | 5 | # |
6 | CONFIG_PPC64=y | 6 | CONFIG_PPC64=y |
7 | CONFIG_64BIT=y | 7 | CONFIG_64BIT=y |
@@ -16,6 +16,10 @@ CONFIG_COMPAT=y | |||
16 | CONFIG_SYSVIPC_COMPAT=y | 16 | CONFIG_SYSVIPC_COMPAT=y |
17 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y | 17 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y |
18 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y | 18 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y |
19 | CONFIG_PPC_OF=y | ||
20 | CONFIG_PPC_UDBG_16550=y | ||
21 | CONFIG_GENERIC_TBSYNC=y | ||
22 | # CONFIG_DEFAULT_UIMAGE is not set | ||
19 | 23 | ||
20 | # | 24 | # |
21 | # Processor support | 25 | # Processor support |
@@ -32,7 +36,6 @@ CONFIG_NR_CPUS=2 | |||
32 | # Code maturity level options | 36 | # Code maturity level options |
33 | # | 37 | # |
34 | CONFIG_EXPERIMENTAL=y | 38 | CONFIG_EXPERIMENTAL=y |
35 | CONFIG_CLEAN_COMPILE=y | ||
36 | CONFIG_LOCK_KERNEL=y | 39 | CONFIG_LOCK_KERNEL=y |
37 | CONFIG_INIT_ENV_ARG_LIMIT=32 | 40 | CONFIG_INIT_ENV_ARG_LIMIT=32 |
38 | 41 | ||
@@ -47,8 +50,6 @@ CONFIG_POSIX_MQUEUE=y | |||
47 | # CONFIG_BSD_PROCESS_ACCT is not set | 50 | # CONFIG_BSD_PROCESS_ACCT is not set |
48 | CONFIG_SYSCTL=y | 51 | CONFIG_SYSCTL=y |
49 | # CONFIG_AUDIT is not set | 52 | # CONFIG_AUDIT is not set |
50 | # CONFIG_HOTPLUG is not set | ||
51 | CONFIG_KOBJECT_UEVENT=y | ||
52 | CONFIG_IKCONFIG=y | 53 | CONFIG_IKCONFIG=y |
53 | CONFIG_IKCONFIG_PROC=y | 54 | CONFIG_IKCONFIG_PROC=y |
54 | # CONFIG_CPUSETS is not set | 55 | # CONFIG_CPUSETS is not set |
@@ -58,8 +59,10 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y | |||
58 | CONFIG_KALLSYMS=y | 59 | CONFIG_KALLSYMS=y |
59 | CONFIG_KALLSYMS_ALL=y | 60 | CONFIG_KALLSYMS_ALL=y |
60 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | 61 | # CONFIG_KALLSYMS_EXTRA_PASS is not set |
62 | CONFIG_HOTPLUG=y | ||
61 | CONFIG_PRINTK=y | 63 | CONFIG_PRINTK=y |
62 | CONFIG_BUG=y | 64 | CONFIG_BUG=y |
65 | CONFIG_ELF_CORE=y | ||
63 | CONFIG_BASE_FULL=y | 66 | CONFIG_BASE_FULL=y |
64 | CONFIG_FUTEX=y | 67 | CONFIG_FUTEX=y |
65 | CONFIG_EPOLL=y | 68 | CONFIG_EPOLL=y |
@@ -68,8 +71,10 @@ CONFIG_CC_ALIGN_FUNCTIONS=0 | |||
68 | CONFIG_CC_ALIGN_LABELS=0 | 71 | CONFIG_CC_ALIGN_LABELS=0 |
69 | CONFIG_CC_ALIGN_LOOPS=0 | 72 | CONFIG_CC_ALIGN_LOOPS=0 |
70 | CONFIG_CC_ALIGN_JUMPS=0 | 73 | CONFIG_CC_ALIGN_JUMPS=0 |
74 | CONFIG_SLAB=y | ||
71 | # CONFIG_TINY_SHMEM is not set | 75 | # CONFIG_TINY_SHMEM is not set |
72 | CONFIG_BASE_SMALL=0 | 76 | CONFIG_BASE_SMALL=0 |
77 | # CONFIG_SLOB is not set | ||
73 | 78 | ||
74 | # | 79 | # |
75 | # Loadable module support | 80 | # Loadable module support |
@@ -111,14 +116,12 @@ CONFIG_PPC_MULTIPLATFORM=y | |||
111 | # CONFIG_PPC_PMAC is not set | 116 | # CONFIG_PPC_PMAC is not set |
112 | CONFIG_PPC_MAPLE=y | 117 | CONFIG_PPC_MAPLE=y |
113 | # CONFIG_PPC_CELL is not set | 118 | # CONFIG_PPC_CELL is not set |
114 | CONFIG_PPC_OF=y | ||
115 | CONFIG_U3_DART=y | 119 | CONFIG_U3_DART=y |
116 | CONFIG_MPIC=y | 120 | CONFIG_MPIC=y |
117 | # CONFIG_PPC_RTAS is not set | 121 | # CONFIG_PPC_RTAS is not set |
118 | # CONFIG_MMIO_NVRAM is not set | 122 | # CONFIG_MMIO_NVRAM is not set |
119 | CONFIG_MPIC_BROKEN_U3=y | 123 | CONFIG_MPIC_BROKEN_U3=y |
120 | # CONFIG_PPC_MPC106 is not set | 124 | # CONFIG_PPC_MPC106 is not set |
121 | CONFIG_GENERIC_TBSYNC=y | ||
122 | # CONFIG_CPU_FREQ is not set | 125 | # CONFIG_CPU_FREQ is not set |
123 | # CONFIG_WANT_EARLY_SERIAL is not set | 126 | # CONFIG_WANT_EARLY_SERIAL is not set |
124 | 127 | ||
@@ -138,6 +141,7 @@ CONFIG_BINFMT_ELF=y | |||
138 | CONFIG_FORCE_MAX_ZONEORDER=13 | 141 | CONFIG_FORCE_MAX_ZONEORDER=13 |
139 | CONFIG_IOMMU_VMERGE=y | 142 | CONFIG_IOMMU_VMERGE=y |
140 | CONFIG_KEXEC=y | 143 | CONFIG_KEXEC=y |
144 | # CONFIG_CRASH_DUMP is not set | ||
141 | CONFIG_IRQ_ALL_CPUS=y | 145 | CONFIG_IRQ_ALL_CPUS=y |
142 | # CONFIG_NUMA is not set | 146 | # CONFIG_NUMA is not set |
143 | CONFIG_ARCH_SELECT_MEMORY_MODEL=y | 147 | CONFIG_ARCH_SELECT_MEMORY_MODEL=y |
@@ -189,6 +193,7 @@ CONFIG_NET=y | |||
189 | # | 193 | # |
190 | # Networking options | 194 | # Networking options |
191 | # | 195 | # |
196 | # CONFIG_NETDEBUG is not set | ||
192 | CONFIG_PACKET=y | 197 | CONFIG_PACKET=y |
193 | CONFIG_PACKET_MMAP=y | 198 | CONFIG_PACKET_MMAP=y |
194 | CONFIG_UNIX=y | 199 | CONFIG_UNIX=y |
@@ -226,6 +231,11 @@ CONFIG_TCP_CONG_BIC=y | |||
226 | # SCTP Configuration (EXPERIMENTAL) | 231 | # SCTP Configuration (EXPERIMENTAL) |
227 | # | 232 | # |
228 | # CONFIG_IP_SCTP is not set | 233 | # CONFIG_IP_SCTP is not set |
234 | |||
235 | # | ||
236 | # TIPC Configuration (EXPERIMENTAL) | ||
237 | # | ||
238 | # CONFIG_TIPC is not set | ||
229 | # CONFIG_ATM is not set | 239 | # CONFIG_ATM is not set |
230 | # CONFIG_BRIDGE is not set | 240 | # CONFIG_BRIDGE is not set |
231 | # CONFIG_VLAN_8021Q is not set | 241 | # CONFIG_VLAN_8021Q is not set |
@@ -461,6 +471,7 @@ CONFIG_E1000=y | |||
461 | # CONFIG_R8169 is not set | 471 | # CONFIG_R8169 is not set |
462 | # CONFIG_SIS190 is not set | 472 | # CONFIG_SIS190 is not set |
463 | # CONFIG_SKGE is not set | 473 | # CONFIG_SKGE is not set |
474 | # CONFIG_SKY2 is not set | ||
464 | # CONFIG_SK98LIN is not set | 475 | # CONFIG_SK98LIN is not set |
465 | # CONFIG_VIA_VELOCITY is not set | 476 | # CONFIG_VIA_VELOCITY is not set |
466 | # CONFIG_TIGON3 is not set | 477 | # CONFIG_TIGON3 is not set |
@@ -553,6 +564,7 @@ CONFIG_HW_CONSOLE=y | |||
553 | CONFIG_SERIAL_8250=y | 564 | CONFIG_SERIAL_8250=y |
554 | CONFIG_SERIAL_8250_CONSOLE=y | 565 | CONFIG_SERIAL_8250_CONSOLE=y |
555 | CONFIG_SERIAL_8250_NR_UARTS=4 | 566 | CONFIG_SERIAL_8250_NR_UARTS=4 |
567 | CONFIG_SERIAL_8250_RUNTIME_UARTS=4 | ||
556 | # CONFIG_SERIAL_8250_EXTENDED is not set | 568 | # CONFIG_SERIAL_8250_EXTENDED is not set |
557 | 569 | ||
558 | # | 570 | # |
@@ -651,6 +663,12 @@ CONFIG_I2C_AMD8111=y | |||
651 | # CONFIG_I2C_DEBUG_CHIP is not set | 663 | # CONFIG_I2C_DEBUG_CHIP is not set |
652 | 664 | ||
653 | # | 665 | # |
666 | # SPI support | ||
667 | # | ||
668 | # CONFIG_SPI is not set | ||
669 | # CONFIG_SPI_MASTER is not set | ||
670 | |||
671 | # | ||
654 | # Dallas's 1-wire bus | 672 | # Dallas's 1-wire bus |
655 | # | 673 | # |
656 | # CONFIG_W1 is not set | 674 | # CONFIG_W1 is not set |
@@ -738,12 +756,14 @@ CONFIG_USB_UHCI_HCD=y | |||
738 | # may also be needed; see USB_STORAGE Help for more information | 756 | # may also be needed; see USB_STORAGE Help for more information |
739 | # | 757 | # |
740 | # CONFIG_USB_STORAGE is not set | 758 | # CONFIG_USB_STORAGE is not set |
759 | # CONFIG_USB_LIBUSUAL is not set | ||
741 | 760 | ||
742 | # | 761 | # |
743 | # USB Input Devices | 762 | # USB Input Devices |
744 | # | 763 | # |
745 | CONFIG_USB_HID=y | 764 | CONFIG_USB_HID=y |
746 | CONFIG_USB_HIDINPUT=y | 765 | CONFIG_USB_HIDINPUT=y |
766 | # CONFIG_USB_HIDINPUT_POWERBOOK is not set | ||
747 | # CONFIG_HID_FF is not set | 767 | # CONFIG_HID_FF is not set |
748 | # CONFIG_USB_HIDDEV is not set | 768 | # CONFIG_USB_HIDDEV is not set |
749 | # CONFIG_USB_AIPTEK is not set | 769 | # CONFIG_USB_AIPTEK is not set |
@@ -757,6 +777,7 @@ CONFIG_USB_HIDINPUT=y | |||
757 | # CONFIG_USB_YEALINK is not set | 777 | # CONFIG_USB_YEALINK is not set |
758 | # CONFIG_USB_XPAD is not set | 778 | # CONFIG_USB_XPAD is not set |
759 | # CONFIG_USB_ATI_REMOTE is not set | 779 | # CONFIG_USB_ATI_REMOTE is not set |
780 | # CONFIG_USB_ATI_REMOTE2 is not set | ||
760 | # CONFIG_USB_KEYSPAN_REMOTE is not set | 781 | # CONFIG_USB_KEYSPAN_REMOTE is not set |
761 | # CONFIG_USB_APPLETOUCH is not set | 782 | # CONFIG_USB_APPLETOUCH is not set |
762 | 783 | ||
@@ -797,6 +818,7 @@ CONFIG_USB_SERIAL_GENERIC=y | |||
797 | # CONFIG_USB_SERIAL_AIRPRIME is not set | 818 | # CONFIG_USB_SERIAL_AIRPRIME is not set |
798 | # CONFIG_USB_SERIAL_ANYDATA is not set | 819 | # CONFIG_USB_SERIAL_ANYDATA is not set |
799 | # CONFIG_USB_SERIAL_BELKIN is not set | 820 | # CONFIG_USB_SERIAL_BELKIN is not set |
821 | # CONFIG_USB_SERIAL_WHITEHEAT is not set | ||
800 | # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set | 822 | # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set |
801 | # CONFIG_USB_SERIAL_CP2101 is not set | 823 | # CONFIG_USB_SERIAL_CP2101 is not set |
802 | CONFIG_USB_SERIAL_CYPRESS_M8=m | 824 | CONFIG_USB_SERIAL_CYPRESS_M8=m |
@@ -873,7 +895,7 @@ CONFIG_USB_EZUSB=y | |||
873 | # CONFIG_INFINIBAND is not set | 895 | # CONFIG_INFINIBAND is not set |
874 | 896 | ||
875 | # | 897 | # |
876 | # SN Devices | 898 | # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) |
877 | # | 899 | # |
878 | 900 | ||
879 | # | 901 | # |
@@ -891,6 +913,7 @@ CONFIG_JBD=y | |||
891 | # CONFIG_JFS_FS is not set | 913 | # CONFIG_JFS_FS is not set |
892 | CONFIG_FS_POSIX_ACL=y | 914 | CONFIG_FS_POSIX_ACL=y |
893 | # CONFIG_XFS_FS is not set | 915 | # CONFIG_XFS_FS is not set |
916 | # CONFIG_OCFS2_FS is not set | ||
894 | # CONFIG_MINIX_FS is not set | 917 | # CONFIG_MINIX_FS is not set |
895 | # CONFIG_ROMFS_FS is not set | 918 | # CONFIG_ROMFS_FS is not set |
896 | CONFIG_INOTIFY=y | 919 | CONFIG_INOTIFY=y |
@@ -927,6 +950,7 @@ CONFIG_HUGETLBFS=y | |||
927 | CONFIG_HUGETLB_PAGE=y | 950 | CONFIG_HUGETLB_PAGE=y |
928 | CONFIG_RAMFS=y | 951 | CONFIG_RAMFS=y |
929 | # CONFIG_RELAYFS_FS is not set | 952 | # CONFIG_RELAYFS_FS is not set |
953 | # CONFIG_CONFIGFS_FS is not set | ||
930 | 954 | ||
931 | # | 955 | # |
932 | # Miscellaneous filesystems | 956 | # Miscellaneous filesystems |
@@ -988,6 +1012,7 @@ CONFIG_MSDOS_PARTITION=y | |||
988 | # CONFIG_SGI_PARTITION is not set | 1012 | # CONFIG_SGI_PARTITION is not set |
989 | # CONFIG_ULTRIX_PARTITION is not set | 1013 | # CONFIG_ULTRIX_PARTITION is not set |
990 | # CONFIG_SUN_PARTITION is not set | 1014 | # CONFIG_SUN_PARTITION is not set |
1015 | # CONFIG_KARMA_PARTITION is not set | ||
991 | # CONFIG_EFI_PARTITION is not set | 1016 | # CONFIG_EFI_PARTITION is not set |
992 | 1017 | ||
993 | # | 1018 | # |
@@ -1053,18 +1078,20 @@ CONFIG_ZLIB_INFLATE=y | |||
1053 | # Kernel hacking | 1078 | # Kernel hacking |
1054 | # | 1079 | # |
1055 | # CONFIG_PRINTK_TIME is not set | 1080 | # CONFIG_PRINTK_TIME is not set |
1056 | CONFIG_DEBUG_KERNEL=y | ||
1057 | CONFIG_MAGIC_SYSRQ=y | 1081 | CONFIG_MAGIC_SYSRQ=y |
1082 | CONFIG_DEBUG_KERNEL=y | ||
1058 | CONFIG_LOG_BUF_SHIFT=17 | 1083 | CONFIG_LOG_BUF_SHIFT=17 |
1059 | CONFIG_DETECT_SOFTLOCKUP=y | 1084 | CONFIG_DETECT_SOFTLOCKUP=y |
1060 | # CONFIG_SCHEDSTATS is not set | 1085 | # CONFIG_SCHEDSTATS is not set |
1061 | CONFIG_DEBUG_SLAB=y | 1086 | CONFIG_DEBUG_SLAB=y |
1087 | # CONFIG_DEBUG_MUTEXES is not set | ||
1062 | # CONFIG_DEBUG_SPINLOCK is not set | 1088 | # CONFIG_DEBUG_SPINLOCK is not set |
1063 | CONFIG_DEBUG_SPINLOCK_SLEEP=y | 1089 | CONFIG_DEBUG_SPINLOCK_SLEEP=y |
1064 | # CONFIG_DEBUG_KOBJECT is not set | 1090 | # CONFIG_DEBUG_KOBJECT is not set |
1065 | # CONFIG_DEBUG_INFO is not set | 1091 | # CONFIG_DEBUG_INFO is not set |
1066 | CONFIG_DEBUG_FS=y | 1092 | CONFIG_DEBUG_FS=y |
1067 | # CONFIG_DEBUG_VM is not set | 1093 | # CONFIG_DEBUG_VM is not set |
1094 | # CONFIG_FORCED_INLINING is not set | ||
1068 | # CONFIG_RCU_TORTURE_TEST is not set | 1095 | # CONFIG_RCU_TORTURE_TEST is not set |
1069 | CONFIG_DEBUG_STACKOVERFLOW=y | 1096 | CONFIG_DEBUG_STACKOVERFLOW=y |
1070 | CONFIG_DEBUG_STACK_USAGE=y | 1097 | CONFIG_DEBUG_STACK_USAGE=y |
@@ -1073,6 +1100,11 @@ CONFIG_XMON=y | |||
1073 | CONFIG_XMON_DEFAULT=y | 1100 | CONFIG_XMON_DEFAULT=y |
1074 | # CONFIG_IRQSTACKS is not set | 1101 | # CONFIG_IRQSTACKS is not set |
1075 | CONFIG_BOOTX_TEXT=y | 1102 | CONFIG_BOOTX_TEXT=y |
1103 | # CONFIG_PPC_EARLY_DEBUG_LPAR is not set | ||
1104 | # CONFIG_PPC_EARLY_DEBUG_G5 is not set | ||
1105 | # CONFIG_PPC_EARLY_DEBUG_RTAS is not set | ||
1106 | # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set | ||
1107 | # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set | ||
1076 | 1108 | ||
1077 | # | 1109 | # |
1078 | # Security options | 1110 | # Security options |
diff --git a/arch/powerpc/configs/mpc834x_sys_defconfig b/arch/powerpc/configs/mpc834x_sys_defconfig index 3bff761965c2..5078b0441d61 100644 --- a/arch/powerpc/configs/mpc834x_sys_defconfig +++ b/arch/powerpc/configs/mpc834x_sys_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.15-g461d4edf-dirty | 3 | # Linux kernel version: 2.6.16-rc6 |
4 | # Fri Jan 13 11:01:47 2006 | 4 | # Wed Mar 15 16:19:56 2006 |
5 | # | 5 | # |
6 | # CONFIG_PPC64 is not set | 6 | # CONFIG_PPC64 is not set |
7 | CONFIG_PPC32=y | 7 | CONFIG_PPC32=y |
@@ -43,7 +43,6 @@ CONFIG_PPC_STD_MMU_32=y | |||
43 | # Code maturity level options | 43 | # Code maturity level options |
44 | # | 44 | # |
45 | CONFIG_EXPERIMENTAL=y | 45 | CONFIG_EXPERIMENTAL=y |
46 | CONFIG_CLEAN_COMPILE=y | ||
47 | CONFIG_BROKEN_ON_SMP=y | 46 | CONFIG_BROKEN_ON_SMP=y |
48 | CONFIG_INIT_ENV_ARG_LIMIT=32 | 47 | CONFIG_INIT_ENV_ARG_LIMIT=32 |
49 | 48 | ||
@@ -189,6 +188,7 @@ CONFIG_NET=y | |||
189 | # | 188 | # |
190 | # Networking options | 189 | # Networking options |
191 | # | 190 | # |
191 | # CONFIG_NETDEBUG is not set | ||
192 | CONFIG_PACKET=y | 192 | CONFIG_PACKET=y |
193 | # CONFIG_PACKET_MMAP is not set | 193 | # CONFIG_PACKET_MMAP is not set |
194 | CONFIG_UNIX=y | 194 | CONFIG_UNIX=y |
@@ -226,6 +226,11 @@ CONFIG_TCP_CONG_BIC=y | |||
226 | # SCTP Configuration (EXPERIMENTAL) | 226 | # SCTP Configuration (EXPERIMENTAL) |
227 | # | 227 | # |
228 | # CONFIG_IP_SCTP is not set | 228 | # CONFIG_IP_SCTP is not set |
229 | |||
230 | # | ||
231 | # TIPC Configuration (EXPERIMENTAL) | ||
232 | # | ||
233 | # CONFIG_TIPC is not set | ||
229 | # CONFIG_ATM is not set | 234 | # CONFIG_ATM is not set |
230 | # CONFIG_BRIDGE is not set | 235 | # CONFIG_BRIDGE is not set |
231 | # CONFIG_VLAN_8021Q is not set | 236 | # CONFIG_VLAN_8021Q is not set |
@@ -511,6 +516,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4 | |||
511 | # | 516 | # |
512 | CONFIG_SERIAL_CORE=y | 517 | CONFIG_SERIAL_CORE=y |
513 | CONFIG_SERIAL_CORE_CONSOLE=y | 518 | CONFIG_SERIAL_CORE_CONSOLE=y |
519 | # CONFIG_SERIAL_JSM is not set | ||
514 | CONFIG_UNIX98_PTYS=y | 520 | CONFIG_UNIX98_PTYS=y |
515 | CONFIG_LEGACY_PTYS=y | 521 | CONFIG_LEGACY_PTYS=y |
516 | CONFIG_LEGACY_PTY_COUNT=256 | 522 | CONFIG_LEGACY_PTY_COUNT=256 |
@@ -615,6 +621,12 @@ CONFIG_I2C_MPC=y | |||
615 | # CONFIG_I2C_DEBUG_CHIP is not set | 621 | # CONFIG_I2C_DEBUG_CHIP is not set |
616 | 622 | ||
617 | # | 623 | # |
624 | # SPI support | ||
625 | # | ||
626 | # CONFIG_SPI is not set | ||
627 | # CONFIG_SPI_MASTER is not set | ||
628 | |||
629 | # | ||
618 | # Dallas's 1-wire bus | 630 | # Dallas's 1-wire bus |
619 | # | 631 | # |
620 | # CONFIG_W1 is not set | 632 | # CONFIG_W1 is not set |
@@ -632,6 +644,7 @@ CONFIG_HWMON=y | |||
632 | # CONFIG_SENSORS_ASB100 is not set | 644 | # CONFIG_SENSORS_ASB100 is not set |
633 | # CONFIG_SENSORS_ATXP1 is not set | 645 | # CONFIG_SENSORS_ATXP1 is not set |
634 | # CONFIG_SENSORS_DS1621 is not set | 646 | # CONFIG_SENSORS_DS1621 is not set |
647 | # CONFIG_SENSORS_F71805F is not set | ||
635 | # CONFIG_SENSORS_FSCHER is not set | 648 | # CONFIG_SENSORS_FSCHER is not set |
636 | # CONFIG_SENSORS_FSCPOS is not set | 649 | # CONFIG_SENSORS_FSCPOS is not set |
637 | # CONFIG_SENSORS_GL518SM is not set | 650 | # CONFIG_SENSORS_GL518SM is not set |
@@ -716,7 +729,7 @@ CONFIG_USB_ARCH_HAS_OHCI=y | |||
716 | # CONFIG_INFINIBAND is not set | 729 | # CONFIG_INFINIBAND is not set |
717 | 730 | ||
718 | # | 731 | # |
719 | # SN Devices | 732 | # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) |
720 | # | 733 | # |
721 | 734 | ||
722 | # | 735 | # |
@@ -826,6 +839,7 @@ CONFIG_PARTITION_ADVANCED=y | |||
826 | # CONFIG_SGI_PARTITION is not set | 839 | # CONFIG_SGI_PARTITION is not set |
827 | # CONFIG_ULTRIX_PARTITION is not set | 840 | # CONFIG_ULTRIX_PARTITION is not set |
828 | # CONFIG_SUN_PARTITION is not set | 841 | # CONFIG_SUN_PARTITION is not set |
842 | # CONFIG_KARMA_PARTITION is not set | ||
829 | # CONFIG_EFI_PARTITION is not set | 843 | # CONFIG_EFI_PARTITION is not set |
830 | 844 | ||
831 | # | 845 | # |
@@ -899,13 +913,3 @@ CONFIG_CRYPTO_DES=y | |||
899 | # | 913 | # |
900 | # Hardware crypto devices | 914 | # Hardware crypto devices |
901 | # | 915 | # |
902 | |||
903 | # | ||
904 | # SEC2.x Options | ||
905 | # | ||
906 | CONFIG_MPC8349E_SEC2x=y | ||
907 | |||
908 | # | ||
909 | # SEC2.x Test Options | ||
910 | # | ||
911 | CONFIG_MPC8349E_SEC2xTEST=y | ||
diff --git a/arch/powerpc/configs/mpc8540_ads_defconfig b/arch/powerpc/configs/mpc8540_ads_defconfig new file mode 100644 index 000000000000..7f0780f1aa39 --- /dev/null +++ b/arch/powerpc/configs/mpc8540_ads_defconfig | |||
@@ -0,0 +1,728 @@ | |||
1 | # | ||
2 | # Automatically generated make config: don't edit | ||
3 | # Linux kernel version: 2.6.16 | ||
4 | # Mon Mar 27 23:37:36 2006 | ||
5 | # | ||
6 | # CONFIG_PPC64 is not set | ||
7 | CONFIG_PPC32=y | ||
8 | CONFIG_PPC_MERGE=y | ||
9 | CONFIG_MMU=y | ||
10 | CONFIG_GENERIC_HARDIRQS=y | ||
11 | CONFIG_RWSEM_XCHGADD_ALGORITHM=y | ||
12 | CONFIG_GENERIC_HWEIGHT=y | ||
13 | CONFIG_GENERIC_CALIBRATE_DELAY=y | ||
14 | CONFIG_PPC=y | ||
15 | CONFIG_EARLY_PRINTK=y | ||
16 | CONFIG_GENERIC_NVRAM=y | ||
17 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y | ||
18 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y | ||
19 | CONFIG_PPC_OF=y | ||
20 | CONFIG_PPC_UDBG_16550=y | ||
21 | # CONFIG_GENERIC_TBSYNC is not set | ||
22 | CONFIG_DEFAULT_UIMAGE=y | ||
23 | |||
24 | # | ||
25 | # Processor support | ||
26 | # | ||
27 | # CONFIG_CLASSIC32 is not set | ||
28 | # CONFIG_PPC_52xx is not set | ||
29 | # CONFIG_PPC_82xx is not set | ||
30 | # CONFIG_PPC_83xx is not set | ||
31 | CONFIG_PPC_85xx=y | ||
32 | # CONFIG_40x is not set | ||
33 | # CONFIG_44x is not set | ||
34 | # CONFIG_8xx is not set | ||
35 | # CONFIG_E200 is not set | ||
36 | CONFIG_85xx=y | ||
37 | CONFIG_E500=y | ||
38 | CONFIG_BOOKE=y | ||
39 | CONFIG_FSL_BOOKE=y | ||
40 | # CONFIG_PHYS_64BIT is not set | ||
41 | CONFIG_SPE=y | ||
42 | |||
43 | # | ||
44 | # Code maturity level options | ||
45 | # | ||
46 | CONFIG_EXPERIMENTAL=y | ||
47 | CONFIG_BROKEN_ON_SMP=y | ||
48 | CONFIG_INIT_ENV_ARG_LIMIT=32 | ||
49 | |||
50 | # | ||
51 | # General setup | ||
52 | # | ||
53 | CONFIG_LOCALVERSION="" | ||
54 | CONFIG_LOCALVERSION_AUTO=y | ||
55 | CONFIG_SWAP=y | ||
56 | CONFIG_SYSVIPC=y | ||
57 | # CONFIG_POSIX_MQUEUE is not set | ||
58 | # CONFIG_BSD_PROCESS_ACCT is not set | ||
59 | CONFIG_SYSCTL=y | ||
60 | # CONFIG_AUDIT is not set | ||
61 | # CONFIG_IKCONFIG is not set | ||
62 | # CONFIG_RELAY is not set | ||
63 | CONFIG_INITRAMFS_SOURCE="" | ||
64 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set | ||
65 | CONFIG_EMBEDDED=y | ||
66 | CONFIG_KALLSYMS=y | ||
67 | # CONFIG_KALLSYMS_ALL is not set | ||
68 | # CONFIG_KALLSYMS_EXTRA_PASS is not set | ||
69 | CONFIG_HOTPLUG=y | ||
70 | CONFIG_PRINTK=y | ||
71 | CONFIG_BUG=y | ||
72 | CONFIG_ELF_CORE=y | ||
73 | CONFIG_BASE_FULL=y | ||
74 | CONFIG_FUTEX=y | ||
75 | CONFIG_EPOLL=y | ||
76 | CONFIG_SHMEM=y | ||
77 | CONFIG_SLAB=y | ||
78 | # CONFIG_TINY_SHMEM is not set | ||
79 | CONFIG_BASE_SMALL=0 | ||
80 | # CONFIG_SLOB is not set | ||
81 | |||
82 | # | ||
83 | # Loadable module support | ||
84 | # | ||
85 | # CONFIG_MODULES is not set | ||
86 | |||
87 | # | ||
88 | # Block layer | ||
89 | # | ||
90 | # CONFIG_LBD is not set | ||
91 | # CONFIG_BLK_DEV_IO_TRACE is not set | ||
92 | # CONFIG_LSF is not set | ||
93 | |||
94 | # | ||
95 | # IO Schedulers | ||
96 | # | ||
97 | CONFIG_IOSCHED_NOOP=y | ||
98 | CONFIG_IOSCHED_AS=y | ||
99 | CONFIG_IOSCHED_DEADLINE=y | ||
100 | CONFIG_IOSCHED_CFQ=y | ||
101 | CONFIG_DEFAULT_AS=y | ||
102 | # CONFIG_DEFAULT_DEADLINE is not set | ||
103 | # CONFIG_DEFAULT_CFQ is not set | ||
104 | # CONFIG_DEFAULT_NOOP is not set | ||
105 | CONFIG_DEFAULT_IOSCHED="anticipatory" | ||
106 | CONFIG_MPIC=y | ||
107 | # CONFIG_WANT_EARLY_SERIAL is not set | ||
108 | |||
109 | # | ||
110 | # Platform support | ||
111 | # | ||
112 | CONFIG_MPC8540_ADS=y | ||
113 | CONFIG_MPC8540=y | ||
114 | CONFIG_PPC_INDIRECT_PCI_BE=y | ||
115 | |||
116 | # | ||
117 | # Kernel options | ||
118 | # | ||
119 | # CONFIG_HIGHMEM is not set | ||
120 | # CONFIG_HZ_100 is not set | ||
121 | CONFIG_HZ_250=y | ||
122 | # CONFIG_HZ_1000 is not set | ||
123 | CONFIG_HZ=250 | ||
124 | CONFIG_PREEMPT_NONE=y | ||
125 | # CONFIG_PREEMPT_VOLUNTARY is not set | ||
126 | # CONFIG_PREEMPT is not set | ||
127 | CONFIG_BINFMT_ELF=y | ||
128 | CONFIG_BINFMT_MISC=y | ||
129 | CONFIG_MATH_EMULATION=y | ||
130 | CONFIG_ARCH_FLATMEM_ENABLE=y | ||
131 | CONFIG_SELECT_MEMORY_MODEL=y | ||
132 | CONFIG_FLATMEM_MANUAL=y | ||
133 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
134 | # CONFIG_SPARSEMEM_MANUAL is not set | ||
135 | CONFIG_FLATMEM=y | ||
136 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
137 | # CONFIG_SPARSEMEM_STATIC is not set | ||
138 | CONFIG_SPLIT_PTLOCK_CPUS=4 | ||
139 | CONFIG_PROC_DEVICETREE=y | ||
140 | # CONFIG_CMDLINE_BOOL is not set | ||
141 | # CONFIG_PM is not set | ||
142 | # CONFIG_SOFTWARE_SUSPEND is not set | ||
143 | # CONFIG_SECCOMP is not set | ||
144 | CONFIG_ISA_DMA_API=y | ||
145 | |||
146 | # | ||
147 | # Bus options | ||
148 | # | ||
149 | # CONFIG_PPC_I8259 is not set | ||
150 | CONFIG_PPC_INDIRECT_PCI=y | ||
151 | CONFIG_FSL_SOC=y | ||
152 | # CONFIG_PCI is not set | ||
153 | # CONFIG_PCI_DOMAINS is not set | ||
154 | |||
155 | # | ||
156 | # PCCARD (PCMCIA/CardBus) support | ||
157 | # | ||
158 | # CONFIG_PCCARD is not set | ||
159 | |||
160 | # | ||
161 | # PCI Hotplug Support | ||
162 | # | ||
163 | |||
164 | # | ||
165 | # Advanced setup | ||
166 | # | ||
167 | # CONFIG_ADVANCED_OPTIONS is not set | ||
168 | |||
169 | # | ||
170 | # Default settings for advanced configuration options are used | ||
171 | # | ||
172 | CONFIG_HIGHMEM_START=0xfe000000 | ||
173 | CONFIG_LOWMEM_SIZE=0x30000000 | ||
174 | CONFIG_KERNEL_START=0xc0000000 | ||
175 | CONFIG_TASK_SIZE=0x80000000 | ||
176 | CONFIG_BOOT_LOAD=0x00800000 | ||
177 | |||
178 | # | ||
179 | # Networking | ||
180 | # | ||
181 | CONFIG_NET=y | ||
182 | |||
183 | # | ||
184 | # Networking options | ||
185 | # | ||
186 | # CONFIG_NETDEBUG is not set | ||
187 | CONFIG_PACKET=y | ||
188 | # CONFIG_PACKET_MMAP is not set | ||
189 | CONFIG_UNIX=y | ||
190 | # CONFIG_NET_KEY is not set | ||
191 | CONFIG_INET=y | ||
192 | CONFIG_IP_MULTICAST=y | ||
193 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
194 | CONFIG_IP_FIB_HASH=y | ||
195 | CONFIG_IP_PNP=y | ||
196 | CONFIG_IP_PNP_DHCP=y | ||
197 | CONFIG_IP_PNP_BOOTP=y | ||
198 | # CONFIG_IP_PNP_RARP is not set | ||
199 | # CONFIG_NET_IPIP is not set | ||
200 | # CONFIG_NET_IPGRE is not set | ||
201 | # CONFIG_IP_MROUTE is not set | ||
202 | # CONFIG_ARPD is not set | ||
203 | CONFIG_SYN_COOKIES=y | ||
204 | # CONFIG_INET_AH is not set | ||
205 | # CONFIG_INET_ESP is not set | ||
206 | # CONFIG_INET_IPCOMP is not set | ||
207 | # CONFIG_INET_TUNNEL is not set | ||
208 | CONFIG_INET_DIAG=y | ||
209 | CONFIG_INET_TCP_DIAG=y | ||
210 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
211 | CONFIG_TCP_CONG_BIC=y | ||
212 | # CONFIG_IPV6 is not set | ||
213 | # CONFIG_NETFILTER is not set | ||
214 | |||
215 | # | ||
216 | # DCCP Configuration (EXPERIMENTAL) | ||
217 | # | ||
218 | # CONFIG_IP_DCCP is not set | ||
219 | |||
220 | # | ||
221 | # SCTP Configuration (EXPERIMENTAL) | ||
222 | # | ||
223 | # CONFIG_IP_SCTP is not set | ||
224 | |||
225 | # | ||
226 | # TIPC Configuration (EXPERIMENTAL) | ||
227 | # | ||
228 | # CONFIG_TIPC is not set | ||
229 | # CONFIG_ATM is not set | ||
230 | # CONFIG_BRIDGE is not set | ||
231 | # CONFIG_VLAN_8021Q is not set | ||
232 | # CONFIG_DECNET is not set | ||
233 | # CONFIG_LLC2 is not set | ||
234 | # CONFIG_IPX is not set | ||
235 | # CONFIG_ATALK is not set | ||
236 | # CONFIG_X25 is not set | ||
237 | # CONFIG_LAPB is not set | ||
238 | # CONFIG_NET_DIVERT is not set | ||
239 | # CONFIG_ECONET is not set | ||
240 | # CONFIG_WAN_ROUTER is not set | ||
241 | |||
242 | # | ||
243 | # QoS and/or fair queueing | ||
244 | # | ||
245 | # CONFIG_NET_SCHED is not set | ||
246 | |||
247 | # | ||
248 | # Network testing | ||
249 | # | ||
250 | # CONFIG_NET_PKTGEN is not set | ||
251 | # CONFIG_HAMRADIO is not set | ||
252 | # CONFIG_IRDA is not set | ||
253 | # CONFIG_BT is not set | ||
254 | # CONFIG_IEEE80211 is not set | ||
255 | |||
256 | # | ||
257 | # Device Drivers | ||
258 | # | ||
259 | |||
260 | # | ||
261 | # Generic Driver Options | ||
262 | # | ||
263 | CONFIG_STANDALONE=y | ||
264 | CONFIG_PREVENT_FIRMWARE_BUILD=y | ||
265 | # CONFIG_FW_LOADER is not set | ||
266 | # CONFIG_DEBUG_DRIVER is not set | ||
267 | |||
268 | # | ||
269 | # Connector - unified userspace <-> kernelspace linker | ||
270 | # | ||
271 | # CONFIG_CONNECTOR is not set | ||
272 | |||
273 | # | ||
274 | # Memory Technology Devices (MTD) | ||
275 | # | ||
276 | # CONFIG_MTD is not set | ||
277 | |||
278 | # | ||
279 | # Parallel port support | ||
280 | # | ||
281 | # CONFIG_PARPORT is not set | ||
282 | |||
283 | # | ||
284 | # Plug and Play support | ||
285 | # | ||
286 | |||
287 | # | ||
288 | # Block devices | ||
289 | # | ||
290 | # CONFIG_BLK_DEV_FD is not set | ||
291 | # CONFIG_BLK_DEV_COW_COMMON is not set | ||
292 | CONFIG_BLK_DEV_LOOP=y | ||
293 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set | ||
294 | # CONFIG_BLK_DEV_NBD is not set | ||
295 | CONFIG_BLK_DEV_RAM=y | ||
296 | CONFIG_BLK_DEV_RAM_COUNT=16 | ||
297 | CONFIG_BLK_DEV_RAM_SIZE=32768 | ||
298 | CONFIG_BLK_DEV_INITRD=y | ||
299 | # CONFIG_CDROM_PKTCDVD is not set | ||
300 | # CONFIG_ATA_OVER_ETH is not set | ||
301 | |||
302 | # | ||
303 | # ATA/ATAPI/MFM/RLL support | ||
304 | # | ||
305 | # CONFIG_IDE is not set | ||
306 | |||
307 | # | ||
308 | # SCSI device support | ||
309 | # | ||
310 | # CONFIG_RAID_ATTRS is not set | ||
311 | # CONFIG_SCSI is not set | ||
312 | |||
313 | # | ||
314 | # Multi-device support (RAID and LVM) | ||
315 | # | ||
316 | # CONFIG_MD is not set | ||
317 | |||
318 | # | ||
319 | # Fusion MPT device support | ||
320 | # | ||
321 | # CONFIG_FUSION is not set | ||
322 | |||
323 | # | ||
324 | # IEEE 1394 (FireWire) support | ||
325 | # | ||
326 | |||
327 | # | ||
328 | # I2O device support | ||
329 | # | ||
330 | |||
331 | # | ||
332 | # Macintosh device drivers | ||
333 | # | ||
334 | # CONFIG_WINDFARM is not set | ||
335 | |||
336 | # | ||
337 | # Network device support | ||
338 | # | ||
339 | CONFIG_NETDEVICES=y | ||
340 | # CONFIG_DUMMY is not set | ||
341 | # CONFIG_BONDING is not set | ||
342 | # CONFIG_EQUALIZER is not set | ||
343 | # CONFIG_TUN is not set | ||
344 | |||
345 | # | ||
346 | # PHY device support | ||
347 | # | ||
348 | CONFIG_PHYLIB=y | ||
349 | |||
350 | # | ||
351 | # MII PHY device drivers | ||
352 | # | ||
353 | # CONFIG_MARVELL_PHY is not set | ||
354 | # CONFIG_DAVICOM_PHY is not set | ||
355 | # CONFIG_QSEMI_PHY is not set | ||
356 | # CONFIG_LXT_PHY is not set | ||
357 | # CONFIG_CICADA_PHY is not set | ||
358 | |||
359 | # | ||
360 | # Ethernet (10 or 100Mbit) | ||
361 | # | ||
362 | CONFIG_NET_ETHERNET=y | ||
363 | CONFIG_MII=y | ||
364 | |||
365 | # | ||
366 | # Ethernet (1000 Mbit) | ||
367 | # | ||
368 | CONFIG_GIANFAR=y | ||
369 | CONFIG_GFAR_NAPI=y | ||
370 | |||
371 | # | ||
372 | # Ethernet (10000 Mbit) | ||
373 | # | ||
374 | |||
375 | # | ||
376 | # Token Ring devices | ||
377 | # | ||
378 | |||
379 | # | ||
380 | # Wireless LAN (non-hamradio) | ||
381 | # | ||
382 | # CONFIG_NET_RADIO is not set | ||
383 | |||
384 | # | ||
385 | # Wan interfaces | ||
386 | # | ||
387 | # CONFIG_WAN is not set | ||
388 | # CONFIG_PPP is not set | ||
389 | # CONFIG_SLIP is not set | ||
390 | # CONFIG_SHAPER is not set | ||
391 | # CONFIG_NETCONSOLE is not set | ||
392 | # CONFIG_NETPOLL is not set | ||
393 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
394 | |||
395 | # | ||
396 | # ISDN subsystem | ||
397 | # | ||
398 | # CONFIG_ISDN is not set | ||
399 | |||
400 | # | ||
401 | # Telephony Support | ||
402 | # | ||
403 | # CONFIG_PHONE is not set | ||
404 | |||
405 | # | ||
406 | # Input device support | ||
407 | # | ||
408 | CONFIG_INPUT=y | ||
409 | |||
410 | # | ||
411 | # Userland interfaces | ||
412 | # | ||
413 | # CONFIG_INPUT_MOUSEDEV is not set | ||
414 | # CONFIG_INPUT_JOYDEV is not set | ||
415 | # CONFIG_INPUT_TSDEV is not set | ||
416 | # CONFIG_INPUT_EVDEV is not set | ||
417 | # CONFIG_INPUT_EVBUG is not set | ||
418 | |||
419 | # | ||
420 | # Input Device Drivers | ||
421 | # | ||
422 | # CONFIG_INPUT_KEYBOARD is not set | ||
423 | # CONFIG_INPUT_MOUSE is not set | ||
424 | # CONFIG_INPUT_JOYSTICK is not set | ||
425 | # CONFIG_INPUT_TOUCHSCREEN is not set | ||
426 | # CONFIG_INPUT_MISC is not set | ||
427 | |||
428 | # | ||
429 | # Hardware I/O ports | ||
430 | # | ||
431 | # CONFIG_SERIO is not set | ||
432 | # CONFIG_GAMEPORT is not set | ||
433 | |||
434 | # | ||
435 | # Character devices | ||
436 | # | ||
437 | # CONFIG_VT is not set | ||
438 | # CONFIG_SERIAL_NONSTANDARD is not set | ||
439 | |||
440 | # | ||
441 | # Serial drivers | ||
442 | # | ||
443 | CONFIG_SERIAL_8250=y | ||
444 | CONFIG_SERIAL_8250_CONSOLE=y | ||
445 | CONFIG_SERIAL_8250_NR_UARTS=4 | ||
446 | CONFIG_SERIAL_8250_RUNTIME_UARTS=4 | ||
447 | # CONFIG_SERIAL_8250_EXTENDED is not set | ||
448 | |||
449 | # | ||
450 | # Non-8250 serial port support | ||
451 | # | ||
452 | CONFIG_SERIAL_CORE=y | ||
453 | CONFIG_SERIAL_CORE_CONSOLE=y | ||
454 | CONFIG_UNIX98_PTYS=y | ||
455 | CONFIG_LEGACY_PTYS=y | ||
456 | CONFIG_LEGACY_PTY_COUNT=256 | ||
457 | |||
458 | # | ||
459 | # IPMI | ||
460 | # | ||
461 | # CONFIG_IPMI_HANDLER is not set | ||
462 | |||
463 | # | ||
464 | # Watchdog Cards | ||
465 | # | ||
466 | # CONFIG_WATCHDOG is not set | ||
467 | # CONFIG_NVRAM is not set | ||
468 | CONFIG_GEN_RTC=y | ||
469 | # CONFIG_GEN_RTC_X is not set | ||
470 | # CONFIG_DTLK is not set | ||
471 | # CONFIG_R3964 is not set | ||
472 | |||
473 | # | ||
474 | # Ftape, the floppy tape device driver | ||
475 | # | ||
476 | # CONFIG_AGP is not set | ||
477 | # CONFIG_RAW_DRIVER is not set | ||
478 | |||
479 | # | ||
480 | # TPM devices | ||
481 | # | ||
482 | # CONFIG_TCG_TPM is not set | ||
483 | # CONFIG_TELCLOCK is not set | ||
484 | |||
485 | # | ||
486 | # I2C support | ||
487 | # | ||
488 | # CONFIG_I2C is not set | ||
489 | |||
490 | # | ||
491 | # SPI support | ||
492 | # | ||
493 | # CONFIG_SPI is not set | ||
494 | # CONFIG_SPI_MASTER is not set | ||
495 | |||
496 | # | ||
497 | # Dallas's 1-wire bus | ||
498 | # | ||
499 | # CONFIG_W1 is not set | ||
500 | |||
501 | # | ||
502 | # Hardware Monitoring support | ||
503 | # | ||
504 | CONFIG_HWMON=y | ||
505 | # CONFIG_HWMON_VID is not set | ||
506 | # CONFIG_SENSORS_F71805F is not set | ||
507 | # CONFIG_HWMON_DEBUG_CHIP is not set | ||
508 | |||
509 | # | ||
510 | # Misc devices | ||
511 | # | ||
512 | |||
513 | # | ||
514 | # Multimedia devices | ||
515 | # | ||
516 | # CONFIG_VIDEO_DEV is not set | ||
517 | |||
518 | # | ||
519 | # Digital Video Broadcasting Devices | ||
520 | # | ||
521 | # CONFIG_DVB is not set | ||
522 | |||
523 | # | ||
524 | # Graphics support | ||
525 | # | ||
526 | # CONFIG_FB is not set | ||
527 | |||
528 | # | ||
529 | # Sound | ||
530 | # | ||
531 | # CONFIG_SOUND is not set | ||
532 | |||
533 | # | ||
534 | # USB support | ||
535 | # | ||
536 | # CONFIG_USB_ARCH_HAS_HCD is not set | ||
537 | # CONFIG_USB_ARCH_HAS_OHCI is not set | ||
538 | # CONFIG_USB_ARCH_HAS_EHCI is not set | ||
539 | |||
540 | # | ||
541 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' | ||
542 | # | ||
543 | |||
544 | # | ||
545 | # USB Gadget Support | ||
546 | # | ||
547 | # CONFIG_USB_GADGET is not set | ||
548 | |||
549 | # | ||
550 | # MMC/SD Card support | ||
551 | # | ||
552 | # CONFIG_MMC is not set | ||
553 | |||
554 | # | ||
555 | # InfiniBand support | ||
556 | # | ||
557 | |||
558 | # | ||
559 | # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) | ||
560 | # | ||
561 | |||
562 | # | ||
563 | # File systems | ||
564 | # | ||
565 | CONFIG_EXT2_FS=y | ||
566 | # CONFIG_EXT2_FS_XATTR is not set | ||
567 | # CONFIG_EXT2_FS_XIP is not set | ||
568 | CONFIG_EXT3_FS=y | ||
569 | CONFIG_EXT3_FS_XATTR=y | ||
570 | # CONFIG_EXT3_FS_POSIX_ACL is not set | ||
571 | # CONFIG_EXT3_FS_SECURITY is not set | ||
572 | CONFIG_JBD=y | ||
573 | # CONFIG_JBD_DEBUG is not set | ||
574 | CONFIG_FS_MBCACHE=y | ||
575 | # CONFIG_REISERFS_FS is not set | ||
576 | # CONFIG_JFS_FS is not set | ||
577 | # CONFIG_FS_POSIX_ACL is not set | ||
578 | # CONFIG_XFS_FS is not set | ||
579 | # CONFIG_OCFS2_FS is not set | ||
580 | # CONFIG_MINIX_FS is not set | ||
581 | # CONFIG_ROMFS_FS is not set | ||
582 | CONFIG_INOTIFY=y | ||
583 | # CONFIG_QUOTA is not set | ||
584 | CONFIG_DNOTIFY=y | ||
585 | # CONFIG_AUTOFS_FS is not set | ||
586 | # CONFIG_AUTOFS4_FS is not set | ||
587 | # CONFIG_FUSE_FS is not set | ||
588 | |||
589 | # | ||
590 | # CD-ROM/DVD Filesystems | ||
591 | # | ||
592 | # CONFIG_ISO9660_FS is not set | ||
593 | # CONFIG_UDF_FS is not set | ||
594 | |||
595 | # | ||
596 | # DOS/FAT/NT Filesystems | ||
597 | # | ||
598 | # CONFIG_MSDOS_FS is not set | ||
599 | # CONFIG_VFAT_FS is not set | ||
600 | # CONFIG_NTFS_FS is not set | ||
601 | |||
602 | # | ||
603 | # Pseudo filesystems | ||
604 | # | ||
605 | CONFIG_PROC_FS=y | ||
606 | CONFIG_PROC_KCORE=y | ||
607 | CONFIG_SYSFS=y | ||
608 | CONFIG_TMPFS=y | ||
609 | # CONFIG_HUGETLB_PAGE is not set | ||
610 | CONFIG_RAMFS=y | ||
611 | # CONFIG_CONFIGFS_FS is not set | ||
612 | |||
613 | # | ||
614 | # Miscellaneous filesystems | ||
615 | # | ||
616 | # CONFIG_ADFS_FS is not set | ||
617 | # CONFIG_AFFS_FS is not set | ||
618 | # CONFIG_HFS_FS is not set | ||
619 | # CONFIG_HFSPLUS_FS is not set | ||
620 | # CONFIG_BEFS_FS is not set | ||
621 | # CONFIG_BFS_FS is not set | ||
622 | # CONFIG_EFS_FS is not set | ||
623 | # CONFIG_CRAMFS is not set | ||
624 | # CONFIG_VXFS_FS is not set | ||
625 | # CONFIG_HPFS_FS is not set | ||
626 | # CONFIG_QNX4FS_FS is not set | ||
627 | # CONFIG_SYSV_FS is not set | ||
628 | # CONFIG_UFS_FS is not set | ||
629 | |||
630 | # | ||
631 | # Network File Systems | ||
632 | # | ||
633 | CONFIG_NFS_FS=y | ||
634 | # CONFIG_NFS_V3 is not set | ||
635 | # CONFIG_NFS_V4 is not set | ||
636 | # CONFIG_NFS_DIRECTIO is not set | ||
637 | # CONFIG_NFSD is not set | ||
638 | CONFIG_ROOT_NFS=y | ||
639 | CONFIG_LOCKD=y | ||
640 | CONFIG_NFS_COMMON=y | ||
641 | CONFIG_SUNRPC=y | ||
642 | # CONFIG_RPCSEC_GSS_KRB5 is not set | ||
643 | # CONFIG_RPCSEC_GSS_SPKM3 is not set | ||
644 | # CONFIG_SMB_FS is not set | ||
645 | # CONFIG_CIFS is not set | ||
646 | # CONFIG_NCP_FS is not set | ||
647 | # CONFIG_CODA_FS is not set | ||
648 | # CONFIG_AFS_FS is not set | ||
649 | # CONFIG_9P_FS is not set | ||
650 | |||
651 | # | ||
652 | # Partition Types | ||
653 | # | ||
654 | CONFIG_PARTITION_ADVANCED=y | ||
655 | # CONFIG_ACORN_PARTITION is not set | ||
656 | # CONFIG_OSF_PARTITION is not set | ||
657 | # CONFIG_AMIGA_PARTITION is not set | ||
658 | # CONFIG_ATARI_PARTITION is not set | ||
659 | # CONFIG_MAC_PARTITION is not set | ||
660 | # CONFIG_MSDOS_PARTITION is not set | ||
661 | # CONFIG_LDM_PARTITION is not set | ||
662 | # CONFIG_SGI_PARTITION is not set | ||
663 | # CONFIG_ULTRIX_PARTITION is not set | ||
664 | # CONFIG_SUN_PARTITION is not set | ||
665 | # CONFIG_KARMA_PARTITION is not set | ||
666 | # CONFIG_EFI_PARTITION is not set | ||
667 | |||
668 | # | ||
669 | # Native Language Support | ||
670 | # | ||
671 | # CONFIG_NLS is not set | ||
672 | |||
673 | # | ||
674 | # Library routines | ||
675 | # | ||
676 | # CONFIG_CRC_CCITT is not set | ||
677 | # CONFIG_CRC16 is not set | ||
678 | CONFIG_CRC32=y | ||
679 | # CONFIG_LIBCRC32C is not set | ||
680 | |||
681 | # | ||
682 | # Instrumentation Support | ||
683 | # | ||
684 | # CONFIG_PROFILING is not set | ||
685 | |||
686 | # | ||
687 | # Kernel hacking | ||
688 | # | ||
689 | # CONFIG_PRINTK_TIME is not set | ||
690 | # CONFIG_MAGIC_SYSRQ is not set | ||
691 | CONFIG_DEBUG_KERNEL=y | ||
692 | CONFIG_LOG_BUF_SHIFT=14 | ||
693 | CONFIG_DETECT_SOFTLOCKUP=y | ||
694 | # CONFIG_SCHEDSTATS is not set | ||
695 | # CONFIG_DEBUG_SLAB is not set | ||
696 | CONFIG_DEBUG_MUTEXES=y | ||
697 | # CONFIG_DEBUG_SPINLOCK is not set | ||
698 | # CONFIG_DEBUG_SPINLOCK_SLEEP is not set | ||
699 | # CONFIG_DEBUG_KOBJECT is not set | ||
700 | # CONFIG_DEBUG_INFO is not set | ||
701 | # CONFIG_DEBUG_FS is not set | ||
702 | # CONFIG_DEBUG_VM is not set | ||
703 | # CONFIG_UNWIND_INFO is not set | ||
704 | CONFIG_FORCED_INLINING=y | ||
705 | # CONFIG_RCU_TORTURE_TEST is not set | ||
706 | # CONFIG_DEBUGGER is not set | ||
707 | # CONFIG_BDI_SWITCH is not set | ||
708 | # CONFIG_BOOTX_TEXT is not set | ||
709 | # CONFIG_PPC_EARLY_DEBUG_LPAR is not set | ||
710 | # CONFIG_PPC_EARLY_DEBUG_G5 is not set | ||
711 | # CONFIG_PPC_EARLY_DEBUG_RTAS is not set | ||
712 | # CONFIG_PPC_EARLY_DEBUG_MAPLE is not set | ||
713 | # CONFIG_PPC_EARLY_DEBUG_ISERIES is not set | ||
714 | |||
715 | # | ||
716 | # Security options | ||
717 | # | ||
718 | # CONFIG_KEYS is not set | ||
719 | # CONFIG_SECURITY is not set | ||
720 | |||
721 | # | ||
722 | # Cryptographic options | ||
723 | # | ||
724 | # CONFIG_CRYPTO is not set | ||
725 | |||
726 | # | ||
727 | # Hardware crypto devices | ||
728 | # | ||
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig index 2ace57d1e333..57a027971d67 100644 --- a/arch/powerpc/configs/pmac32_defconfig +++ b/arch/powerpc/configs/pmac32_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.15 | 3 | # Linux kernel version: 2.6.16-rc6 |
4 | # Sat Jan 14 16:26:08 2006 | 4 | # Wed Mar 15 16:21:32 2006 |
5 | # | 5 | # |
6 | # CONFIG_PPC64 is not set | 6 | # CONFIG_PPC64 is not set |
7 | CONFIG_PPC32=y | 7 | CONFIG_PPC32=y |
@@ -17,8 +17,8 @@ CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y | |||
17 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y | 17 | CONFIG_ARCH_MAY_HAVE_PC_FDC=y |
18 | CONFIG_PPC_OF=y | 18 | CONFIG_PPC_OF=y |
19 | # CONFIG_PPC_UDBG_16550 is not set | 19 | # CONFIG_PPC_UDBG_16550 is not set |
20 | # CONFIG_CRASH_DUMP is not set | ||
21 | # CONFIG_GENERIC_TBSYNC is not set | 20 | # CONFIG_GENERIC_TBSYNC is not set |
21 | # CONFIG_DEFAULT_UIMAGE is not set | ||
22 | 22 | ||
23 | # | 23 | # |
24 | # Processor support | 24 | # Processor support |
@@ -43,7 +43,6 @@ CONFIG_PPC_STD_MMU_32=y | |||
43 | # Code maturity level options | 43 | # Code maturity level options |
44 | # | 44 | # |
45 | CONFIG_EXPERIMENTAL=y | 45 | CONFIG_EXPERIMENTAL=y |
46 | CONFIG_CLEAN_COMPILE=y | ||
47 | CONFIG_BROKEN_ON_SMP=y | 46 | CONFIG_BROKEN_ON_SMP=y |
48 | CONFIG_INIT_ENV_ARG_LIMIT=32 | 47 | CONFIG_INIT_ENV_ARG_LIMIT=32 |
49 | 48 | ||
@@ -236,6 +235,7 @@ CONFIG_NET=y | |||
236 | # | 235 | # |
237 | # Networking options | 236 | # Networking options |
238 | # | 237 | # |
238 | # CONFIG_NETDEBUG is not set | ||
239 | CONFIG_PACKET=y | 239 | CONFIG_PACKET=y |
240 | # CONFIG_PACKET_MMAP is not set | 240 | # CONFIG_PACKET_MMAP is not set |
241 | CONFIG_UNIX=y | 241 | CONFIG_UNIX=y |
@@ -271,6 +271,25 @@ CONFIG_NETFILTER=y | |||
271 | # Core Netfilter Configuration | 271 | # Core Netfilter Configuration |
272 | # | 272 | # |
273 | # CONFIG_NETFILTER_NETLINK is not set | 273 | # CONFIG_NETFILTER_NETLINK is not set |
274 | CONFIG_NETFILTER_XTABLES=m | ||
275 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | ||
276 | CONFIG_NETFILTER_XT_TARGET_MARK=m | ||
277 | CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m | ||
278 | CONFIG_NETFILTER_XT_TARGET_NOTRACK=m | ||
279 | CONFIG_NETFILTER_XT_MATCH_COMMENT=m | ||
280 | CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m | ||
281 | # CONFIG_NETFILTER_XT_MATCH_DCCP is not set | ||
282 | CONFIG_NETFILTER_XT_MATCH_HELPER=m | ||
283 | CONFIG_NETFILTER_XT_MATCH_LENGTH=m | ||
284 | CONFIG_NETFILTER_XT_MATCH_LIMIT=m | ||
285 | CONFIG_NETFILTER_XT_MATCH_MAC=m | ||
286 | CONFIG_NETFILTER_XT_MATCH_MARK=m | ||
287 | CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m | ||
288 | CONFIG_NETFILTER_XT_MATCH_REALM=m | ||
289 | CONFIG_NETFILTER_XT_MATCH_SCTP=m | ||
290 | CONFIG_NETFILTER_XT_MATCH_STATE=m | ||
291 | CONFIG_NETFILTER_XT_MATCH_STRING=m | ||
292 | CONFIG_NETFILTER_XT_MATCH_TCPMSS=m | ||
274 | 293 | ||
275 | # | 294 | # |
276 | # IP: Netfilter Configuration | 295 | # IP: Netfilter Configuration |
@@ -288,37 +307,22 @@ CONFIG_IP_NF_AMANDA=m | |||
288 | CONFIG_IP_NF_PPTP=m | 307 | CONFIG_IP_NF_PPTP=m |
289 | # CONFIG_IP_NF_QUEUE is not set | 308 | # CONFIG_IP_NF_QUEUE is not set |
290 | CONFIG_IP_NF_IPTABLES=m | 309 | CONFIG_IP_NF_IPTABLES=m |
291 | CONFIG_IP_NF_MATCH_LIMIT=m | ||
292 | CONFIG_IP_NF_MATCH_IPRANGE=m | 310 | CONFIG_IP_NF_MATCH_IPRANGE=m |
293 | CONFIG_IP_NF_MATCH_MAC=m | ||
294 | CONFIG_IP_NF_MATCH_PKTTYPE=m | ||
295 | CONFIG_IP_NF_MATCH_MARK=m | ||
296 | CONFIG_IP_NF_MATCH_MULTIPORT=m | 311 | CONFIG_IP_NF_MATCH_MULTIPORT=m |
297 | CONFIG_IP_NF_MATCH_TOS=m | 312 | CONFIG_IP_NF_MATCH_TOS=m |
298 | CONFIG_IP_NF_MATCH_RECENT=m | 313 | CONFIG_IP_NF_MATCH_RECENT=m |
299 | CONFIG_IP_NF_MATCH_ECN=m | 314 | CONFIG_IP_NF_MATCH_ECN=m |
300 | CONFIG_IP_NF_MATCH_DSCP=m | 315 | CONFIG_IP_NF_MATCH_DSCP=m |
301 | CONFIG_IP_NF_MATCH_AH_ESP=m | 316 | CONFIG_IP_NF_MATCH_AH_ESP=m |
302 | CONFIG_IP_NF_MATCH_LENGTH=m | ||
303 | CONFIG_IP_NF_MATCH_TTL=m | 317 | CONFIG_IP_NF_MATCH_TTL=m |
304 | CONFIG_IP_NF_MATCH_TCPMSS=m | ||
305 | CONFIG_IP_NF_MATCH_HELPER=m | ||
306 | CONFIG_IP_NF_MATCH_STATE=m | ||
307 | CONFIG_IP_NF_MATCH_CONNTRACK=m | ||
308 | CONFIG_IP_NF_MATCH_OWNER=m | 318 | CONFIG_IP_NF_MATCH_OWNER=m |
309 | # CONFIG_IP_NF_MATCH_ADDRTYPE is not set | 319 | CONFIG_IP_NF_MATCH_ADDRTYPE=m |
310 | # CONFIG_IP_NF_MATCH_REALM is not set | 320 | CONFIG_IP_NF_MATCH_HASHLIMIT=m |
311 | # CONFIG_IP_NF_MATCH_SCTP is not set | ||
312 | CONFIG_IP_NF_MATCH_DCCP=m | ||
313 | # CONFIG_IP_NF_MATCH_COMMENT is not set | ||
314 | # CONFIG_IP_NF_MATCH_HASHLIMIT is not set | ||
315 | CONFIG_IP_NF_MATCH_STRING=m | ||
316 | CONFIG_IP_NF_FILTER=m | 321 | CONFIG_IP_NF_FILTER=m |
317 | CONFIG_IP_NF_TARGET_REJECT=m | 322 | CONFIG_IP_NF_TARGET_REJECT=m |
318 | # CONFIG_IP_NF_TARGET_LOG is not set | 323 | CONFIG_IP_NF_TARGET_LOG=m |
319 | CONFIG_IP_NF_TARGET_ULOG=m | 324 | CONFIG_IP_NF_TARGET_ULOG=m |
320 | CONFIG_IP_NF_TARGET_TCPMSS=m | 325 | CONFIG_IP_NF_TARGET_TCPMSS=m |
321 | # CONFIG_IP_NF_TARGET_NFQUEUE is not set | ||
322 | CONFIG_IP_NF_NAT=m | 326 | CONFIG_IP_NF_NAT=m |
323 | CONFIG_IP_NF_NAT_NEEDED=y | 327 | CONFIG_IP_NF_NAT_NEEDED=y |
324 | CONFIG_IP_NF_TARGET_MASQUERADE=m | 328 | CONFIG_IP_NF_TARGET_MASQUERADE=m |
@@ -331,9 +335,12 @@ CONFIG_IP_NF_NAT_FTP=m | |||
331 | CONFIG_IP_NF_NAT_TFTP=m | 335 | CONFIG_IP_NF_NAT_TFTP=m |
332 | CONFIG_IP_NF_NAT_AMANDA=m | 336 | CONFIG_IP_NF_NAT_AMANDA=m |
333 | CONFIG_IP_NF_NAT_PPTP=m | 337 | CONFIG_IP_NF_NAT_PPTP=m |
334 | # CONFIG_IP_NF_MANGLE is not set | 338 | CONFIG_IP_NF_MANGLE=m |
339 | CONFIG_IP_NF_TARGET_TOS=m | ||
340 | CONFIG_IP_NF_TARGET_ECN=m | ||
341 | CONFIG_IP_NF_TARGET_DSCP=m | ||
342 | CONFIG_IP_NF_TARGET_TTL=m | ||
335 | CONFIG_IP_NF_RAW=m | 343 | CONFIG_IP_NF_RAW=m |
336 | CONFIG_IP_NF_TARGET_NOTRACK=m | ||
337 | CONFIG_IP_NF_ARPTABLES=m | 344 | CONFIG_IP_NF_ARPTABLES=m |
338 | CONFIG_IP_NF_ARPFILTER=m | 345 | CONFIG_IP_NF_ARPFILTER=m |
339 | CONFIG_IP_NF_ARP_MANGLE=m | 346 | CONFIG_IP_NF_ARP_MANGLE=m |
@@ -360,6 +367,11 @@ CONFIG_IP_DCCP_TFRC_LIB=m | |||
360 | # SCTP Configuration (EXPERIMENTAL) | 367 | # SCTP Configuration (EXPERIMENTAL) |
361 | # | 368 | # |
362 | # CONFIG_IP_SCTP is not set | 369 | # CONFIG_IP_SCTP is not set |
370 | |||
371 | # | ||
372 | # TIPC Configuration (EXPERIMENTAL) | ||
373 | # | ||
374 | # CONFIG_TIPC is not set | ||
363 | # CONFIG_ATM is not set | 375 | # CONFIG_ATM is not set |
364 | # CONFIG_BRIDGE is not set | 376 | # CONFIG_BRIDGE is not set |
365 | # CONFIG_VLAN_8021Q is not set | 377 | # CONFIG_VLAN_8021Q is not set |
@@ -377,6 +389,7 @@ CONFIG_IP_DCCP_TFRC_LIB=m | |||
377 | # QoS and/or fair queueing | 389 | # QoS and/or fair queueing |
378 | # | 390 | # |
379 | # CONFIG_NET_SCHED is not set | 391 | # CONFIG_NET_SCHED is not set |
392 | CONFIG_NET_CLS_ROUTE=y | ||
380 | 393 | ||
381 | # | 394 | # |
382 | # Network testing | 395 | # Network testing |
@@ -568,7 +581,6 @@ CONFIG_IDEDMA_PCI_AUTO=y | |||
568 | # CONFIG_BLK_DEV_NS87415 is not set | 581 | # CONFIG_BLK_DEV_NS87415 is not set |
569 | # CONFIG_BLK_DEV_PDC202XX_OLD is not set | 582 | # CONFIG_BLK_DEV_PDC202XX_OLD is not set |
570 | CONFIG_BLK_DEV_PDC202XX_NEW=y | 583 | CONFIG_BLK_DEV_PDC202XX_NEW=y |
571 | # CONFIG_PDC202XX_FORCE is not set | ||
572 | # CONFIG_BLK_DEV_SVWKS is not set | 584 | # CONFIG_BLK_DEV_SVWKS is not set |
573 | # CONFIG_BLK_DEV_SIIMAGE is not set | 585 | # CONFIG_BLK_DEV_SIIMAGE is not set |
574 | # CONFIG_BLK_DEV_SLC90E66 is not set | 586 | # CONFIG_BLK_DEV_SLC90E66 is not set |
@@ -654,8 +666,7 @@ CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 | |||
654 | # CONFIG_SCSI_IPR is not set | 666 | # CONFIG_SCSI_IPR is not set |
655 | # CONFIG_SCSI_QLOGIC_FC is not set | 667 | # CONFIG_SCSI_QLOGIC_FC is not set |
656 | # CONFIG_SCSI_QLOGIC_1280 is not set | 668 | # CONFIG_SCSI_QLOGIC_1280 is not set |
657 | CONFIG_SCSI_QLA2XXX=y | 669 | # CONFIG_SCSI_QLA_FC is not set |
658 | # CONFIG_SCSI_QLA2XXX_EMBEDDED_FIRMWARE is not set | ||
659 | # CONFIG_SCSI_LPFC is not set | 670 | # CONFIG_SCSI_LPFC is not set |
660 | # CONFIG_SCSI_DC395x is not set | 671 | # CONFIG_SCSI_DC395x is not set |
661 | # CONFIG_SCSI_DC390T is not set | 672 | # CONFIG_SCSI_DC390T is not set |
@@ -991,6 +1002,7 @@ CONFIG_SERIAL_8250_RUNTIME_UARTS=4 | |||
991 | # | 1002 | # |
992 | CONFIG_SERIAL_CORE=m | 1003 | CONFIG_SERIAL_CORE=m |
993 | CONFIG_SERIAL_PMACZILOG=m | 1004 | CONFIG_SERIAL_PMACZILOG=m |
1005 | # CONFIG_SERIAL_JSM is not set | ||
994 | CONFIG_UNIX98_PTYS=y | 1006 | CONFIG_UNIX98_PTYS=y |
995 | CONFIG_LEGACY_PTYS=y | 1007 | CONFIG_LEGACY_PTYS=y |
996 | CONFIG_LEGACY_PTY_COUNT=256 | 1008 | CONFIG_LEGACY_PTY_COUNT=256 |
@@ -1098,6 +1110,12 @@ CONFIG_I2C_POWERMAC=y | |||
1098 | # CONFIG_I2C_DEBUG_CHIP is not set | 1110 | # CONFIG_I2C_DEBUG_CHIP is not set |
1099 | 1111 | ||
1100 | # | 1112 | # |
1113 | # SPI support | ||
1114 | # | ||
1115 | # CONFIG_SPI is not set | ||
1116 | # CONFIG_SPI_MASTER is not set | ||
1117 | |||
1118 | # | ||
1101 | # Dallas's 1-wire bus | 1119 | # Dallas's 1-wire bus |
1102 | # | 1120 | # |
1103 | # CONFIG_W1 is not set | 1121 | # CONFIG_W1 is not set |
@@ -1348,6 +1366,7 @@ CONFIG_USB_PRINTER=m | |||
1348 | # | 1366 | # |
1349 | CONFIG_USB_HID=y | 1367 | CONFIG_USB_HID=y |
1350 | CONFIG_USB_HIDINPUT=y | 1368 | CONFIG_USB_HIDINPUT=y |
1369 | CONFIG_USB_HIDINPUT_POWERBOOK=y | ||
1351 | # CONFIG_HID_FF is not set | 1370 | # CONFIG_HID_FF is not set |
1352 | # CONFIG_USB_HIDDEV is not set | 1371 | # CONFIG_USB_HIDDEV is not set |
1353 | # CONFIG_USB_AIPTEK is not set | 1372 | # CONFIG_USB_AIPTEK is not set |
@@ -1488,7 +1507,7 @@ CONFIG_USB_EZUSB=y | |||
1488 | # CONFIG_INFINIBAND is not set | 1507 | # CONFIG_INFINIBAND is not set |
1489 | 1508 | ||
1490 | # | 1509 | # |
1491 | # SN Devices | 1510 | # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) |
1492 | # | 1511 | # |
1493 | 1512 | ||
1494 | # | 1513 | # |
@@ -1609,6 +1628,7 @@ CONFIG_MSDOS_PARTITION=y | |||
1609 | # CONFIG_SGI_PARTITION is not set | 1628 | # CONFIG_SGI_PARTITION is not set |
1610 | # CONFIG_ULTRIX_PARTITION is not set | 1629 | # CONFIG_ULTRIX_PARTITION is not set |
1611 | # CONFIG_SUN_PARTITION is not set | 1630 | # CONFIG_SUN_PARTITION is not set |
1631 | # CONFIG_KARMA_PARTITION is not set | ||
1612 | # CONFIG_EFI_PARTITION is not set | 1632 | # CONFIG_EFI_PARTITION is not set |
1613 | 1633 | ||
1614 | # | 1634 | # |
@@ -1692,6 +1712,7 @@ CONFIG_DETECT_SOFTLOCKUP=y | |||
1692 | # CONFIG_DEBUG_INFO is not set | 1712 | # CONFIG_DEBUG_INFO is not set |
1693 | # CONFIG_DEBUG_FS is not set | 1713 | # CONFIG_DEBUG_FS is not set |
1694 | # CONFIG_DEBUG_VM is not set | 1714 | # CONFIG_DEBUG_VM is not set |
1715 | # CONFIG_FORCED_INLINING is not set | ||
1695 | # CONFIG_RCU_TORTURE_TEST is not set | 1716 | # CONFIG_RCU_TORTURE_TEST is not set |
1696 | CONFIG_DEBUGGER=y | 1717 | CONFIG_DEBUGGER=y |
1697 | CONFIG_XMON=y | 1718 | CONFIG_XMON=y |
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 0362a70aa97c..395e49847788 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig | |||
@@ -407,7 +407,7 @@ CONFIG_IDEPCI_SHARE_IRQ=y | |||
407 | # CONFIG_BLK_DEV_OFFBOARD is not set | 407 | # CONFIG_BLK_DEV_OFFBOARD is not set |
408 | CONFIG_BLK_DEV_GENERIC=y | 408 | CONFIG_BLK_DEV_GENERIC=y |
409 | # CONFIG_BLK_DEV_OPTI621 is not set | 409 | # CONFIG_BLK_DEV_OPTI621 is not set |
410 | # CONFIG_BLK_DEV_SL82C105 is not set | 410 | CONFIG_BLK_DEV_SL82C105=y |
411 | CONFIG_BLK_DEV_IDEDMA_PCI=y | 411 | CONFIG_BLK_DEV_IDEDMA_PCI=y |
412 | # CONFIG_BLK_DEV_IDEDMA_FORCED is not set | 412 | # CONFIG_BLK_DEV_IDEDMA_FORCED is not set |
413 | CONFIG_IDEDMA_PCI_AUTO=y | 413 | CONFIG_IDEDMA_PCI_AUTO=y |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 80e9fe2632b8..0cc0995b81b0 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -12,12 +12,12 @@ endif | |||
12 | 12 | ||
13 | obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ | 13 | obj-y := semaphore.o cputable.o ptrace.o syscalls.o \ |
14 | irq.o align.o signal_32.o pmc.o vdso.o \ | 14 | irq.o align.o signal_32.o pmc.o vdso.o \ |
15 | init_task.o process.o systbl.o | 15 | init_task.o process.o systbl.o idle.o |
16 | obj-y += vdso32/ | 16 | obj-y += vdso32/ |
17 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ | 17 | obj-$(CONFIG_PPC64) += setup_64.o binfmt_elf32.o sys_ppc32.o \ |
18 | signal_64.o ptrace32.o \ | 18 | signal_64.o ptrace32.o \ |
19 | paca.o cpu_setup_power4.o \ | 19 | paca.o cpu_setup_power4.o \ |
20 | firmware.o sysfs.o idle_64.o | 20 | firmware.o sysfs.o |
21 | obj-$(CONFIG_PPC64) += vdso64/ | 21 | obj-$(CONFIG_PPC64) += vdso64/ |
22 | obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o | 22 | obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o |
23 | obj-$(CONFIG_POWER4) += idle_power4.o | 23 | obj-$(CONFIG_POWER4) += idle_power4.o |
@@ -34,6 +34,11 @@ obj-$(CONFIG_IBMEBUS) += ibmebus.o | |||
34 | obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o | 34 | obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o |
35 | obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o | 35 | obj64-$(CONFIG_PPC_MULTIPLATFORM) += nvram_64.o |
36 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 36 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
37 | obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o | ||
38 | obj-$(CONFIG_TAU) += tau_6xx.o | ||
39 | obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o | ||
40 | obj32-$(CONFIG_MODULES) += module_32.o | ||
41 | obj-$(CONFIG_E500) += perfmon_fsl_booke.o | ||
37 | 42 | ||
38 | ifeq ($(CONFIG_PPC_MERGE),y) | 43 | ifeq ($(CONFIG_PPC_MERGE),y) |
39 | 44 | ||
@@ -51,7 +56,6 @@ obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o | |||
51 | obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o | 56 | obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o |
52 | obj-$(CONFIG_MODULES) += ppc_ksyms.o | 57 | obj-$(CONFIG_MODULES) += ppc_ksyms.o |
53 | obj-$(CONFIG_BOOTX_TEXT) += btext.o | 58 | obj-$(CONFIG_BOOTX_TEXT) += btext.o |
54 | obj-$(CONFIG_6xx) += idle_6xx.o | ||
55 | obj-$(CONFIG_SMP) += smp.o | 59 | obj-$(CONFIG_SMP) += smp.o |
56 | obj-$(CONFIG_KPROBES) += kprobes.o | 60 | obj-$(CONFIG_KPROBES) += kprobes.o |
57 | obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o | 61 | obj-$(CONFIG_PPC_UDBG_16550) += legacy_serial.o udbg_16550.o |
@@ -77,6 +81,7 @@ smpobj-$(CONFIG_SMP) += smp.o | |||
77 | 81 | ||
78 | endif | 82 | endif |
79 | 83 | ||
84 | obj-$(CONFIG_PPC32) += $(obj32-y) | ||
80 | obj-$(CONFIG_PPC64) += $(obj64-y) | 85 | obj-$(CONFIG_PPC64) += $(obj64-y) |
81 | 86 | ||
82 | extra-$(CONFIG_PPC_FPU) += fpu.o | 87 | extra-$(CONFIG_PPC_FPU) += fpu.o |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index c9a660e4c2db..54b48f330051 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -105,8 +105,6 @@ int main(void) | |||
105 | DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); | 105 | DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); |
106 | DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); | 106 | DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); |
107 | DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); | 107 | DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); |
108 | DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); | ||
109 | |||
110 | /* paca */ | 108 | /* paca */ |
111 | DEFINE(PACA_SIZE, sizeof(struct paca_struct)); | 109 | DEFINE(PACA_SIZE, sizeof(struct paca_struct)); |
112 | DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index)); | 110 | DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index)); |
@@ -136,6 +134,9 @@ int main(void) | |||
136 | DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); | 134 | DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); |
137 | DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr)); | 135 | DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr)); |
138 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); | 136 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); |
137 | DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr)); | ||
138 | DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time)); | ||
139 | DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); | ||
139 | 140 | ||
140 | DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); | 141 | DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); |
141 | DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1)); | 142 | DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1)); |
diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S new file mode 100644 index 000000000000..55ed7716636f --- /dev/null +++ b/arch/powerpc/kernel/cpu_setup_6xx.S | |||
@@ -0,0 +1,474 @@ | |||
1 | /* | ||
2 | * This file contains low level CPU setup functions. | ||
3 | * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org) | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version | ||
8 | * 2 of the License, or (at your option) any later version. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <asm/processor.h> | ||
14 | #include <asm/page.h> | ||
15 | #include <asm/cputable.h> | ||
16 | #include <asm/ppc_asm.h> | ||
17 | #include <asm/asm-offsets.h> | ||
18 | #include <asm/cache.h> | ||
19 | |||
20 | _GLOBAL(__setup_cpu_603) | ||
21 | b setup_common_caches | ||
22 | _GLOBAL(__setup_cpu_604) | ||
23 | mflr r4 | ||
24 | bl setup_common_caches | ||
25 | bl setup_604_hid0 | ||
26 | mtlr r4 | ||
27 | blr | ||
28 | _GLOBAL(__setup_cpu_750) | ||
29 | mflr r4 | ||
30 | bl __init_fpu_registers | ||
31 | bl setup_common_caches | ||
32 | bl setup_750_7400_hid0 | ||
33 | mtlr r4 | ||
34 | blr | ||
35 | _GLOBAL(__setup_cpu_750cx) | ||
36 | mflr r4 | ||
37 | bl __init_fpu_registers | ||
38 | bl setup_common_caches | ||
39 | bl setup_750_7400_hid0 | ||
40 | bl setup_750cx | ||
41 | mtlr r4 | ||
42 | blr | ||
43 | _GLOBAL(__setup_cpu_750fx) | ||
44 | mflr r4 | ||
45 | bl __init_fpu_registers | ||
46 | bl setup_common_caches | ||
47 | bl setup_750_7400_hid0 | ||
48 | bl setup_750fx | ||
49 | mtlr r4 | ||
50 | blr | ||
51 | _GLOBAL(__setup_cpu_7400) | ||
52 | mflr r4 | ||
53 | bl __init_fpu_registers | ||
54 | bl setup_7400_workarounds | ||
55 | bl setup_common_caches | ||
56 | bl setup_750_7400_hid0 | ||
57 | mtlr r4 | ||
58 | blr | ||
59 | _GLOBAL(__setup_cpu_7410) | ||
60 | mflr r4 | ||
61 | bl __init_fpu_registers | ||
62 | bl setup_7410_workarounds | ||
63 | bl setup_common_caches | ||
64 | bl setup_750_7400_hid0 | ||
65 | li r3,0 | ||
66 | mtspr SPRN_L2CR2,r3 | ||
67 | mtlr r4 | ||
68 | blr | ||
69 | _GLOBAL(__setup_cpu_745x) | ||
70 | mflr r4 | ||
71 | bl setup_common_caches | ||
72 | bl setup_745x_specifics | ||
73 | mtlr r4 | ||
74 | blr | ||
75 | |||
76 | /* Enable caches for 603's, 604, 750 & 7400 */ | ||
77 | setup_common_caches: | ||
78 | mfspr r11,SPRN_HID0 | ||
79 | andi. r0,r11,HID0_DCE | ||
80 | ori r11,r11,HID0_ICE|HID0_DCE | ||
81 | ori r8,r11,HID0_ICFI | ||
82 | bne 1f /* don't invalidate the D-cache */ | ||
83 | ori r8,r8,HID0_DCI /* unless it wasn't enabled */ | ||
84 | 1: sync | ||
85 | mtspr SPRN_HID0,r8 /* enable and invalidate caches */ | ||
86 | sync | ||
87 | mtspr SPRN_HID0,r11 /* enable caches */ | ||
88 | sync | ||
89 | isync | ||
90 | blr | ||
91 | |||
92 | /* 604, 604e, 604ev, ... | ||
93 | * Enable superscalar execution & branch history table | ||
94 | */ | ||
95 | setup_604_hid0: | ||
96 | mfspr r11,SPRN_HID0 | ||
97 | ori r11,r11,HID0_SIED|HID0_BHTE | ||
98 | ori r8,r11,HID0_BTCD | ||
99 | sync | ||
100 | mtspr SPRN_HID0,r8 /* flush branch target address cache */ | ||
101 | sync /* on 604e/604r */ | ||
102 | mtspr SPRN_HID0,r11 | ||
103 | sync | ||
104 | isync | ||
105 | blr | ||
106 | |||
107 | /* 7400 <= rev 2.7 and 7410 rev = 1.0 suffer from some | ||
108 | * erratas we work around here. | ||
109 | * Moto MPC710CE.pdf describes them, those are errata | ||
110 | * #3, #4 and #5 | ||
111 | * Note that we assume the firmware didn't choose to | ||
112 | * apply other workarounds (there are other ones documented | ||
113 | * in the .pdf). It appear that Apple firmware only works | ||
114 | * around #3 and with the same fix we use. We may want to | ||
115 | * check if the CPU is using 60x bus mode in which case | ||
116 | * the workaround for errata #4 is useless. Also, we may | ||
117 | * want to explicitely clear HID0_NOPDST as this is not | ||
118 | * needed once we have applied workaround #5 (though it's | ||
119 | * not set by Apple's firmware at least). | ||
120 | */ | ||
121 | setup_7400_workarounds: | ||
122 | mfpvr r3 | ||
123 | rlwinm r3,r3,0,20,31 | ||
124 | cmpwi 0,r3,0x0207 | ||
125 | ble 1f | ||
126 | blr | ||
127 | setup_7410_workarounds: | ||
128 | mfpvr r3 | ||
129 | rlwinm r3,r3,0,20,31 | ||
130 | cmpwi 0,r3,0x0100 | ||
131 | bnelr | ||
132 | 1: | ||
133 | mfspr r11,SPRN_MSSSR0 | ||
134 | /* Errata #3: Set L1OPQ_SIZE to 0x10 */ | ||
135 | rlwinm r11,r11,0,9,6 | ||
136 | oris r11,r11,0x0100 | ||
137 | /* Errata #4: Set L2MQ_SIZE to 1 (check for MPX mode first ?) */ | ||
138 | oris r11,r11,0x0002 | ||
139 | /* Errata #5: Set DRLT_SIZE to 0x01 */ | ||
140 | rlwinm r11,r11,0,5,2 | ||
141 | oris r11,r11,0x0800 | ||
142 | sync | ||
143 | mtspr SPRN_MSSSR0,r11 | ||
144 | sync | ||
145 | isync | ||
146 | blr | ||
147 | |||
148 | /* 740/750/7400/7410 | ||
149 | * Enable Store Gathering (SGE), Address Brodcast (ABE), | ||
150 | * Branch History Table (BHTE), Branch Target ICache (BTIC) | ||
151 | * Dynamic Power Management (DPM), Speculative (SPD) | ||
152 | * Clear Instruction cache throttling (ICTC) | ||
153 | */ | ||
154 | setup_750_7400_hid0: | ||
155 | mfspr r11,SPRN_HID0 | ||
156 | ori r11,r11,HID0_SGE | HID0_ABE | HID0_BHTE | HID0_BTIC | ||
157 | oris r11,r11,HID0_DPM@h | ||
158 | BEGIN_FTR_SECTION | ||
159 | xori r11,r11,HID0_BTIC | ||
160 | END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) | ||
161 | BEGIN_FTR_SECTION | ||
162 | xoris r11,r11,HID0_DPM@h /* disable dynamic power mgmt */ | ||
163 | END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM) | ||
164 | li r3,HID0_SPD | ||
165 | andc r11,r11,r3 /* clear SPD: enable speculative */ | ||
166 | li r3,0 | ||
167 | mtspr SPRN_ICTC,r3 /* Instruction Cache Throttling off */ | ||
168 | isync | ||
169 | mtspr SPRN_HID0,r11 | ||
170 | sync | ||
171 | isync | ||
172 | blr | ||
173 | |||
174 | /* 750cx specific | ||
175 | * Looks like we have to disable NAP feature for some PLL settings... | ||
176 | * (waiting for confirmation) | ||
177 | */ | ||
178 | setup_750cx: | ||
179 | mfspr r10, SPRN_HID1 | ||
180 | rlwinm r10,r10,4,28,31 | ||
181 | cmpwi cr0,r10,7 | ||
182 | cmpwi cr1,r10,9 | ||
183 | cmpwi cr2,r10,11 | ||
184 | cror 4*cr0+eq,4*cr0+eq,4*cr1+eq | ||
185 | cror 4*cr0+eq,4*cr0+eq,4*cr2+eq | ||
186 | bnelr | ||
187 | lwz r6,CPU_SPEC_FEATURES(r5) | ||
188 | li r7,CPU_FTR_CAN_NAP | ||
189 | andc r6,r6,r7 | ||
190 | stw r6,CPU_SPEC_FEATURES(r5) | ||
191 | blr | ||
192 | |||
193 | /* 750fx specific | ||
194 | */ | ||
195 | setup_750fx: | ||
196 | blr | ||
197 | |||
198 | /* MPC 745x | ||
199 | * Enable Store Gathering (SGE), Branch Folding (FOLD) | ||
200 | * Branch History Table (BHTE), Branch Target ICache (BTIC) | ||
201 | * Dynamic Power Management (DPM), Speculative (SPD) | ||
202 | * Ensure our data cache instructions really operate. | ||
203 | * Timebase has to be running or we wouldn't have made it here, | ||
204 | * just ensure we don't disable it. | ||
205 | * Clear Instruction cache throttling (ICTC) | ||
206 | * Enable L2 HW prefetch | ||
207 | */ | ||
208 | setup_745x_specifics: | ||
209 | /* We check for the presence of an L3 cache setup by | ||
210 | * the firmware. If any, we disable NAP capability as | ||
211 | * it's known to be bogus on rev 2.1 and earlier | ||
212 | */ | ||
213 | mfspr r11,SPRN_L3CR | ||
214 | andis. r11,r11,L3CR_L3E@h | ||
215 | beq 1f | ||
216 | lwz r6,CPU_SPEC_FEATURES(r5) | ||
217 | andi. r0,r6,CPU_FTR_L3_DISABLE_NAP | ||
218 | beq 1f | ||
219 | li r7,CPU_FTR_CAN_NAP | ||
220 | andc r6,r6,r7 | ||
221 | stw r6,CPU_SPEC_FEATURES(r5) | ||
222 | 1: | ||
223 | mfspr r11,SPRN_HID0 | ||
224 | |||
225 | /* All of the bits we have to set..... | ||
226 | */ | ||
227 | ori r11,r11,HID0_SGE | HID0_FOLD | HID0_BHTE | ||
228 | ori r11,r11,HID0_LRSTK | HID0_BTIC | ||
229 | oris r11,r11,HID0_DPM@h | ||
230 | BEGIN_FTR_SECTION | ||
231 | xori r11,r11,HID0_BTIC | ||
232 | END_FTR_SECTION_IFSET(CPU_FTR_NO_BTIC) | ||
233 | BEGIN_FTR_SECTION | ||
234 | xoris r11,r11,HID0_DPM@h /* disable dynamic power mgmt */ | ||
235 | END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM) | ||
236 | |||
237 | /* All of the bits we have to clear.... | ||
238 | */ | ||
239 | li r3,HID0_SPD | HID0_NOPDST | HID0_NOPTI | ||
240 | andc r11,r11,r3 /* clear SPD: enable speculative */ | ||
241 | li r3,0 | ||
242 | |||
243 | mtspr SPRN_ICTC,r3 /* Instruction Cache Throttling off */ | ||
244 | isync | ||
245 | mtspr SPRN_HID0,r11 | ||
246 | sync | ||
247 | isync | ||
248 | |||
249 | /* Enable L2 HW prefetch, if L2 is enabled | ||
250 | */ | ||
251 | mfspr r3,SPRN_L2CR | ||
252 | andis. r3,r3,L2CR_L2E@h | ||
253 | beqlr | ||
254 | mfspr r3,SPRN_MSSCR0 | ||
255 | ori r3,r3,3 | ||
256 | sync | ||
257 | mtspr SPRN_MSSCR0,r3 | ||
258 | sync | ||
259 | isync | ||
260 | blr | ||
261 | |||
262 | /* | ||
263 | * Initialize the FPU registers. This is needed to work around an errata | ||
264 | * in some 750 cpus where using a not yet initialized FPU register after | ||
265 | * power on reset may hang the CPU | ||
266 | */ | ||
267 | _GLOBAL(__init_fpu_registers) | ||
268 | mfmsr r10 | ||
269 | ori r11,r10,MSR_FP | ||
270 | mtmsr r11 | ||
271 | isync | ||
272 | addis r9,r3,empty_zero_page@ha | ||
273 | addi r9,r9,empty_zero_page@l | ||
274 | REST_32FPRS(0,r9) | ||
275 | sync | ||
276 | mtmsr r10 | ||
277 | isync | ||
278 | blr | ||
279 | |||
280 | |||
281 | /* Definitions for the table use to save CPU states */ | ||
282 | #define CS_HID0 0 | ||
283 | #define CS_HID1 4 | ||
284 | #define CS_HID2 8 | ||
285 | #define CS_MSSCR0 12 | ||
286 | #define CS_MSSSR0 16 | ||
287 | #define CS_ICTRL 20 | ||
288 | #define CS_LDSTCR 24 | ||
289 | #define CS_LDSTDB 28 | ||
290 | #define CS_SIZE 32 | ||
291 | |||
292 | .data | ||
293 | .balign L1_CACHE_BYTES | ||
294 | cpu_state_storage: | ||
295 | .space CS_SIZE | ||
296 | .balign L1_CACHE_BYTES,0 | ||
297 | .text | ||
298 | |||
299 | /* Called in normal context to backup CPU 0 state. This | ||
300 | * does not include cache settings. This function is also | ||
301 | * called for machine sleep. This does not include the MMU | ||
302 | * setup, BATs, etc... but rather the "special" registers | ||
303 | * like HID0, HID1, MSSCR0, etc... | ||
304 | */ | ||
305 | _GLOBAL(__save_cpu_setup) | ||
306 | /* Some CR fields are volatile, we back it up all */ | ||
307 | mfcr r7 | ||
308 | |||
309 | /* Get storage ptr */ | ||
310 | lis r5,cpu_state_storage@h | ||
311 | ori r5,r5,cpu_state_storage@l | ||
312 | |||
313 | /* Save HID0 (common to all CONFIG_6xx cpus) */ | ||
314 | mfspr r3,SPRN_HID0 | ||
315 | stw r3,CS_HID0(r5) | ||
316 | |||
317 | /* Now deal with CPU type dependent registers */ | ||
318 | mfspr r3,SPRN_PVR | ||
319 | srwi r3,r3,16 | ||
320 | cmplwi cr0,r3,0x8000 /* 7450 */ | ||
321 | cmplwi cr1,r3,0x000c /* 7400 */ | ||
322 | cmplwi cr2,r3,0x800c /* 7410 */ | ||
323 | cmplwi cr3,r3,0x8001 /* 7455 */ | ||
324 | cmplwi cr4,r3,0x8002 /* 7457 */ | ||
325 | cmplwi cr5,r3,0x8003 /* 7447A */ | ||
326 | cmplwi cr6,r3,0x7000 /* 750FX */ | ||
327 | cmplwi cr7,r3,0x8004 /* 7448 */ | ||
328 | /* cr1 is 7400 || 7410 */ | ||
329 | cror 4*cr1+eq,4*cr1+eq,4*cr2+eq | ||
330 | /* cr0 is 74xx */ | ||
331 | cror 4*cr0+eq,4*cr0+eq,4*cr3+eq | ||
332 | cror 4*cr0+eq,4*cr0+eq,4*cr4+eq | ||
333 | cror 4*cr0+eq,4*cr0+eq,4*cr1+eq | ||
334 | cror 4*cr0+eq,4*cr0+eq,4*cr5+eq | ||
335 | cror 4*cr0+eq,4*cr0+eq,4*cr7+eq | ||
336 | bne 1f | ||
337 | /* Backup 74xx specific regs */ | ||
338 | mfspr r4,SPRN_MSSCR0 | ||
339 | stw r4,CS_MSSCR0(r5) | ||
340 | mfspr r4,SPRN_MSSSR0 | ||
341 | stw r4,CS_MSSSR0(r5) | ||
342 | beq cr1,1f | ||
343 | /* Backup 745x specific registers */ | ||
344 | mfspr r4,SPRN_HID1 | ||
345 | stw r4,CS_HID1(r5) | ||
346 | mfspr r4,SPRN_ICTRL | ||
347 | stw r4,CS_ICTRL(r5) | ||
348 | mfspr r4,SPRN_LDSTCR | ||
349 | stw r4,CS_LDSTCR(r5) | ||
350 | mfspr r4,SPRN_LDSTDB | ||
351 | stw r4,CS_LDSTDB(r5) | ||
352 | 1: | ||
353 | bne cr6,1f | ||
354 | /* Backup 750FX specific registers */ | ||
355 | mfspr r4,SPRN_HID1 | ||
356 | stw r4,CS_HID1(r5) | ||
357 | /* If rev 2.x, backup HID2 */ | ||
358 | mfspr r3,SPRN_PVR | ||
359 | andi. r3,r3,0xff00 | ||
360 | cmpwi cr0,r3,0x0200 | ||
361 | bne 1f | ||
362 | mfspr r4,SPRN_HID2 | ||
363 | stw r4,CS_HID2(r5) | ||
364 | 1: | ||
365 | mtcr r7 | ||
366 | blr | ||
367 | |||
368 | /* Called with no MMU context (typically MSR:IR/DR off) to | ||
369 | * restore CPU state as backed up by the previous | ||
370 | * function. This does not include cache setting | ||
371 | */ | ||
372 | _GLOBAL(__restore_cpu_setup) | ||
373 | /* Some CR fields are volatile, we back it up all */ | ||
374 | mfcr r7 | ||
375 | |||
376 | /* Get storage ptr */ | ||
377 | lis r5,(cpu_state_storage-KERNELBASE)@h | ||
378 | ori r5,r5,cpu_state_storage@l | ||
379 | |||
380 | /* Restore HID0 */ | ||
381 | lwz r3,CS_HID0(r5) | ||
382 | sync | ||
383 | isync | ||
384 | mtspr SPRN_HID0,r3 | ||
385 | sync | ||
386 | isync | ||
387 | |||
388 | /* Now deal with CPU type dependent registers */ | ||
389 | mfspr r3,SPRN_PVR | ||
390 | srwi r3,r3,16 | ||
391 | cmplwi cr0,r3,0x8000 /* 7450 */ | ||
392 | cmplwi cr1,r3,0x000c /* 7400 */ | ||
393 | cmplwi cr2,r3,0x800c /* 7410 */ | ||
394 | cmplwi cr3,r3,0x8001 /* 7455 */ | ||
395 | cmplwi cr4,r3,0x8002 /* 7457 */ | ||
396 | cmplwi cr5,r3,0x8003 /* 7447A */ | ||
397 | cmplwi cr6,r3,0x7000 /* 750FX */ | ||
398 | cmplwi cr7,r3,0x8004 /* 7448 */ | ||
399 | /* cr1 is 7400 || 7410 */ | ||
400 | cror 4*cr1+eq,4*cr1+eq,4*cr2+eq | ||
401 | /* cr0 is 74xx */ | ||
402 | cror 4*cr0+eq,4*cr0+eq,4*cr3+eq | ||
403 | cror 4*cr0+eq,4*cr0+eq,4*cr4+eq | ||
404 | cror 4*cr0+eq,4*cr0+eq,4*cr1+eq | ||
405 | cror 4*cr0+eq,4*cr0+eq,4*cr5+eq | ||
406 | cror 4*cr0+eq,4*cr0+eq,4*cr7+eq | ||
407 | bne 2f | ||
408 | /* Restore 74xx specific regs */ | ||
409 | lwz r4,CS_MSSCR0(r5) | ||
410 | sync | ||
411 | mtspr SPRN_MSSCR0,r4 | ||
412 | sync | ||
413 | isync | ||
414 | lwz r4,CS_MSSSR0(r5) | ||
415 | sync | ||
416 | mtspr SPRN_MSSSR0,r4 | ||
417 | sync | ||
418 | isync | ||
419 | bne cr2,1f | ||
420 | /* Clear 7410 L2CR2 */ | ||
421 | li r4,0 | ||
422 | mtspr SPRN_L2CR2,r4 | ||
423 | 1: beq cr1,2f | ||
424 | /* Restore 745x specific registers */ | ||
425 | lwz r4,CS_HID1(r5) | ||
426 | sync | ||
427 | mtspr SPRN_HID1,r4 | ||
428 | isync | ||
429 | sync | ||
430 | lwz r4,CS_ICTRL(r5) | ||
431 | sync | ||
432 | mtspr SPRN_ICTRL,r4 | ||
433 | isync | ||
434 | sync | ||
435 | lwz r4,CS_LDSTCR(r5) | ||
436 | sync | ||
437 | mtspr SPRN_LDSTCR,r4 | ||
438 | isync | ||
439 | sync | ||
440 | lwz r4,CS_LDSTDB(r5) | ||
441 | sync | ||
442 | mtspr SPRN_LDSTDB,r4 | ||
443 | isync | ||
444 | sync | ||
445 | 2: bne cr6,1f | ||
446 | /* Restore 750FX specific registers | ||
447 | * that is restore HID2 on rev 2.x and PLL config & switch | ||
448 | * to PLL 0 on all | ||
449 | */ | ||
450 | /* If rev 2.x, restore HID2 with low voltage bit cleared */ | ||
451 | mfspr r3,SPRN_PVR | ||
452 | andi. r3,r3,0xff00 | ||
453 | cmpwi cr0,r3,0x0200 | ||
454 | bne 4f | ||
455 | lwz r4,CS_HID2(r5) | ||
456 | rlwinm r4,r4,0,19,17 | ||
457 | mtspr SPRN_HID2,r4 | ||
458 | sync | ||
459 | 4: | ||
460 | lwz r4,CS_HID1(r5) | ||
461 | rlwinm r5,r4,0,16,14 | ||
462 | mtspr SPRN_HID1,r5 | ||
463 | /* Wait for PLL to stabilize */ | ||
464 | mftbl r5 | ||
465 | 3: mftbl r6 | ||
466 | sub r6,r6,r5 | ||
467 | cmplwi cr0,r6,10000 | ||
468 | ble 3b | ||
469 | /* Setup final PLL */ | ||
470 | mtspr SPRN_HID1,r4 | ||
471 | 1: | ||
472 | mtcr r7 | ||
473 | blr | ||
474 | |||
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index e4e81374cb9a..39e348a3ade2 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -894,7 +894,7 @@ struct cpu_spec cpu_specs[] = { | |||
894 | .platform = "ppc405", | 894 | .platform = "ppc405", |
895 | }, | 895 | }, |
896 | { /* Xilinx Virtex-II Pro */ | 896 | { /* Xilinx Virtex-II Pro */ |
897 | .pvr_mask = 0xffff0000, | 897 | .pvr_mask = 0xfffff000, |
898 | .pvr_value = 0x20010000, | 898 | .pvr_value = 0x20010000, |
899 | .cpu_name = "Virtex-II Pro", | 899 | .cpu_name = "Virtex-II Pro", |
900 | .cpu_features = CPU_FTRS_40X, | 900 | .cpu_features = CPU_FTRS_40X, |
@@ -904,6 +904,16 @@ struct cpu_spec cpu_specs[] = { | |||
904 | .dcache_bsize = 32, | 904 | .dcache_bsize = 32, |
905 | .platform = "ppc405", | 905 | .platform = "ppc405", |
906 | }, | 906 | }, |
907 | { /* Xilinx Virtex-4 FX */ | ||
908 | .pvr_mask = 0xfffff000, | ||
909 | .pvr_value = 0x20011000, | ||
910 | .cpu_name = "Virtex-4 FX", | ||
911 | .cpu_features = CPU_FTRS_40X, | ||
912 | .cpu_user_features = PPC_FEATURE_32 | | ||
913 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | ||
914 | .icache_bsize = 32, | ||
915 | .dcache_bsize = 32, | ||
916 | }, | ||
907 | { /* 405EP */ | 917 | { /* 405EP */ |
908 | .pvr_mask = 0xffff0000, | 918 | .pvr_mask = 0xffff0000, |
909 | .pvr_value = 0x51210000, | 919 | .pvr_value = 0x51210000, |
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 211d72653ea6..764d07329716 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c | |||
@@ -61,7 +61,7 @@ static int __init parse_elfcorehdr(char *p) | |||
61 | if (p) | 61 | if (p) |
62 | elfcorehdr_addr = memparse(p, &p); | 62 | elfcorehdr_addr = memparse(p, &p); |
63 | 63 | ||
64 | return 0; | 64 | return 1; |
65 | } | 65 | } |
66 | __setup("elfcorehdr=", parse_elfcorehdr); | 66 | __setup("elfcorehdr=", parse_elfcorehdr); |
67 | #endif | 67 | #endif |
@@ -71,7 +71,7 @@ static int __init parse_savemaxmem(char *p) | |||
71 | if (p) | 71 | if (p) |
72 | saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1; | 72 | saved_max_pfn = (memparse(p, &p) >> PAGE_SHIFT) - 1; |
73 | 73 | ||
74 | return 0; | 74 | return 1; |
75 | } | 75 | } |
76 | __setup("savemaxmem=", parse_savemaxmem); | 76 | __setup("savemaxmem=", parse_savemaxmem); |
77 | 77 | ||
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 4827ca1ec89b..b3a979467225 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -135,10 +135,10 @@ transfer_to_handler: | |||
135 | mfspr r11,SPRN_HID0 | 135 | mfspr r11,SPRN_HID0 |
136 | mtcr r11 | 136 | mtcr r11 |
137 | BEGIN_FTR_SECTION | 137 | BEGIN_FTR_SECTION |
138 | bt- 8,power_save_6xx_restore /* Check DOZE */ | 138 | bt- 8,4f /* Check DOZE */ |
139 | END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE) | 139 | END_FTR_SECTION_IFSET(CPU_FTR_CAN_DOZE) |
140 | BEGIN_FTR_SECTION | 140 | BEGIN_FTR_SECTION |
141 | bt- 9,power_save_6xx_restore /* Check NAP */ | 141 | bt- 9,4f /* Check NAP */ |
142 | END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP) | 142 | END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP) |
143 | #endif /* CONFIG_6xx */ | 143 | #endif /* CONFIG_6xx */ |
144 | .globl transfer_to_handler_cont | 144 | .globl transfer_to_handler_cont |
@@ -157,6 +157,10 @@ transfer_to_handler_cont: | |||
157 | SYNC | 157 | SYNC |
158 | RFI /* jump to handler, enable MMU */ | 158 | RFI /* jump to handler, enable MMU */ |
159 | 159 | ||
160 | #ifdef CONFIG_6xx | ||
161 | 4: b power_save_6xx_restore | ||
162 | #endif | ||
163 | |||
160 | /* | 164 | /* |
161 | * On kernel stack overflow, load up an initial stack pointer | 165 | * On kernel stack overflow, load up an initial stack pointer |
162 | * and call StackOverflow(regs), which should not return. | 166 | * and call StackOverflow(regs), which should not return. |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 24be0cf86d7f..19ad5c6b1818 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/kernel/entry.S | ||
3 | * | ||
4 | * PowerPC version | 2 | * PowerPC version |
5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 3 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) |
6 | * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP | 4 | * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP |
@@ -63,6 +61,7 @@ system_call_common: | |||
63 | std r12,_MSR(r1) | 61 | std r12,_MSR(r1) |
64 | std r0,GPR0(r1) | 62 | std r0,GPR0(r1) |
65 | std r10,GPR1(r1) | 63 | std r10,GPR1(r1) |
64 | ACCOUNT_CPU_USER_ENTRY(r10, r11) | ||
66 | std r2,GPR2(r1) | 65 | std r2,GPR2(r1) |
67 | std r3,GPR3(r1) | 66 | std r3,GPR3(r1) |
68 | std r4,GPR4(r1) | 67 | std r4,GPR4(r1) |
@@ -170,8 +169,9 @@ syscall_error_cont: | |||
170 | stdcx. r0,0,r1 /* to clear the reservation */ | 169 | stdcx. r0,0,r1 /* to clear the reservation */ |
171 | andi. r6,r8,MSR_PR | 170 | andi. r6,r8,MSR_PR |
172 | ld r4,_LINK(r1) | 171 | ld r4,_LINK(r1) |
173 | beq- 1f /* only restore r13 if */ | 172 | beq- 1f |
174 | ld r13,GPR13(r1) /* returning to usermode */ | 173 | ACCOUNT_CPU_USER_EXIT(r11, r12) |
174 | ld r13,GPR13(r1) /* only restore r13 if returning to usermode */ | ||
175 | 1: ld r2,GPR2(r1) | 175 | 1: ld r2,GPR2(r1) |
176 | li r12,MSR_RI | 176 | li r12,MSR_RI |
177 | andc r11,r10,r12 | 177 | andc r11,r10,r12 |
@@ -322,7 +322,7 @@ _GLOBAL(ret_from_fork) | |||
322 | * the fork code also. | 322 | * the fork code also. |
323 | * | 323 | * |
324 | * The code which creates the new task context is in 'copy_thread' | 324 | * The code which creates the new task context is in 'copy_thread' |
325 | * in arch/ppc64/kernel/process.c | 325 | * in arch/powerpc/kernel/process.c |
326 | */ | 326 | */ |
327 | .align 7 | 327 | .align 7 |
328 | _GLOBAL(_switch) | 328 | _GLOBAL(_switch) |
@@ -486,6 +486,7 @@ restore: | |||
486 | * userspace | 486 | * userspace |
487 | */ | 487 | */ |
488 | beq 1f | 488 | beq 1f |
489 | ACCOUNT_CPU_USER_EXIT(r3, r4) | ||
489 | REST_GPR(13, r1) | 490 | REST_GPR(13, r1) |
490 | 1: | 491 | 1: |
491 | ld r3,_CTR(r1) | 492 | ld r3,_CTR(r1) |
@@ -616,6 +617,12 @@ _GLOBAL(enter_rtas) | |||
616 | mfsrr1 r10 | 617 | mfsrr1 r10 |
617 | std r10,_SRR1(r1) | 618 | std r10,_SRR1(r1) |
618 | 619 | ||
620 | /* Temporary workaround to clear CR until RTAS can be modified to | ||
621 | * ignore all bits. | ||
622 | */ | ||
623 | li r0,0 | ||
624 | mtcr r0 | ||
625 | |||
619 | /* There is no way it is acceptable to get here with interrupts enabled, | 626 | /* There is no way it is acceptable to get here with interrupts enabled, |
620 | * check it with the asm equivalent of WARN_ON | 627 | * check it with the asm equivalent of WARN_ON |
621 | */ | 628 | */ |
diff --git a/arch/powerpc/kernel/firmware.c b/arch/powerpc/kernel/firmware.c index 65eae752a527..0bfe9061720a 100644 --- a/arch/powerpc/kernel/firmware.c +++ b/arch/powerpc/kernel/firmware.c | |||
@@ -14,32 +14,9 @@ | |||
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/config.h> | 16 | #include <linux/config.h> |
17 | #include <linux/module.h> | ||
17 | 18 | ||
18 | #include <asm/firmware.h> | 19 | #include <asm/firmware.h> |
19 | 20 | ||
20 | unsigned long ppc64_firmware_features; | 21 | unsigned long powerpc_firmware_features; |
21 | 22 | EXPORT_SYMBOL_GPL(powerpc_firmware_features); | |
22 | #ifdef CONFIG_PPC_PSERIES | ||
23 | firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = { | ||
24 | {FW_FEATURE_PFT, "hcall-pft"}, | ||
25 | {FW_FEATURE_TCE, "hcall-tce"}, | ||
26 | {FW_FEATURE_SPRG0, "hcall-sprg0"}, | ||
27 | {FW_FEATURE_DABR, "hcall-dabr"}, | ||
28 | {FW_FEATURE_COPY, "hcall-copy"}, | ||
29 | {FW_FEATURE_ASR, "hcall-asr"}, | ||
30 | {FW_FEATURE_DEBUG, "hcall-debug"}, | ||
31 | {FW_FEATURE_PERF, "hcall-perf"}, | ||
32 | {FW_FEATURE_DUMP, "hcall-dump"}, | ||
33 | {FW_FEATURE_INTERRUPT, "hcall-interrupt"}, | ||
34 | {FW_FEATURE_MIGRATE, "hcall-migrate"}, | ||
35 | {FW_FEATURE_PERFMON, "hcall-perfmon"}, | ||
36 | {FW_FEATURE_CRQ, "hcall-crq"}, | ||
37 | {FW_FEATURE_VIO, "hcall-vio"}, | ||
38 | {FW_FEATURE_RDMA, "hcall-rdma"}, | ||
39 | {FW_FEATURE_LLAN, "hcall-lLAN"}, | ||
40 | {FW_FEATURE_BULK, "hcall-bulk"}, | ||
41 | {FW_FEATURE_XDABR, "hcall-xdabr"}, | ||
42 | {FW_FEATURE_MULTITCE, "hcall-multi-tce"}, | ||
43 | {FW_FEATURE_SPLPAR, "hcall-splpar"}, | ||
44 | }; | ||
45 | #endif | ||
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index 8b49679fad54..47c7fa148c9a 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/kernel/head_44x.S | ||
3 | * | ||
4 | * Kernel execution entry point code. | 2 | * Kernel execution entry point code. |
5 | * | 3 | * |
6 | * Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org> | 4 | * Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org> |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 9b65029dd2a3..a5ae04a57c78 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/kernel/head.S | ||
3 | * | ||
4 | * PowerPC version | 2 | * PowerPC version |
5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 3 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) |
6 | * | 4 | * |
@@ -279,6 +277,7 @@ exception_marker: | |||
279 | std r10,0(r1); /* make stack chain pointer */ \ | 277 | std r10,0(r1); /* make stack chain pointer */ \ |
280 | std r0,GPR0(r1); /* save r0 in stackframe */ \ | 278 | std r0,GPR0(r1); /* save r0 in stackframe */ \ |
281 | std r10,GPR1(r1); /* save r1 in stackframe */ \ | 279 | std r10,GPR1(r1); /* save r1 in stackframe */ \ |
280 | ACCOUNT_CPU_USER_ENTRY(r9, r10); \ | ||
282 | std r2,GPR2(r1); /* save r2 in stackframe */ \ | 281 | std r2,GPR2(r1); /* save r2 in stackframe */ \ |
283 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ | 282 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ |
284 | SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ | 283 | SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ |
@@ -846,6 +845,14 @@ fast_exception_return: | |||
846 | ld r11,_NIP(r1) | 845 | ld r11,_NIP(r1) |
847 | andi. r3,r12,MSR_RI /* check if RI is set */ | 846 | andi. r3,r12,MSR_RI /* check if RI is set */ |
848 | beq- unrecov_fer | 847 | beq- unrecov_fer |
848 | |||
849 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
850 | andi. r3,r12,MSR_PR | ||
851 | beq 2f | ||
852 | ACCOUNT_CPU_USER_EXIT(r3, r4) | ||
853 | 2: | ||
854 | #endif | ||
855 | |||
849 | ld r3,_CCR(r1) | 856 | ld r3,_CCR(r1) |
850 | ld r4,_LINK(r1) | 857 | ld r4,_LINK(r1) |
851 | ld r5,_CTR(r1) | 858 | ld r5,_CTR(r1) |
@@ -1537,7 +1544,11 @@ _STATIC(__boot_from_prom) | |||
1537 | mr r28,r6 | 1544 | mr r28,r6 |
1538 | mr r27,r7 | 1545 | mr r27,r7 |
1539 | 1546 | ||
1540 | /* Align the stack to 16-byte boundary for broken yaboot */ | 1547 | /* |
1548 | * Align the stack to 16-byte boundary | ||
1549 | * Depending on the size and layout of the ELF sections in the initial | ||
1550 | * boot binary, the stack pointer will be unalignet on PowerMac | ||
1551 | */ | ||
1541 | rldicr r1,r1,0,59 | 1552 | rldicr r1,r1,0,59 |
1542 | 1553 | ||
1543 | /* Make sure we are running in 64 bits mode */ | 1554 | /* Make sure we are running in 64 bits mode */ |
@@ -1840,21 +1851,6 @@ _STATIC(start_here_multiplatform) | |||
1840 | bl .__save_cpu_setup | 1851 | bl .__save_cpu_setup |
1841 | sync | 1852 | sync |
1842 | 1853 | ||
1843 | /* Setup a valid physical PACA pointer in SPRG3 for early_setup | ||
1844 | * note that boot_cpuid can always be 0 nowadays since there is | ||
1845 | * nowhere it can be initialized differently before we reach this | ||
1846 | * code | ||
1847 | */ | ||
1848 | LOAD_REG_IMMEDIATE(r27, boot_cpuid) | ||
1849 | add r27,r27,r26 | ||
1850 | lwz r27,0(r27) | ||
1851 | |||
1852 | LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */ | ||
1853 | mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */ | ||
1854 | add r13,r13,r24 /* for this processor. */ | ||
1855 | add r13,r13,r26 /* convert to physical addr */ | ||
1856 | mtspr SPRN_SPRG3,r13 | ||
1857 | |||
1858 | /* Do very early kernel initializations, including initial hash table, | 1854 | /* Do very early kernel initializations, including initial hash table, |
1859 | * stab and slb setup before we turn on relocation. */ | 1855 | * stab and slb setup before we turn on relocation. */ |
1860 | 1856 | ||
@@ -1923,6 +1919,17 @@ _STATIC(start_here_common) | |||
1923 | /* Not reached */ | 1919 | /* Not reached */ |
1924 | BUG_OPCODE | 1920 | BUG_OPCODE |
1925 | 1921 | ||
1922 | /* Put the paca pointer into r13 and SPRG3 */ | ||
1923 | _GLOBAL(setup_boot_paca) | ||
1924 | LOAD_REG_IMMEDIATE(r3, boot_cpuid) | ||
1925 | lwz r3,0(r3) | ||
1926 | LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */ | ||
1927 | mulli r3,r3,PACA_SIZE /* Calculate vaddr of right paca */ | ||
1928 | add r13,r3,r4 /* for this processor. */ | ||
1929 | mtspr SPRN_SPRG3,r13 | ||
1930 | |||
1931 | blr | ||
1932 | |||
1926 | /* | 1933 | /* |
1927 | * We put a few things here that have to be page-aligned. | 1934 | * We put a few things here that have to be page-aligned. |
1928 | * This stuff goes at the beginning of the bss, which is page-aligned. | 1935 | * This stuff goes at the beginning of the bss, which is page-aligned. |
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index bc6d1ac55235..28941f5ce673 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/kernel/except_8xx.S | ||
3 | * | ||
4 | * PowerPC version | 2 | * PowerPC version |
5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 3 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) |
6 | * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP | 4 | * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP |
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h new file mode 100644 index 000000000000..8536e7676160 --- /dev/null +++ b/arch/powerpc/kernel/head_booke.h | |||
@@ -0,0 +1,363 @@ | |||
1 | #ifndef __HEAD_BOOKE_H__ | ||
2 | #define __HEAD_BOOKE_H__ | ||
3 | |||
4 | /* | ||
5 | * Macros used for common Book-e exception handling | ||
6 | */ | ||
7 | |||
8 | #define SET_IVOR(vector_number, vector_label) \ | ||
9 | li r26,vector_label@l; \ | ||
10 | mtspr SPRN_IVOR##vector_number,r26; \ | ||
11 | sync | ||
12 | |||
13 | #define NORMAL_EXCEPTION_PROLOG \ | ||
14 | mtspr SPRN_SPRG0,r10; /* save two registers to work with */\ | ||
15 | mtspr SPRN_SPRG1,r11; \ | ||
16 | mtspr SPRN_SPRG4W,r1; \ | ||
17 | mfcr r10; /* save CR in r10 for now */\ | ||
18 | mfspr r11,SPRN_SRR1; /* check whether user or kernel */\ | ||
19 | andi. r11,r11,MSR_PR; \ | ||
20 | beq 1f; \ | ||
21 | mfspr r1,SPRN_SPRG3; /* if from user, start at top of */\ | ||
22 | lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\ | ||
23 | addi r1,r1,THREAD_SIZE; \ | ||
24 | 1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\ | ||
25 | mr r11,r1; \ | ||
26 | stw r10,_CCR(r11); /* save various registers */\ | ||
27 | stw r12,GPR12(r11); \ | ||
28 | stw r9,GPR9(r11); \ | ||
29 | mfspr r10,SPRN_SPRG0; \ | ||
30 | stw r10,GPR10(r11); \ | ||
31 | mfspr r12,SPRN_SPRG1; \ | ||
32 | stw r12,GPR11(r11); \ | ||
33 | mflr r10; \ | ||
34 | stw r10,_LINK(r11); \ | ||
35 | mfspr r10,SPRN_SPRG4R; \ | ||
36 | mfspr r12,SPRN_SRR0; \ | ||
37 | stw r10,GPR1(r11); \ | ||
38 | mfspr r9,SPRN_SRR1; \ | ||
39 | stw r10,0(r11); \ | ||
40 | rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ | ||
41 | stw r0,GPR0(r11); \ | ||
42 | SAVE_4GPRS(3, r11); \ | ||
43 | SAVE_2GPRS(7, r11) | ||
44 | |||
45 | /* To handle the additional exception priority levels on 40x and Book-E | ||
46 | * processors we allocate a 4k stack per additional priority level. The various | ||
47 | * head_xxx.S files allocate space (exception_stack_top) for each priority's | ||
48 | * stack times the number of CPUs | ||
49 | * | ||
50 | * On 40x critical is the only additional level | ||
51 | * On 44x/e500 we have critical and machine check | ||
52 | * On e200 we have critical and debug (machine check occurs via critical) | ||
53 | * | ||
54 | * Additionally we reserve a SPRG for each priority level so we can free up a | ||
55 | * GPR to use as the base for indirect access to the exception stacks. This | ||
56 | * is necessary since the MMU is always on, for Book-E parts, and the stacks | ||
57 | * are offset from KERNELBASE. | ||
58 | * | ||
59 | */ | ||
60 | #define BOOKE_EXCEPTION_STACK_SIZE (8192) | ||
61 | |||
62 | /* CRIT_SPRG only used in critical exception handling */ | ||
63 | #define CRIT_SPRG SPRN_SPRG2 | ||
64 | /* MCHECK_SPRG only used in machine check exception handling */ | ||
65 | #define MCHECK_SPRG SPRN_SPRG6W | ||
66 | |||
67 | #define MCHECK_STACK_TOP (exception_stack_top - 4096) | ||
68 | #define CRIT_STACK_TOP (exception_stack_top) | ||
69 | |||
70 | /* only on e200 for now */ | ||
71 | #define DEBUG_STACK_TOP (exception_stack_top - 4096) | ||
72 | #define DEBUG_SPRG SPRN_SPRG6W | ||
73 | |||
74 | #ifdef CONFIG_SMP | ||
75 | #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ | ||
76 | mfspr r8,SPRN_PIR; \ | ||
77 | mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \ | ||
78 | neg r8,r8; \ | ||
79 | addis r8,r8,level##_STACK_TOP@ha; \ | ||
80 | addi r8,r8,level##_STACK_TOP@l | ||
81 | #else | ||
82 | #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ | ||
83 | lis r8,level##_STACK_TOP@h; \ | ||
84 | ori r8,r8,level##_STACK_TOP@l | ||
85 | #endif | ||
86 | |||
87 | /* | ||
88 | * Exception prolog for critical/machine check exceptions. This is a | ||
89 | * little different from the normal exception prolog above since a | ||
90 | * critical/machine check exception can potentially occur at any point | ||
91 | * during normal exception processing. Thus we cannot use the same SPRG | ||
92 | * registers as the normal prolog above. Instead we use a portion of the | ||
93 | * critical/machine check exception stack at low physical addresses. | ||
94 | */ | ||
95 | #define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \ | ||
96 | mtspr exc_level##_SPRG,r8; \ | ||
97 | BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \ | ||
98 | stw r10,GPR10-INT_FRAME_SIZE(r8); \ | ||
99 | stw r11,GPR11-INT_FRAME_SIZE(r8); \ | ||
100 | mfcr r10; /* save CR in r10 for now */\ | ||
101 | mfspr r11,exc_level_srr1; /* check whether user or kernel */\ | ||
102 | andi. r11,r11,MSR_PR; \ | ||
103 | mr r11,r8; \ | ||
104 | mfspr r8,exc_level##_SPRG; \ | ||
105 | beq 1f; \ | ||
106 | /* COMING FROM USER MODE */ \ | ||
107 | mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\ | ||
108 | lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ | ||
109 | addi r11,r11,THREAD_SIZE; \ | ||
110 | 1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\ | ||
111 | stw r10,_CCR(r11); /* save various registers */\ | ||
112 | stw r12,GPR12(r11); \ | ||
113 | stw r9,GPR9(r11); \ | ||
114 | mflr r10; \ | ||
115 | stw r10,_LINK(r11); \ | ||
116 | mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\ | ||
117 | stw r12,_DEAR(r11); /* since they may have had stuff */\ | ||
118 | mfspr r9,SPRN_ESR; /* in them at the point where the */\ | ||
119 | stw r9,_ESR(r11); /* exception was taken */\ | ||
120 | mfspr r12,exc_level_srr0; \ | ||
121 | stw r1,GPR1(r11); \ | ||
122 | mfspr r9,exc_level_srr1; \ | ||
123 | stw r1,0(r11); \ | ||
124 | mr r1,r11; \ | ||
125 | rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ | ||
126 | stw r0,GPR0(r11); \ | ||
127 | SAVE_4GPRS(3, r11); \ | ||
128 | SAVE_2GPRS(7, r11) | ||
129 | |||
130 | #define CRITICAL_EXCEPTION_PROLOG \ | ||
131 | EXC_LEVEL_EXCEPTION_PROLOG(CRIT, SPRN_CSRR0, SPRN_CSRR1) | ||
132 | #define DEBUG_EXCEPTION_PROLOG \ | ||
133 | EXC_LEVEL_EXCEPTION_PROLOG(DEBUG, SPRN_DSRR0, SPRN_DSRR1) | ||
134 | #define MCHECK_EXCEPTION_PROLOG \ | ||
135 | EXC_LEVEL_EXCEPTION_PROLOG(MCHECK, SPRN_MCSRR0, SPRN_MCSRR1) | ||
136 | |||
137 | /* | ||
138 | * Exception vectors. | ||
139 | */ | ||
140 | #define START_EXCEPTION(label) \ | ||
141 | .align 5; \ | ||
142 | label: | ||
143 | |||
144 | #define FINISH_EXCEPTION(func) \ | ||
145 | bl transfer_to_handler_full; \ | ||
146 | .long func; \ | ||
147 | .long ret_from_except_full | ||
148 | |||
149 | #define EXCEPTION(n, label, hdlr, xfer) \ | ||
150 | START_EXCEPTION(label); \ | ||
151 | NORMAL_EXCEPTION_PROLOG; \ | ||
152 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
153 | xfer(n, hdlr) | ||
154 | |||
155 | #define CRITICAL_EXCEPTION(n, label, hdlr) \ | ||
156 | START_EXCEPTION(label); \ | ||
157 | CRITICAL_EXCEPTION_PROLOG; \ | ||
158 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
159 | EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ | ||
160 | NOCOPY, crit_transfer_to_handler, \ | ||
161 | ret_from_crit_exc) | ||
162 | |||
163 | #define MCHECK_EXCEPTION(n, label, hdlr) \ | ||
164 | START_EXCEPTION(label); \ | ||
165 | MCHECK_EXCEPTION_PROLOG; \ | ||
166 | mfspr r5,SPRN_ESR; \ | ||
167 | stw r5,_ESR(r11); \ | ||
168 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
169 | EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ | ||
170 | NOCOPY, mcheck_transfer_to_handler, \ | ||
171 | ret_from_mcheck_exc) | ||
172 | |||
173 | #define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \ | ||
174 | li r10,trap; \ | ||
175 | stw r10,_TRAP(r11); \ | ||
176 | lis r10,msr@h; \ | ||
177 | ori r10,r10,msr@l; \ | ||
178 | copyee(r10, r9); \ | ||
179 | bl tfer; \ | ||
180 | .long hdlr; \ | ||
181 | .long ret | ||
182 | |||
183 | #define COPY_EE(d, s) rlwimi d,s,0,16,16 | ||
184 | #define NOCOPY(d, s) | ||
185 | |||
186 | #define EXC_XFER_STD(n, hdlr) \ | ||
187 | EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \ | ||
188 | ret_from_except_full) | ||
189 | |||
190 | #define EXC_XFER_LITE(n, hdlr) \ | ||
191 | EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \ | ||
192 | ret_from_except) | ||
193 | |||
194 | #define EXC_XFER_EE(n, hdlr) \ | ||
195 | EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \ | ||
196 | ret_from_except_full) | ||
197 | |||
198 | #define EXC_XFER_EE_LITE(n, hdlr) \ | ||
199 | EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \ | ||
200 | ret_from_except) | ||
201 | |||
202 | /* Check for a single step debug exception while in an exception | ||
203 | * handler before state has been saved. This is to catch the case | ||
204 | * where an instruction that we are trying to single step causes | ||
205 | * an exception (eg ITLB/DTLB miss) and thus the first instruction of | ||
206 | * the exception handler generates a single step debug exception. | ||
207 | * | ||
208 | * If we get a debug trap on the first instruction of an exception handler, | ||
209 | * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is | ||
210 | * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR). | ||
211 | * The exception handler was handling a non-critical interrupt, so it will | ||
212 | * save (and later restore) the MSR via SPRN_CSRR1, which will still have | ||
213 | * the MSR_DE bit set. | ||
214 | */ | ||
215 | #ifdef CONFIG_E200 | ||
216 | #define DEBUG_EXCEPTION \ | ||
217 | START_EXCEPTION(Debug); \ | ||
218 | DEBUG_EXCEPTION_PROLOG; \ | ||
219 | \ | ||
220 | /* \ | ||
221 | * If there is a single step or branch-taken exception in an \ | ||
222 | * exception entry sequence, it was probably meant to apply to \ | ||
223 | * the code where the exception occurred (since exception entry \ | ||
224 | * doesn't turn off DE automatically). We simulate the effect \ | ||
225 | * of turning off DE on entry to an exception handler by turning \ | ||
226 | * off DE in the CSRR1 value and clearing the debug status. \ | ||
227 | */ \ | ||
228 | mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \ | ||
229 | andis. r10,r10,DBSR_IC@h; \ | ||
230 | beq+ 2f; \ | ||
231 | \ | ||
232 | lis r10,KERNELBASE@h; /* check if exception in vectors */ \ | ||
233 | ori r10,r10,KERNELBASE@l; \ | ||
234 | cmplw r12,r10; \ | ||
235 | blt+ 2f; /* addr below exception vectors */ \ | ||
236 | \ | ||
237 | lis r10,Debug@h; \ | ||
238 | ori r10,r10,Debug@l; \ | ||
239 | cmplw r12,r10; \ | ||
240 | bgt+ 2f; /* addr above exception vectors */ \ | ||
241 | \ | ||
242 | /* here it looks like we got an inappropriate debug exception. */ \ | ||
243 | 1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CDRR1 value */ \ | ||
244 | lis r10,DBSR_IC@h; /* clear the IC event */ \ | ||
245 | mtspr SPRN_DBSR,r10; \ | ||
246 | /* restore state and get out */ \ | ||
247 | lwz r10,_CCR(r11); \ | ||
248 | lwz r0,GPR0(r11); \ | ||
249 | lwz r1,GPR1(r11); \ | ||
250 | mtcrf 0x80,r10; \ | ||
251 | mtspr SPRN_DSRR0,r12; \ | ||
252 | mtspr SPRN_DSRR1,r9; \ | ||
253 | lwz r9,GPR9(r11); \ | ||
254 | lwz r12,GPR12(r11); \ | ||
255 | mtspr DEBUG_SPRG,r8; \ | ||
256 | BOOKE_LOAD_EXC_LEVEL_STACK(DEBUG); /* r8 points to the debug stack */ \ | ||
257 | lwz r10,GPR10-INT_FRAME_SIZE(r8); \ | ||
258 | lwz r11,GPR11-INT_FRAME_SIZE(r8); \ | ||
259 | mfspr r8,DEBUG_SPRG; \ | ||
260 | \ | ||
261 | RFDI; \ | ||
262 | b .; \ | ||
263 | \ | ||
264 | /* continue normal handling for a critical exception... */ \ | ||
265 | 2: mfspr r4,SPRN_DBSR; \ | ||
266 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
267 | EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, debug_transfer_to_handler, ret_from_debug_exc) | ||
268 | #else | ||
269 | #define DEBUG_EXCEPTION \ | ||
270 | START_EXCEPTION(Debug); \ | ||
271 | CRITICAL_EXCEPTION_PROLOG; \ | ||
272 | \ | ||
273 | /* \ | ||
274 | * If there is a single step or branch-taken exception in an \ | ||
275 | * exception entry sequence, it was probably meant to apply to \ | ||
276 | * the code where the exception occurred (since exception entry \ | ||
277 | * doesn't turn off DE automatically). We simulate the effect \ | ||
278 | * of turning off DE on entry to an exception handler by turning \ | ||
279 | * off DE in the CSRR1 value and clearing the debug status. \ | ||
280 | */ \ | ||
281 | mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \ | ||
282 | andis. r10,r10,DBSR_IC@h; \ | ||
283 | beq+ 2f; \ | ||
284 | \ | ||
285 | lis r10,KERNELBASE@h; /* check if exception in vectors */ \ | ||
286 | ori r10,r10,KERNELBASE@l; \ | ||
287 | cmplw r12,r10; \ | ||
288 | blt+ 2f; /* addr below exception vectors */ \ | ||
289 | \ | ||
290 | lis r10,Debug@h; \ | ||
291 | ori r10,r10,Debug@l; \ | ||
292 | cmplw r12,r10; \ | ||
293 | bgt+ 2f; /* addr above exception vectors */ \ | ||
294 | \ | ||
295 | /* here it looks like we got an inappropriate debug exception. */ \ | ||
296 | 1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CSRR1 value */ \ | ||
297 | lis r10,DBSR_IC@h; /* clear the IC event */ \ | ||
298 | mtspr SPRN_DBSR,r10; \ | ||
299 | /* restore state and get out */ \ | ||
300 | lwz r10,_CCR(r11); \ | ||
301 | lwz r0,GPR0(r11); \ | ||
302 | lwz r1,GPR1(r11); \ | ||
303 | mtcrf 0x80,r10; \ | ||
304 | mtspr SPRN_CSRR0,r12; \ | ||
305 | mtspr SPRN_CSRR1,r9; \ | ||
306 | lwz r9,GPR9(r11); \ | ||
307 | lwz r12,GPR12(r11); \ | ||
308 | mtspr CRIT_SPRG,r8; \ | ||
309 | BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \ | ||
310 | lwz r10,GPR10-INT_FRAME_SIZE(r8); \ | ||
311 | lwz r11,GPR11-INT_FRAME_SIZE(r8); \ | ||
312 | mfspr r8,CRIT_SPRG; \ | ||
313 | \ | ||
314 | rfci; \ | ||
315 | b .; \ | ||
316 | \ | ||
317 | /* continue normal handling for a critical exception... */ \ | ||
318 | 2: mfspr r4,SPRN_DBSR; \ | ||
319 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
320 | EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc) | ||
321 | #endif | ||
322 | |||
323 | #define INSTRUCTION_STORAGE_EXCEPTION \ | ||
324 | START_EXCEPTION(InstructionStorage) \ | ||
325 | NORMAL_EXCEPTION_PROLOG; \ | ||
326 | mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \ | ||
327 | stw r5,_ESR(r11); \ | ||
328 | mr r4,r12; /* Pass SRR0 as arg2 */ \ | ||
329 | li r5,0; /* Pass zero as arg3 */ \ | ||
330 | EXC_XFER_EE_LITE(0x0400, handle_page_fault) | ||
331 | |||
332 | #define ALIGNMENT_EXCEPTION \ | ||
333 | START_EXCEPTION(Alignment) \ | ||
334 | NORMAL_EXCEPTION_PROLOG; \ | ||
335 | mfspr r4,SPRN_DEAR; /* Grab the DEAR and save it */ \ | ||
336 | stw r4,_DEAR(r11); \ | ||
337 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
338 | EXC_XFER_EE(0x0600, alignment_exception) | ||
339 | |||
340 | #define PROGRAM_EXCEPTION \ | ||
341 | START_EXCEPTION(Program) \ | ||
342 | NORMAL_EXCEPTION_PROLOG; \ | ||
343 | mfspr r4,SPRN_ESR; /* Grab the ESR and save it */ \ | ||
344 | stw r4,_ESR(r11); \ | ||
345 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
346 | EXC_XFER_STD(0x0700, program_check_exception) | ||
347 | |||
348 | #define DECREMENTER_EXCEPTION \ | ||
349 | START_EXCEPTION(Decrementer) \ | ||
350 | NORMAL_EXCEPTION_PROLOG; \ | ||
351 | lis r0,TSR_DIS@h; /* Setup the DEC interrupt mask */ \ | ||
352 | mtspr SPRN_TSR,r0; /* Clear the DEC interrupt */ \ | ||
353 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
354 | EXC_XFER_LITE(0x0900, timer_interrupt) | ||
355 | |||
356 | #define FP_UNAVAILABLE_EXCEPTION \ | ||
357 | START_EXCEPTION(FloatingPointUnavailable) \ | ||
358 | NORMAL_EXCEPTION_PROLOG; \ | ||
359 | bne load_up_fpu; /* if from user, just load it up */ \ | ||
360 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
361 | EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception) | ||
362 | |||
363 | #endif /* __HEAD_BOOKE_H__ */ | ||
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 8d60fa99fc4b..dd86bbed7627 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/kernel/head_fsl_booke.S | ||
3 | * | ||
4 | * Kernel execution entry point code. | 2 | * Kernel execution entry point code. |
5 | * | 3 | * |
6 | * Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org> | 4 | * Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org> |
@@ -316,6 +314,7 @@ skpinv: addi r6,r6,1 /* Increment */ | |||
316 | */ | 314 | */ |
317 | lis r2,DBCR0_IDM@h | 315 | lis r2,DBCR0_IDM@h |
318 | mtspr SPRN_DBCR0,r2 | 316 | mtspr SPRN_DBCR0,r2 |
317 | isync | ||
319 | /* clear any residual debug events */ | 318 | /* clear any residual debug events */ |
320 | li r2,-1 | 319 | li r2,-1 |
321 | mtspr SPRN_DBSR,r2 | 320 | mtspr SPRN_DBSR,r2 |
@@ -1002,12 +1001,15 @@ _GLOBAL(giveup_fpu) | |||
1002 | _GLOBAL(abort) | 1001 | _GLOBAL(abort) |
1003 | li r13,0 | 1002 | li r13,0 |
1004 | mtspr SPRN_DBCR0,r13 /* disable all debug events */ | 1003 | mtspr SPRN_DBCR0,r13 /* disable all debug events */ |
1004 | isync | ||
1005 | mfmsr r13 | 1005 | mfmsr r13 |
1006 | ori r13,r13,MSR_DE@l /* Enable Debug Events */ | 1006 | ori r13,r13,MSR_DE@l /* Enable Debug Events */ |
1007 | mtmsr r13 | 1007 | mtmsr r13 |
1008 | isync | ||
1008 | mfspr r13,SPRN_DBCR0 | 1009 | mfspr r13,SPRN_DBCR0 |
1009 | lis r13,(DBCR0_IDM|DBCR0_RST_CHIP)@h | 1010 | lis r13,(DBCR0_IDM|DBCR0_RST_CHIP)@h |
1010 | mtspr SPRN_DBCR0,r13 | 1011 | mtspr SPRN_DBCR0,r13 |
1012 | isync | ||
1011 | 1013 | ||
1012 | _GLOBAL(set_context) | 1014 | _GLOBAL(set_context) |
1013 | 1015 | ||
diff --git a/arch/powerpc/kernel/idle_64.c b/arch/powerpc/kernel/idle.c index b879d3057ef8..e9f321d74d85 100644 --- a/arch/powerpc/kernel/idle_64.c +++ b/arch/powerpc/kernel/idle.c | |||
@@ -2,13 +2,17 @@ | |||
2 | * Idle daemon for PowerPC. Idle daemon will handle any action | 2 | * Idle daemon for PowerPC. Idle daemon will handle any action |
3 | * that needs to be taken when the system becomes idle. | 3 | * that needs to be taken when the system becomes idle. |
4 | * | 4 | * |
5 | * Originally Written by Cort Dougan (cort@cs.nmt.edu) | 5 | * Originally written by Cort Dougan (cort@cs.nmt.edu). |
6 | * Subsequent 32-bit hacking by Tom Rini, Armin Kuster, | ||
7 | * Paul Mackerras and others. | ||
6 | * | 8 | * |
7 | * iSeries supported added by Mike Corrigan <mikejc@us.ibm.com> | 9 | * iSeries supported added by Mike Corrigan <mikejc@us.ibm.com> |
8 | * | 10 | * |
9 | * Additional shared processor, SMT, and firmware support | 11 | * Additional shared processor, SMT, and firmware support |
10 | * Copyright (c) 2003 Dave Engebretsen <engebret@us.ibm.com> | 12 | * Copyright (c) 2003 Dave Engebretsen <engebret@us.ibm.com> |
11 | * | 13 | * |
14 | * 32-bit and 64-bit versions merged by Paul Mackerras <paulus@samba.org> | ||
15 | * | ||
12 | * This program is free software; you can redistribute it and/or | 16 | * This program is free software; you can redistribute it and/or |
13 | * modify it under the terms of the GNU General Public License | 17 | * modify it under the terms of the GNU General Public License |
14 | * as published by the Free Software Foundation; either version | 18 | * as published by the Free Software Foundation; either version |
@@ -29,18 +33,43 @@ | |||
29 | #include <asm/machdep.h> | 33 | #include <asm/machdep.h> |
30 | #include <asm/smp.h> | 34 | #include <asm/smp.h> |
31 | 35 | ||
32 | extern void power4_idle(void); | 36 | #ifdef CONFIG_HOTPLUG_CPU |
37 | #define cpu_should_die() (cpu_is_offline(smp_processor_id()) && \ | ||
38 | system_state == SYSTEM_RUNNING) | ||
39 | #else | ||
40 | #define cpu_should_die() 0 | ||
41 | #endif | ||
33 | 42 | ||
34 | void default_idle(void) | 43 | /* |
44 | * The body of the idle task. | ||
45 | */ | ||
46 | void cpu_idle(void) | ||
35 | { | 47 | { |
36 | unsigned int cpu = smp_processor_id(); | 48 | if (ppc_md.idle_loop) |
37 | set_thread_flag(TIF_POLLING_NRFLAG); | 49 | ppc_md.idle_loop(); /* doesn't return */ |
38 | 50 | ||
51 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
39 | while (1) { | 52 | while (1) { |
40 | if (!need_resched()) { | 53 | ppc64_runlatch_off(); |
41 | while (!need_resched() && !cpu_is_offline(cpu)) { | ||
42 | ppc64_runlatch_off(); | ||
43 | 54 | ||
55 | while (!need_resched() && !cpu_should_die()) { | ||
56 | if (ppc_md.power_save) { | ||
57 | clear_thread_flag(TIF_POLLING_NRFLAG); | ||
58 | /* | ||
59 | * smp_mb is so clearing of TIF_POLLING_NRFLAG | ||
60 | * is ordered w.r.t. need_resched() test. | ||
61 | */ | ||
62 | smp_mb(); | ||
63 | local_irq_disable(); | ||
64 | |||
65 | /* check again after disabling irqs */ | ||
66 | if (!need_resched() && !cpu_should_die()) | ||
67 | ppc_md.power_save(); | ||
68 | |||
69 | local_irq_enable(); | ||
70 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
71 | |||
72 | } else { | ||
44 | /* | 73 | /* |
45 | * Go into low thread priority and possibly | 74 | * Go into low thread priority and possibly |
46 | * low power mode. | 75 | * low power mode. |
@@ -48,46 +77,18 @@ void default_idle(void) | |||
48 | HMT_low(); | 77 | HMT_low(); |
49 | HMT_very_low(); | 78 | HMT_very_low(); |
50 | } | 79 | } |
51 | |||
52 | HMT_medium(); | ||
53 | } | 80 | } |
54 | 81 | ||
82 | HMT_medium(); | ||
55 | ppc64_runlatch_on(); | 83 | ppc64_runlatch_on(); |
84 | if (cpu_should_die()) | ||
85 | cpu_die(); | ||
56 | preempt_enable_no_resched(); | 86 | preempt_enable_no_resched(); |
57 | schedule(); | 87 | schedule(); |
58 | preempt_disable(); | 88 | preempt_disable(); |
59 | if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) | ||
60 | cpu_die(); | ||
61 | } | 89 | } |
62 | } | 90 | } |
63 | 91 | ||
64 | void native_idle(void) | ||
65 | { | ||
66 | while (1) { | ||
67 | ppc64_runlatch_off(); | ||
68 | |||
69 | if (!need_resched()) | ||
70 | power4_idle(); | ||
71 | |||
72 | if (need_resched()) { | ||
73 | ppc64_runlatch_on(); | ||
74 | preempt_enable_no_resched(); | ||
75 | schedule(); | ||
76 | preempt_disable(); | ||
77 | } | ||
78 | |||
79 | if (cpu_is_offline(smp_processor_id()) && | ||
80 | system_state == SYSTEM_RUNNING) | ||
81 | cpu_die(); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | void cpu_idle(void) | ||
86 | { | ||
87 | BUG_ON(NULL == ppc_md.idle_loop); | ||
88 | ppc_md.idle_loop(); | ||
89 | } | ||
90 | |||
91 | int powersave_nap; | 92 | int powersave_nap; |
92 | 93 | ||
93 | #ifdef CONFIG_SYSCTL | 94 | #ifdef CONFIG_SYSCTL |
diff --git a/arch/powerpc/kernel/idle_6xx.S b/arch/powerpc/kernel/idle_6xx.S index 444fdcc769f1..12a4efbaa08f 100644 --- a/arch/powerpc/kernel/idle_6xx.S +++ b/arch/powerpc/kernel/idle_6xx.S | |||
@@ -87,19 +87,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP) | |||
87 | cmpwi 0,r3,0 | 87 | cmpwi 0,r3,0 |
88 | beqlr | 88 | beqlr |
89 | 89 | ||
90 | /* Clear MSR:EE */ | ||
91 | mfmsr r7 | ||
92 | rlwinm r0,r7,0,17,15 | ||
93 | mtmsr r0 | ||
94 | |||
95 | /* Check current_thread_info()->flags */ | ||
96 | rlwinm r4,r1,0,0,18 | ||
97 | lwz r4,TI_FLAGS(r4) | ||
98 | andi. r0,r4,_TIF_NEED_RESCHED | ||
99 | beq 1f | ||
100 | mtmsr r7 /* out of line this ? */ | ||
101 | blr | ||
102 | 1: | ||
103 | /* Some pre-nap cleanups needed on some CPUs */ | 90 | /* Some pre-nap cleanups needed on some CPUs */ |
104 | andis. r0,r3,HID0_NAP@h | 91 | andis. r0,r3,HID0_NAP@h |
105 | beq 2f | 92 | beq 2f |
@@ -157,7 +144,8 @@ BEGIN_FTR_SECTION | |||
157 | DSSALL | 144 | DSSALL |
158 | sync | 145 | sync |
159 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | 146 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) |
160 | ori r7,r7,MSR_EE /* Could be ommited (already set) */ | 147 | mfmsr r7 |
148 | ori r7,r7,MSR_EE | ||
161 | oris r7,r7,MSR_POW@h | 149 | oris r7,r7,MSR_POW@h |
162 | sync | 150 | sync |
163 | isync | 151 | isync |
@@ -220,8 +208,6 @@ _GLOBAL(nap_save_msscr0) | |||
220 | _GLOBAL(nap_save_hid1) | 208 | _GLOBAL(nap_save_hid1) |
221 | .space 4*NR_CPUS | 209 | .space 4*NR_CPUS |
222 | 210 | ||
223 | _GLOBAL(powersave_nap) | ||
224 | .long 0 | ||
225 | _GLOBAL(powersave_lowspeed) | 211 | _GLOBAL(powersave_lowspeed) |
226 | .long 0 | 212 | .long 0 |
227 | 213 | ||
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S index c16b4afab582..6dad1c02496e 100644 --- a/arch/powerpc/kernel/idle_power4.S +++ b/arch/powerpc/kernel/idle_power4.S | |||
@@ -1,11 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * This file contains the power_save function for 6xx & 7xxx CPUs | 2 | * This file contains the power_save function for 970-family CPUs. |
3 | * rewritten in assembler | ||
4 | * | ||
5 | * Warning ! This code assumes that if your machine has a 750fx | ||
6 | * it will have PLL 1 set to low speed mode (used during NAP/DOZE). | ||
7 | * if this is not the case some additional changes will have to | ||
8 | * be done to check a runtime var (a bit like powersave-nap) | ||
9 | * | 3 | * |
10 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
11 | * modify it under the terms of the GNU General Public License | 5 | * modify it under the terms of the GNU General Public License |
@@ -26,49 +20,23 @@ | |||
26 | 20 | ||
27 | .text | 21 | .text |
28 | 22 | ||
29 | /* | ||
30 | * Here is the power_save_6xx function. This could eventually be | ||
31 | * split into several functions & changing the function pointer | ||
32 | * depending on the various features. | ||
33 | */ | ||
34 | _GLOBAL(power4_idle) | 23 | _GLOBAL(power4_idle) |
35 | BEGIN_FTR_SECTION | 24 | BEGIN_FTR_SECTION |
36 | blr | 25 | blr |
37 | END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP) | 26 | END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP) |
38 | /* We must dynamically check for the NAP feature as it | ||
39 | * can be cleared by CPU init after the fixups are done | ||
40 | */ | ||
41 | LOAD_REG_ADDRBASE(r3,cur_cpu_spec) | ||
42 | ld r4,ADDROFF(cur_cpu_spec)(r3) | ||
43 | ld r4,CPU_SPEC_FEATURES(r4) | ||
44 | andi. r0,r4,CPU_FTR_CAN_NAP | ||
45 | beqlr | ||
46 | /* Now check if user or arch enabled NAP mode */ | 27 | /* Now check if user or arch enabled NAP mode */ |
47 | LOAD_REG_ADDRBASE(r3,powersave_nap) | 28 | LOAD_REG_ADDRBASE(r3,powersave_nap) |
48 | lwz r4,ADDROFF(powersave_nap)(r3) | 29 | lwz r4,ADDROFF(powersave_nap)(r3) |
49 | cmpwi 0,r4,0 | 30 | cmpwi 0,r4,0 |
50 | beqlr | 31 | beqlr |
51 | 32 | ||
52 | /* Clear MSR:EE */ | ||
53 | mfmsr r7 | ||
54 | li r4,0 | ||
55 | ori r4,r4,MSR_EE | ||
56 | andc r0,r7,r4 | ||
57 | mtmsrd r0 | ||
58 | |||
59 | /* Check current_thread_info()->flags */ | ||
60 | clrrdi r4,r1,THREAD_SHIFT | ||
61 | ld r4,TI_FLAGS(r4) | ||
62 | andi. r0,r4,_TIF_NEED_RESCHED | ||
63 | beq 1f | ||
64 | mtmsrd r7 /* out of line this ? */ | ||
65 | blr | ||
66 | 1: | ||
67 | /* Go to NAP now */ | 33 | /* Go to NAP now */ |
68 | BEGIN_FTR_SECTION | 34 | BEGIN_FTR_SECTION |
69 | DSSALL | 35 | DSSALL |
70 | sync | 36 | sync |
71 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | 37 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) |
38 | mfmsr r7 | ||
39 | ori r7,r7,MSR_EE | ||
72 | oris r7,r7,MSR_POW@h | 40 | oris r7,r7,MSR_POW@h |
73 | sync | 41 | sync |
74 | isync | 42 | isync |
diff --git a/arch/powerpc/kernel/iomap.c b/arch/powerpc/kernel/iomap.c index 6160c8dbb7c5..fd8214caedee 100644 --- a/arch/powerpc/kernel/iomap.c +++ b/arch/powerpc/kernel/iomap.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/kernel/iomap.c | ||
3 | * | ||
4 | * ppc64 "iomap" interface implementation. | 2 | * ppc64 "iomap" interface implementation. |
5 | * | 3 | * |
6 | * (C) Copyright 2004 Linus Torvalds | 4 | * (C) Copyright 2004 Linus Torvalds |
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 946f3219fd29..d9a7fdef59b9 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/kernel/iommu.c | ||
3 | * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation | 2 | * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation |
4 | * | 3 | * |
5 | * Rewrite, cleanup, new allocation schemes, virtual merging: | 4 | * Rewrite, cleanup, new allocation schemes, virtual merging: |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index d1fffce86df9..bb5c9501234c 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/kernel/irq.c | ||
3 | * | ||
4 | * Derived from arch/i386/kernel/irq.c | 2 | * Derived from arch/i386/kernel/irq.c |
5 | * Copyright (C) 1992 Linus Torvalds | 3 | * Copyright (C) 1992 Linus Torvalds |
6 | * Adapted from arch/i386 by Gary Thomas | 4 | * Adapted from arch/i386 by Gary Thomas |
@@ -137,9 +135,8 @@ skip: | |||
137 | #ifdef CONFIG_TAU_INT | 135 | #ifdef CONFIG_TAU_INT |
138 | if (tau_initialized){ | 136 | if (tau_initialized){ |
139 | seq_puts(p, "TAU: "); | 137 | seq_puts(p, "TAU: "); |
140 | for (j = 0; j < NR_CPUS; j++) | 138 | for_each_online_cpu(j) |
141 | if (cpu_online(j)) | 139 | seq_printf(p, "%10u ", tau_interrupts(j)); |
142 | seq_printf(p, "%10u ", tau_interrupts(j)); | ||
143 | seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); | 140 | seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); |
144 | } | 141 | } |
145 | #endif | 142 | #endif |
@@ -371,6 +368,7 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq) | |||
371 | return NO_IRQ; | 368 | return NO_IRQ; |
372 | 369 | ||
373 | } | 370 | } |
371 | #endif /* CONFIG_PPC64 */ | ||
374 | 372 | ||
375 | #ifdef CONFIG_IRQSTACKS | 373 | #ifdef CONFIG_IRQSTACKS |
376 | struct thread_info *softirq_ctx[NR_CPUS]; | 374 | struct thread_info *softirq_ctx[NR_CPUS]; |
@@ -381,7 +379,7 @@ void irq_ctx_init(void) | |||
381 | struct thread_info *tp; | 379 | struct thread_info *tp; |
382 | int i; | 380 | int i; |
383 | 381 | ||
384 | for_each_cpu(i) { | 382 | for_each_possible_cpu(i) { |
385 | memset((void *)softirq_ctx[i], 0, THREAD_SIZE); | 383 | memset((void *)softirq_ctx[i], 0, THREAD_SIZE); |
386 | tp = softirq_ctx[i]; | 384 | tp = softirq_ctx[i]; |
387 | tp->cpu = i; | 385 | tp->cpu = i; |
@@ -394,10 +392,24 @@ void irq_ctx_init(void) | |||
394 | } | 392 | } |
395 | } | 393 | } |
396 | 394 | ||
395 | static inline void do_softirq_onstack(void) | ||
396 | { | ||
397 | struct thread_info *curtp, *irqtp; | ||
398 | |||
399 | curtp = current_thread_info(); | ||
400 | irqtp = softirq_ctx[smp_processor_id()]; | ||
401 | irqtp->task = curtp->task; | ||
402 | call_do_softirq(irqtp); | ||
403 | irqtp->task = NULL; | ||
404 | } | ||
405 | |||
406 | #else | ||
407 | #define do_softirq_onstack() __do_softirq() | ||
408 | #endif /* CONFIG_IRQSTACKS */ | ||
409 | |||
397 | void do_softirq(void) | 410 | void do_softirq(void) |
398 | { | 411 | { |
399 | unsigned long flags; | 412 | unsigned long flags; |
400 | struct thread_info *curtp, *irqtp; | ||
401 | 413 | ||
402 | if (in_interrupt()) | 414 | if (in_interrupt()) |
403 | return; | 415 | return; |
@@ -405,19 +417,18 @@ void do_softirq(void) | |||
405 | local_irq_save(flags); | 417 | local_irq_save(flags); |
406 | 418 | ||
407 | if (local_softirq_pending()) { | 419 | if (local_softirq_pending()) { |
408 | curtp = current_thread_info(); | 420 | account_system_vtime(current); |
409 | irqtp = softirq_ctx[smp_processor_id()]; | 421 | local_bh_disable(); |
410 | irqtp->task = curtp->task; | 422 | do_softirq_onstack(); |
411 | call_do_softirq(irqtp); | 423 | account_system_vtime(current); |
412 | irqtp->task = NULL; | 424 | __local_bh_enable(); |
413 | } | 425 | } |
414 | 426 | ||
415 | local_irq_restore(flags); | 427 | local_irq_restore(flags); |
416 | } | 428 | } |
417 | EXPORT_SYMBOL(do_softirq); | 429 | EXPORT_SYMBOL(do_softirq); |
418 | 430 | ||
419 | #endif /* CONFIG_IRQSTACKS */ | 431 | #ifdef CONFIG_PPC64 |
420 | |||
421 | static int __init setup_noirqdistrib(char *str) | 432 | static int __init setup_noirqdistrib(char *str) |
422 | { | 433 | { |
423 | distribute_irqs = 0; | 434 | distribute_irqs = 0; |
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index cfab48566db1..ad7a90212204 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
@@ -1,6 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Kernel Probes (KProbes) | 2 | * Kernel Probes (KProbes) |
3 | * arch/ppc64/kernel/kprobes.c | ||
4 | * | 3 | * |
5 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
@@ -31,9 +30,11 @@ | |||
31 | #include <linux/kprobes.h> | 30 | #include <linux/kprobes.h> |
32 | #include <linux/ptrace.h> | 31 | #include <linux/ptrace.h> |
33 | #include <linux/preempt.h> | 32 | #include <linux/preempt.h> |
33 | #include <linux/module.h> | ||
34 | #include <asm/cacheflush.h> | 34 | #include <asm/cacheflush.h> |
35 | #include <asm/kdebug.h> | 35 | #include <asm/kdebug.h> |
36 | #include <asm/sstep.h> | 36 | #include <asm/sstep.h> |
37 | #include <asm/uaccess.h> | ||
37 | 38 | ||
38 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; | 39 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; |
39 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | 40 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); |
@@ -82,9 +83,9 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) | |||
82 | 83 | ||
83 | void __kprobes arch_remove_kprobe(struct kprobe *p) | 84 | void __kprobes arch_remove_kprobe(struct kprobe *p) |
84 | { | 85 | { |
85 | down(&kprobe_mutex); | 86 | mutex_lock(&kprobe_mutex); |
86 | free_insn_slot(p->ainsn.insn); | 87 | free_insn_slot(p->ainsn.insn); |
87 | up(&kprobe_mutex); | 88 | mutex_unlock(&kprobe_mutex); |
88 | } | 89 | } |
89 | 90 | ||
90 | static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | 91 | static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) |
@@ -373,17 +374,62 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) | |||
373 | { | 374 | { |
374 | struct kprobe *cur = kprobe_running(); | 375 | struct kprobe *cur = kprobe_running(); |
375 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | 376 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); |
376 | 377 | const struct exception_table_entry *entry; | |
377 | if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) | 378 | |
378 | return 1; | 379 | switch(kcb->kprobe_status) { |
379 | 380 | case KPROBE_HIT_SS: | |
380 | if (kcb->kprobe_status & KPROBE_HIT_SS) { | 381 | case KPROBE_REENTER: |
381 | resume_execution(cur, regs); | 382 | /* |
383 | * We are here because the instruction being single | ||
384 | * stepped caused a page fault. We reset the current | ||
385 | * kprobe and the nip points back to the probe address | ||
386 | * and allow the page fault handler to continue as a | ||
387 | * normal page fault. | ||
388 | */ | ||
389 | regs->nip = (unsigned long)cur->addr; | ||
382 | regs->msr &= ~MSR_SE; | 390 | regs->msr &= ~MSR_SE; |
383 | regs->msr |= kcb->kprobe_saved_msr; | 391 | regs->msr |= kcb->kprobe_saved_msr; |
384 | 392 | if (kcb->kprobe_status == KPROBE_REENTER) | |
385 | reset_current_kprobe(); | 393 | restore_previous_kprobe(kcb); |
394 | else | ||
395 | reset_current_kprobe(); | ||
386 | preempt_enable_no_resched(); | 396 | preempt_enable_no_resched(); |
397 | break; | ||
398 | case KPROBE_HIT_ACTIVE: | ||
399 | case KPROBE_HIT_SSDONE: | ||
400 | /* | ||
401 | * We increment the nmissed count for accounting, | ||
402 | * we can also use npre/npostfault count for accouting | ||
403 | * these specific fault cases. | ||
404 | */ | ||
405 | kprobes_inc_nmissed_count(cur); | ||
406 | |||
407 | /* | ||
408 | * We come here because instructions in the pre/post | ||
409 | * handler caused the page_fault, this could happen | ||
410 | * if handler tries to access user space by | ||
411 | * copy_from_user(), get_user() etc. Let the | ||
412 | * user-specified handler try to fix it first. | ||
413 | */ | ||
414 | if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) | ||
415 | return 1; | ||
416 | |||
417 | /* | ||
418 | * In case the user-specified fault handler returned | ||
419 | * zero, try to fix up. | ||
420 | */ | ||
421 | if ((entry = search_exception_tables(regs->nip)) != NULL) { | ||
422 | regs->nip = entry->fixup; | ||
423 | return 1; | ||
424 | } | ||
425 | |||
426 | /* | ||
427 | * fixup_exception() could not handle it, | ||
428 | * Let do_page_fault() fix it. | ||
429 | */ | ||
430 | break; | ||
431 | default: | ||
432 | break; | ||
387 | } | 433 | } |
388 | return 0; | 434 | return 0; |
389 | } | 435 | } |
@@ -397,6 +443,9 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, | |||
397 | struct die_args *args = (struct die_args *)data; | 443 | struct die_args *args = (struct die_args *)data; |
398 | int ret = NOTIFY_DONE; | 444 | int ret = NOTIFY_DONE; |
399 | 445 | ||
446 | if (args->regs && user_mode(args->regs)) | ||
447 | return ret; | ||
448 | |||
400 | switch (val) { | 449 | switch (val) { |
401 | case DIE_BPT: | 450 | case DIE_BPT: |
402 | if (kprobe_handler(args->regs)) | 451 | if (kprobe_handler(args->regs)) |
diff --git a/arch/powerpc/kernel/l2cr_6xx.S b/arch/powerpc/kernel/l2cr_6xx.S new file mode 100644 index 000000000000..d7f4e982b539 --- /dev/null +++ b/arch/powerpc/kernel/l2cr_6xx.S | |||
@@ -0,0 +1,471 @@ | |||
1 | /* | ||
2 | L2CR functions | ||
3 | Copyright © 1997-1998 by PowerLogix R & D, Inc. | ||
4 | |||
5 | This program is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published by | ||
7 | the Free Software Foundation; either version 2 of the License, or | ||
8 | (at your option) any later version. | ||
9 | |||
10 | This program is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
18 | */ | ||
19 | /* | ||
20 | Thur, Dec. 12, 1998. | ||
21 | - First public release, contributed by PowerLogix. | ||
22 | *********** | ||
23 | Sat, Aug. 7, 1999. | ||
24 | - Terry: Made sure code disabled interrupts before running. (Previously | ||
25 | it was assumed interrupts were already disabled). | ||
26 | - Terry: Updated for tentative G4 support. 4MB of memory is now flushed | ||
27 | instead of 2MB. (Prob. only 3 is necessary). | ||
28 | - Terry: Updated for workaround to HID0[DPM] processor bug | ||
29 | during global invalidates. | ||
30 | *********** | ||
31 | Thu, July 13, 2000. | ||
32 | - Terry: Added isync to correct for an errata. | ||
33 | |||
34 | 22 August 2001. | ||
35 | - DanM: Finally added the 7450 patch I've had for the past | ||
36 | several months. The L2CR is similar, but I'm going | ||
37 | to assume the user of this functions knows what they | ||
38 | are doing. | ||
39 | |||
40 | Author: Terry Greeniaus (tgree@phys.ualberta.ca) | ||
41 | Please e-mail updates to this file to me, thanks! | ||
42 | */ | ||
43 | #include <linux/config.h> | ||
44 | #include <asm/processor.h> | ||
45 | #include <asm/cputable.h> | ||
46 | #include <asm/ppc_asm.h> | ||
47 | #include <asm/cache.h> | ||
48 | #include <asm/page.h> | ||
49 | |||
50 | /* Usage: | ||
51 | |||
52 | When setting the L2CR register, you must do a few special | ||
53 | things. If you are enabling the cache, you must perform a | ||
54 | global invalidate. If you are disabling the cache, you must | ||
55 | flush the cache contents first. This routine takes care of | ||
56 | doing these things. When first enabling the cache, make sure | ||
57 | you pass in the L2CR you want, as well as passing in the | ||
58 | global invalidate bit set. A global invalidate will only be | ||
59 | performed if the L2I bit is set in applyThis. When enabling | ||
60 | the cache, you should also set the L2E bit in applyThis. If | ||
61 | you want to modify the L2CR contents after the cache has been | ||
62 | enabled, the recommended procedure is to first call | ||
63 | __setL2CR(0) to disable the cache and then call it again with | ||
64 | the new values for L2CR. Examples: | ||
65 | |||
66 | _setL2CR(0) - disables the cache | ||
67 | _setL2CR(0xB3A04000) - enables my G3 upgrade card: | ||
68 | - L2E set to turn on the cache | ||
69 | - L2SIZ set to 1MB | ||
70 | - L2CLK set to 1:1 | ||
71 | - L2RAM set to pipelined synchronous late-write | ||
72 | - L2I set to perform a global invalidation | ||
73 | - L2OH set to 0.5 nS | ||
74 | - L2DF set because this upgrade card | ||
75 | requires it | ||
76 | |||
77 | A similar call should work for your card. You need to know | ||
78 | the correct setting for your card and then place them in the | ||
79 | fields I have outlined above. Other fields support optional | ||
80 | features, such as L2DO which caches only data, or L2TS which | ||
81 | causes cache pushes from the L1 cache to go to the L2 cache | ||
82 | instead of to main memory. | ||
83 | |||
84 | IMPORTANT: | ||
85 | Starting with the 7450, the bits in this register have moved | ||
86 | or behave differently. The Enable, Parity Enable, Size, | ||
87 | and L2 Invalidate are the only bits that have not moved. | ||
88 | The size is read-only for these processors with internal L2 | ||
89 | cache, and the invalidate is a control as well as status. | ||
90 | -- Dan | ||
91 | |||
92 | */ | ||
93 | /* | ||
94 | * Summary: this procedure ignores the L2I bit in the value passed in, | ||
95 | * flushes the cache if it was already enabled, always invalidates the | ||
96 | * cache, then enables the cache if the L2E bit is set in the value | ||
97 | * passed in. | ||
98 | * -- paulus. | ||
99 | */ | ||
100 | _GLOBAL(_set_L2CR) | ||
101 | /* Make sure this is a 750 or 7400 chip */ | ||
102 | BEGIN_FTR_SECTION | ||
103 | li r3,-1 | ||
104 | blr | ||
105 | END_FTR_SECTION_IFCLR(CPU_FTR_L2CR) | ||
106 | |||
107 | mflr r9 | ||
108 | |||
109 | /* Stop DST streams */ | ||
110 | BEGIN_FTR_SECTION | ||
111 | DSSALL | ||
112 | sync | ||
113 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | ||
114 | |||
115 | /* Turn off interrupts and data relocation. */ | ||
116 | mfmsr r7 /* Save MSR in r7 */ | ||
117 | rlwinm r4,r7,0,17,15 | ||
118 | rlwinm r4,r4,0,28,26 /* Turn off DR bit */ | ||
119 | sync | ||
120 | mtmsr r4 | ||
121 | isync | ||
122 | |||
123 | /* Before we perform the global invalidation, we must disable dynamic | ||
124 | * power management via HID0[DPM] to work around a processor bug where | ||
125 | * DPM can possibly interfere with the state machine in the processor | ||
126 | * that invalidates the L2 cache tags. | ||
127 | */ | ||
128 | mfspr r8,SPRN_HID0 /* Save HID0 in r8 */ | ||
129 | rlwinm r4,r8,0,12,10 /* Turn off HID0[DPM] */ | ||
130 | sync | ||
131 | mtspr SPRN_HID0,r4 /* Disable DPM */ | ||
132 | sync | ||
133 | |||
134 | /* Get the current enable bit of the L2CR into r4 */ | ||
135 | mfspr r4,SPRN_L2CR | ||
136 | |||
137 | /* Tweak some bits */ | ||
138 | rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */ | ||
139 | rlwinm r3,r3,0,11,9 /* Turn off the invalidate bit */ | ||
140 | rlwinm r3,r3,0,1,31 /* Turn off the enable bit */ | ||
141 | |||
142 | /* Check to see if we need to flush */ | ||
143 | rlwinm. r4,r4,0,0,0 | ||
144 | beq 2f | ||
145 | |||
146 | /* Flush the cache. First, read the first 4MB of memory (physical) to | ||
147 | * put new data in the cache. (Actually we only need | ||
148 | * the size of the L2 cache plus the size of the L1 cache, but 4MB will | ||
149 | * cover everything just to be safe). | ||
150 | */ | ||
151 | |||
152 | /**** Might be a good idea to set L2DO here - to prevent instructions | ||
153 | from getting into the cache. But since we invalidate | ||
154 | the next time we enable the cache it doesn't really matter. | ||
155 | Don't do this unless you accomodate all processor variations. | ||
156 | The bit moved on the 7450..... | ||
157 | ****/ | ||
158 | |||
159 | BEGIN_FTR_SECTION | ||
160 | /* Disable L2 prefetch on some 745x and try to ensure | ||
161 | * L2 prefetch engines are idle. As explained by errata | ||
162 | * text, we can't be sure they are, we just hope very hard | ||
163 | * that well be enough (sic !). At least I noticed Apple | ||
164 | * doesn't even bother doing the dcbf's here... | ||
165 | */ | ||
166 | mfspr r4,SPRN_MSSCR0 | ||
167 | rlwinm r4,r4,0,0,29 | ||
168 | sync | ||
169 | mtspr SPRN_MSSCR0,r4 | ||
170 | sync | ||
171 | isync | ||
172 | lis r4,KERNELBASE@h | ||
173 | dcbf 0,r4 | ||
174 | dcbf 0,r4 | ||
175 | dcbf 0,r4 | ||
176 | dcbf 0,r4 | ||
177 | END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) | ||
178 | |||
179 | /* TODO: use HW flush assist when available */ | ||
180 | |||
181 | lis r4,0x0002 | ||
182 | mtctr r4 | ||
183 | li r4,0 | ||
184 | 1: | ||
185 | lwzx r0,r0,r4 | ||
186 | addi r4,r4,32 /* Go to start of next cache line */ | ||
187 | bdnz 1b | ||
188 | isync | ||
189 | |||
190 | /* Now, flush the first 4MB of memory */ | ||
191 | lis r4,0x0002 | ||
192 | mtctr r4 | ||
193 | li r4,0 | ||
194 | sync | ||
195 | 1: | ||
196 | dcbf 0,r4 | ||
197 | addi r4,r4,32 /* Go to start of next cache line */ | ||
198 | bdnz 1b | ||
199 | |||
200 | 2: | ||
201 | /* Set up the L2CR configuration bits (and switch L2 off) */ | ||
202 | /* CPU errata: Make sure the mtspr below is already in the | ||
203 | * L1 icache | ||
204 | */ | ||
205 | b 20f | ||
206 | .balign L1_CACHE_BYTES | ||
207 | 22: | ||
208 | sync | ||
209 | mtspr SPRN_L2CR,r3 | ||
210 | sync | ||
211 | b 23f | ||
212 | 20: | ||
213 | b 21f | ||
214 | 21: sync | ||
215 | isync | ||
216 | b 22b | ||
217 | |||
218 | 23: | ||
219 | /* Perform a global invalidation */ | ||
220 | oris r3,r3,0x0020 | ||
221 | sync | ||
222 | mtspr SPRN_L2CR,r3 | ||
223 | sync | ||
224 | isync /* For errata */ | ||
225 | |||
226 | BEGIN_FTR_SECTION | ||
227 | /* On the 7450, we wait for the L2I bit to clear...... | ||
228 | */ | ||
229 | 10: mfspr r3,SPRN_L2CR | ||
230 | andis. r4,r3,0x0020 | ||
231 | bne 10b | ||
232 | b 11f | ||
233 | END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) | ||
234 | |||
235 | /* Wait for the invalidation to complete */ | ||
236 | 3: mfspr r3,SPRN_L2CR | ||
237 | rlwinm. r4,r3,0,31,31 | ||
238 | bne 3b | ||
239 | |||
240 | 11: rlwinm r3,r3,0,11,9 /* Turn off the L2I bit */ | ||
241 | sync | ||
242 | mtspr SPRN_L2CR,r3 | ||
243 | sync | ||
244 | |||
245 | /* See if we need to enable the cache */ | ||
246 | cmplwi r5,0 | ||
247 | beq 4f | ||
248 | |||
249 | /* Enable the cache */ | ||
250 | oris r3,r3,0x8000 | ||
251 | mtspr SPRN_L2CR,r3 | ||
252 | sync | ||
253 | |||
254 | /* Enable L2 HW prefetch on 744x/745x */ | ||
255 | BEGIN_FTR_SECTION | ||
256 | mfspr r3,SPRN_MSSCR0 | ||
257 | ori r3,r3,3 | ||
258 | sync | ||
259 | mtspr SPRN_MSSCR0,r3 | ||
260 | sync | ||
261 | isync | ||
262 | END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) | ||
263 | 4: | ||
264 | |||
265 | /* Restore HID0[DPM] to whatever it was before */ | ||
266 | sync | ||
267 | mtspr 1008,r8 | ||
268 | sync | ||
269 | |||
270 | /* Restore MSR (restores EE and DR bits to original state) */ | ||
271 | SYNC | ||
272 | mtmsr r7 | ||
273 | isync | ||
274 | |||
275 | mtlr r9 | ||
276 | blr | ||
277 | |||
278 | _GLOBAL(_get_L2CR) | ||
279 | /* Return the L2CR contents */ | ||
280 | li r3,0 | ||
281 | BEGIN_FTR_SECTION | ||
282 | mfspr r3,SPRN_L2CR | ||
283 | END_FTR_SECTION_IFSET(CPU_FTR_L2CR) | ||
284 | blr | ||
285 | |||
286 | |||
287 | /* | ||
288 | * Here is a similar routine for dealing with the L3 cache | ||
289 | * on the 745x family of chips | ||
290 | */ | ||
291 | |||
292 | _GLOBAL(_set_L3CR) | ||
293 | /* Make sure this is a 745x chip */ | ||
294 | BEGIN_FTR_SECTION | ||
295 | li r3,-1 | ||
296 | blr | ||
297 | END_FTR_SECTION_IFCLR(CPU_FTR_L3CR) | ||
298 | |||
299 | /* Turn off interrupts and data relocation. */ | ||
300 | mfmsr r7 /* Save MSR in r7 */ | ||
301 | rlwinm r4,r7,0,17,15 | ||
302 | rlwinm r4,r4,0,28,26 /* Turn off DR bit */ | ||
303 | sync | ||
304 | mtmsr r4 | ||
305 | isync | ||
306 | |||
307 | /* Stop DST streams */ | ||
308 | DSSALL | ||
309 | sync | ||
310 | |||
311 | /* Get the current enable bit of the L3CR into r4 */ | ||
312 | mfspr r4,SPRN_L3CR | ||
313 | |||
314 | /* Tweak some bits */ | ||
315 | rlwinm r5,r3,0,0,0 /* r5 contains the new enable bit */ | ||
316 | rlwinm r3,r3,0,22,20 /* Turn off the invalidate bit */ | ||
317 | rlwinm r3,r3,0,2,31 /* Turn off the enable & PE bits */ | ||
318 | rlwinm r3,r3,0,5,3 /* Turn off the clken bit */ | ||
319 | /* Check to see if we need to flush */ | ||
320 | rlwinm. r4,r4,0,0,0 | ||
321 | beq 2f | ||
322 | |||
323 | /* Flush the cache. | ||
324 | */ | ||
325 | |||
326 | /* TODO: use HW flush assist */ | ||
327 | |||
328 | lis r4,0x0008 | ||
329 | mtctr r4 | ||
330 | li r4,0 | ||
331 | 1: | ||
332 | lwzx r0,r0,r4 | ||
333 | dcbf 0,r4 | ||
334 | addi r4,r4,32 /* Go to start of next cache line */ | ||
335 | bdnz 1b | ||
336 | |||
337 | 2: | ||
338 | /* Set up the L3CR configuration bits (and switch L3 off) */ | ||
339 | sync | ||
340 | mtspr SPRN_L3CR,r3 | ||
341 | sync | ||
342 | |||
343 | oris r3,r3,L3CR_L3RES@h /* Set reserved bit 5 */ | ||
344 | mtspr SPRN_L3CR,r3 | ||
345 | sync | ||
346 | oris r3,r3,L3CR_L3CLKEN@h /* Set clken */ | ||
347 | mtspr SPRN_L3CR,r3 | ||
348 | sync | ||
349 | |||
350 | /* Wait for stabilize */ | ||
351 | li r0,256 | ||
352 | mtctr r0 | ||
353 | 1: bdnz 1b | ||
354 | |||
355 | /* Perform a global invalidation */ | ||
356 | ori r3,r3,0x0400 | ||
357 | sync | ||
358 | mtspr SPRN_L3CR,r3 | ||
359 | sync | ||
360 | isync | ||
361 | |||
362 | /* We wait for the L3I bit to clear...... */ | ||
363 | 10: mfspr r3,SPRN_L3CR | ||
364 | andi. r4,r3,0x0400 | ||
365 | bne 10b | ||
366 | |||
367 | /* Clear CLKEN */ | ||
368 | rlwinm r3,r3,0,5,3 /* Turn off the clken bit */ | ||
369 | mtspr SPRN_L3CR,r3 | ||
370 | sync | ||
371 | |||
372 | /* Wait for stabilize */ | ||
373 | li r0,256 | ||
374 | mtctr r0 | ||
375 | 1: bdnz 1b | ||
376 | |||
377 | /* See if we need to enable the cache */ | ||
378 | cmplwi r5,0 | ||
379 | beq 4f | ||
380 | |||
381 | /* Enable the cache */ | ||
382 | oris r3,r3,(L3CR_L3E | L3CR_L3CLKEN)@h | ||
383 | mtspr SPRN_L3CR,r3 | ||
384 | sync | ||
385 | |||
386 | /* Wait for stabilize */ | ||
387 | li r0,256 | ||
388 | mtctr r0 | ||
389 | 1: bdnz 1b | ||
390 | |||
391 | /* Restore MSR (restores EE and DR bits to original state) */ | ||
392 | 4: SYNC | ||
393 | mtmsr r7 | ||
394 | isync | ||
395 | blr | ||
396 | |||
397 | _GLOBAL(_get_L3CR) | ||
398 | /* Return the L3CR contents */ | ||
399 | li r3,0 | ||
400 | BEGIN_FTR_SECTION | ||
401 | mfspr r3,SPRN_L3CR | ||
402 | END_FTR_SECTION_IFSET(CPU_FTR_L3CR) | ||
403 | blr | ||
404 | |||
405 | /* --- End of PowerLogix code --- | ||
406 | */ | ||
407 | |||
408 | |||
409 | /* flush_disable_L1() - Flush and disable L1 cache | ||
410 | * | ||
411 | * clobbers r0, r3, ctr, cr0 | ||
412 | * Must be called with interrupts disabled and MMU enabled. | ||
413 | */ | ||
414 | _GLOBAL(__flush_disable_L1) | ||
415 | /* Stop pending alitvec streams and memory accesses */ | ||
416 | BEGIN_FTR_SECTION | ||
417 | DSSALL | ||
418 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | ||
419 | sync | ||
420 | |||
421 | /* Load counter to 0x4000 cache lines (512k) and | ||
422 | * load cache with datas | ||
423 | */ | ||
424 | li r3,0x4000 /* 512kB / 32B */ | ||
425 | mtctr r3 | ||
426 | lis r3,KERNELBASE@h | ||
427 | 1: | ||
428 | lwz r0,0(r3) | ||
429 | addi r3,r3,0x0020 /* Go to start of next cache line */ | ||
430 | bdnz 1b | ||
431 | isync | ||
432 | sync | ||
433 | |||
434 | /* Now flush those cache lines */ | ||
435 | li r3,0x4000 /* 512kB / 32B */ | ||
436 | mtctr r3 | ||
437 | lis r3,KERNELBASE@h | ||
438 | 1: | ||
439 | dcbf 0,r3 | ||
440 | addi r3,r3,0x0020 /* Go to start of next cache line */ | ||
441 | bdnz 1b | ||
442 | sync | ||
443 | |||
444 | /* We can now disable the L1 cache (HID0:DCE, HID0:ICE) */ | ||
445 | mfspr r3,SPRN_HID0 | ||
446 | rlwinm r3,r3,0,18,15 | ||
447 | mtspr SPRN_HID0,r3 | ||
448 | sync | ||
449 | isync | ||
450 | blr | ||
451 | |||
452 | /* inval_enable_L1 - Invalidate and enable L1 cache | ||
453 | * | ||
454 | * Assumes L1 is already disabled and MSR:EE is off | ||
455 | * | ||
456 | * clobbers r3 | ||
457 | */ | ||
458 | _GLOBAL(__inval_enable_L1) | ||
459 | /* Enable and then Flash inval the instruction & data cache */ | ||
460 | mfspr r3,SPRN_HID0 | ||
461 | ori r3,r3, HID0_ICE|HID0_ICFI|HID0_DCE|HID0_DCI | ||
462 | sync | ||
463 | isync | ||
464 | mtspr SPRN_HID0,r3 | ||
465 | xori r3,r3, HID0_ICFI|HID0_DCI | ||
466 | mtspr SPRN_HID0,r3 | ||
467 | sync | ||
468 | |||
469 | blr | ||
470 | |||
471 | |||
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index c7a799a09516..6e67b5b49ba1 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c | |||
@@ -37,7 +37,7 @@ static int legacy_serial_console = -1; | |||
37 | static int __init add_legacy_port(struct device_node *np, int want_index, | 37 | static int __init add_legacy_port(struct device_node *np, int want_index, |
38 | int iotype, phys_addr_t base, | 38 | int iotype, phys_addr_t base, |
39 | phys_addr_t taddr, unsigned long irq, | 39 | phys_addr_t taddr, unsigned long irq, |
40 | unsigned int flags) | 40 | upf_t flags) |
41 | { | 41 | { |
42 | u32 *clk, *spd, clock = BASE_BAUD * 16; | 42 | u32 *clk, *spd, clock = BASE_BAUD * 16; |
43 | int index; | 43 | int index; |
@@ -113,7 +113,7 @@ static int __init add_legacy_soc_port(struct device_node *np, | |||
113 | { | 113 | { |
114 | phys_addr_t addr; | 114 | phys_addr_t addr; |
115 | u32 *addrp; | 115 | u32 *addrp; |
116 | unsigned int flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ; | 116 | upf_t flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ; |
117 | 117 | ||
118 | /* We only support ports that have a clock frequency properly | 118 | /* We only support ports that have a clock frequency properly |
119 | * encoded in the device-tree. | 119 | * encoded in the device-tree. |
@@ -236,6 +236,23 @@ static int __init add_legacy_pci_port(struct device_node *np, | |||
236 | } | 236 | } |
237 | #endif | 237 | #endif |
238 | 238 | ||
239 | static void __init setup_legacy_serial_console(int console) | ||
240 | { | ||
241 | struct legacy_serial_info *info = | ||
242 | &legacy_serial_infos[console]; | ||
243 | void __iomem *addr; | ||
244 | |||
245 | if (info->taddr == 0) | ||
246 | return; | ||
247 | addr = ioremap(info->taddr, 0x1000); | ||
248 | if (addr == NULL) | ||
249 | return; | ||
250 | if (info->speed == 0) | ||
251 | info->speed = udbg_probe_uart_speed(addr, info->clock); | ||
252 | DBG("default console speed = %d\n", info->speed); | ||
253 | udbg_init_uart(addr, info->speed, info->clock); | ||
254 | } | ||
255 | |||
239 | /* | 256 | /* |
240 | * This is called very early, as part of setup_system() or eventually | 257 | * This is called very early, as part of setup_system() or eventually |
241 | * setup_arch(), basically before anything else in this file. This function | 258 | * setup_arch(), basically before anything else in this file. This function |
@@ -318,25 +335,8 @@ void __init find_legacy_serial_ports(void) | |||
318 | #endif | 335 | #endif |
319 | 336 | ||
320 | DBG("legacy_serial_console = %d\n", legacy_serial_console); | 337 | DBG("legacy_serial_console = %d\n", legacy_serial_console); |
321 | 338 | if (legacy_serial_console >= 0) | |
322 | /* udbg is 64 bits only for now, that will change soon though ... */ | 339 | setup_legacy_serial_console(legacy_serial_console); |
323 | while (legacy_serial_console >= 0) { | ||
324 | struct legacy_serial_info *info = | ||
325 | &legacy_serial_infos[legacy_serial_console]; | ||
326 | void __iomem *addr; | ||
327 | |||
328 | if (info->taddr == 0) | ||
329 | break; | ||
330 | addr = ioremap(info->taddr, 0x1000); | ||
331 | if (addr == NULL) | ||
332 | break; | ||
333 | if (info->speed == 0) | ||
334 | info->speed = udbg_probe_uart_speed(addr, info->clock); | ||
335 | DBG("default console speed = %d\n", info->speed); | ||
336 | udbg_init_uart(addr, info->speed, info->clock); | ||
337 | break; | ||
338 | } | ||
339 | |||
340 | DBG(" <- find_legacy_serial_port()\n"); | 340 | DBG(" <- find_legacy_serial_port()\n"); |
341 | } | 341 | } |
342 | 342 | ||
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index e789fef4eb8a..1b73508ecb2b 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
@@ -56,7 +56,7 @@ static unsigned long get_purr(void) | |||
56 | unsigned long sum_purr = 0; | 56 | unsigned long sum_purr = 0; |
57 | int cpu; | 57 | int cpu; |
58 | 58 | ||
59 | for_each_cpu(cpu) { | 59 | for_each_possible_cpu(cpu) { |
60 | sum_purr += lppaca[cpu].emulated_time_base; | 60 | sum_purr += lppaca[cpu].emulated_time_base; |
61 | 61 | ||
62 | #ifdef PURR_DEBUG | 62 | #ifdef PURR_DEBUG |
@@ -222,7 +222,7 @@ static unsigned long get_purr(void) | |||
222 | int cpu; | 222 | int cpu; |
223 | struct cpu_usage *cu; | 223 | struct cpu_usage *cu; |
224 | 224 | ||
225 | for_each_cpu(cpu) { | 225 | for_each_possible_cpu(cpu) { |
226 | cu = &per_cpu(cpu_usage_array, cpu); | 226 | cu = &per_cpu(cpu_usage_array, cpu); |
227 | sum_purr += cu->current_tb; | 227 | sum_purr += cu->current_tb; |
228 | } | 228 | } |
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c new file mode 100644 index 000000000000..92f4e5f64f02 --- /dev/null +++ b/arch/powerpc/kernel/module_32.c | |||
@@ -0,0 +1,320 @@ | |||
1 | /* Kernel module help for PPC. | ||
2 | Copyright (C) 2001 Rusty Russell. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2 of the License, or | ||
7 | (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/moduleloader.h> | ||
20 | #include <linux/elf.h> | ||
21 | #include <linux/vmalloc.h> | ||
22 | #include <linux/fs.h> | ||
23 | #include <linux/string.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/cache.h> | ||
26 | |||
27 | #if 0 | ||
28 | #define DEBUGP printk | ||
29 | #else | ||
30 | #define DEBUGP(fmt , ...) | ||
31 | #endif | ||
32 | |||
33 | LIST_HEAD(module_bug_list); | ||
34 | |||
35 | void *module_alloc(unsigned long size) | ||
36 | { | ||
37 | if (size == 0) | ||
38 | return NULL; | ||
39 | return vmalloc(size); | ||
40 | } | ||
41 | |||
42 | /* Free memory returned from module_alloc */ | ||
43 | void module_free(struct module *mod, void *module_region) | ||
44 | { | ||
45 | vfree(module_region); | ||
46 | /* FIXME: If module_region == mod->init_region, trim exception | ||
47 | table entries. */ | ||
48 | } | ||
49 | |||
50 | /* Count how many different relocations (different symbol, different | ||
51 | addend) */ | ||
52 | static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num) | ||
53 | { | ||
54 | unsigned int i, j, ret = 0; | ||
55 | |||
56 | /* Sure, this is order(n^2), but it's usually short, and not | ||
57 | time critical */ | ||
58 | for (i = 0; i < num; i++) { | ||
59 | for (j = 0; j < i; j++) { | ||
60 | /* If this addend appeared before, it's | ||
61 | already been counted */ | ||
62 | if (ELF32_R_SYM(rela[i].r_info) | ||
63 | == ELF32_R_SYM(rela[j].r_info) | ||
64 | && rela[i].r_addend == rela[j].r_addend) | ||
65 | break; | ||
66 | } | ||
67 | if (j == i) ret++; | ||
68 | } | ||
69 | return ret; | ||
70 | } | ||
71 | |||
72 | /* Get the potential trampolines size required of the init and | ||
73 | non-init sections */ | ||
74 | static unsigned long get_plt_size(const Elf32_Ehdr *hdr, | ||
75 | const Elf32_Shdr *sechdrs, | ||
76 | const char *secstrings, | ||
77 | int is_init) | ||
78 | { | ||
79 | unsigned long ret = 0; | ||
80 | unsigned i; | ||
81 | |||
82 | /* Everything marked ALLOC (this includes the exported | ||
83 | symbols) */ | ||
84 | for (i = 1; i < hdr->e_shnum; i++) { | ||
85 | /* If it's called *.init*, and we're not init, we're | ||
86 | not interested */ | ||
87 | if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) | ||
88 | != is_init) | ||
89 | continue; | ||
90 | |||
91 | /* We don't want to look at debug sections. */ | ||
92 | if (strstr(secstrings + sechdrs[i].sh_name, ".debug") != 0) | ||
93 | continue; | ||
94 | |||
95 | if (sechdrs[i].sh_type == SHT_RELA) { | ||
96 | DEBUGP("Found relocations in section %u\n", i); | ||
97 | DEBUGP("Ptr: %p. Number: %u\n", | ||
98 | (void *)hdr + sechdrs[i].sh_offset, | ||
99 | sechdrs[i].sh_size / sizeof(Elf32_Rela)); | ||
100 | ret += count_relocs((void *)hdr | ||
101 | + sechdrs[i].sh_offset, | ||
102 | sechdrs[i].sh_size | ||
103 | / sizeof(Elf32_Rela)) | ||
104 | * sizeof(struct ppc_plt_entry); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | int module_frob_arch_sections(Elf32_Ehdr *hdr, | ||
112 | Elf32_Shdr *sechdrs, | ||
113 | char *secstrings, | ||
114 | struct module *me) | ||
115 | { | ||
116 | unsigned int i; | ||
117 | |||
118 | /* Find .plt and .init.plt sections */ | ||
119 | for (i = 0; i < hdr->e_shnum; i++) { | ||
120 | if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0) | ||
121 | me->arch.init_plt_section = i; | ||
122 | else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0) | ||
123 | me->arch.core_plt_section = i; | ||
124 | } | ||
125 | if (!me->arch.core_plt_section || !me->arch.init_plt_section) { | ||
126 | printk("Module doesn't contain .plt or .init.plt sections.\n"); | ||
127 | return -ENOEXEC; | ||
128 | } | ||
129 | |||
130 | /* Override their sizes */ | ||
131 | sechdrs[me->arch.core_plt_section].sh_size | ||
132 | = get_plt_size(hdr, sechdrs, secstrings, 0); | ||
133 | sechdrs[me->arch.init_plt_section].sh_size | ||
134 | = get_plt_size(hdr, sechdrs, secstrings, 1); | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | int apply_relocate(Elf32_Shdr *sechdrs, | ||
139 | const char *strtab, | ||
140 | unsigned int symindex, | ||
141 | unsigned int relsec, | ||
142 | struct module *module) | ||
143 | { | ||
144 | printk(KERN_ERR "%s: Non-ADD RELOCATION unsupported\n", | ||
145 | module->name); | ||
146 | return -ENOEXEC; | ||
147 | } | ||
148 | |||
149 | static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val) | ||
150 | { | ||
151 | if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16) | ||
152 | && entry->jump[1] == 0x396b0000 + (val & 0xffff)) | ||
153 | return 1; | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | /* Set up a trampoline in the PLT to bounce us to the distant function */ | ||
158 | static uint32_t do_plt_call(void *location, | ||
159 | Elf32_Addr val, | ||
160 | Elf32_Shdr *sechdrs, | ||
161 | struct module *mod) | ||
162 | { | ||
163 | struct ppc_plt_entry *entry; | ||
164 | |||
165 | DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location); | ||
166 | /* Init, or core PLT? */ | ||
167 | if (location >= mod->module_core | ||
168 | && location < mod->module_core + mod->core_size) | ||
169 | entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr; | ||
170 | else | ||
171 | entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr; | ||
172 | |||
173 | /* Find this entry, or if that fails, the next avail. entry */ | ||
174 | while (entry->jump[0]) { | ||
175 | if (entry_matches(entry, val)) return (uint32_t)entry; | ||
176 | entry++; | ||
177 | } | ||
178 | |||
179 | /* Stolen from Paul Mackerras as well... */ | ||
180 | entry->jump[0] = 0x3d600000+((val+0x8000)>>16); /* lis r11,sym@ha */ | ||
181 | entry->jump[1] = 0x396b0000 + (val&0xffff); /* addi r11,r11,sym@l*/ | ||
182 | entry->jump[2] = 0x7d6903a6; /* mtctr r11 */ | ||
183 | entry->jump[3] = 0x4e800420; /* bctr */ | ||
184 | |||
185 | DEBUGP("Initialized plt for 0x%x at %p\n", val, entry); | ||
186 | return (uint32_t)entry; | ||
187 | } | ||
188 | |||
189 | int apply_relocate_add(Elf32_Shdr *sechdrs, | ||
190 | const char *strtab, | ||
191 | unsigned int symindex, | ||
192 | unsigned int relsec, | ||
193 | struct module *module) | ||
194 | { | ||
195 | unsigned int i; | ||
196 | Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; | ||
197 | Elf32_Sym *sym; | ||
198 | uint32_t *location; | ||
199 | uint32_t value; | ||
200 | |||
201 | DEBUGP("Applying ADD relocate section %u to %u\n", relsec, | ||
202 | sechdrs[relsec].sh_info); | ||
203 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { | ||
204 | /* This is where to make the change */ | ||
205 | location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr | ||
206 | + rela[i].r_offset; | ||
207 | /* This is the symbol it is referring to. Note that all | ||
208 | undefined symbols have been resolved. */ | ||
209 | sym = (Elf32_Sym *)sechdrs[symindex].sh_addr | ||
210 | + ELF32_R_SYM(rela[i].r_info); | ||
211 | /* `Everything is relative'. */ | ||
212 | value = sym->st_value + rela[i].r_addend; | ||
213 | |||
214 | switch (ELF32_R_TYPE(rela[i].r_info)) { | ||
215 | case R_PPC_ADDR32: | ||
216 | /* Simply set it */ | ||
217 | *(uint32_t *)location = value; | ||
218 | break; | ||
219 | |||
220 | case R_PPC_ADDR16_LO: | ||
221 | /* Low half of the symbol */ | ||
222 | *(uint16_t *)location = value; | ||
223 | break; | ||
224 | |||
225 | case R_PPC_ADDR16_HA: | ||
226 | /* Sign-adjusted lower 16 bits: PPC ELF ABI says: | ||
227 | (((x >> 16) + ((x & 0x8000) ? 1 : 0))) & 0xFFFF. | ||
228 | This is the same, only sane. | ||
229 | */ | ||
230 | *(uint16_t *)location = (value + 0x8000) >> 16; | ||
231 | break; | ||
232 | |||
233 | case R_PPC_REL24: | ||
234 | if ((int)(value - (uint32_t)location) < -0x02000000 | ||
235 | || (int)(value - (uint32_t)location) >= 0x02000000) | ||
236 | value = do_plt_call(location, value, | ||
237 | sechdrs, module); | ||
238 | |||
239 | /* Only replace bits 2 through 26 */ | ||
240 | DEBUGP("REL24 value = %08X. location = %08X\n", | ||
241 | value, (uint32_t)location); | ||
242 | DEBUGP("Location before: %08X.\n", | ||
243 | *(uint32_t *)location); | ||
244 | *(uint32_t *)location | ||
245 | = (*(uint32_t *)location & ~0x03fffffc) | ||
246 | | ((value - (uint32_t)location) | ||
247 | & 0x03fffffc); | ||
248 | DEBUGP("Location after: %08X.\n", | ||
249 | *(uint32_t *)location); | ||
250 | DEBUGP("ie. jump to %08X+%08X = %08X\n", | ||
251 | *(uint32_t *)location & 0x03fffffc, | ||
252 | (uint32_t)location, | ||
253 | (*(uint32_t *)location & 0x03fffffc) | ||
254 | + (uint32_t)location); | ||
255 | break; | ||
256 | |||
257 | case R_PPC_REL32: | ||
258 | /* 32-bit relative jump. */ | ||
259 | *(uint32_t *)location = value - (uint32_t)location; | ||
260 | break; | ||
261 | |||
262 | default: | ||
263 | printk("%s: unknown ADD relocation: %u\n", | ||
264 | module->name, | ||
265 | ELF32_R_TYPE(rela[i].r_info)); | ||
266 | return -ENOEXEC; | ||
267 | } | ||
268 | } | ||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | int module_finalize(const Elf_Ehdr *hdr, | ||
273 | const Elf_Shdr *sechdrs, | ||
274 | struct module *me) | ||
275 | { | ||
276 | char *secstrings; | ||
277 | unsigned int i; | ||
278 | |||
279 | me->arch.bug_table = NULL; | ||
280 | me->arch.num_bugs = 0; | ||
281 | |||
282 | /* Find the __bug_table section, if present */ | ||
283 | secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | ||
284 | for (i = 1; i < hdr->e_shnum; i++) { | ||
285 | if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) | ||
286 | continue; | ||
287 | me->arch.bug_table = (void *) sechdrs[i].sh_addr; | ||
288 | me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); | ||
289 | break; | ||
290 | } | ||
291 | |||
292 | /* | ||
293 | * Strictly speaking this should have a spinlock to protect against | ||
294 | * traversals, but since we only traverse on BUG()s, a spinlock | ||
295 | * could potentially lead to deadlock and thus be counter-productive. | ||
296 | */ | ||
297 | list_add(&me->arch.bug_list, &module_bug_list); | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | void module_arch_cleanup(struct module *mod) | ||
303 | { | ||
304 | list_del(&mod->arch.bug_list); | ||
305 | } | ||
306 | |||
307 | struct bug_entry *module_find_bug(unsigned long bugaddr) | ||
308 | { | ||
309 | struct mod_arch_specific *mod; | ||
310 | unsigned int i; | ||
311 | struct bug_entry *bug; | ||
312 | |||
313 | list_for_each_entry(mod, &module_bug_list, bug_list) { | ||
314 | bug = mod->bug_table; | ||
315 | for (i = 0; i < mod->num_bugs; ++i, ++bug) | ||
316 | if (bugaddr == bug->bug_addr) | ||
317 | return bug; | ||
318 | } | ||
319 | return NULL; | ||
320 | } | ||
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index fd7db8d542db..ada50aa5b600 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c | |||
@@ -160,7 +160,7 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file, | |||
160 | case IOC_NVRAM_GET_OFFSET: { | 160 | case IOC_NVRAM_GET_OFFSET: { |
161 | int part, offset; | 161 | int part, offset; |
162 | 162 | ||
163 | if (_machine != PLATFORM_POWERMAC) | 163 | if (!machine_is(powermac)) |
164 | return -EINVAL; | 164 | return -EINVAL; |
165 | if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) | 165 | if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) |
166 | return -EFAULT; | 166 | return -EFAULT; |
@@ -174,8 +174,9 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file, | |||
174 | return 0; | 174 | return 0; |
175 | } | 175 | } |
176 | #endif /* CONFIG_PPC_PMAC */ | 176 | #endif /* CONFIG_PPC_PMAC */ |
177 | default: | ||
178 | return -EINVAL; | ||
177 | } | 179 | } |
178 | return -EINVAL; | ||
179 | } | 180 | } |
180 | 181 | ||
181 | struct file_operations nvram_fops = { | 182 | struct file_operations nvram_fops = { |
@@ -443,7 +444,7 @@ static int nvram_setup_partition(void) | |||
443 | * in our nvram, as Apple defined partitions use pretty much | 444 | * in our nvram, as Apple defined partitions use pretty much |
444 | * all of the space | 445 | * all of the space |
445 | */ | 446 | */ |
446 | if (_machine == PLATFORM_POWERMAC) | 447 | if (machine_is(powermac)) |
447 | return -ENOSPC; | 448 | return -ENOSPC; |
448 | 449 | ||
449 | /* see if we have an OS partition that meets our needs. | 450 | /* see if we have an OS partition that meets our needs. |
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index 22d83d4d1af5..9feeeef5a875 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c | |||
@@ -147,15 +147,12 @@ postcore_initcall(of_bus_driver_init); | |||
147 | 147 | ||
148 | int of_register_driver(struct of_platform_driver *drv) | 148 | int of_register_driver(struct of_platform_driver *drv) |
149 | { | 149 | { |
150 | int count = 0; | ||
151 | |||
152 | /* initialize common driver fields */ | 150 | /* initialize common driver fields */ |
153 | drv->driver.name = drv->name; | 151 | drv->driver.name = drv->name; |
154 | drv->driver.bus = &of_platform_bus_type; | 152 | drv->driver.bus = &of_platform_bus_type; |
155 | 153 | ||
156 | /* register with core */ | 154 | /* register with core */ |
157 | count = driver_register(&drv->driver); | 155 | return driver_register(&drv->driver); |
158 | return count ? count : 1; | ||
159 | } | 156 | } |
160 | 157 | ||
161 | void of_unregister_driver(struct of_platform_driver *drv) | 158 | void of_unregister_driver(struct of_platform_driver *drv) |
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index 5d1b708086bd..f505a8827e3e 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c | |||
@@ -56,14 +56,11 @@ struct lppaca lppaca[] = { | |||
56 | * processors. The processor VPD array needs one entry per physical | 56 | * processors. The processor VPD array needs one entry per physical |
57 | * processor (not thread). | 57 | * processor (not thread). |
58 | */ | 58 | */ |
59 | #define PACA_INIT_COMMON(number, start, asrr, asrv) \ | 59 | #define PACA_INIT_COMMON(number) \ |
60 | .lppaca_ptr = &lppaca[number], \ | 60 | .lppaca_ptr = &lppaca[number], \ |
61 | .lock_token = 0x8000, \ | 61 | .lock_token = 0x8000, \ |
62 | .paca_index = (number), /* Paca Index */ \ | 62 | .paca_index = (number), /* Paca Index */ \ |
63 | .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \ | 63 | .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \ |
64 | .stab_real = (asrr), /* Real pointer to segment table */ \ | ||
65 | .stab_addr = (asrv), /* Virt pointer to segment table */ \ | ||
66 | .cpu_start = (start), /* Processor start */ \ | ||
67 | .hw_cpu_id = 0xffff, | 64 | .hw_cpu_id = 0xffff, |
68 | 65 | ||
69 | #ifdef CONFIG_PPC_ISERIES | 66 | #ifdef CONFIG_PPC_ISERIES |
@@ -72,30 +69,20 @@ struct lppaca lppaca[] = { | |||
72 | 69 | ||
73 | #define PACA_INIT(number) \ | 70 | #define PACA_INIT(number) \ |
74 | { \ | 71 | { \ |
75 | PACA_INIT_COMMON(number, 0, 0, 0) \ | 72 | PACA_INIT_COMMON(number) \ |
76 | PACA_INIT_ISERIES(number) \ | ||
77 | } | ||
78 | |||
79 | #define BOOTCPU_PACA_INIT(number) \ | ||
80 | { \ | ||
81 | PACA_INIT_COMMON(number, 1, 0, (u64)&initial_stab) \ | ||
82 | PACA_INIT_ISERIES(number) \ | 73 | PACA_INIT_ISERIES(number) \ |
83 | } | 74 | } |
84 | 75 | ||
85 | #else | 76 | #else |
86 | #define PACA_INIT(number) \ | 77 | #define PACA_INIT(number) \ |
87 | { \ | 78 | { \ |
88 | PACA_INIT_COMMON(number, 0, 0, 0) \ | 79 | PACA_INIT_COMMON(number) \ |
89 | } | 80 | } |
90 | 81 | ||
91 | #define BOOTCPU_PACA_INIT(number) \ | ||
92 | { \ | ||
93 | PACA_INIT_COMMON(number, 1, STAB0_PHYS_ADDR, (u64)&initial_stab) \ | ||
94 | } | ||
95 | #endif | 82 | #endif |
96 | 83 | ||
97 | struct paca_struct paca[] = { | 84 | struct paca_struct paca[] = { |
98 | BOOTCPU_PACA_INIT(0), | 85 | PACA_INIT(0), |
99 | #if NR_CPUS > 1 | 86 | #if NR_CPUS > 1 |
100 | PACA_INIT( 1), PACA_INIT( 2), PACA_INIT( 3), | 87 | PACA_INIT( 1), PACA_INIT( 2), PACA_INIT( 3), |
101 | #if NR_CPUS > 4 | 88 | #if NR_CPUS > 4 |
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 704c846b2b0f..b129d2e4b759 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c | |||
@@ -787,7 +787,7 @@ pci_busdev_to_OF_node(struct pci_bus *bus, int devfn) | |||
787 | * fix has to be done by making the remapping per-host and always | 787 | * fix has to be done by making the remapping per-host and always |
788 | * filling the pci_to_OF map. --BenH | 788 | * filling the pci_to_OF map. --BenH |
789 | */ | 789 | */ |
790 | if (_machine == _MACH_Pmac && busnr >= 0xf0) | 790 | if (machine_is(powermac) && busnr >= 0xf0) |
791 | busnr -= 0xf0; | 791 | busnr -= 0xf0; |
792 | else | 792 | else |
793 | #endif | 793 | #endif |
@@ -1728,7 +1728,7 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) | |||
1728 | * (bus 0 is HT root), we return the AGP one instead. | 1728 | * (bus 0 is HT root), we return the AGP one instead. |
1729 | */ | 1729 | */ |
1730 | #ifdef CONFIG_PPC_PMAC | 1730 | #ifdef CONFIG_PPC_PMAC |
1731 | if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4")) | 1731 | if (machine_is(powermac) && machine_is_compatible("MacRISC4")) |
1732 | if (bus == 0) | 1732 | if (bus == 0) |
1733 | bus = 0xf0; | 1733 | bus = 0xf0; |
1734 | #endif /* CONFIG_PPC_PMAC */ | 1734 | #endif /* CONFIG_PPC_PMAC */ |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index c367520bc1c3..4c4449be81ce 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -78,6 +78,7 @@ int global_phb_number; /* Global phb counter */ | |||
78 | 78 | ||
79 | /* Cached ISA bridge dev. */ | 79 | /* Cached ISA bridge dev. */ |
80 | struct pci_dev *ppc64_isabridge_dev = NULL; | 80 | struct pci_dev *ppc64_isabridge_dev = NULL; |
81 | EXPORT_SYMBOL_GPL(ppc64_isabridge_dev); | ||
81 | 82 | ||
82 | static void fixup_broken_pcnet32(struct pci_dev* dev) | 83 | static void fixup_broken_pcnet32(struct pci_dev* dev) |
83 | { | 84 | { |
@@ -589,7 +590,6 @@ void __devinit scan_phb(struct pci_controller *hose) | |||
589 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | 590 | #endif /* CONFIG_PPC_MULTIPLATFORM */ |
590 | if (mode == PCI_PROBE_NORMAL) | 591 | if (mode == PCI_PROBE_NORMAL) |
591 | hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); | 592 | hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); |
592 | pci_bus_add_devices(bus); | ||
593 | } | 593 | } |
594 | 594 | ||
595 | static int __init pcibios_init(void) | 595 | static int __init pcibios_init(void) |
@@ -608,8 +608,10 @@ static int __init pcibios_init(void) | |||
608 | printk("PCI: Probing PCI hardware\n"); | 608 | printk("PCI: Probing PCI hardware\n"); |
609 | 609 | ||
610 | /* Scan all of the recorded PCI controllers. */ | 610 | /* Scan all of the recorded PCI controllers. */ |
611 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) | 611 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { |
612 | scan_phb(hose); | 612 | scan_phb(hose); |
613 | pci_bus_add_devices(hose->bus); | ||
614 | } | ||
613 | 615 | ||
614 | #ifndef CONFIG_PPC_ISERIES | 616 | #ifndef CONFIG_PPC_ISERIES |
615 | if (pci_probe_only) | 617 | if (pci_probe_only) |
diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c index bdf15dbbf4f0..c336f3e31cff 100644 --- a/arch/powerpc/kernel/pci_iommu.c +++ b/arch/powerpc/kernel/pci_iommu.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/kernel/pci_iommu.c | ||
3 | * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation | 2 | * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation |
4 | * | 3 | * |
5 | * Rewrite, cleanup, new allocation schemes: | 4 | * Rewrite, cleanup, new allocation schemes: |
diff --git a/arch/powerpc/kernel/perfmon_fsl_booke.c b/arch/powerpc/kernel/perfmon_fsl_booke.c new file mode 100644 index 000000000000..32455dfcc36b --- /dev/null +++ b/arch/powerpc/kernel/perfmon_fsl_booke.c | |||
@@ -0,0 +1,222 @@ | |||
1 | /* kernel/perfmon_fsl_booke.c | ||
2 | * Freescale Book-E Performance Monitor code | ||
3 | * | ||
4 | * Author: Andy Fleming | ||
5 | * Copyright (c) 2004 Freescale Semiconductor, Inc | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/errno.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/unistd.h> | ||
19 | #include <linux/ptrace.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/user.h> | ||
22 | #include <linux/a.out.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/config.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/prctl.h> | ||
28 | |||
29 | #include <asm/pgtable.h> | ||
30 | #include <asm/uaccess.h> | ||
31 | #include <asm/system.h> | ||
32 | #include <asm/io.h> | ||
33 | #include <asm/reg.h> | ||
34 | #include <asm/xmon.h> | ||
35 | #include <asm/pmc.h> | ||
36 | |||
37 | static inline u32 get_pmlca(int ctr); | ||
38 | static inline void set_pmlca(int ctr, u32 pmlca); | ||
39 | |||
40 | static inline u32 get_pmlca(int ctr) | ||
41 | { | ||
42 | u32 pmlca; | ||
43 | |||
44 | switch (ctr) { | ||
45 | case 0: | ||
46 | pmlca = mfpmr(PMRN_PMLCA0); | ||
47 | break; | ||
48 | case 1: | ||
49 | pmlca = mfpmr(PMRN_PMLCA1); | ||
50 | break; | ||
51 | case 2: | ||
52 | pmlca = mfpmr(PMRN_PMLCA2); | ||
53 | break; | ||
54 | case 3: | ||
55 | pmlca = mfpmr(PMRN_PMLCA3); | ||
56 | break; | ||
57 | default: | ||
58 | panic("Bad ctr number\n"); | ||
59 | } | ||
60 | |||
61 | return pmlca; | ||
62 | } | ||
63 | |||
64 | static inline void set_pmlca(int ctr, u32 pmlca) | ||
65 | { | ||
66 | switch (ctr) { | ||
67 | case 0: | ||
68 | mtpmr(PMRN_PMLCA0, pmlca); | ||
69 | break; | ||
70 | case 1: | ||
71 | mtpmr(PMRN_PMLCA1, pmlca); | ||
72 | break; | ||
73 | case 2: | ||
74 | mtpmr(PMRN_PMLCA2, pmlca); | ||
75 | break; | ||
76 | case 3: | ||
77 | mtpmr(PMRN_PMLCA3, pmlca); | ||
78 | break; | ||
79 | default: | ||
80 | panic("Bad ctr number\n"); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | void init_pmc_stop(int ctr) | ||
85 | { | ||
86 | u32 pmlca = (PMLCA_FC | PMLCA_FCS | PMLCA_FCU | | ||
87 | PMLCA_FCM1 | PMLCA_FCM0); | ||
88 | u32 pmlcb = 0; | ||
89 | |||
90 | switch (ctr) { | ||
91 | case 0: | ||
92 | mtpmr(PMRN_PMLCA0, pmlca); | ||
93 | mtpmr(PMRN_PMLCB0, pmlcb); | ||
94 | break; | ||
95 | case 1: | ||
96 | mtpmr(PMRN_PMLCA1, pmlca); | ||
97 | mtpmr(PMRN_PMLCB1, pmlcb); | ||
98 | break; | ||
99 | case 2: | ||
100 | mtpmr(PMRN_PMLCA2, pmlca); | ||
101 | mtpmr(PMRN_PMLCB2, pmlcb); | ||
102 | break; | ||
103 | case 3: | ||
104 | mtpmr(PMRN_PMLCA3, pmlca); | ||
105 | mtpmr(PMRN_PMLCB3, pmlcb); | ||
106 | break; | ||
107 | default: | ||
108 | panic("Bad ctr number!\n"); | ||
109 | } | ||
110 | } | ||
111 | |||
112 | void set_pmc_event(int ctr, int event) | ||
113 | { | ||
114 | u32 pmlca; | ||
115 | |||
116 | pmlca = get_pmlca(ctr); | ||
117 | |||
118 | pmlca = (pmlca & ~PMLCA_EVENT_MASK) | | ||
119 | ((event << PMLCA_EVENT_SHIFT) & | ||
120 | PMLCA_EVENT_MASK); | ||
121 | |||
122 | set_pmlca(ctr, pmlca); | ||
123 | } | ||
124 | |||
125 | void set_pmc_user_kernel(int ctr, int user, int kernel) | ||
126 | { | ||
127 | u32 pmlca; | ||
128 | |||
129 | pmlca = get_pmlca(ctr); | ||
130 | |||
131 | if(user) | ||
132 | pmlca &= ~PMLCA_FCU; | ||
133 | else | ||
134 | pmlca |= PMLCA_FCU; | ||
135 | |||
136 | if(kernel) | ||
137 | pmlca &= ~PMLCA_FCS; | ||
138 | else | ||
139 | pmlca |= PMLCA_FCS; | ||
140 | |||
141 | set_pmlca(ctr, pmlca); | ||
142 | } | ||
143 | |||
144 | void set_pmc_marked(int ctr, int mark0, int mark1) | ||
145 | { | ||
146 | u32 pmlca = get_pmlca(ctr); | ||
147 | |||
148 | if(mark0) | ||
149 | pmlca &= ~PMLCA_FCM0; | ||
150 | else | ||
151 | pmlca |= PMLCA_FCM0; | ||
152 | |||
153 | if(mark1) | ||
154 | pmlca &= ~PMLCA_FCM1; | ||
155 | else | ||
156 | pmlca |= PMLCA_FCM1; | ||
157 | |||
158 | set_pmlca(ctr, pmlca); | ||
159 | } | ||
160 | |||
161 | void pmc_start_ctr(int ctr, int enable) | ||
162 | { | ||
163 | u32 pmlca = get_pmlca(ctr); | ||
164 | |||
165 | pmlca &= ~PMLCA_FC; | ||
166 | |||
167 | if (enable) | ||
168 | pmlca |= PMLCA_CE; | ||
169 | else | ||
170 | pmlca &= ~PMLCA_CE; | ||
171 | |||
172 | set_pmlca(ctr, pmlca); | ||
173 | } | ||
174 | |||
175 | void pmc_start_ctrs(int enable) | ||
176 | { | ||
177 | u32 pmgc0 = mfpmr(PMRN_PMGC0); | ||
178 | |||
179 | pmgc0 &= ~PMGC0_FAC; | ||
180 | pmgc0 |= PMGC0_FCECE; | ||
181 | |||
182 | if (enable) | ||
183 | pmgc0 |= PMGC0_PMIE; | ||
184 | else | ||
185 | pmgc0 &= ~PMGC0_PMIE; | ||
186 | |||
187 | mtpmr(PMRN_PMGC0, pmgc0); | ||
188 | } | ||
189 | |||
190 | void pmc_stop_ctrs(void) | ||
191 | { | ||
192 | u32 pmgc0 = mfpmr(PMRN_PMGC0); | ||
193 | |||
194 | pmgc0 |= PMGC0_FAC; | ||
195 | |||
196 | pmgc0 &= ~(PMGC0_PMIE | PMGC0_FCECE); | ||
197 | |||
198 | mtpmr(PMRN_PMGC0, pmgc0); | ||
199 | } | ||
200 | |||
201 | void dump_pmcs(void) | ||
202 | { | ||
203 | printk("pmgc0: %x\n", mfpmr(PMRN_PMGC0)); | ||
204 | printk("pmc\t\tpmlca\t\tpmlcb\n"); | ||
205 | printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC0), | ||
206 | mfpmr(PMRN_PMLCA0), mfpmr(PMRN_PMLCB0)); | ||
207 | printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC1), | ||
208 | mfpmr(PMRN_PMLCA1), mfpmr(PMRN_PMLCB1)); | ||
209 | printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC2), | ||
210 | mfpmr(PMRN_PMLCA2), mfpmr(PMRN_PMLCB2)); | ||
211 | printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC3), | ||
212 | mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3)); | ||
213 | } | ||
214 | |||
215 | EXPORT_SYMBOL(init_pmc_stop); | ||
216 | EXPORT_SYMBOL(set_pmc_event); | ||
217 | EXPORT_SYMBOL(set_pmc_user_kernel); | ||
218 | EXPORT_SYMBOL(set_pmc_marked); | ||
219 | EXPORT_SYMBOL(pmc_start_ctr); | ||
220 | EXPORT_SYMBOL(pmc_start_ctrs); | ||
221 | EXPORT_SYMBOL(pmc_stop_ctrs); | ||
222 | EXPORT_SYMBOL(dump_pmcs); | ||
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 8a731ea877b7..dfa5398ab3c8 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -57,7 +57,6 @@ extern void machine_check_exception(struct pt_regs *regs); | |||
57 | extern void alignment_exception(struct pt_regs *regs); | 57 | extern void alignment_exception(struct pt_regs *regs); |
58 | extern void program_check_exception(struct pt_regs *regs); | 58 | extern void program_check_exception(struct pt_regs *regs); |
59 | extern void single_step_exception(struct pt_regs *regs); | 59 | extern void single_step_exception(struct pt_regs *regs); |
60 | extern int pmac_newworld; | ||
61 | extern int sys_sigreturn(struct pt_regs *regs); | 60 | extern int sys_sigreturn(struct pt_regs *regs); |
62 | 61 | ||
63 | EXPORT_SYMBOL(clear_pages); | 62 | EXPORT_SYMBOL(clear_pages); |
@@ -110,15 +109,6 @@ EXPORT_SYMBOL(_insw_ns); | |||
110 | EXPORT_SYMBOL(_outsw_ns); | 109 | EXPORT_SYMBOL(_outsw_ns); |
111 | EXPORT_SYMBOL(_insl_ns); | 110 | EXPORT_SYMBOL(_insl_ns); |
112 | EXPORT_SYMBOL(_outsl_ns); | 111 | EXPORT_SYMBOL(_outsl_ns); |
113 | EXPORT_SYMBOL(ioremap); | ||
114 | #ifdef CONFIG_44x | ||
115 | EXPORT_SYMBOL(ioremap64); | ||
116 | #endif | ||
117 | EXPORT_SYMBOL(__ioremap); | ||
118 | EXPORT_SYMBOL(iounmap); | ||
119 | #ifdef CONFIG_PPC32 | ||
120 | EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ | ||
121 | #endif | ||
122 | 112 | ||
123 | #if defined(CONFIG_PPC32) && (defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)) | 113 | #if defined(CONFIG_PPC32) && (defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)) |
124 | EXPORT_SYMBOL(ppc_ide_md); | 114 | EXPORT_SYMBOL(ppc_ide_md); |
@@ -161,7 +151,6 @@ EXPORT_SYMBOL(__flush_icache_range); | |||
161 | EXPORT_SYMBOL(flush_dcache_range); | 151 | EXPORT_SYMBOL(flush_dcache_range); |
162 | 152 | ||
163 | #ifdef CONFIG_SMP | 153 | #ifdef CONFIG_SMP |
164 | EXPORT_SYMBOL(smp_call_function); | ||
165 | #ifdef CONFIG_PPC32 | 154 | #ifdef CONFIG_PPC32 |
166 | EXPORT_SYMBOL(smp_hw_index); | 155 | EXPORT_SYMBOL(smp_hw_index); |
167 | #endif | 156 | #endif |
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c index 7ba42a405f41..3c2cf661f6d9 100644 --- a/arch/powerpc/kernel/proc_ppc64.c +++ b/arch/powerpc/kernel/proc_ppc64.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | 25 | ||
26 | #include <asm/machdep.h> | ||
26 | #include <asm/vdso_datapage.h> | 27 | #include <asm/vdso_datapage.h> |
27 | #include <asm/rtas.h> | 28 | #include <asm/rtas.h> |
28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
@@ -51,7 +52,7 @@ static int __init proc_ppc64_create(void) | |||
51 | if (!root) | 52 | if (!root) |
52 | return 1; | 53 | return 1; |
53 | 54 | ||
54 | if (!(platform_is_pseries() || _machine == PLATFORM_CELL)) | 55 | if (!machine_is(pseries) && !machine_is(cell)) |
55 | return 0; | 56 | return 0; |
56 | 57 | ||
57 | if (!proc_mkdir("rtas", root)) | 58 | if (!proc_mkdir("rtas", root)) |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index c225cf154bfe..2dd47d2dd998 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/kernel/process.c | ||
3 | * | ||
4 | * Derived from "arch/i386/kernel/process.c" | 2 | * Derived from "arch/i386/kernel/process.c" |
5 | * Copyright (C) 1995 Linus Torvalds | 3 | * Copyright (C) 1995 Linus Torvalds |
6 | * | 4 | * |
@@ -37,7 +35,6 @@ | |||
37 | #include <linux/mqueue.h> | 35 | #include <linux/mqueue.h> |
38 | #include <linux/hardirq.h> | 36 | #include <linux/hardirq.h> |
39 | #include <linux/utsname.h> | 37 | #include <linux/utsname.h> |
40 | #include <linux/kprobes.h> | ||
41 | 38 | ||
42 | #include <asm/pgtable.h> | 39 | #include <asm/pgtable.h> |
43 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
@@ -47,9 +44,10 @@ | |||
47 | #include <asm/mmu.h> | 44 | #include <asm/mmu.h> |
48 | #include <asm/prom.h> | 45 | #include <asm/prom.h> |
49 | #include <asm/machdep.h> | 46 | #include <asm/machdep.h> |
47 | #include <asm/time.h> | ||
48 | #include <asm/syscalls.h> | ||
50 | #ifdef CONFIG_PPC64 | 49 | #ifdef CONFIG_PPC64 |
51 | #include <asm/firmware.h> | 50 | #include <asm/firmware.h> |
52 | #include <asm/time.h> | ||
53 | #endif | 51 | #endif |
54 | 52 | ||
55 | extern unsigned long _get_SP(void); | 53 | extern unsigned long _get_SP(void); |
@@ -330,6 +328,11 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
330 | #endif | 328 | #endif |
331 | 329 | ||
332 | local_irq_save(flags); | 330 | local_irq_save(flags); |
331 | |||
332 | account_system_vtime(current); | ||
333 | account_process_vtime(current); | ||
334 | calculate_steal_time(); | ||
335 | |||
333 | last = _switch(old_thread, new_thread); | 336 | last = _switch(old_thread, new_thread); |
334 | 337 | ||
335 | local_irq_restore(flags); | 338 | local_irq_restore(flags); |
@@ -360,7 +363,11 @@ static void show_instructions(struct pt_regs *regs) | |||
360 | if (!(i % 8)) | 363 | if (!(i % 8)) |
361 | printk("\n"); | 364 | printk("\n"); |
362 | 365 | ||
363 | if (BAD_PC(pc) || __get_user(instr, (unsigned int *)pc)) { | 366 | /* We use __get_user here *only* to avoid an OOPS on a |
367 | * bad address because the pc *should* only be a | ||
368 | * kernel address. | ||
369 | */ | ||
370 | if (BAD_PC(pc) || __get_user(instr, (unsigned int __user *)pc)) { | ||
364 | printk("XXXXXXXX "); | 371 | printk("XXXXXXXX "); |
365 | } else { | 372 | } else { |
366 | if (regs->nip == pc) | 373 | if (regs->nip == pc) |
@@ -457,7 +464,6 @@ void show_regs(struct pt_regs * regs) | |||
457 | 464 | ||
458 | void exit_thread(void) | 465 | void exit_thread(void) |
459 | { | 466 | { |
460 | kprobe_flush_task(current); | ||
461 | discard_lazy_cpu_state(); | 467 | discard_lazy_cpu_state(); |
462 | } | 468 | } |
463 | 469 | ||
@@ -764,7 +770,7 @@ out: | |||
764 | return error; | 770 | return error; |
765 | } | 771 | } |
766 | 772 | ||
767 | static int validate_sp(unsigned long sp, struct task_struct *p, | 773 | int validate_sp(unsigned long sp, struct task_struct *p, |
768 | unsigned long nbytes) | 774 | unsigned long nbytes) |
769 | { | 775 | { |
770 | unsigned long stack_page = (unsigned long)task_stack_page(p); | 776 | unsigned long stack_page = (unsigned long)task_stack_page(p); |
@@ -802,6 +808,8 @@ static int validate_sp(unsigned long sp, struct task_struct *p, | |||
802 | #define FRAME_MARKER 2 | 808 | #define FRAME_MARKER 2 |
803 | #endif | 809 | #endif |
804 | 810 | ||
811 | EXPORT_SYMBOL(validate_sp); | ||
812 | |||
805 | unsigned long get_wchan(struct task_struct *p) | 813 | unsigned long get_wchan(struct task_struct *p) |
806 | { | 814 | { |
807 | unsigned long ip, sp; | 815 | unsigned long ip, sp; |
@@ -826,7 +834,6 @@ unsigned long get_wchan(struct task_struct *p) | |||
826 | } while (count++ < 16); | 834 | } while (count++ < 16); |
827 | return 0; | 835 | return 0; |
828 | } | 836 | } |
829 | EXPORT_SYMBOL(get_wchan); | ||
830 | 837 | ||
831 | static int kstack_depth_to_print = 64; | 838 | static int kstack_depth_to_print = 64; |
832 | 839 | ||
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 6dbd21726770..4336390bcf34 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -383,14 +383,14 @@ static int __devinit finish_node_interrupts(struct device_node *np, | |||
383 | /* Apple uses bits in there in a different way, let's | 383 | /* Apple uses bits in there in a different way, let's |
384 | * only keep the real sense bit on macs | 384 | * only keep the real sense bit on macs |
385 | */ | 385 | */ |
386 | if (_machine == PLATFORM_POWERMAC) | 386 | if (machine_is(powermac)) |
387 | sense &= 0x1; | 387 | sense &= 0x1; |
388 | np->intrs[intrcount].sense = map_mpic_senses[sense]; | 388 | np->intrs[intrcount].sense = map_mpic_senses[sense]; |
389 | } | 389 | } |
390 | 390 | ||
391 | #ifdef CONFIG_PPC64 | 391 | #ifdef CONFIG_PPC64 |
392 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ | 392 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ |
393 | if (_machine == PLATFORM_POWERMAC && ic && ic->parent) { | 393 | if (machine_is(powermac) && ic && ic->parent) { |
394 | char *name = get_property(ic->parent, "name", NULL); | 394 | char *name = get_property(ic->parent, "name", NULL); |
395 | if (name && !strcmp(name, "u3")) | 395 | if (name && !strcmp(name, "u3")) |
396 | np->intrs[intrcount].line += 128; | 396 | np->intrs[intrcount].line += 128; |
@@ -570,6 +570,18 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, | |||
570 | return rc; | 570 | return rc; |
571 | } | 571 | } |
572 | 572 | ||
573 | unsigned long __init of_get_flat_dt_root(void) | ||
574 | { | ||
575 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
576 | initial_boot_params->off_dt_struct; | ||
577 | |||
578 | while(*((u32 *)p) == OF_DT_NOP) | ||
579 | p += 4; | ||
580 | BUG_ON (*((u32 *)p) != OF_DT_BEGIN_NODE); | ||
581 | p += 4; | ||
582 | return _ALIGN(p + strlen((char *)p) + 1, 4); | ||
583 | } | ||
584 | |||
573 | /** | 585 | /** |
574 | * This function can be used within scan_flattened_dt callback to get | 586 | * This function can be used within scan_flattened_dt callback to get |
575 | * access to properties | 587 | * access to properties |
@@ -612,6 +624,25 @@ void* __init of_get_flat_dt_prop(unsigned long node, const char *name, | |||
612 | } while(1); | 624 | } while(1); |
613 | } | 625 | } |
614 | 626 | ||
627 | int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) | ||
628 | { | ||
629 | const char* cp; | ||
630 | unsigned long cplen, l; | ||
631 | |||
632 | cp = of_get_flat_dt_prop(node, "compatible", &cplen); | ||
633 | if (cp == NULL) | ||
634 | return 0; | ||
635 | while (cplen > 0) { | ||
636 | if (strncasecmp(cp, compat, strlen(compat)) == 0) | ||
637 | return 1; | ||
638 | l = strlen(cp) + 1; | ||
639 | cp += l; | ||
640 | cplen -= l; | ||
641 | } | ||
642 | |||
643 | return 0; | ||
644 | } | ||
645 | |||
615 | static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, | 646 | static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, |
616 | unsigned long align) | 647 | unsigned long align) |
617 | { | 648 | { |
@@ -686,7 +717,7 @@ static unsigned long __init unflatten_dt_node(unsigned long mem, | |||
686 | #ifdef DEBUG | 717 | #ifdef DEBUG |
687 | if ((strlen(p) + l + 1) != allocl) { | 718 | if ((strlen(p) + l + 1) != allocl) { |
688 | DBG("%s: p: %d, l: %d, a: %d\n", | 719 | DBG("%s: p: %d, l: %d, a: %d\n", |
689 | pathp, strlen(p), l, allocl); | 720 | pathp, (int)strlen(p), l, allocl); |
690 | } | 721 | } |
691 | #endif | 722 | #endif |
692 | p += strlen(p); | 723 | p += strlen(p); |
@@ -829,10 +860,6 @@ void __init unflatten_device_tree(void) | |||
829 | 860 | ||
830 | /* Allocate memory for the expanded device tree */ | 861 | /* Allocate memory for the expanded device tree */ |
831 | mem = lmb_alloc(size + 4, __alignof__(struct device_node)); | 862 | mem = lmb_alloc(size + 4, __alignof__(struct device_node)); |
832 | if (!mem) { | ||
833 | DBG("Couldn't allocate memory with lmb_alloc()!\n"); | ||
834 | panic("Couldn't allocate memory with lmb_alloc()!\n"); | ||
835 | } | ||
836 | mem = (unsigned long) __va(mem); | 863 | mem = (unsigned long) __va(mem); |
837 | 864 | ||
838 | ((u32 *)mem)[size / 4] = 0xdeadbeef; | 865 | ((u32 *)mem)[size / 4] = 0xdeadbeef; |
@@ -858,35 +885,73 @@ void __init unflatten_device_tree(void) | |||
858 | DBG(" <- unflatten_device_tree()\n"); | 885 | DBG(" <- unflatten_device_tree()\n"); |
859 | } | 886 | } |
860 | 887 | ||
861 | |||
862 | static int __init early_init_dt_scan_cpus(unsigned long node, | 888 | static int __init early_init_dt_scan_cpus(unsigned long node, |
863 | const char *uname, int depth, void *data) | 889 | const char *uname, int depth, |
890 | void *data) | ||
864 | { | 891 | { |
892 | static int logical_cpuid = 0; | ||
893 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | ||
894 | #ifdef CONFIG_ALTIVEC | ||
865 | u32 *prop; | 895 | u32 *prop; |
866 | unsigned long size; | 896 | #endif |
867 | char *type = of_get_flat_dt_prop(node, "device_type", &size); | 897 | u32 *intserv; |
898 | int i, nthreads; | ||
899 | unsigned long len; | ||
900 | int found = 0; | ||
868 | 901 | ||
869 | /* We are scanning "cpu" nodes only */ | 902 | /* We are scanning "cpu" nodes only */ |
870 | if (type == NULL || strcmp(type, "cpu") != 0) | 903 | if (type == NULL || strcmp(type, "cpu") != 0) |
871 | return 0; | 904 | return 0; |
872 | 905 | ||
873 | boot_cpuid = 0; | 906 | /* Get physical cpuid */ |
874 | boot_cpuid_phys = 0; | 907 | intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len); |
875 | if (initial_boot_params && initial_boot_params->version >= 2) { | 908 | if (intserv) { |
876 | /* version 2 of the kexec param format adds the phys cpuid | 909 | nthreads = len / sizeof(int); |
877 | * of booted proc. | ||
878 | */ | ||
879 | boot_cpuid_phys = initial_boot_params->boot_cpuid_phys; | ||
880 | } else { | 910 | } else { |
881 | /* Check if it's the boot-cpu, set it's hw index now */ | 911 | intserv = of_get_flat_dt_prop(node, "reg", NULL); |
882 | if (of_get_flat_dt_prop(node, | 912 | nthreads = 1; |
913 | } | ||
914 | |||
915 | /* | ||
916 | * Now see if any of these threads match our boot cpu. | ||
917 | * NOTE: This must match the parsing done in smp_setup_cpu_maps. | ||
918 | */ | ||
919 | for (i = 0; i < nthreads; i++) { | ||
920 | /* | ||
921 | * version 2 of the kexec param format adds the phys cpuid of | ||
922 | * booted proc. | ||
923 | */ | ||
924 | if (initial_boot_params && initial_boot_params->version >= 2) { | ||
925 | if (intserv[i] == | ||
926 | initial_boot_params->boot_cpuid_phys) { | ||
927 | found = 1; | ||
928 | break; | ||
929 | } | ||
930 | } else { | ||
931 | /* | ||
932 | * Check if it's the boot-cpu, set it's hw index now, | ||
933 | * unfortunately this format did not support booting | ||
934 | * off secondary threads. | ||
935 | */ | ||
936 | if (of_get_flat_dt_prop(node, | ||
883 | "linux,boot-cpu", NULL) != NULL) { | 937 | "linux,boot-cpu", NULL) != NULL) { |
884 | prop = of_get_flat_dt_prop(node, "reg", NULL); | 938 | found = 1; |
885 | if (prop != NULL) | 939 | break; |
886 | boot_cpuid_phys = *prop; | 940 | } |
887 | } | 941 | } |
942 | |||
943 | #ifdef CONFIG_SMP | ||
944 | /* logical cpu id is always 0 on UP kernels */ | ||
945 | logical_cpuid++; | ||
946 | #endif | ||
947 | } | ||
948 | |||
949 | if (found) { | ||
950 | DBG("boot cpu: logical %d physical %d\n", logical_cpuid, | ||
951 | intserv[i]); | ||
952 | boot_cpuid = logical_cpuid; | ||
953 | set_hard_smp_processor_id(boot_cpuid, intserv[i]); | ||
888 | } | 954 | } |
889 | set_hard_smp_processor_id(0, boot_cpuid_phys); | ||
890 | 955 | ||
891 | #ifdef CONFIG_ALTIVEC | 956 | #ifdef CONFIG_ALTIVEC |
892 | /* Check if we have a VMX and eventually update CPU features */ | 957 | /* Check if we have a VMX and eventually update CPU features */ |
@@ -905,16 +970,10 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
905 | #endif /* CONFIG_ALTIVEC */ | 970 | #endif /* CONFIG_ALTIVEC */ |
906 | 971 | ||
907 | #ifdef CONFIG_PPC_PSERIES | 972 | #ifdef CONFIG_PPC_PSERIES |
908 | /* | 973 | if (nthreads > 1) |
909 | * Check for an SMT capable CPU and set the CPU feature. We do | ||
910 | * this by looking at the size of the ibm,ppc-interrupt-server#s | ||
911 | * property | ||
912 | */ | ||
913 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", | ||
914 | &size); | ||
915 | cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; | ||
916 | if (prop && ((size / sizeof(u32)) > 1)) | ||
917 | cur_cpu_spec->cpu_features |= CPU_FTR_SMT; | 974 | cur_cpu_spec->cpu_features |= CPU_FTR_SMT; |
975 | else | ||
976 | cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; | ||
918 | #endif | 977 | #endif |
919 | 978 | ||
920 | return 0; | 979 | return 0; |
@@ -923,7 +982,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
923 | static int __init early_init_dt_scan_chosen(unsigned long node, | 982 | static int __init early_init_dt_scan_chosen(unsigned long node, |
924 | const char *uname, int depth, void *data) | 983 | const char *uname, int depth, void *data) |
925 | { | 984 | { |
926 | u32 *prop; | ||
927 | unsigned long *lprop; | 985 | unsigned long *lprop; |
928 | unsigned long l; | 986 | unsigned long l; |
929 | char *p; | 987 | char *p; |
@@ -934,14 +992,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
934 | (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) | 992 | (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) |
935 | return 0; | 993 | return 0; |
936 | 994 | ||
937 | /* get platform type */ | ||
938 | prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); | ||
939 | if (prop == NULL) | ||
940 | return 0; | ||
941 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
942 | _machine = *prop; | ||
943 | #endif | ||
944 | |||
945 | #ifdef CONFIG_PPC64 | 995 | #ifdef CONFIG_PPC64 |
946 | /* check if iommu is forced on or off */ | 996 | /* check if iommu is forced on or off */ |
947 | if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) | 997 | if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) |
@@ -968,15 +1018,15 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
968 | * set of RTAS infos now if available | 1018 | * set of RTAS infos now if available |
969 | */ | 1019 | */ |
970 | { | 1020 | { |
971 | u64 *basep, *entryp; | 1021 | u64 *basep, *entryp, *sizep; |
972 | 1022 | ||
973 | basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL); | 1023 | basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL); |
974 | entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL); | 1024 | entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL); |
975 | prop = of_get_flat_dt_prop(node, "linux,rtas-size", NULL); | 1025 | sizep = of_get_flat_dt_prop(node, "linux,rtas-size", NULL); |
976 | if (basep && entryp && prop) { | 1026 | if (basep && entryp && sizep) { |
977 | rtas.base = *basep; | 1027 | rtas.base = *basep; |
978 | rtas.entry = *entryp; | 1028 | rtas.entry = *entryp; |
979 | rtas.size = *prop; | 1029 | rtas.size = *sizep; |
980 | } | 1030 | } |
981 | } | 1031 | } |
982 | #endif /* CONFIG_PPC_RTAS */ | 1032 | #endif /* CONFIG_PPC_RTAS */ |
@@ -1005,25 +1055,13 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
1005 | 1055 | ||
1006 | if (strstr(cmd_line, "mem=")) { | 1056 | if (strstr(cmd_line, "mem=")) { |
1007 | char *p, *q; | 1057 | char *p, *q; |
1008 | unsigned long maxmem = 0; | ||
1009 | 1058 | ||
1010 | for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) { | 1059 | for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) { |
1011 | q = p + 4; | 1060 | q = p + 4; |
1012 | if (p > cmd_line && p[-1] != ' ') | 1061 | if (p > cmd_line && p[-1] != ' ') |
1013 | continue; | 1062 | continue; |
1014 | maxmem = simple_strtoul(q, &q, 0); | 1063 | memory_limit = memparse(q, &q); |
1015 | if (*q == 'k' || *q == 'K') { | ||
1016 | maxmem <<= 10; | ||
1017 | ++q; | ||
1018 | } else if (*q == 'm' || *q == 'M') { | ||
1019 | maxmem <<= 20; | ||
1020 | ++q; | ||
1021 | } else if (*q == 'g' || *q == 'G') { | ||
1022 | maxmem <<= 30; | ||
1023 | ++q; | ||
1024 | } | ||
1025 | } | 1064 | } |
1026 | memory_limit = maxmem; | ||
1027 | } | 1065 | } |
1028 | 1066 | ||
1029 | /* break now */ | 1067 | /* break now */ |
@@ -1759,7 +1797,7 @@ static int of_finish_dynamic_node(struct device_node *node) | |||
1759 | /* We don't support that function on PowerMac, at least | 1797 | /* We don't support that function on PowerMac, at least |
1760 | * not yet | 1798 | * not yet |
1761 | */ | 1799 | */ |
1762 | if (_machine == PLATFORM_POWERMAC) | 1800 | if (machine_is(powermac)) |
1763 | return -ENODEV; | 1801 | return -ENODEV; |
1764 | 1802 | ||
1765 | /* fix up new node's linux_phandle field */ | 1803 | /* fix up new node's linux_phandle field */ |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 813c2cd194c2..d66c5e77fcff 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -180,6 +180,16 @@ static unsigned long __initdata prom_tce_alloc_start; | |||
180 | static unsigned long __initdata prom_tce_alloc_end; | 180 | static unsigned long __initdata prom_tce_alloc_end; |
181 | #endif | 181 | #endif |
182 | 182 | ||
183 | /* Platforms codes are now obsolete in the kernel. Now only used within this | ||
184 | * file and ultimately gone too. Feel free to change them if you need, they | ||
185 | * are not shared with anything outside of this file anymore | ||
186 | */ | ||
187 | #define PLATFORM_PSERIES 0x0100 | ||
188 | #define PLATFORM_PSERIES_LPAR 0x0101 | ||
189 | #define PLATFORM_LPAR 0x0001 | ||
190 | #define PLATFORM_POWERMAC 0x0400 | ||
191 | #define PLATFORM_GENERIC 0x0500 | ||
192 | |||
183 | static int __initdata of_platform; | 193 | static int __initdata of_platform; |
184 | 194 | ||
185 | static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; | 195 | static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; |
@@ -397,6 +407,11 @@ static void __init __attribute__((noreturn)) prom_panic(const char *reason) | |||
397 | reason = PTRRELOC(reason); | 407 | reason = PTRRELOC(reason); |
398 | #endif | 408 | #endif |
399 | prom_print(reason); | 409 | prom_print(reason); |
410 | /* Do not call exit because it clears the screen on pmac | ||
411 | * it also causes some sort of double-fault on early pmacs */ | ||
412 | if (RELOC(of_platform) == PLATFORM_POWERMAC) | ||
413 | asm("trap\n"); | ||
414 | |||
400 | /* ToDo: should put up an SRC here on p/iSeries */ | 415 | /* ToDo: should put up an SRC here on p/iSeries */ |
401 | call_prom("exit", 0, 0); | 416 | call_prom("exit", 0, 0); |
402 | 417 | ||
@@ -1487,7 +1502,10 @@ static int __init prom_find_machine_type(void) | |||
1487 | int len, i = 0; | 1502 | int len, i = 0; |
1488 | #ifdef CONFIG_PPC64 | 1503 | #ifdef CONFIG_PPC64 |
1489 | phandle rtas; | 1504 | phandle rtas; |
1505 | int x; | ||
1490 | #endif | 1506 | #endif |
1507 | |||
1508 | /* Look for a PowerMac */ | ||
1491 | len = prom_getprop(_prom->root, "compatible", | 1509 | len = prom_getprop(_prom->root, "compatible", |
1492 | compat, sizeof(compat)-1); | 1510 | compat, sizeof(compat)-1); |
1493 | if (len > 0) { | 1511 | if (len > 0) { |
@@ -1500,28 +1518,36 @@ static int __init prom_find_machine_type(void) | |||
1500 | if (strstr(p, RELOC("Power Macintosh")) || | 1518 | if (strstr(p, RELOC("Power Macintosh")) || |
1501 | strstr(p, RELOC("MacRISC"))) | 1519 | strstr(p, RELOC("MacRISC"))) |
1502 | return PLATFORM_POWERMAC; | 1520 | return PLATFORM_POWERMAC; |
1503 | #ifdef CONFIG_PPC64 | ||
1504 | if (strstr(p, RELOC("Momentum,Maple"))) | ||
1505 | return PLATFORM_MAPLE; | ||
1506 | if (strstr(p, RELOC("IBM,CPB"))) | ||
1507 | return PLATFORM_CELL; | ||
1508 | #endif | ||
1509 | i += sl + 1; | 1521 | i += sl + 1; |
1510 | } | 1522 | } |
1511 | } | 1523 | } |
1512 | #ifdef CONFIG_PPC64 | 1524 | #ifdef CONFIG_PPC64 |
1525 | /* If not a mac, try to figure out if it's an IBM pSeries or any other | ||
1526 | * PAPR compliant platform. We assume it is if : | ||
1527 | * - /device_type is "chrp" (please, do NOT use that for future | ||
1528 | * non-IBM designs ! | ||
1529 | * - it has /rtas | ||
1530 | */ | ||
1531 | len = prom_getprop(_prom->root, "model", | ||
1532 | compat, sizeof(compat)-1); | ||
1533 | if (len <= 0) | ||
1534 | return PLATFORM_GENERIC; | ||
1535 | compat[len] = 0; | ||
1536 | if (strcmp(compat, "chrp")) | ||
1537 | return PLATFORM_GENERIC; | ||
1538 | |||
1513 | /* Default to pSeries. We need to know if we are running LPAR */ | 1539 | /* Default to pSeries. We need to know if we are running LPAR */ |
1514 | rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); | 1540 | rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); |
1515 | if (PHANDLE_VALID(rtas)) { | 1541 | if (!PHANDLE_VALID(rtas)) |
1516 | int x = prom_getproplen(rtas, "ibm,hypertas-functions"); | 1542 | return PLATFORM_GENERIC; |
1517 | if (x != PROM_ERROR) { | 1543 | x = prom_getproplen(rtas, "ibm,hypertas-functions"); |
1518 | prom_printf("Hypertas detected, assuming LPAR !\n"); | 1544 | if (x != PROM_ERROR) { |
1519 | return PLATFORM_PSERIES_LPAR; | 1545 | prom_printf("Hypertas detected, assuming LPAR !\n"); |
1520 | } | 1546 | return PLATFORM_PSERIES_LPAR; |
1521 | } | 1547 | } |
1522 | return PLATFORM_PSERIES; | 1548 | return PLATFORM_PSERIES; |
1523 | #else | 1549 | #else |
1524 | return PLATFORM_CHRP; | 1550 | return PLATFORM_GENERIC; |
1525 | #endif | 1551 | #endif |
1526 | } | 1552 | } |
1527 | 1553 | ||
@@ -2029,7 +2055,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2029 | { | 2055 | { |
2030 | struct prom_t *_prom; | 2056 | struct prom_t *_prom; |
2031 | unsigned long hdr; | 2057 | unsigned long hdr; |
2032 | u32 getprop_rval; | ||
2033 | unsigned long offset = reloc_offset(); | 2058 | unsigned long offset = reloc_offset(); |
2034 | 2059 | ||
2035 | #ifdef CONFIG_PPC32 | 2060 | #ifdef CONFIG_PPC32 |
@@ -2060,6 +2085,12 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2060 | */ | 2085 | */ |
2061 | prom_init_stdout(); | 2086 | prom_init_stdout(); |
2062 | 2087 | ||
2088 | /* | ||
2089 | * Get default machine type. At this point, we do not differentiate | ||
2090 | * between pSeries SMP and pSeries LPAR | ||
2091 | */ | ||
2092 | RELOC(of_platform) = prom_find_machine_type(); | ||
2093 | |||
2063 | /* Bail if this is a kdump kernel. */ | 2094 | /* Bail if this is a kdump kernel. */ |
2064 | if (PHYSICAL_START > 0) | 2095 | if (PHYSICAL_START > 0) |
2065 | prom_panic("Error: You can't boot a kdump kernel from OF!\n"); | 2096 | prom_panic("Error: You can't boot a kdump kernel from OF!\n"); |
@@ -2069,15 +2100,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2069 | */ | 2100 | */ |
2070 | prom_check_initrd(r3, r4); | 2101 | prom_check_initrd(r3, r4); |
2071 | 2102 | ||
2072 | /* | ||
2073 | * Get default machine type. At this point, we do not differentiate | ||
2074 | * between pSeries SMP and pSeries LPAR | ||
2075 | */ | ||
2076 | RELOC(of_platform) = prom_find_machine_type(); | ||
2077 | getprop_rval = RELOC(of_platform); | ||
2078 | prom_setprop(_prom->chosen, "/chosen", "linux,platform", | ||
2079 | &getprop_rval, sizeof(getprop_rval)); | ||
2080 | |||
2081 | #ifdef CONFIG_PPC_PSERIES | 2103 | #ifdef CONFIG_PPC_PSERIES |
2082 | /* | 2104 | /* |
2083 | * On pSeries, inform the firmware about our capabilities | 2105 | * On pSeries, inform the firmware about our capabilities |
diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h index 5ccbdbe0d5c9..c42a860c8d25 100644 --- a/arch/powerpc/kernel/ptrace-common.h +++ b/arch/powerpc/kernel/ptrace-common.h | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/ppc64/kernel/ptrace-common.h | ||
3 | * | ||
4 | * Copyright (c) 2002 Stephen Rothwell, IBM Coproration | 2 | * Copyright (c) 2002 Stephen Rothwell, IBM Coproration |
5 | * Extracted from ptrace.c and ptrace32.c | 3 | * Extracted from ptrace.c and ptrace32.c |
6 | * | 4 | * |
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 7a95b8a28354..456286cf1d14 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/kernel/rtas-proc.c | ||
3 | * Copyright (C) 2000 Tilmann Bitterberg | 2 | * Copyright (C) 2000 Tilmann Bitterberg |
4 | * (tilmann@bitterberg.de) | 3 | * (tilmann@bitterberg.de) |
5 | * | 4 | * |
@@ -258,7 +257,7 @@ static int __init proc_rtas_init(void) | |||
258 | { | 257 | { |
259 | struct proc_dir_entry *entry; | 258 | struct proc_dir_entry *entry; |
260 | 259 | ||
261 | if (_machine != PLATFORM_PSERIES && _machine != PLATFORM_PSERIES_LPAR) | 260 | if (!machine_is(pseries)) |
262 | return 1; | 261 | return 1; |
263 | 262 | ||
264 | rtas_node = of_find_node_by_name(NULL, "rtas"); | 263 | rtas_node = of_find_node_by_name(NULL, "rtas"); |
diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c index 635d3b9a8811..34d073fb6091 100644 --- a/arch/powerpc/kernel/rtas-rtc.c +++ b/arch/powerpc/kernel/rtas-rtc.c | |||
@@ -52,7 +52,7 @@ void rtas_get_rtc_time(struct rtc_time *rtc_tm) | |||
52 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); | 52 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); |
53 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | 53 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { |
54 | if (in_interrupt() && printk_ratelimit()) { | 54 | if (in_interrupt() && printk_ratelimit()) { |
55 | memset(&rtc_tm, 0, sizeof(struct rtc_time)); | 55 | memset(rtc_tm, 0, sizeof(struct rtc_time)); |
56 | printk(KERN_WARNING "error: reading clock" | 56 | printk(KERN_WARNING "error: reading clock" |
57 | " would delay interrupt\n"); | 57 | " would delay interrupt\n"); |
58 | return; /* delay not allowed */ | 58 | return; /* delay not allowed */ |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index b5b2add7ad1e..06636c927a7e 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/hvcall.h> | 25 | #include <asm/hvcall.h> |
26 | #include <asm/semaphore.h> | 26 | #include <asm/semaphore.h> |
27 | #include <asm/machdep.h> | 27 | #include <asm/machdep.h> |
28 | #include <asm/firmware.h> | ||
28 | #include <asm/page.h> | 29 | #include <asm/page.h> |
29 | #include <asm/param.h> | 30 | #include <asm/param.h> |
30 | #include <asm/system.h> | 31 | #include <asm/system.h> |
@@ -32,6 +33,7 @@ | |||
32 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
33 | #include <asm/lmb.h> | 34 | #include <asm/lmb.h> |
34 | #include <asm/udbg.h> | 35 | #include <asm/udbg.h> |
36 | #include <asm/syscalls.h> | ||
35 | 37 | ||
36 | struct rtas_t rtas = { | 38 | struct rtas_t rtas = { |
37 | .lock = SPIN_LOCK_UNLOCKED | 39 | .lock = SPIN_LOCK_UNLOCKED |
@@ -591,7 +593,7 @@ static void rtas_percpu_suspend_me(void *info) | |||
591 | data->waiting = 0; | 593 | data->waiting = 0; |
592 | data->args->args[data->args->nargs] = | 594 | data->args->args[data->args->nargs] = |
593 | rtas_call(ibm_suspend_me_token, 0, 1, NULL); | 595 | rtas_call(ibm_suspend_me_token, 0, 1, NULL); |
594 | for_each_cpu(i) | 596 | for_each_possible_cpu(i) |
595 | plpar_hcall_norets(H_PROD,i); | 597 | plpar_hcall_norets(H_PROD,i); |
596 | } else { | 598 | } else { |
597 | data->waiting = -EBUSY; | 599 | data->waiting = -EBUSY; |
@@ -624,7 +626,7 @@ static int rtas_ibm_suspend_me(struct rtas_args *args) | |||
624 | /* Prod each CPU. This won't hurt, and will wake | 626 | /* Prod each CPU. This won't hurt, and will wake |
625 | * anyone we successfully put to sleep with H_Join | 627 | * anyone we successfully put to sleep with H_Join |
626 | */ | 628 | */ |
627 | for_each_cpu(i) | 629 | for_each_possible_cpu(i) |
628 | plpar_hcall_norets(H_PROD, i); | 630 | plpar_hcall_norets(H_PROD, i); |
629 | 631 | ||
630 | return data.waiting; | 632 | return data.waiting; |
@@ -767,7 +769,7 @@ void __init rtas_initialize(void) | |||
767 | * the stop-self token if any | 769 | * the stop-self token if any |
768 | */ | 770 | */ |
769 | #ifdef CONFIG_PPC64 | 771 | #ifdef CONFIG_PPC64 |
770 | if (_machine == PLATFORM_PSERIES_LPAR) { | 772 | if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR)) { |
771 | rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); | 773 | rtas_region = min(lmb.rmo_size, RTAS_INSTANTIATE_MAX); |
772 | ibm_suspend_me_token = rtas_token("ibm,suspend-me"); | 774 | ibm_suspend_me_token = rtas_token("ibm,suspend-me"); |
773 | } | 775 | } |
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 5579f6559912..57b539a03fa9 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/kernel/rtas_pci.c | ||
3 | * | ||
4 | * Copyright (C) 2001 Dave Engebretsen, IBM Corporation | 2 | * Copyright (C) 2001 Dave Engebretsen, IBM Corporation |
5 | * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM | 3 | * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM |
6 | * | 4 | * |
@@ -280,8 +278,7 @@ static int phb_set_bus_ranges(struct device_node *dev, | |||
280 | return 0; | 278 | return 0; |
281 | } | 279 | } |
282 | 280 | ||
283 | static int __devinit setup_phb(struct device_node *dev, | 281 | int __devinit setup_phb(struct device_node *dev, struct pci_controller *phb) |
284 | struct pci_controller *phb) | ||
285 | { | 282 | { |
286 | if (is_python(dev)) | 283 | if (is_python(dev)) |
287 | python_countermeasures(dev); | 284 | python_countermeasures(dev); |
@@ -359,27 +356,6 @@ unsigned long __init find_and_init_phbs(void) | |||
359 | return 0; | 356 | return 0; |
360 | } | 357 | } |
361 | 358 | ||
362 | struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) | ||
363 | { | ||
364 | struct pci_controller *phb; | ||
365 | int primary; | ||
366 | |||
367 | primary = list_empty(&hose_list); | ||
368 | phb = pcibios_alloc_controller(dn); | ||
369 | if (!phb) | ||
370 | return NULL; | ||
371 | setup_phb(dn, phb); | ||
372 | pci_process_bridge_OF_ranges(phb, dn, primary); | ||
373 | |||
374 | pci_setup_phb_io_dynamic(phb, primary); | ||
375 | |||
376 | pci_devs_phb_init_dynamic(phb); | ||
377 | scan_phb(phb); | ||
378 | |||
379 | return phb; | ||
380 | } | ||
381 | EXPORT_SYMBOL(init_phb_dynamic); | ||
382 | |||
383 | /* RPA-specific bits for removing PHBs */ | 359 | /* RPA-specific bits for removing PHBs */ |
384 | int pcibios_remove_root_bus(struct pci_controller *phb) | 360 | int pcibios_remove_root_bus(struct pci_controller *phb) |
385 | { | 361 | { |
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index fc89d009d18d..1d93e73a7003 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
@@ -9,6 +9,9 @@ | |||
9 | * as published by the Free Software Foundation; either version | 9 | * as published by the Free Software Foundation; either version |
10 | * 2 of the License, or (at your option) any later version. | 10 | * 2 of the License, or (at your option) any later version. |
11 | */ | 11 | */ |
12 | |||
13 | #undef DEBUG | ||
14 | |||
12 | #include <linux/config.h> | 15 | #include <linux/config.h> |
13 | #include <linux/module.h> | 16 | #include <linux/module.h> |
14 | #include <linux/string.h> | 17 | #include <linux/string.h> |
@@ -42,6 +45,7 @@ | |||
42 | #include <asm/time.h> | 45 | #include <asm/time.h> |
43 | #include <asm/cputable.h> | 46 | #include <asm/cputable.h> |
44 | #include <asm/sections.h> | 47 | #include <asm/sections.h> |
48 | #include <asm/firmware.h> | ||
45 | #include <asm/btext.h> | 49 | #include <asm/btext.h> |
46 | #include <asm/nvram.h> | 50 | #include <asm/nvram.h> |
47 | #include <asm/setup.h> | 51 | #include <asm/setup.h> |
@@ -57,8 +61,6 @@ | |||
57 | 61 | ||
58 | #include "setup.h" | 62 | #include "setup.h" |
59 | 63 | ||
60 | #undef DEBUG | ||
61 | |||
62 | #ifdef DEBUG | 64 | #ifdef DEBUG |
63 | #include <asm/udbg.h> | 65 | #include <asm/udbg.h> |
64 | #define DBG(fmt...) udbg_printf(fmt) | 66 | #define DBG(fmt...) udbg_printf(fmt) |
@@ -66,10 +68,12 @@ | |||
66 | #define DBG(fmt...) | 68 | #define DBG(fmt...) |
67 | #endif | 69 | #endif |
68 | 70 | ||
69 | #ifdef CONFIG_PPC_MULTIPLATFORM | 71 | /* The main machine-dep calls structure |
70 | int _machine = 0; | 72 | */ |
71 | EXPORT_SYMBOL(_machine); | 73 | struct machdep_calls ppc_md; |
72 | #endif | 74 | EXPORT_SYMBOL(ppc_md); |
75 | struct machdep_calls *machine_id; | ||
76 | EXPORT_SYMBOL(machine_id); | ||
73 | 77 | ||
74 | unsigned long klimit = (unsigned long) _end; | 78 | unsigned long klimit = (unsigned long) _end; |
75 | 79 | ||
@@ -163,14 +167,14 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
163 | #if defined(CONFIG_SMP) && defined(CONFIG_PPC32) | 167 | #if defined(CONFIG_SMP) && defined(CONFIG_PPC32) |
164 | unsigned long bogosum = 0; | 168 | unsigned long bogosum = 0; |
165 | int i; | 169 | int i; |
166 | for (i = 0; i < NR_CPUS; ++i) | 170 | for_each_online_cpu(i) |
167 | if (cpu_online(i)) | 171 | bogosum += loops_per_jiffy; |
168 | bogosum += loops_per_jiffy; | ||
169 | seq_printf(m, "total bogomips\t: %lu.%02lu\n", | 172 | seq_printf(m, "total bogomips\t: %lu.%02lu\n", |
170 | bogosum/(500000/HZ), bogosum/(5000/HZ) % 100); | 173 | bogosum/(500000/HZ), bogosum/(5000/HZ) % 100); |
171 | #endif /* CONFIG_SMP && CONFIG_PPC32 */ | 174 | #endif /* CONFIG_SMP && CONFIG_PPC32 */ |
172 | seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq); | 175 | seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq); |
173 | 176 | if (ppc_md.name) | |
177 | seq_printf(m, "platform\t: %s\n", ppc_md.name); | ||
174 | if (ppc_md.show_cpuinfo != NULL) | 178 | if (ppc_md.show_cpuinfo != NULL) |
175 | ppc_md.show_cpuinfo(m); | 179 | ppc_md.show_cpuinfo(m); |
176 | 180 | ||
@@ -354,12 +358,13 @@ void __init check_for_initrd(void) | |||
354 | * must be called before using this. | 358 | * must be called before using this. |
355 | * | 359 | * |
356 | * While we're here, we may as well set the "physical" cpu ids in the paca. | 360 | * While we're here, we may as well set the "physical" cpu ids in the paca. |
361 | * | ||
362 | * NOTE: This must match the parsing done in early_init_dt_scan_cpus. | ||
357 | */ | 363 | */ |
358 | void __init smp_setup_cpu_maps(void) | 364 | void __init smp_setup_cpu_maps(void) |
359 | { | 365 | { |
360 | struct device_node *dn = NULL; | 366 | struct device_node *dn = NULL; |
361 | int cpu = 0; | 367 | int cpu = 0; |
362 | int swap_cpuid = 0; | ||
363 | 368 | ||
364 | while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) { | 369 | while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) { |
365 | int *intserv; | 370 | int *intserv; |
@@ -378,30 +383,17 @@ void __init smp_setup_cpu_maps(void) | |||
378 | for (j = 0; j < nthreads && cpu < NR_CPUS; j++) { | 383 | for (j = 0; j < nthreads && cpu < NR_CPUS; j++) { |
379 | cpu_set(cpu, cpu_present_map); | 384 | cpu_set(cpu, cpu_present_map); |
380 | set_hard_smp_processor_id(cpu, intserv[j]); | 385 | set_hard_smp_processor_id(cpu, intserv[j]); |
381 | |||
382 | if (intserv[j] == boot_cpuid_phys) | ||
383 | swap_cpuid = cpu; | ||
384 | cpu_set(cpu, cpu_possible_map); | 386 | cpu_set(cpu, cpu_possible_map); |
385 | cpu++; | 387 | cpu++; |
386 | } | 388 | } |
387 | } | 389 | } |
388 | 390 | ||
389 | /* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that | ||
390 | * boot cpu is logical 0. | ||
391 | */ | ||
392 | if (boot_cpuid_phys != get_hard_smp_processor_id(0)) { | ||
393 | u32 tmp; | ||
394 | tmp = get_hard_smp_processor_id(0); | ||
395 | set_hard_smp_processor_id(0, boot_cpuid_phys); | ||
396 | set_hard_smp_processor_id(swap_cpuid, tmp); | ||
397 | } | ||
398 | |||
399 | #ifdef CONFIG_PPC64 | 391 | #ifdef CONFIG_PPC64 |
400 | /* | 392 | /* |
401 | * On pSeries LPAR, we need to know how many cpus | 393 | * On pSeries LPAR, we need to know how many cpus |
402 | * could possibly be added to this partition. | 394 | * could possibly be added to this partition. |
403 | */ | 395 | */ |
404 | if (_machine == PLATFORM_PSERIES_LPAR && | 396 | if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR) && |
405 | (dn = of_find_node_by_path("/rtas"))) { | 397 | (dn = of_find_node_by_path("/rtas"))) { |
406 | int num_addr_cell, num_size_cell, maxcpus; | 398 | int num_addr_cell, num_size_cell, maxcpus; |
407 | unsigned int *ireg; | 399 | unsigned int *ireg; |
@@ -440,7 +432,7 @@ void __init smp_setup_cpu_maps(void) | |||
440 | /* | 432 | /* |
441 | * Do the sibling map; assume only two threads per processor. | 433 | * Do the sibling map; assume only two threads per processor. |
442 | */ | 434 | */ |
443 | for_each_cpu(cpu) { | 435 | for_each_possible_cpu(cpu) { |
444 | cpu_set(cpu, cpu_sibling_map[cpu]); | 436 | cpu_set(cpu, cpu_sibling_map[cpu]); |
445 | if (cpu_has_feature(CPU_FTR_SMT)) | 437 | if (cpu_has_feature(CPU_FTR_SMT)) |
446 | cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); | 438 | cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]); |
@@ -493,3 +485,34 @@ static __init int add_pcspkr(void) | |||
493 | return ret; | 485 | return ret; |
494 | } | 486 | } |
495 | device_initcall(add_pcspkr); | 487 | device_initcall(add_pcspkr); |
488 | |||
489 | void probe_machine(void) | ||
490 | { | ||
491 | extern struct machdep_calls __machine_desc_start; | ||
492 | extern struct machdep_calls __machine_desc_end; | ||
493 | |||
494 | /* | ||
495 | * Iterate all ppc_md structures until we find the proper | ||
496 | * one for the current machine type | ||
497 | */ | ||
498 | DBG("Probing machine type ...\n"); | ||
499 | |||
500 | for (machine_id = &__machine_desc_start; | ||
501 | machine_id < &__machine_desc_end; | ||
502 | machine_id++) { | ||
503 | DBG(" %s ...", machine_id->name); | ||
504 | memcpy(&ppc_md, machine_id, sizeof(struct machdep_calls)); | ||
505 | if (ppc_md.probe()) { | ||
506 | DBG(" match !\n"); | ||
507 | break; | ||
508 | } | ||
509 | DBG("\n"); | ||
510 | } | ||
511 | /* What can we do if we didn't find ? */ | ||
512 | if (machine_id >= &__machine_desc_end) { | ||
513 | DBG("No suitable machine found !\n"); | ||
514 | for (;;); | ||
515 | } | ||
516 | |||
517 | printk(KERN_INFO "Using %s machine description\n", ppc_md.name); | ||
518 | } | ||
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index db72a92943bf..a72bf5dceeee 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -53,9 +53,6 @@ | |||
53 | extern void platform_init(void); | 53 | extern void platform_init(void); |
54 | extern void bootx_init(unsigned long r4, unsigned long phys); | 54 | extern void bootx_init(unsigned long r4, unsigned long phys); |
55 | 55 | ||
56 | extern void ppc6xx_idle(void); | ||
57 | extern void power4_idle(void); | ||
58 | |||
59 | boot_infos_t *boot_infos; | 56 | boot_infos_t *boot_infos; |
60 | struct ide_machdep_calls ppc_ide_md; | 57 | struct ide_machdep_calls ppc_ide_md; |
61 | 58 | ||
@@ -70,10 +67,6 @@ unsigned int DMA_MODE_WRITE; | |||
70 | int have_of = 1; | 67 | int have_of = 1; |
71 | 68 | ||
72 | #ifdef CONFIG_PPC_MULTIPLATFORM | 69 | #ifdef CONFIG_PPC_MULTIPLATFORM |
73 | extern void prep_init(void); | ||
74 | extern void pmac_init(void); | ||
75 | extern void chrp_init(void); | ||
76 | |||
77 | dev_t boot_dev; | 70 | dev_t boot_dev; |
78 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | 71 | #endif /* CONFIG_PPC_MULTIPLATFORM */ |
79 | 72 | ||
@@ -85,9 +78,6 @@ unsigned long SYSRQ_KEY = 0x54; | |||
85 | unsigned long vgacon_remap_base; | 78 | unsigned long vgacon_remap_base; |
86 | #endif | 79 | #endif |
87 | 80 | ||
88 | struct machdep_calls ppc_md; | ||
89 | EXPORT_SYMBOL(ppc_md); | ||
90 | |||
91 | /* | 81 | /* |
92 | * These are used in binfmt_elf.c to put aux entries on the stack | 82 | * These are used in binfmt_elf.c to put aux entries on the stack |
93 | * for each elf executable being started. | 83 | * for each elf executable being started. |
@@ -111,7 +101,7 @@ unsigned long __init early_init(unsigned long dt_ptr) | |||
111 | 101 | ||
112 | /* First zero the BSS -- use memset_io, some platforms don't have | 102 | /* First zero the BSS -- use memset_io, some platforms don't have |
113 | * caches on yet */ | 103 | * caches on yet */ |
114 | memset_io(PTRRELOC(&__bss_start), 0, _end - __bss_start); | 104 | memset_io((void __iomem *)PTRRELOC(&__bss_start), 0, _end - __bss_start); |
115 | 105 | ||
116 | /* | 106 | /* |
117 | * Identify the CPU type and fix up code sections | 107 | * Identify the CPU type and fix up code sections |
@@ -123,48 +113,6 @@ unsigned long __init early_init(unsigned long dt_ptr) | |||
123 | return KERNELBASE + offset; | 113 | return KERNELBASE + offset; |
124 | } | 114 | } |
125 | 115 | ||
126 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
127 | /* | ||
128 | * The PPC_MULTIPLATFORM version of platform_init... | ||
129 | */ | ||
130 | void __init platform_init(void) | ||
131 | { | ||
132 | /* if we didn't get any bootinfo telling us what we are... */ | ||
133 | if (_machine == 0) { | ||
134 | /* prep boot loader tells us if we're prep or not */ | ||
135 | if ( *(unsigned long *)(KERNELBASE) == (0xdeadc0de) ) | ||
136 | _machine = _MACH_prep; | ||
137 | } | ||
138 | |||
139 | #ifdef CONFIG_PPC_PREP | ||
140 | /* not much more to do here, if prep */ | ||
141 | if (_machine == _MACH_prep) { | ||
142 | prep_init(); | ||
143 | return; | ||
144 | } | ||
145 | #endif | ||
146 | |||
147 | #ifdef CONFIG_ADB | ||
148 | if (strstr(cmd_line, "adb_sync")) { | ||
149 | extern int __adb_probe_sync; | ||
150 | __adb_probe_sync = 1; | ||
151 | } | ||
152 | #endif /* CONFIG_ADB */ | ||
153 | |||
154 | switch (_machine) { | ||
155 | #ifdef CONFIG_PPC_PMAC | ||
156 | case _MACH_Pmac: | ||
157 | pmac_init(); | ||
158 | break; | ||
159 | #endif | ||
160 | #ifdef CONFIG_PPC_CHRP | ||
161 | case _MACH_chrp: | ||
162 | chrp_init(); | ||
163 | break; | ||
164 | #endif | ||
165 | } | ||
166 | } | ||
167 | #endif | ||
168 | 116 | ||
169 | /* | 117 | /* |
170 | * Find out what kind of machine we're on and save any data we need | 118 | * Find out what kind of machine we're on and save any data we need |
@@ -190,11 +138,17 @@ void __init machine_init(unsigned long dt_ptr, unsigned long phys) | |||
190 | strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line)); | 138 | strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line)); |
191 | #endif /* CONFIG_CMDLINE */ | 139 | #endif /* CONFIG_CMDLINE */ |
192 | 140 | ||
193 | /* Base init based on machine type */ | 141 | #ifdef CONFIG_PPC_MULTIPLATFORM |
142 | probe_machine(); | ||
143 | #else | ||
144 | /* Base init based on machine type. Obsoloete, please kill ! */ | ||
194 | platform_init(); | 145 | platform_init(); |
146 | #endif | ||
195 | 147 | ||
196 | #ifdef CONFIG_6xx | 148 | #ifdef CONFIG_6xx |
197 | ppc_md.power_save = ppc6xx_idle; | 149 | if (cpu_has_feature(CPU_FTR_CAN_DOZE) || |
150 | cpu_has_feature(CPU_FTR_CAN_NAP)) | ||
151 | ppc_md.power_save = ppc6xx_idle; | ||
198 | #endif | 152 | #endif |
199 | 153 | ||
200 | if (ppc_md.progress) | 154 | if (ppc_md.progress) |
@@ -272,9 +226,8 @@ int __init ppc_init(void) | |||
272 | if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff); | 226 | if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff); |
273 | 227 | ||
274 | /* register CPU devices */ | 228 | /* register CPU devices */ |
275 | for (i = 0; i < NR_CPUS; i++) | 229 | for_each_possible_cpu(i) |
276 | if (cpu_possible(i)) | 230 | register_cpu(&cpu_devices[i], i, NULL); |
277 | register_cpu(&cpu_devices[i], i, NULL); | ||
278 | 231 | ||
279 | /* call platform init */ | 232 | /* call platform init */ |
280 | if (ppc_md.init != NULL) { | 233 | if (ppc_md.init != NULL) { |
@@ -353,12 +306,6 @@ void __init setup_arch(char **cmdline_p) | |||
353 | do_init_bootmem(); | 306 | do_init_bootmem(); |
354 | if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab); | 307 | if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab); |
355 | 308 | ||
356 | #ifdef CONFIG_PPC_OCP | ||
357 | /* Initialize OCP device list */ | ||
358 | ocp_early_init(); | ||
359 | if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab); | ||
360 | #endif | ||
361 | |||
362 | #ifdef CONFIG_DUMMY_CONSOLE | 309 | #ifdef CONFIG_DUMMY_CONSOLE |
363 | conswitchp = &dummy_con; | 310 | conswitchp = &dummy_con; |
364 | #endif | 311 | #endif |
@@ -367,7 +314,4 @@ void __init setup_arch(char **cmdline_p) | |||
367 | if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); | 314 | if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); |
368 | 315 | ||
369 | paging_init(); | 316 | paging_init(); |
370 | |||
371 | /* this is for modules since _machine can be a define -- Cort */ | ||
372 | ppc_md.ppc_machine = _machine; | ||
373 | } | 317 | } |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index f96c49b03ba0..59aa92cd6fa4 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -73,7 +73,6 @@ | |||
73 | 73 | ||
74 | int have_of = 1; | 74 | int have_of = 1; |
75 | int boot_cpuid = 0; | 75 | int boot_cpuid = 0; |
76 | int boot_cpuid_phys = 0; | ||
77 | dev_t boot_dev; | 76 | dev_t boot_dev; |
78 | u64 ppc64_pft_size; | 77 | u64 ppc64_pft_size; |
79 | 78 | ||
@@ -96,11 +95,6 @@ int dcache_bsize; | |||
96 | int icache_bsize; | 95 | int icache_bsize; |
97 | int ucache_bsize; | 96 | int ucache_bsize; |
98 | 97 | ||
99 | /* The main machine-dep calls structure | ||
100 | */ | ||
101 | struct machdep_calls ppc_md; | ||
102 | EXPORT_SYMBOL(ppc_md); | ||
103 | |||
104 | #ifdef CONFIG_MAGIC_SYSRQ | 98 | #ifdef CONFIG_MAGIC_SYSRQ |
105 | unsigned long SYSRQ_KEY; | 99 | unsigned long SYSRQ_KEY; |
106 | #endif /* CONFIG_MAGIC_SYSRQ */ | 100 | #endif /* CONFIG_MAGIC_SYSRQ */ |
@@ -161,32 +155,6 @@ early_param("smt-enabled", early_smt_enabled); | |||
161 | #define check_smt_enabled() | 155 | #define check_smt_enabled() |
162 | #endif /* CONFIG_SMP */ | 156 | #endif /* CONFIG_SMP */ |
163 | 157 | ||
164 | extern struct machdep_calls pSeries_md; | ||
165 | extern struct machdep_calls pmac_md; | ||
166 | extern struct machdep_calls maple_md; | ||
167 | extern struct machdep_calls cell_md; | ||
168 | extern struct machdep_calls iseries_md; | ||
169 | |||
170 | /* Ultimately, stuff them in an elf section like initcalls... */ | ||
171 | static struct machdep_calls __initdata *machines[] = { | ||
172 | #ifdef CONFIG_PPC_PSERIES | ||
173 | &pSeries_md, | ||
174 | #endif /* CONFIG_PPC_PSERIES */ | ||
175 | #ifdef CONFIG_PPC_PMAC | ||
176 | &pmac_md, | ||
177 | #endif /* CONFIG_PPC_PMAC */ | ||
178 | #ifdef CONFIG_PPC_MAPLE | ||
179 | &maple_md, | ||
180 | #endif /* CONFIG_PPC_MAPLE */ | ||
181 | #ifdef CONFIG_PPC_CELL | ||
182 | &cell_md, | ||
183 | #endif | ||
184 | #ifdef CONFIG_PPC_ISERIES | ||
185 | &iseries_md, | ||
186 | #endif | ||
187 | NULL | ||
188 | }; | ||
189 | |||
190 | /* | 158 | /* |
191 | * Early initialization entry point. This is called by head.S | 159 | * Early initialization entry point. This is called by head.S |
192 | * with MMU translation disabled. We rely on the "feature" of | 160 | * with MMU translation disabled. We rely on the "feature" of |
@@ -208,13 +176,10 @@ static struct machdep_calls __initdata *machines[] = { | |||
208 | 176 | ||
209 | void __init early_setup(unsigned long dt_ptr) | 177 | void __init early_setup(unsigned long dt_ptr) |
210 | { | 178 | { |
211 | struct paca_struct *lpaca = get_paca(); | ||
212 | static struct machdep_calls **mach; | ||
213 | |||
214 | /* Enable early debugging if any specified (see udbg.h) */ | 179 | /* Enable early debugging if any specified (see udbg.h) */ |
215 | udbg_early_init(); | 180 | udbg_early_init(); |
216 | 181 | ||
217 | DBG(" -> early_setup()\n"); | 182 | DBG(" -> early_setup(), dt_ptr: 0x%lx\n", dt_ptr); |
218 | 183 | ||
219 | /* | 184 | /* |
220 | * Do early initializations using the flattened device | 185 | * Do early initializations using the flattened device |
@@ -223,22 +188,16 @@ void __init early_setup(unsigned long dt_ptr) | |||
223 | */ | 188 | */ |
224 | early_init_devtree(__va(dt_ptr)); | 189 | early_init_devtree(__va(dt_ptr)); |
225 | 190 | ||
226 | /* | 191 | /* Now we know the logical id of our boot cpu, setup the paca. */ |
227 | * Iterate all ppc_md structures until we find the proper | 192 | setup_boot_paca(); |
228 | * one for the current machine type | ||
229 | */ | ||
230 | DBG("Probing machine type for platform %x...\n", _machine); | ||
231 | 193 | ||
232 | for (mach = machines; *mach; mach++) { | 194 | /* Fix up paca fields required for the boot cpu */ |
233 | if ((*mach)->probe(_machine)) | 195 | get_paca()->cpu_start = 1; |
234 | break; | 196 | get_paca()->stab_real = __pa((u64)&initial_stab); |
235 | } | 197 | get_paca()->stab_addr = (u64)&initial_stab; |
236 | /* What can we do if we didn't find ? */ | 198 | |
237 | if (*mach == NULL) { | 199 | /* Probe the machine type */ |
238 | DBG("No suitable machine found !\n"); | 200 | probe_machine(); |
239 | for (;;); | ||
240 | } | ||
241 | ppc_md = **mach; | ||
242 | 201 | ||
243 | #ifdef CONFIG_CRASH_DUMP | 202 | #ifdef CONFIG_CRASH_DUMP |
244 | kdump_setup(); | 203 | kdump_setup(); |
@@ -260,7 +219,7 @@ void __init early_setup(unsigned long dt_ptr) | |||
260 | if (cpu_has_feature(CPU_FTR_SLB)) | 219 | if (cpu_has_feature(CPU_FTR_SLB)) |
261 | slb_initialize(); | 220 | slb_initialize(); |
262 | else | 221 | else |
263 | stab_initialize(lpaca->stab_real); | 222 | stab_initialize(get_paca()->stab_real); |
264 | } | 223 | } |
265 | 224 | ||
266 | DBG(" <- early_setup()\n"); | 225 | DBG(" <- early_setup()\n"); |
@@ -340,7 +299,7 @@ static void __init initialize_cache_info(void) | |||
340 | const char *dc, *ic; | 299 | const char *dc, *ic; |
341 | 300 | ||
342 | /* Then read cache informations */ | 301 | /* Then read cache informations */ |
343 | if (_machine == PLATFORM_POWERMAC) { | 302 | if (machine_is(powermac)) { |
344 | dc = "d-cache-block-size"; | 303 | dc = "d-cache-block-size"; |
345 | ic = "i-cache-block-size"; | 304 | ic = "i-cache-block-size"; |
346 | } else { | 305 | } else { |
@@ -484,7 +443,6 @@ void __init setup_system(void) | |||
484 | printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); | 443 | printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); |
485 | printk("ppc64_interrupt_controller = 0x%ld\n", | 444 | printk("ppc64_interrupt_controller = 0x%ld\n", |
486 | ppc64_interrupt_controller); | 445 | ppc64_interrupt_controller); |
487 | printk("platform = 0x%x\n", _machine); | ||
488 | printk("physicalMemorySize = 0x%lx\n", lmb_phys_mem_size()); | 446 | printk("physicalMemorySize = 0x%lx\n", lmb_phys_mem_size()); |
489 | printk("ppc64_caches.dcache_line_size = 0x%x\n", | 447 | printk("ppc64_caches.dcache_line_size = 0x%x\n", |
490 | ppc64_caches.dline_size); | 448 | ppc64_caches.dline_size); |
@@ -497,8 +455,6 @@ void __init setup_system(void) | |||
497 | #endif | 455 | #endif |
498 | printk("-----------------------------------------------------\n"); | 456 | printk("-----------------------------------------------------\n"); |
499 | 457 | ||
500 | mm_init_ppc64(); | ||
501 | |||
502 | DBG(" <- setup_system()\n"); | 458 | DBG(" <- setup_system()\n"); |
503 | } | 459 | } |
504 | 460 | ||
@@ -518,7 +474,7 @@ static void __init irqstack_early_init(void) | |||
518 | * interrupt stacks must be under 256MB, we cannot afford to take | 474 | * interrupt stacks must be under 256MB, we cannot afford to take |
519 | * SLB misses on them. | 475 | * SLB misses on them. |
520 | */ | 476 | */ |
521 | for_each_cpu(i) { | 477 | for_each_possible_cpu(i) { |
522 | softirq_ctx[i] = (struct thread_info *) | 478 | softirq_ctx[i] = (struct thread_info *) |
523 | __va(lmb_alloc_base(THREAD_SIZE, | 479 | __va(lmb_alloc_base(THREAD_SIZE, |
524 | THREAD_SIZE, 0x10000000)); | 480 | THREAD_SIZE, 0x10000000)); |
@@ -551,7 +507,7 @@ static void __init emergency_stack_init(void) | |||
551 | */ | 507 | */ |
552 | limit = min(0x10000000UL, lmb.rmo_size); | 508 | limit = min(0x10000000UL, lmb.rmo_size); |
553 | 509 | ||
554 | for_each_cpu(i) | 510 | for_each_possible_cpu(i) |
555 | paca[i].emergency_sp = | 511 | paca[i].emergency_sp = |
556 | __va(lmb_alloc_base(HW_PAGE_SIZE, 128, limit)) + HW_PAGE_SIZE; | 512 | __va(lmb_alloc_base(HW_PAGE_SIZE, 128, limit)) + HW_PAGE_SIZE; |
557 | } | 513 | } |
@@ -581,7 +537,8 @@ void __init setup_arch(char **cmdline_p) | |||
581 | panic_timeout = 180; | 537 | panic_timeout = 180; |
582 | 538 | ||
583 | if (ppc_md.panic) | 539 | if (ppc_md.panic) |
584 | notifier_chain_register(&panic_notifier_list, &ppc64_panic_block); | 540 | atomic_notifier_chain_register(&panic_notifier_list, |
541 | &ppc64_panic_block); | ||
585 | 542 | ||
586 | init_mm.start_code = PAGE_OFFSET; | 543 | init_mm.start_code = PAGE_OFFSET; |
587 | init_mm.end_code = (unsigned long) _etext; | 544 | init_mm.end_code = (unsigned long) _etext; |
@@ -603,12 +560,6 @@ void __init setup_arch(char **cmdline_p) | |||
603 | 560 | ||
604 | ppc_md.setup_arch(); | 561 | ppc_md.setup_arch(); |
605 | 562 | ||
606 | /* Use the default idle loop if the platform hasn't provided one. */ | ||
607 | if (NULL == ppc_md.idle_loop) { | ||
608 | ppc_md.idle_loop = default_idle; | ||
609 | printk(KERN_INFO "Using default idle loop\n"); | ||
610 | } | ||
611 | |||
612 | paging_init(); | 563 | paging_init(); |
613 | ppc64_boot_msg(0x15, "Setup Done"); | 564 | ppc64_boot_msg(0x15, "Setup Done"); |
614 | } | 565 | } |
@@ -673,7 +624,7 @@ void __init setup_per_cpu_areas(void) | |||
673 | size = PERCPU_ENOUGH_ROOM; | 624 | size = PERCPU_ENOUGH_ROOM; |
674 | #endif | 625 | #endif |
675 | 626 | ||
676 | for_each_cpu(i) { | 627 | for_each_possible_cpu(i) { |
677 | ptr = alloc_bootmem_node(NODE_DATA(cpu_to_node(i)), size); | 628 | ptr = alloc_bootmem_node(NODE_DATA(cpu_to_node(i)), size); |
678 | if (!ptr) | 629 | if (!ptr) |
679 | panic("Cannot allocate cpu data for CPU %d\n", i); | 630 | panic("Cannot allocate cpu data for CPU %d\n", i); |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index d7a4e814974d..01e3c08cb550 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -42,6 +42,7 @@ | |||
42 | 42 | ||
43 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
44 | #include <asm/cacheflush.h> | 44 | #include <asm/cacheflush.h> |
45 | #include <asm/syscalls.h> | ||
45 | #include <asm/sigcontext.h> | 46 | #include <asm/sigcontext.h> |
46 | #include <asm/vdso.h> | 47 | #include <asm/vdso.h> |
47 | #ifdef CONFIG_PPC64 | 48 | #ifdef CONFIG_PPC64 |
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 4324f8a8ba24..27f65b95184d 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/ppc64/kernel/signal.c | ||
3 | * | ||
4 | * PowerPC version | 2 | * PowerPC version |
5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 3 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) |
6 | * | 4 | * |
@@ -35,6 +33,7 @@ | |||
35 | #include <asm/pgtable.h> | 33 | #include <asm/pgtable.h> |
36 | #include <asm/unistd.h> | 34 | #include <asm/unistd.h> |
37 | #include <asm/cacheflush.h> | 35 | #include <asm/cacheflush.h> |
36 | #include <asm/syscalls.h> | ||
38 | #include <asm/vdso.h> | 37 | #include <asm/vdso.h> |
39 | 38 | ||
40 | #define DEBUG_SIG 0 | 39 | #define DEBUG_SIG 0 |
@@ -213,7 +212,7 @@ static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs | |||
213 | /* Default to using normal stack */ | 212 | /* Default to using normal stack */ |
214 | newsp = regs->gpr[1]; | 213 | newsp = regs->gpr[1]; |
215 | 214 | ||
216 | if (ka->sa.sa_flags & SA_ONSTACK) { | 215 | if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) { |
217 | if (! on_sig_stack(regs->gpr[1])) | 216 | if (! on_sig_stack(regs->gpr[1])) |
218 | newsp = (current->sas_ss_sp + current->sas_ss_size); | 217 | newsp = (current->sas_ss_sp + current->sas_ss_size); |
219 | } | 218 | } |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 13595a64f013..530f7dba0bd2 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -362,7 +362,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
362 | 362 | ||
363 | smp_space_timers(max_cpus); | 363 | smp_space_timers(max_cpus); |
364 | 364 | ||
365 | for_each_cpu(cpu) | 365 | for_each_possible_cpu(cpu) |
366 | if (cpu != boot_cpuid) | 366 | if (cpu != boot_cpuid) |
367 | smp_create_idle(cpu); | 367 | smp_create_idle(cpu); |
368 | } | 368 | } |
@@ -541,7 +541,7 @@ int __devinit start_secondary(void *unused) | |||
541 | smp_ops->take_timebase(); | 541 | smp_ops->take_timebase(); |
542 | 542 | ||
543 | if (system_state > SYSTEM_BOOTING) | 543 | if (system_state > SYSTEM_BOOTING) |
544 | per_cpu(last_jiffy, cpu) = get_tb(); | 544 | snapshot_timebase(); |
545 | 545 | ||
546 | spin_lock(&call_lock); | 546 | spin_lock(&call_lock); |
547 | cpu_set(cpu, cpu_online_map); | 547 | cpu_set(cpu, cpu_online_map); |
@@ -573,6 +573,8 @@ void __init smp_cpus_done(unsigned int max_cpus) | |||
573 | 573 | ||
574 | set_cpus_allowed(current, old_mask); | 574 | set_cpus_allowed(current, old_mask); |
575 | 575 | ||
576 | snapshot_timebases(); | ||
577 | |||
576 | dump_numa_cpu_topology(); | 578 | dump_numa_cpu_topology(); |
577 | } | 579 | } |
578 | 580 | ||
diff --git a/arch/powerpc/kernel/swsusp_32.S b/arch/powerpc/kernel/swsusp_32.S new file mode 100644 index 000000000000..69773cc1a85f --- /dev/null +++ b/arch/powerpc/kernel/swsusp_32.S | |||
@@ -0,0 +1,349 @@ | |||
1 | #include <linux/config.h> | ||
2 | #include <linux/threads.h> | ||
3 | #include <asm/processor.h> | ||
4 | #include <asm/page.h> | ||
5 | #include <asm/cputable.h> | ||
6 | #include <asm/thread_info.h> | ||
7 | #include <asm/ppc_asm.h> | ||
8 | #include <asm/asm-offsets.h> | ||
9 | |||
10 | |||
11 | /* | ||
12 | * Structure for storing CPU registers on the save area. | ||
13 | */ | ||
14 | #define SL_SP 0 | ||
15 | #define SL_PC 4 | ||
16 | #define SL_MSR 8 | ||
17 | #define SL_SDR1 0xc | ||
18 | #define SL_SPRG0 0x10 /* 4 sprg's */ | ||
19 | #define SL_DBAT0 0x20 | ||
20 | #define SL_IBAT0 0x28 | ||
21 | #define SL_DBAT1 0x30 | ||
22 | #define SL_IBAT1 0x38 | ||
23 | #define SL_DBAT2 0x40 | ||
24 | #define SL_IBAT2 0x48 | ||
25 | #define SL_DBAT3 0x50 | ||
26 | #define SL_IBAT3 0x58 | ||
27 | #define SL_TB 0x60 | ||
28 | #define SL_R2 0x68 | ||
29 | #define SL_CR 0x6c | ||
30 | #define SL_LR 0x70 | ||
31 | #define SL_R12 0x74 /* r12 to r31 */ | ||
32 | #define SL_SIZE (SL_R12 + 80) | ||
33 | |||
34 | .section .data | ||
35 | .align 5 | ||
36 | |||
37 | _GLOBAL(swsusp_save_area) | ||
38 | .space SL_SIZE | ||
39 | |||
40 | |||
41 | .section .text | ||
42 | .align 5 | ||
43 | |||
44 | _GLOBAL(swsusp_arch_suspend) | ||
45 | |||
46 | lis r11,swsusp_save_area@h | ||
47 | ori r11,r11,swsusp_save_area@l | ||
48 | |||
49 | mflr r0 | ||
50 | stw r0,SL_LR(r11) | ||
51 | mfcr r0 | ||
52 | stw r0,SL_CR(r11) | ||
53 | stw r1,SL_SP(r11) | ||
54 | stw r2,SL_R2(r11) | ||
55 | stmw r12,SL_R12(r11) | ||
56 | |||
57 | /* Save MSR & SDR1 */ | ||
58 | mfmsr r4 | ||
59 | stw r4,SL_MSR(r11) | ||
60 | mfsdr1 r4 | ||
61 | stw r4,SL_SDR1(r11) | ||
62 | |||
63 | /* Get a stable timebase and save it */ | ||
64 | 1: mftbu r4 | ||
65 | stw r4,SL_TB(r11) | ||
66 | mftb r5 | ||
67 | stw r5,SL_TB+4(r11) | ||
68 | mftbu r3 | ||
69 | cmpw r3,r4 | ||
70 | bne 1b | ||
71 | |||
72 | /* Save SPRGs */ | ||
73 | mfsprg r4,0 | ||
74 | stw r4,SL_SPRG0(r11) | ||
75 | mfsprg r4,1 | ||
76 | stw r4,SL_SPRG0+4(r11) | ||
77 | mfsprg r4,2 | ||
78 | stw r4,SL_SPRG0+8(r11) | ||
79 | mfsprg r4,3 | ||
80 | stw r4,SL_SPRG0+12(r11) | ||
81 | |||
82 | /* Save BATs */ | ||
83 | mfdbatu r4,0 | ||
84 | stw r4,SL_DBAT0(r11) | ||
85 | mfdbatl r4,0 | ||
86 | stw r4,SL_DBAT0+4(r11) | ||
87 | mfdbatu r4,1 | ||
88 | stw r4,SL_DBAT1(r11) | ||
89 | mfdbatl r4,1 | ||
90 | stw r4,SL_DBAT1+4(r11) | ||
91 | mfdbatu r4,2 | ||
92 | stw r4,SL_DBAT2(r11) | ||
93 | mfdbatl r4,2 | ||
94 | stw r4,SL_DBAT2+4(r11) | ||
95 | mfdbatu r4,3 | ||
96 | stw r4,SL_DBAT3(r11) | ||
97 | mfdbatl r4,3 | ||
98 | stw r4,SL_DBAT3+4(r11) | ||
99 | mfibatu r4,0 | ||
100 | stw r4,SL_IBAT0(r11) | ||
101 | mfibatl r4,0 | ||
102 | stw r4,SL_IBAT0+4(r11) | ||
103 | mfibatu r4,1 | ||
104 | stw r4,SL_IBAT1(r11) | ||
105 | mfibatl r4,1 | ||
106 | stw r4,SL_IBAT1+4(r11) | ||
107 | mfibatu r4,2 | ||
108 | stw r4,SL_IBAT2(r11) | ||
109 | mfibatl r4,2 | ||
110 | stw r4,SL_IBAT2+4(r11) | ||
111 | mfibatu r4,3 | ||
112 | stw r4,SL_IBAT3(r11) | ||
113 | mfibatl r4,3 | ||
114 | stw r4,SL_IBAT3+4(r11) | ||
115 | |||
116 | #if 0 | ||
117 | /* Backup various CPU config stuffs */ | ||
118 | bl __save_cpu_setup | ||
119 | #endif | ||
120 | /* Call the low level suspend stuff (we should probably have made | ||
121 | * a stackframe... | ||
122 | */ | ||
123 | bl swsusp_save | ||
124 | |||
125 | /* Restore LR from the save area */ | ||
126 | lis r11,swsusp_save_area@h | ||
127 | ori r11,r11,swsusp_save_area@l | ||
128 | lwz r0,SL_LR(r11) | ||
129 | mtlr r0 | ||
130 | |||
131 | blr | ||
132 | |||
133 | |||
134 | /* Resume code */ | ||
135 | _GLOBAL(swsusp_arch_resume) | ||
136 | |||
137 | /* Stop pending alitvec streams and memory accesses */ | ||
138 | BEGIN_FTR_SECTION | ||
139 | DSSALL | ||
140 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | ||
141 | sync | ||
142 | |||
143 | /* Disable MSR:DR to make sure we don't take a TLB or | ||
144 | * hash miss during the copy, as our hash table will | ||
145 | * for a while be unuseable. For .text, we assume we are | ||
146 | * covered by a BAT. This works only for non-G5 at this | ||
147 | * point. G5 will need a better approach, possibly using | ||
148 | * a small temporary hash table filled with large mappings, | ||
149 | * disabling the MMU completely isn't a good option for | ||
150 | * performance reasons. | ||
151 | * (Note that 750's may have the same performance issue as | ||
152 | * the G5 in this case, we should investigate using moving | ||
153 | * BATs for these CPUs) | ||
154 | */ | ||
155 | mfmsr r0 | ||
156 | sync | ||
157 | rlwinm r0,r0,0,28,26 /* clear MSR_DR */ | ||
158 | mtmsr r0 | ||
159 | sync | ||
160 | isync | ||
161 | |||
162 | /* Load ptr the list of pages to copy in r3 */ | ||
163 | lis r11,(pagedir_nosave - KERNELBASE)@h | ||
164 | ori r11,r11,pagedir_nosave@l | ||
165 | lwz r10,0(r11) | ||
166 | |||
167 | /* Copy the pages. This is a very basic implementation, to | ||
168 | * be replaced by something more cache efficient */ | ||
169 | 1: | ||
170 | tophys(r3,r10) | ||
171 | li r0,256 | ||
172 | mtctr r0 | ||
173 | lwz r11,pbe_address(r3) /* source */ | ||
174 | tophys(r5,r11) | ||
175 | lwz r10,pbe_orig_address(r3) /* destination */ | ||
176 | tophys(r6,r10) | ||
177 | 2: | ||
178 | lwz r8,0(r5) | ||
179 | lwz r9,4(r5) | ||
180 | lwz r10,8(r5) | ||
181 | lwz r11,12(r5) | ||
182 | addi r5,r5,16 | ||
183 | stw r8,0(r6) | ||
184 | stw r9,4(r6) | ||
185 | stw r10,8(r6) | ||
186 | stw r11,12(r6) | ||
187 | addi r6,r6,16 | ||
188 | bdnz 2b | ||
189 | lwz r10,pbe_next(r3) | ||
190 | cmpwi 0,r10,0 | ||
191 | bne 1b | ||
192 | |||
193 | /* Do a very simple cache flush/inval of the L1 to ensure | ||
194 | * coherency of the icache | ||
195 | */ | ||
196 | lis r3,0x0002 | ||
197 | mtctr r3 | ||
198 | li r3, 0 | ||
199 | 1: | ||
200 | lwz r0,0(r3) | ||
201 | addi r3,r3,0x0020 | ||
202 | bdnz 1b | ||
203 | isync | ||
204 | sync | ||
205 | |||
206 | /* Now flush those cache lines */ | ||
207 | lis r3,0x0002 | ||
208 | mtctr r3 | ||
209 | li r3, 0 | ||
210 | 1: | ||
211 | dcbf 0,r3 | ||
212 | addi r3,r3,0x0020 | ||
213 | bdnz 1b | ||
214 | sync | ||
215 | |||
216 | /* Ok, we are now running with the kernel data of the old | ||
217 | * kernel fully restored. We can get to the save area | ||
218 | * easily now. As for the rest of the code, it assumes the | ||
219 | * loader kernel and the booted one are exactly identical | ||
220 | */ | ||
221 | lis r11,swsusp_save_area@h | ||
222 | ori r11,r11,swsusp_save_area@l | ||
223 | tophys(r11,r11) | ||
224 | |||
225 | #if 0 | ||
226 | /* Restore various CPU config stuffs */ | ||
227 | bl __restore_cpu_setup | ||
228 | #endif | ||
229 | /* Restore the BATs, and SDR1. Then we can turn on the MMU. | ||
230 | * This is a bit hairy as we are running out of those BATs, | ||
231 | * but first, our code is probably in the icache, and we are | ||
232 | * writing the same value to the BAT, so that should be fine, | ||
233 | * though a better solution will have to be found long-term | ||
234 | */ | ||
235 | lwz r4,SL_SDR1(r11) | ||
236 | mtsdr1 r4 | ||
237 | lwz r4,SL_SPRG0(r11) | ||
238 | mtsprg 0,r4 | ||
239 | lwz r4,SL_SPRG0+4(r11) | ||
240 | mtsprg 1,r4 | ||
241 | lwz r4,SL_SPRG0+8(r11) | ||
242 | mtsprg 2,r4 | ||
243 | lwz r4,SL_SPRG0+12(r11) | ||
244 | mtsprg 3,r4 | ||
245 | |||
246 | #if 0 | ||
247 | lwz r4,SL_DBAT0(r11) | ||
248 | mtdbatu 0,r4 | ||
249 | lwz r4,SL_DBAT0+4(r11) | ||
250 | mtdbatl 0,r4 | ||
251 | lwz r4,SL_DBAT1(r11) | ||
252 | mtdbatu 1,r4 | ||
253 | lwz r4,SL_DBAT1+4(r11) | ||
254 | mtdbatl 1,r4 | ||
255 | lwz r4,SL_DBAT2(r11) | ||
256 | mtdbatu 2,r4 | ||
257 | lwz r4,SL_DBAT2+4(r11) | ||
258 | mtdbatl 2,r4 | ||
259 | lwz r4,SL_DBAT3(r11) | ||
260 | mtdbatu 3,r4 | ||
261 | lwz r4,SL_DBAT3+4(r11) | ||
262 | mtdbatl 3,r4 | ||
263 | lwz r4,SL_IBAT0(r11) | ||
264 | mtibatu 0,r4 | ||
265 | lwz r4,SL_IBAT0+4(r11) | ||
266 | mtibatl 0,r4 | ||
267 | lwz r4,SL_IBAT1(r11) | ||
268 | mtibatu 1,r4 | ||
269 | lwz r4,SL_IBAT1+4(r11) | ||
270 | mtibatl 1,r4 | ||
271 | lwz r4,SL_IBAT2(r11) | ||
272 | mtibatu 2,r4 | ||
273 | lwz r4,SL_IBAT2+4(r11) | ||
274 | mtibatl 2,r4 | ||
275 | lwz r4,SL_IBAT3(r11) | ||
276 | mtibatu 3,r4 | ||
277 | lwz r4,SL_IBAT3+4(r11) | ||
278 | mtibatl 3,r4 | ||
279 | #endif | ||
280 | |||
281 | BEGIN_FTR_SECTION | ||
282 | li r4,0 | ||
283 | mtspr SPRN_DBAT4U,r4 | ||
284 | mtspr SPRN_DBAT4L,r4 | ||
285 | mtspr SPRN_DBAT5U,r4 | ||
286 | mtspr SPRN_DBAT5L,r4 | ||
287 | mtspr SPRN_DBAT6U,r4 | ||
288 | mtspr SPRN_DBAT6L,r4 | ||
289 | mtspr SPRN_DBAT7U,r4 | ||
290 | mtspr SPRN_DBAT7L,r4 | ||
291 | mtspr SPRN_IBAT4U,r4 | ||
292 | mtspr SPRN_IBAT4L,r4 | ||
293 | mtspr SPRN_IBAT5U,r4 | ||
294 | mtspr SPRN_IBAT5L,r4 | ||
295 | mtspr SPRN_IBAT6U,r4 | ||
296 | mtspr SPRN_IBAT6L,r4 | ||
297 | mtspr SPRN_IBAT7U,r4 | ||
298 | mtspr SPRN_IBAT7L,r4 | ||
299 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS) | ||
300 | |||
301 | /* Flush all TLBs */ | ||
302 | lis r4,0x1000 | ||
303 | 1: addic. r4,r4,-0x1000 | ||
304 | tlbie r4 | ||
305 | blt 1b | ||
306 | sync | ||
307 | |||
308 | /* restore the MSR and turn on the MMU */ | ||
309 | lwz r3,SL_MSR(r11) | ||
310 | bl turn_on_mmu | ||
311 | tovirt(r11,r11) | ||
312 | |||
313 | /* Restore TB */ | ||
314 | li r3,0 | ||
315 | mttbl r3 | ||
316 | lwz r3,SL_TB(r11) | ||
317 | lwz r4,SL_TB+4(r11) | ||
318 | mttbu r3 | ||
319 | mttbl r4 | ||
320 | |||
321 | /* Kick decrementer */ | ||
322 | li r0,1 | ||
323 | mtdec r0 | ||
324 | |||
325 | /* Restore the callee-saved registers and return */ | ||
326 | lwz r0,SL_CR(r11) | ||
327 | mtcr r0 | ||
328 | lwz r2,SL_R2(r11) | ||
329 | lmw r12,SL_R12(r11) | ||
330 | lwz r1,SL_SP(r11) | ||
331 | lwz r0,SL_LR(r11) | ||
332 | mtlr r0 | ||
333 | |||
334 | // XXX Note: we don't really need to call swsusp_resume | ||
335 | |||
336 | li r3,0 | ||
337 | blr | ||
338 | |||
339 | /* FIXME:This construct is actually not useful since we don't shut | ||
340 | * down the instruction MMU, we could just flip back MSR-DR on. | ||
341 | */ | ||
342 | turn_on_mmu: | ||
343 | mflr r4 | ||
344 | mtsrr0 r4 | ||
345 | mtsrr1 r3 | ||
346 | sync | ||
347 | isync | ||
348 | rfi | ||
349 | |||
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index cd75ab2908fa..ec274e688816 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/resource.h> | 24 | #include <linux/resource.h> |
25 | #include <linux/times.h> | 25 | #include <linux/times.h> |
26 | #include <linux/utsname.h> | 26 | #include <linux/utsname.h> |
27 | #include <linux/timex.h> | ||
28 | #include <linux/smp.h> | 27 | #include <linux/smp.h> |
29 | #include <linux/smp_lock.h> | 28 | #include <linux/smp_lock.h> |
30 | #include <linux/sem.h> | 29 | #include <linux/sem.h> |
@@ -161,78 +160,6 @@ asmlinkage long compat_sys_sysfs(u32 option, u32 arg1, u32 arg2) | |||
161 | return sys_sysfs((int)option, arg1, arg2); | 160 | return sys_sysfs((int)option, arg1, arg2); |
162 | } | 161 | } |
163 | 162 | ||
164 | /* Handle adjtimex compatibility. */ | ||
165 | struct timex32 { | ||
166 | u32 modes; | ||
167 | s32 offset, freq, maxerror, esterror; | ||
168 | s32 status, constant, precision, tolerance; | ||
169 | struct compat_timeval time; | ||
170 | s32 tick; | ||
171 | s32 ppsfreq, jitter, shift, stabil; | ||
172 | s32 jitcnt, calcnt, errcnt, stbcnt; | ||
173 | s32 :32; s32 :32; s32 :32; s32 :32; | ||
174 | s32 :32; s32 :32; s32 :32; s32 :32; | ||
175 | s32 :32; s32 :32; s32 :32; s32 :32; | ||
176 | }; | ||
177 | |||
178 | extern int do_adjtimex(struct timex *); | ||
179 | |||
180 | asmlinkage long compat_sys_adjtimex(struct timex32 __user *utp) | ||
181 | { | ||
182 | struct timex txc; | ||
183 | int ret; | ||
184 | |||
185 | memset(&txc, 0, sizeof(struct timex)); | ||
186 | |||
187 | if(get_user(txc.modes, &utp->modes) || | ||
188 | __get_user(txc.offset, &utp->offset) || | ||
189 | __get_user(txc.freq, &utp->freq) || | ||
190 | __get_user(txc.maxerror, &utp->maxerror) || | ||
191 | __get_user(txc.esterror, &utp->esterror) || | ||
192 | __get_user(txc.status, &utp->status) || | ||
193 | __get_user(txc.constant, &utp->constant) || | ||
194 | __get_user(txc.precision, &utp->precision) || | ||
195 | __get_user(txc.tolerance, &utp->tolerance) || | ||
196 | __get_user(txc.time.tv_sec, &utp->time.tv_sec) || | ||
197 | __get_user(txc.time.tv_usec, &utp->time.tv_usec) || | ||
198 | __get_user(txc.tick, &utp->tick) || | ||
199 | __get_user(txc.ppsfreq, &utp->ppsfreq) || | ||
200 | __get_user(txc.jitter, &utp->jitter) || | ||
201 | __get_user(txc.shift, &utp->shift) || | ||
202 | __get_user(txc.stabil, &utp->stabil) || | ||
203 | __get_user(txc.jitcnt, &utp->jitcnt) || | ||
204 | __get_user(txc.calcnt, &utp->calcnt) || | ||
205 | __get_user(txc.errcnt, &utp->errcnt) || | ||
206 | __get_user(txc.stbcnt, &utp->stbcnt)) | ||
207 | return -EFAULT; | ||
208 | |||
209 | ret = do_adjtimex(&txc); | ||
210 | |||
211 | if(put_user(txc.modes, &utp->modes) || | ||
212 | __put_user(txc.offset, &utp->offset) || | ||
213 | __put_user(txc.freq, &utp->freq) || | ||
214 | __put_user(txc.maxerror, &utp->maxerror) || | ||
215 | __put_user(txc.esterror, &utp->esterror) || | ||
216 | __put_user(txc.status, &utp->status) || | ||
217 | __put_user(txc.constant, &utp->constant) || | ||
218 | __put_user(txc.precision, &utp->precision) || | ||
219 | __put_user(txc.tolerance, &utp->tolerance) || | ||
220 | __put_user(txc.time.tv_sec, &utp->time.tv_sec) || | ||
221 | __put_user(txc.time.tv_usec, &utp->time.tv_usec) || | ||
222 | __put_user(txc.tick, &utp->tick) || | ||
223 | __put_user(txc.ppsfreq, &utp->ppsfreq) || | ||
224 | __put_user(txc.jitter, &utp->jitter) || | ||
225 | __put_user(txc.shift, &utp->shift) || | ||
226 | __put_user(txc.stabil, &utp->stabil) || | ||
227 | __put_user(txc.jitcnt, &utp->jitcnt) || | ||
228 | __put_user(txc.calcnt, &utp->calcnt) || | ||
229 | __put_user(txc.errcnt, &utp->errcnt) || | ||
230 | __put_user(txc.stbcnt, &utp->stbcnt)) | ||
231 | ret = -EFAULT; | ||
232 | |||
233 | return ret; | ||
234 | } | ||
235 | |||
236 | asmlinkage long compat_sys_pause(void) | 163 | asmlinkage long compat_sys_pause(void) |
237 | { | 164 | { |
238 | current->state = TASK_INTERRUPTIBLE; | 165 | current->state = TASK_INTERRUPTIBLE; |
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c index ad895c99813b..9b69d99a9103 100644 --- a/arch/powerpc/kernel/syscalls.c +++ b/arch/powerpc/kernel/syscalls.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
41 | #include <asm/ipc.h> | 41 | #include <asm/ipc.h> |
42 | #include <asm/semaphore.h> | 42 | #include <asm/semaphore.h> |
43 | #include <asm/syscalls.h> | ||
43 | #include <asm/time.h> | 44 | #include <asm/time.h> |
44 | #include <asm/unistd.h> | 45 | #include <asm/unistd.h> |
45 | 46 | ||
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 0f0c3a9ae2e5..73560ef6f802 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
@@ -65,20 +65,20 @@ static int __init smt_setup(void) | |||
65 | unsigned int cpu; | 65 | unsigned int cpu; |
66 | 66 | ||
67 | if (!cpu_has_feature(CPU_FTR_SMT)) | 67 | if (!cpu_has_feature(CPU_FTR_SMT)) |
68 | return 1; | 68 | return -ENODEV; |
69 | 69 | ||
70 | options = find_path_device("/options"); | 70 | options = find_path_device("/options"); |
71 | if (!options) | 71 | if (!options) |
72 | return 1; | 72 | return -ENODEV; |
73 | 73 | ||
74 | val = (unsigned int *)get_property(options, "ibm,smt-snooze-delay", | 74 | val = (unsigned int *)get_property(options, "ibm,smt-snooze-delay", |
75 | NULL); | 75 | NULL); |
76 | if (!smt_snooze_cmdline && val) { | 76 | if (!smt_snooze_cmdline && val) { |
77 | for_each_cpu(cpu) | 77 | for_each_possible_cpu(cpu) |
78 | per_cpu(smt_snooze_delay, cpu) = *val; | 78 | per_cpu(smt_snooze_delay, cpu) = *val; |
79 | } | 79 | } |
80 | 80 | ||
81 | return 1; | 81 | return 0; |
82 | } | 82 | } |
83 | __initcall(smt_setup); | 83 | __initcall(smt_setup); |
84 | 84 | ||
@@ -93,7 +93,7 @@ static int __init setup_smt_snooze_delay(char *str) | |||
93 | smt_snooze_cmdline = 1; | 93 | smt_snooze_cmdline = 1; |
94 | 94 | ||
95 | if (get_option(&str, &snooze)) { | 95 | if (get_option(&str, &snooze)) { |
96 | for_each_cpu(cpu) | 96 | for_each_possible_cpu(cpu) |
97 | per_cpu(smt_snooze_delay, cpu) = snooze; | 97 | per_cpu(smt_snooze_delay, cpu) = snooze; |
98 | } | 98 | } |
99 | 99 | ||
@@ -347,7 +347,7 @@ static int __init topology_init(void) | |||
347 | 347 | ||
348 | register_cpu_notifier(&sysfs_cpu_nb); | 348 | register_cpu_notifier(&sysfs_cpu_nb); |
349 | 349 | ||
350 | for_each_cpu(cpu) { | 350 | for_each_possible_cpu(cpu) { |
351 | struct cpu *c = &per_cpu(cpu_devices, cpu); | 351 | struct cpu *c = &per_cpu(cpu_devices, cpu); |
352 | 352 | ||
353 | #ifdef CONFIG_NUMA | 353 | #ifdef CONFIG_NUMA |
diff --git a/arch/powerpc/kernel/tau_6xx.c b/arch/powerpc/kernel/tau_6xx.c new file mode 100644 index 000000000000..26bd8ea35a4e --- /dev/null +++ b/arch/powerpc/kernel/tau_6xx.c | |||
@@ -0,0 +1,271 @@ | |||
1 | /* | ||
2 | * temp.c Thermal management for cpu's with Thermal Assist Units | ||
3 | * | ||
4 | * Written by Troy Benjegerdes <hozer@drgw.net> | ||
5 | * | ||
6 | * TODO: | ||
7 | * dynamic power management to limit peak CPU temp (using ICTC) | ||
8 | * calibration??? | ||
9 | * | ||
10 | * Silly, crazy ideas: use cpu load (from scheduler) and ICTC to extend battery | ||
11 | * life in portables, and add a 'performance/watt' metric somewhere in /proc | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/jiffies.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/param.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/init.h> | ||
23 | |||
24 | #include <asm/io.h> | ||
25 | #include <asm/reg.h> | ||
26 | #include <asm/nvram.h> | ||
27 | #include <asm/cache.h> | ||
28 | #include <asm/8xx_immap.h> | ||
29 | #include <asm/machdep.h> | ||
30 | |||
31 | static struct tau_temp | ||
32 | { | ||
33 | int interrupts; | ||
34 | unsigned char low; | ||
35 | unsigned char high; | ||
36 | unsigned char grew; | ||
37 | } tau[NR_CPUS]; | ||
38 | |||
39 | struct timer_list tau_timer; | ||
40 | |||
41 | #undef DEBUG | ||
42 | |||
43 | /* TODO: put these in a /proc interface, with some sanity checks, and maybe | ||
44 | * dynamic adjustment to minimize # of interrupts */ | ||
45 | /* configurable values for step size and how much to expand the window when | ||
46 | * we get an interrupt. These are based on the limit that was out of range */ | ||
47 | #define step_size 2 /* step size when temp goes out of range */ | ||
48 | #define window_expand 1 /* expand the window by this much */ | ||
49 | /* configurable values for shrinking the window */ | ||
50 | #define shrink_timer 2*HZ /* period between shrinking the window */ | ||
51 | #define min_window 2 /* minimum window size, degrees C */ | ||
52 | |||
53 | void set_thresholds(unsigned long cpu) | ||
54 | { | ||
55 | #ifdef CONFIG_TAU_INT | ||
56 | /* | ||
57 | * setup THRM1, | ||
58 | * threshold, valid bit, enable interrupts, interrupt when below threshold | ||
59 | */ | ||
60 | mtspr(SPRN_THRM1, THRM1_THRES(tau[cpu].low) | THRM1_V | THRM1_TIE | THRM1_TID); | ||
61 | |||
62 | /* setup THRM2, | ||
63 | * threshold, valid bit, enable interrupts, interrupt when above threshhold | ||
64 | */ | ||
65 | mtspr (SPRN_THRM2, THRM1_THRES(tau[cpu].high) | THRM1_V | THRM1_TIE); | ||
66 | #else | ||
67 | /* same thing but don't enable interrupts */ | ||
68 | mtspr(SPRN_THRM1, THRM1_THRES(tau[cpu].low) | THRM1_V | THRM1_TID); | ||
69 | mtspr(SPRN_THRM2, THRM1_THRES(tau[cpu].high) | THRM1_V); | ||
70 | #endif | ||
71 | } | ||
72 | |||
73 | void TAUupdate(int cpu) | ||
74 | { | ||
75 | unsigned thrm; | ||
76 | |||
77 | #ifdef DEBUG | ||
78 | printk("TAUupdate "); | ||
79 | #endif | ||
80 | |||
81 | /* if both thresholds are crossed, the step_sizes cancel out | ||
82 | * and the window winds up getting expanded twice. */ | ||
83 | if((thrm = mfspr(SPRN_THRM1)) & THRM1_TIV){ /* is valid? */ | ||
84 | if(thrm & THRM1_TIN){ /* crossed low threshold */ | ||
85 | if (tau[cpu].low >= step_size){ | ||
86 | tau[cpu].low -= step_size; | ||
87 | tau[cpu].high -= (step_size - window_expand); | ||
88 | } | ||
89 | tau[cpu].grew = 1; | ||
90 | #ifdef DEBUG | ||
91 | printk("low threshold crossed "); | ||
92 | #endif | ||
93 | } | ||
94 | } | ||
95 | if((thrm = mfspr(SPRN_THRM2)) & THRM1_TIV){ /* is valid? */ | ||
96 | if(thrm & THRM1_TIN){ /* crossed high threshold */ | ||
97 | if (tau[cpu].high <= 127-step_size){ | ||
98 | tau[cpu].low += (step_size - window_expand); | ||
99 | tau[cpu].high += step_size; | ||
100 | } | ||
101 | tau[cpu].grew = 1; | ||
102 | #ifdef DEBUG | ||
103 | printk("high threshold crossed "); | ||
104 | #endif | ||
105 | } | ||
106 | } | ||
107 | |||
108 | #ifdef DEBUG | ||
109 | printk("grew = %d\n", tau[cpu].grew); | ||
110 | #endif | ||
111 | |||
112 | #ifndef CONFIG_TAU_INT /* tau_timeout will do this if not using interrupts */ | ||
113 | set_thresholds(cpu); | ||
114 | #endif | ||
115 | |||
116 | } | ||
117 | |||
118 | #ifdef CONFIG_TAU_INT | ||
119 | /* | ||
120 | * TAU interrupts - called when we have a thermal assist unit interrupt | ||
121 | * with interrupts disabled | ||
122 | */ | ||
123 | |||
124 | void TAUException(struct pt_regs * regs) | ||
125 | { | ||
126 | int cpu = smp_processor_id(); | ||
127 | |||
128 | irq_enter(); | ||
129 | tau[cpu].interrupts++; | ||
130 | |||
131 | TAUupdate(cpu); | ||
132 | |||
133 | irq_exit(); | ||
134 | } | ||
135 | #endif /* CONFIG_TAU_INT */ | ||
136 | |||
137 | static void tau_timeout(void * info) | ||
138 | { | ||
139 | int cpu; | ||
140 | unsigned long flags; | ||
141 | int size; | ||
142 | int shrink; | ||
143 | |||
144 | /* disabling interrupts *should* be okay */ | ||
145 | local_irq_save(flags); | ||
146 | cpu = smp_processor_id(); | ||
147 | |||
148 | #ifndef CONFIG_TAU_INT | ||
149 | TAUupdate(cpu); | ||
150 | #endif | ||
151 | |||
152 | size = tau[cpu].high - tau[cpu].low; | ||
153 | if (size > min_window && ! tau[cpu].grew) { | ||
154 | /* do an exponential shrink of half the amount currently over size */ | ||
155 | shrink = (2 + size - min_window) / 4; | ||
156 | if (shrink) { | ||
157 | tau[cpu].low += shrink; | ||
158 | tau[cpu].high -= shrink; | ||
159 | } else { /* size must have been min_window + 1 */ | ||
160 | tau[cpu].low += 1; | ||
161 | #if 1 /* debug */ | ||
162 | if ((tau[cpu].high - tau[cpu].low) != min_window){ | ||
163 | printk(KERN_ERR "temp.c: line %d, logic error\n", __LINE__); | ||
164 | } | ||
165 | #endif | ||
166 | } | ||
167 | } | ||
168 | |||
169 | tau[cpu].grew = 0; | ||
170 | |||
171 | set_thresholds(cpu); | ||
172 | |||
173 | /* | ||
174 | * Do the enable every time, since otherwise a bunch of (relatively) | ||
175 | * complex sleep code needs to be added. One mtspr every time | ||
176 | * tau_timeout is called is probably not a big deal. | ||
177 | * | ||
178 | * Enable thermal sensor and set up sample interval timer | ||
179 | * need 20 us to do the compare.. until a nice 'cpu_speed' function | ||
180 | * call is implemented, just assume a 500 mhz clock. It doesn't really | ||
181 | * matter if we take too long for a compare since it's all interrupt | ||
182 | * driven anyway. | ||
183 | * | ||
184 | * use a extra long time.. (60 us @ 500 mhz) | ||
185 | */ | ||
186 | mtspr(SPRN_THRM3, THRM3_SITV(500*60) | THRM3_E); | ||
187 | |||
188 | local_irq_restore(flags); | ||
189 | } | ||
190 | |||
191 | static void tau_timeout_smp(unsigned long unused) | ||
192 | { | ||
193 | |||
194 | /* schedule ourselves to be run again */ | ||
195 | mod_timer(&tau_timer, jiffies + shrink_timer) ; | ||
196 | on_each_cpu(tau_timeout, NULL, 1, 0); | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | * setup the TAU | ||
201 | * | ||
202 | * Set things up to use THRM1 as a temperature lower bound, and THRM2 as an upper bound. | ||
203 | * Start off at zero | ||
204 | */ | ||
205 | |||
206 | int tau_initialized = 0; | ||
207 | |||
208 | void __init TAU_init_smp(void * info) | ||
209 | { | ||
210 | unsigned long cpu = smp_processor_id(); | ||
211 | |||
212 | /* set these to a reasonable value and let the timer shrink the | ||
213 | * window */ | ||
214 | tau[cpu].low = 5; | ||
215 | tau[cpu].high = 120; | ||
216 | |||
217 | set_thresholds(cpu); | ||
218 | } | ||
219 | |||
220 | int __init TAU_init(void) | ||
221 | { | ||
222 | /* We assume in SMP that if one CPU has TAU support, they | ||
223 | * all have it --BenH | ||
224 | */ | ||
225 | if (!cpu_has_feature(CPU_FTR_TAU)) { | ||
226 | printk("Thermal assist unit not available\n"); | ||
227 | tau_initialized = 0; | ||
228 | return 1; | ||
229 | } | ||
230 | |||
231 | |||
232 | /* first, set up the window shrinking timer */ | ||
233 | init_timer(&tau_timer); | ||
234 | tau_timer.function = tau_timeout_smp; | ||
235 | tau_timer.expires = jiffies + shrink_timer; | ||
236 | add_timer(&tau_timer); | ||
237 | |||
238 | on_each_cpu(TAU_init_smp, NULL, 1, 0); | ||
239 | |||
240 | printk("Thermal assist unit "); | ||
241 | #ifdef CONFIG_TAU_INT | ||
242 | printk("using interrupts, "); | ||
243 | #else | ||
244 | printk("using timers, "); | ||
245 | #endif | ||
246 | printk("shrink_timer: %d jiffies\n", shrink_timer); | ||
247 | tau_initialized = 1; | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | __initcall(TAU_init); | ||
253 | |||
254 | /* | ||
255 | * return current temp | ||
256 | */ | ||
257 | |||
258 | u32 cpu_temp_both(unsigned long cpu) | ||
259 | { | ||
260 | return ((tau[cpu].high << 16) | tau[cpu].low); | ||
261 | } | ||
262 | |||
263 | int cpu_temp(unsigned long cpu) | ||
264 | { | ||
265 | return ((tau[cpu].high + tau[cpu].low) / 2); | ||
266 | } | ||
267 | |||
268 | int tau_interrupts(unsigned long cpu) | ||
269 | { | ||
270 | return (tau[cpu].interrupts); | ||
271 | } | ||
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 2a7ddc579379..24e3ad756de0 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/percpu.h> | 51 | #include <linux/percpu.h> |
52 | #include <linux/rtc.h> | 52 | #include <linux/rtc.h> |
53 | #include <linux/jiffies.h> | 53 | #include <linux/jiffies.h> |
54 | #include <linux/posix-timers.h> | ||
54 | 55 | ||
55 | #include <asm/io.h> | 56 | #include <asm/io.h> |
56 | #include <asm/processor.h> | 57 | #include <asm/processor.h> |
@@ -98,6 +99,7 @@ unsigned long tb_ticks_per_jiffy; | |||
98 | unsigned long tb_ticks_per_usec = 100; /* sane default */ | 99 | unsigned long tb_ticks_per_usec = 100; /* sane default */ |
99 | EXPORT_SYMBOL(tb_ticks_per_usec); | 100 | EXPORT_SYMBOL(tb_ticks_per_usec); |
100 | unsigned long tb_ticks_per_sec; | 101 | unsigned long tb_ticks_per_sec; |
102 | EXPORT_SYMBOL(tb_ticks_per_sec); /* for cputime_t conversions */ | ||
101 | u64 tb_to_xs; | 103 | u64 tb_to_xs; |
102 | unsigned tb_to_us; | 104 | unsigned tb_to_us; |
103 | 105 | ||
@@ -135,6 +137,224 @@ unsigned long tb_last_stamp; | |||
135 | */ | 137 | */ |
136 | DEFINE_PER_CPU(unsigned long, last_jiffy); | 138 | DEFINE_PER_CPU(unsigned long, last_jiffy); |
137 | 139 | ||
140 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
141 | /* | ||
142 | * Factors for converting from cputime_t (timebase ticks) to | ||
143 | * jiffies, milliseconds, seconds, and clock_t (1/USER_HZ seconds). | ||
144 | * These are all stored as 0.64 fixed-point binary fractions. | ||
145 | */ | ||
146 | u64 __cputime_jiffies_factor; | ||
147 | EXPORT_SYMBOL(__cputime_jiffies_factor); | ||
148 | u64 __cputime_msec_factor; | ||
149 | EXPORT_SYMBOL(__cputime_msec_factor); | ||
150 | u64 __cputime_sec_factor; | ||
151 | EXPORT_SYMBOL(__cputime_sec_factor); | ||
152 | u64 __cputime_clockt_factor; | ||
153 | EXPORT_SYMBOL(__cputime_clockt_factor); | ||
154 | |||
155 | static void calc_cputime_factors(void) | ||
156 | { | ||
157 | struct div_result res; | ||
158 | |||
159 | div128_by_32(HZ, 0, tb_ticks_per_sec, &res); | ||
160 | __cputime_jiffies_factor = res.result_low; | ||
161 | div128_by_32(1000, 0, tb_ticks_per_sec, &res); | ||
162 | __cputime_msec_factor = res.result_low; | ||
163 | div128_by_32(1, 0, tb_ticks_per_sec, &res); | ||
164 | __cputime_sec_factor = res.result_low; | ||
165 | div128_by_32(USER_HZ, 0, tb_ticks_per_sec, &res); | ||
166 | __cputime_clockt_factor = res.result_low; | ||
167 | } | ||
168 | |||
169 | /* | ||
170 | * Read the PURR on systems that have it, otherwise the timebase. | ||
171 | */ | ||
172 | static u64 read_purr(void) | ||
173 | { | ||
174 | if (cpu_has_feature(CPU_FTR_PURR)) | ||
175 | return mfspr(SPRN_PURR); | ||
176 | return mftb(); | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * Account time for a transition between system, hard irq | ||
181 | * or soft irq state. | ||
182 | */ | ||
183 | void account_system_vtime(struct task_struct *tsk) | ||
184 | { | ||
185 | u64 now, delta; | ||
186 | unsigned long flags; | ||
187 | |||
188 | local_irq_save(flags); | ||
189 | now = read_purr(); | ||
190 | delta = now - get_paca()->startpurr; | ||
191 | get_paca()->startpurr = now; | ||
192 | if (!in_interrupt()) { | ||
193 | delta += get_paca()->system_time; | ||
194 | get_paca()->system_time = 0; | ||
195 | } | ||
196 | account_system_time(tsk, 0, delta); | ||
197 | local_irq_restore(flags); | ||
198 | } | ||
199 | |||
200 | /* | ||
201 | * Transfer the user and system times accumulated in the paca | ||
202 | * by the exception entry and exit code to the generic process | ||
203 | * user and system time records. | ||
204 | * Must be called with interrupts disabled. | ||
205 | */ | ||
206 | void account_process_vtime(struct task_struct *tsk) | ||
207 | { | ||
208 | cputime_t utime; | ||
209 | |||
210 | utime = get_paca()->user_time; | ||
211 | get_paca()->user_time = 0; | ||
212 | account_user_time(tsk, utime); | ||
213 | } | ||
214 | |||
215 | static void account_process_time(struct pt_regs *regs) | ||
216 | { | ||
217 | int cpu = smp_processor_id(); | ||
218 | |||
219 | account_process_vtime(current); | ||
220 | run_local_timers(); | ||
221 | if (rcu_pending(cpu)) | ||
222 | rcu_check_callbacks(cpu, user_mode(regs)); | ||
223 | scheduler_tick(); | ||
224 | run_posix_cpu_timers(current); | ||
225 | } | ||
226 | |||
227 | #ifdef CONFIG_PPC_SPLPAR | ||
228 | /* | ||
229 | * Stuff for accounting stolen time. | ||
230 | */ | ||
231 | struct cpu_purr_data { | ||
232 | int initialized; /* thread is running */ | ||
233 | u64 tb0; /* timebase at origin time */ | ||
234 | u64 purr0; /* PURR at origin time */ | ||
235 | u64 tb; /* last TB value read */ | ||
236 | u64 purr; /* last PURR value read */ | ||
237 | u64 stolen; /* stolen time so far */ | ||
238 | spinlock_t lock; | ||
239 | }; | ||
240 | |||
241 | static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data); | ||
242 | |||
243 | static void snapshot_tb_and_purr(void *data) | ||
244 | { | ||
245 | struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); | ||
246 | |||
247 | p->tb0 = mftb(); | ||
248 | p->purr0 = mfspr(SPRN_PURR); | ||
249 | p->tb = p->tb0; | ||
250 | p->purr = 0; | ||
251 | wmb(); | ||
252 | p->initialized = 1; | ||
253 | } | ||
254 | |||
255 | /* | ||
256 | * Called during boot when all cpus have come up. | ||
257 | */ | ||
258 | void snapshot_timebases(void) | ||
259 | { | ||
260 | int cpu; | ||
261 | |||
262 | if (!cpu_has_feature(CPU_FTR_PURR)) | ||
263 | return; | ||
264 | for_each_possible_cpu(cpu) | ||
265 | spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock); | ||
266 | on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1); | ||
267 | } | ||
268 | |||
269 | void calculate_steal_time(void) | ||
270 | { | ||
271 | u64 tb, purr, t0; | ||
272 | s64 stolen; | ||
273 | struct cpu_purr_data *p0, *pme, *phim; | ||
274 | int cpu; | ||
275 | |||
276 | if (!cpu_has_feature(CPU_FTR_PURR)) | ||
277 | return; | ||
278 | cpu = smp_processor_id(); | ||
279 | pme = &per_cpu(cpu_purr_data, cpu); | ||
280 | if (!pme->initialized) | ||
281 | return; /* this can happen in early boot */ | ||
282 | p0 = &per_cpu(cpu_purr_data, cpu & ~1); | ||
283 | phim = &per_cpu(cpu_purr_data, cpu ^ 1); | ||
284 | spin_lock(&p0->lock); | ||
285 | tb = mftb(); | ||
286 | purr = mfspr(SPRN_PURR) - pme->purr0; | ||
287 | if (!phim->initialized || !cpu_online(cpu ^ 1)) { | ||
288 | stolen = (tb - pme->tb) - (purr - pme->purr); | ||
289 | } else { | ||
290 | t0 = pme->tb0; | ||
291 | if (phim->tb0 < t0) | ||
292 | t0 = phim->tb0; | ||
293 | stolen = phim->tb - t0 - phim->purr - purr - p0->stolen; | ||
294 | } | ||
295 | if (stolen > 0) { | ||
296 | account_steal_time(current, stolen); | ||
297 | p0->stolen += stolen; | ||
298 | } | ||
299 | pme->tb = tb; | ||
300 | pme->purr = purr; | ||
301 | spin_unlock(&p0->lock); | ||
302 | } | ||
303 | |||
304 | /* | ||
305 | * Must be called before the cpu is added to the online map when | ||
306 | * a cpu is being brought up at runtime. | ||
307 | */ | ||
308 | static void snapshot_purr(void) | ||
309 | { | ||
310 | int cpu; | ||
311 | u64 purr; | ||
312 | struct cpu_purr_data *p0, *pme, *phim; | ||
313 | unsigned long flags; | ||
314 | |||
315 | if (!cpu_has_feature(CPU_FTR_PURR)) | ||
316 | return; | ||
317 | cpu = smp_processor_id(); | ||
318 | pme = &per_cpu(cpu_purr_data, cpu); | ||
319 | p0 = &per_cpu(cpu_purr_data, cpu & ~1); | ||
320 | phim = &per_cpu(cpu_purr_data, cpu ^ 1); | ||
321 | spin_lock_irqsave(&p0->lock, flags); | ||
322 | pme->tb = pme->tb0 = mftb(); | ||
323 | purr = mfspr(SPRN_PURR); | ||
324 | if (!phim->initialized) { | ||
325 | pme->purr = 0; | ||
326 | pme->purr0 = purr; | ||
327 | } else { | ||
328 | /* set p->purr and p->purr0 for no change in p0->stolen */ | ||
329 | pme->purr = phim->tb - phim->tb0 - phim->purr - p0->stolen; | ||
330 | pme->purr0 = purr - pme->purr; | ||
331 | } | ||
332 | pme->initialized = 1; | ||
333 | spin_unlock_irqrestore(&p0->lock, flags); | ||
334 | } | ||
335 | |||
336 | #endif /* CONFIG_PPC_SPLPAR */ | ||
337 | |||
338 | #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ | ||
339 | #define calc_cputime_factors() | ||
340 | #define account_process_time(regs) update_process_times(user_mode(regs)) | ||
341 | #define calculate_steal_time() do { } while (0) | ||
342 | #endif | ||
343 | |||
344 | #if !(defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR)) | ||
345 | #define snapshot_purr() do { } while (0) | ||
346 | #endif | ||
347 | |||
348 | /* | ||
349 | * Called when a cpu comes up after the system has finished booting, | ||
350 | * i.e. as a result of a hotplug cpu action. | ||
351 | */ | ||
352 | void snapshot_timebase(void) | ||
353 | { | ||
354 | __get_cpu_var(last_jiffy) = get_tb(); | ||
355 | snapshot_purr(); | ||
356 | } | ||
357 | |||
138 | void __delay(unsigned long loops) | 358 | void __delay(unsigned long loops) |
139 | { | 359 | { |
140 | unsigned long start; | 360 | unsigned long start; |
@@ -283,9 +503,9 @@ static inline void update_gtod(u64 new_tb_stamp, u64 new_stamp_xsec, | |||
283 | * the two values of tb_update_count match and are even then the | 503 | * the two values of tb_update_count match and are even then the |
284 | * tb_to_xs and stamp_xsec values are consistent. If not, then it | 504 | * tb_to_xs and stamp_xsec values are consistent. If not, then it |
285 | * loops back and reads them again until this criteria is met. | 505 | * loops back and reads them again until this criteria is met. |
506 | * We expect the caller to have done the first increment of | ||
507 | * vdso_data->tb_update_count already. | ||
286 | */ | 508 | */ |
287 | ++(vdso_data->tb_update_count); | ||
288 | smp_wmb(); | ||
289 | vdso_data->tb_orig_stamp = new_tb_stamp; | 509 | vdso_data->tb_orig_stamp = new_tb_stamp; |
290 | vdso_data->stamp_xsec = new_stamp_xsec; | 510 | vdso_data->stamp_xsec = new_stamp_xsec; |
291 | vdso_data->tb_to_xs = new_tb_to_xs; | 511 | vdso_data->tb_to_xs = new_tb_to_xs; |
@@ -310,20 +530,15 @@ static __inline__ void timer_recalc_offset(u64 cur_tb) | |||
310 | unsigned long offset; | 530 | unsigned long offset; |
311 | u64 new_stamp_xsec; | 531 | u64 new_stamp_xsec; |
312 | u64 tlen, t2x; | 532 | u64 tlen, t2x; |
533 | u64 tb, xsec_old, xsec_new; | ||
534 | struct gettimeofday_vars *varp; | ||
313 | 535 | ||
314 | if (__USE_RTC()) | 536 | if (__USE_RTC()) |
315 | return; | 537 | return; |
316 | tlen = current_tick_length(); | 538 | tlen = current_tick_length(); |
317 | offset = cur_tb - do_gtod.varp->tb_orig_stamp; | 539 | offset = cur_tb - do_gtod.varp->tb_orig_stamp; |
318 | if (tlen == last_tick_len && offset < 0x80000000u) { | 540 | if (tlen == last_tick_len && offset < 0x80000000u) |
319 | /* check that we're still in sync; if not, resync */ | 541 | return; |
320 | struct timeval tv; | ||
321 | __do_gettimeofday(&tv, cur_tb); | ||
322 | if (tv.tv_sec <= xtime.tv_sec && | ||
323 | (tv.tv_sec < xtime.tv_sec || | ||
324 | tv.tv_usec * 1000 <= xtime.tv_nsec)) | ||
325 | return; | ||
326 | } | ||
327 | if (tlen != last_tick_len) { | 542 | if (tlen != last_tick_len) { |
328 | t2x = mulhdu(tlen << TICKLEN_SHIFT, ticklen_to_xs); | 543 | t2x = mulhdu(tlen << TICKLEN_SHIFT, ticklen_to_xs); |
329 | last_tick_len = tlen; | 544 | last_tick_len = tlen; |
@@ -332,6 +547,21 @@ static __inline__ void timer_recalc_offset(u64 cur_tb) | |||
332 | new_stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC; | 547 | new_stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC; |
333 | do_div(new_stamp_xsec, 1000000000); | 548 | do_div(new_stamp_xsec, 1000000000); |
334 | new_stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC; | 549 | new_stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC; |
550 | |||
551 | ++vdso_data->tb_update_count; | ||
552 | smp_mb(); | ||
553 | |||
554 | /* | ||
555 | * Make sure time doesn't go backwards for userspace gettimeofday. | ||
556 | */ | ||
557 | tb = get_tb(); | ||
558 | varp = do_gtod.varp; | ||
559 | xsec_old = mulhdu(tb - varp->tb_orig_stamp, varp->tb_to_xs) | ||
560 | + varp->stamp_xsec; | ||
561 | xsec_new = mulhdu(tb - cur_tb, t2x) + new_stamp_xsec; | ||
562 | if (xsec_new < xsec_old) | ||
563 | new_stamp_xsec += xsec_old - xsec_new; | ||
564 | |||
335 | update_gtod(cur_tb, new_stamp_xsec, t2x); | 565 | update_gtod(cur_tb, new_stamp_xsec, t2x); |
336 | } | 566 | } |
337 | 567 | ||
@@ -382,6 +612,7 @@ static void iSeries_tb_recal(void) | |||
382 | new_tb_ticks_per_jiffy, sign, tick_diff ); | 612 | new_tb_ticks_per_jiffy, sign, tick_diff ); |
383 | tb_ticks_per_jiffy = new_tb_ticks_per_jiffy; | 613 | tb_ticks_per_jiffy = new_tb_ticks_per_jiffy; |
384 | tb_ticks_per_sec = new_tb_ticks_per_sec; | 614 | tb_ticks_per_sec = new_tb_ticks_per_sec; |
615 | calc_cputime_factors(); | ||
385 | div128_by_32( XSEC_PER_SEC, 0, tb_ticks_per_sec, &divres ); | 616 | div128_by_32( XSEC_PER_SEC, 0, tb_ticks_per_sec, &divres ); |
386 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; | 617 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; |
387 | tb_to_xs = divres.result_low; | 618 | tb_to_xs = divres.result_low; |
@@ -430,6 +661,7 @@ void timer_interrupt(struct pt_regs * regs) | |||
430 | irq_enter(); | 661 | irq_enter(); |
431 | 662 | ||
432 | profile_tick(CPU_PROFILING, regs); | 663 | profile_tick(CPU_PROFILING, regs); |
664 | calculate_steal_time(); | ||
433 | 665 | ||
434 | #ifdef CONFIG_PPC_ISERIES | 666 | #ifdef CONFIG_PPC_ISERIES |
435 | get_lppaca()->int_dword.fields.decr_int = 0; | 667 | get_lppaca()->int_dword.fields.decr_int = 0; |
@@ -451,7 +683,7 @@ void timer_interrupt(struct pt_regs * regs) | |||
451 | * is the case. | 683 | * is the case. |
452 | */ | 684 | */ |
453 | if (!cpu_is_offline(cpu)) | 685 | if (!cpu_is_offline(cpu)) |
454 | update_process_times(user_mode(regs)); | 686 | account_process_time(regs); |
455 | 687 | ||
456 | /* | 688 | /* |
457 | * No need to check whether cpu is offline here; boot_cpuid | 689 | * No need to check whether cpu is offline here; boot_cpuid |
@@ -508,13 +740,27 @@ void wakeup_decrementer(void) | |||
508 | void __init smp_space_timers(unsigned int max_cpus) | 740 | void __init smp_space_timers(unsigned int max_cpus) |
509 | { | 741 | { |
510 | int i; | 742 | int i; |
743 | unsigned long half = tb_ticks_per_jiffy / 2; | ||
511 | unsigned long offset = tb_ticks_per_jiffy / max_cpus; | 744 | unsigned long offset = tb_ticks_per_jiffy / max_cpus; |
512 | unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); | 745 | unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); |
513 | 746 | ||
514 | /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */ | 747 | /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */ |
515 | previous_tb -= tb_ticks_per_jiffy; | 748 | previous_tb -= tb_ticks_per_jiffy; |
516 | for_each_cpu(i) { | 749 | /* |
517 | if (i != boot_cpuid) { | 750 | * The stolen time calculation for POWER5 shared-processor LPAR |
751 | * systems works better if the two threads' timebase interrupts | ||
752 | * are staggered by half a jiffy with respect to each other. | ||
753 | */ | ||
754 | for_each_possible_cpu(i) { | ||
755 | if (i == boot_cpuid) | ||
756 | continue; | ||
757 | if (i == (boot_cpuid ^ 1)) | ||
758 | per_cpu(last_jiffy, i) = | ||
759 | per_cpu(last_jiffy, boot_cpuid) - half; | ||
760 | else if (i & 1) | ||
761 | per_cpu(last_jiffy, i) = | ||
762 | per_cpu(last_jiffy, i ^ 1) + half; | ||
763 | else { | ||
518 | previous_tb += offset; | 764 | previous_tb += offset; |
519 | per_cpu(last_jiffy, i) = previous_tb; | 765 | per_cpu(last_jiffy, i) = previous_tb; |
520 | } | 766 | } |
@@ -564,6 +810,10 @@ int do_settimeofday(struct timespec *tv) | |||
564 | } | 810 | } |
565 | #endif | 811 | #endif |
566 | 812 | ||
813 | /* Make userspace gettimeofday spin until we're done. */ | ||
814 | ++vdso_data->tb_update_count; | ||
815 | smp_mb(); | ||
816 | |||
567 | /* | 817 | /* |
568 | * Subtract off the number of nanoseconds since the | 818 | * Subtract off the number of nanoseconds since the |
569 | * beginning of the last tick. | 819 | * beginning of the last tick. |
@@ -706,6 +956,7 @@ void __init time_init(void) | |||
706 | tb_ticks_per_sec = ppc_tb_freq; | 956 | tb_ticks_per_sec = ppc_tb_freq; |
707 | tb_ticks_per_usec = ppc_tb_freq / 1000000; | 957 | tb_ticks_per_usec = ppc_tb_freq / 1000000; |
708 | tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000); | 958 | tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000); |
959 | calc_cputime_factors(); | ||
709 | 960 | ||
710 | /* | 961 | /* |
711 | * Calculate the length of each tick in ns. It will not be | 962 | * Calculate the length of each tick in ns. It will not be |
@@ -724,10 +975,16 @@ void __init time_init(void) | |||
724 | * It is computed as: | 975 | * It is computed as: |
725 | * ticklen_to_xs = 2^N / (tb_ticks_per_jiffy * 1e9) | 976 | * ticklen_to_xs = 2^N / (tb_ticks_per_jiffy * 1e9) |
726 | * where N = 64 + 20 - TICKLEN_SCALE - TICKLEN_SHIFT | 977 | * where N = 64 + 20 - TICKLEN_SCALE - TICKLEN_SHIFT |
727 | * so as to give the result as a 0.64 fixed-point fraction. | 978 | * which turns out to be N = 51 - SHIFT_HZ. |
979 | * This gives the result as a 0.64 fixed-point fraction. | ||
980 | * That value is reduced by an offset amounting to 1 xsec per | ||
981 | * 2^31 timebase ticks to avoid problems with time going backwards | ||
982 | * by 1 xsec when we do timer_recalc_offset due to losing the | ||
983 | * fractional xsec. That offset is equal to ppc_tb_freq/2^51 | ||
984 | * since there are 2^20 xsec in a second. | ||
728 | */ | 985 | */ |
729 | div128_by_32(1ULL << (64 + 20 - TICKLEN_SCALE - TICKLEN_SHIFT), 0, | 986 | div128_by_32((1ULL << 51) - ppc_tb_freq, 0, |
730 | tb_ticks_per_jiffy, &res); | 987 | tb_ticks_per_jiffy << SHIFT_HZ, &res); |
731 | div128_by_32(res.result_high, res.result_low, NSEC_PER_SEC, &res); | 988 | div128_by_32(res.result_high, res.result_low, NSEC_PER_SEC, &res); |
732 | ticklen_to_xs = res.result_low; | 989 | ticklen_to_xs = res.result_low; |
733 | 990 | ||
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 98660aedeeb7..4cbde211eb69 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -74,19 +74,19 @@ EXPORT_SYMBOL(__debugger_dabr_match); | |||
74 | EXPORT_SYMBOL(__debugger_fault_handler); | 74 | EXPORT_SYMBOL(__debugger_fault_handler); |
75 | #endif | 75 | #endif |
76 | 76 | ||
77 | struct notifier_block *powerpc_die_chain; | 77 | ATOMIC_NOTIFIER_HEAD(powerpc_die_chain); |
78 | static DEFINE_SPINLOCK(die_notifier_lock); | ||
79 | 78 | ||
80 | int register_die_notifier(struct notifier_block *nb) | 79 | int register_die_notifier(struct notifier_block *nb) |
81 | { | 80 | { |
82 | int err = 0; | 81 | return atomic_notifier_chain_register(&powerpc_die_chain, nb); |
83 | unsigned long flags; | 82 | } |
83 | EXPORT_SYMBOL(register_die_notifier); | ||
84 | 84 | ||
85 | spin_lock_irqsave(&die_notifier_lock, flags); | 85 | int unregister_die_notifier(struct notifier_block *nb) |
86 | err = notifier_chain_register(&powerpc_die_chain, nb); | 86 | { |
87 | spin_unlock_irqrestore(&die_notifier_lock, flags); | 87 | return atomic_notifier_chain_unregister(&powerpc_die_chain, nb); |
88 | return err; | ||
89 | } | 88 | } |
89 | EXPORT_SYMBOL(unregister_die_notifier); | ||
90 | 90 | ||
91 | /* | 91 | /* |
92 | * Trap & Exception support | 92 | * Trap & Exception support |
@@ -97,7 +97,6 @@ static DEFINE_SPINLOCK(die_lock); | |||
97 | int die(const char *str, struct pt_regs *regs, long err) | 97 | int die(const char *str, struct pt_regs *regs, long err) |
98 | { | 98 | { |
99 | static int die_counter, crash_dump_start = 0; | 99 | static int die_counter, crash_dump_start = 0; |
100 | int nl = 0; | ||
101 | 100 | ||
102 | if (debugger(regs)) | 101 | if (debugger(regs)) |
103 | return 1; | 102 | return 1; |
@@ -106,7 +105,7 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
106 | spin_lock_irq(&die_lock); | 105 | spin_lock_irq(&die_lock); |
107 | bust_spinlocks(1); | 106 | bust_spinlocks(1); |
108 | #ifdef CONFIG_PMAC_BACKLIGHT | 107 | #ifdef CONFIG_PMAC_BACKLIGHT |
109 | if (_machine == _MACH_Pmac) { | 108 | if (machine_is(powermac)) { |
110 | set_backlight_enable(1); | 109 | set_backlight_enable(1); |
111 | set_backlight_level(BACKLIGHT_MAX); | 110 | set_backlight_level(BACKLIGHT_MAX); |
112 | } | 111 | } |
@@ -114,46 +113,18 @@ int die(const char *str, struct pt_regs *regs, long err) | |||
114 | printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); | 113 | printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); |
115 | #ifdef CONFIG_PREEMPT | 114 | #ifdef CONFIG_PREEMPT |
116 | printk("PREEMPT "); | 115 | printk("PREEMPT "); |
117 | nl = 1; | ||
118 | #endif | 116 | #endif |
119 | #ifdef CONFIG_SMP | 117 | #ifdef CONFIG_SMP |
120 | printk("SMP NR_CPUS=%d ", NR_CPUS); | 118 | printk("SMP NR_CPUS=%d ", NR_CPUS); |
121 | nl = 1; | ||
122 | #endif | 119 | #endif |
123 | #ifdef CONFIG_DEBUG_PAGEALLOC | 120 | #ifdef CONFIG_DEBUG_PAGEALLOC |
124 | printk("DEBUG_PAGEALLOC "); | 121 | printk("DEBUG_PAGEALLOC "); |
125 | nl = 1; | ||
126 | #endif | 122 | #endif |
127 | #ifdef CONFIG_NUMA | 123 | #ifdef CONFIG_NUMA |
128 | printk("NUMA "); | 124 | printk("NUMA "); |
129 | nl = 1; | ||
130 | #endif | 125 | #endif |
131 | #ifdef CONFIG_PPC64 | 126 | printk("%s\n", ppc_md.name ? "" : ppc_md.name); |
132 | switch (_machine) { | 127 | |
133 | case PLATFORM_PSERIES: | ||
134 | printk("PSERIES "); | ||
135 | nl = 1; | ||
136 | break; | ||
137 | case PLATFORM_PSERIES_LPAR: | ||
138 | printk("PSERIES LPAR "); | ||
139 | nl = 1; | ||
140 | break; | ||
141 | case PLATFORM_ISERIES_LPAR: | ||
142 | printk("ISERIES LPAR "); | ||
143 | nl = 1; | ||
144 | break; | ||
145 | case PLATFORM_POWERMAC: | ||
146 | printk("POWERMAC "); | ||
147 | nl = 1; | ||
148 | break; | ||
149 | case PLATFORM_CELL: | ||
150 | printk("CELL "); | ||
151 | nl = 1; | ||
152 | break; | ||
153 | } | ||
154 | #endif | ||
155 | if (nl) | ||
156 | printk("\n"); | ||
157 | print_modules(); | 128 | print_modules(); |
158 | show_regs(regs); | 129 | show_regs(regs); |
159 | bust_spinlocks(0); | 130 | bust_spinlocks(0); |
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 04f7df39ffbb..573afb68d69e 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/ppc64/kernel/vdso.c | ||
3 | * | ||
4 | * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp. | 2 | * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp. |
5 | * <benh@kernel.crashing.org> | 3 | * <benh@kernel.crashing.org> |
6 | * | 4 | * |
@@ -35,6 +33,7 @@ | |||
35 | #include <asm/machdep.h> | 33 | #include <asm/machdep.h> |
36 | #include <asm/cputable.h> | 34 | #include <asm/cputable.h> |
37 | #include <asm/sections.h> | 35 | #include <asm/sections.h> |
36 | #include <asm/firmware.h> | ||
38 | #include <asm/vdso.h> | 37 | #include <asm/vdso.h> |
39 | #include <asm/vdso_datapage.h> | 38 | #include <asm/vdso_datapage.h> |
40 | 39 | ||
@@ -669,7 +668,13 @@ void __init vdso_init(void) | |||
669 | vdso_data->version.major = SYSTEMCFG_MAJOR; | 668 | vdso_data->version.major = SYSTEMCFG_MAJOR; |
670 | vdso_data->version.minor = SYSTEMCFG_MINOR; | 669 | vdso_data->version.minor = SYSTEMCFG_MINOR; |
671 | vdso_data->processor = mfspr(SPRN_PVR); | 670 | vdso_data->processor = mfspr(SPRN_PVR); |
672 | vdso_data->platform = _machine; | 671 | /* |
672 | * Fake the old platform number for pSeries and iSeries and add | ||
673 | * in LPAR bit if necessary | ||
674 | */ | ||
675 | vdso_data->platform = machine_is(iseries) ? 0x200 : 0x100; | ||
676 | if (firmware_has_feature(FW_FEATURE_LPAR)) | ||
677 | vdso_data->platform |= 1; | ||
673 | vdso_data->physicalMemorySize = lmb_phys_mem_size(); | 678 | vdso_data->physicalMemorySize = lmb_phys_mem_size(); |
674 | vdso_data->dcache_size = ppc64_caches.dsize; | 679 | vdso_data->dcache_size = ppc64_caches.dsize; |
675 | vdso_data->dcache_line_size = ppc64_caches.dline_size; | 680 | vdso_data->dcache_line_size = ppc64_caches.dline_size; |
diff --git a/arch/powerpc/kernel/vdso32/sigtramp.S b/arch/powerpc/kernel/vdso32/sigtramp.S index e04642781917..0c6a37b29dde 100644 --- a/arch/powerpc/kernel/vdso32/sigtramp.S +++ b/arch/powerpc/kernel/vdso32/sigtramp.S | |||
@@ -261,7 +261,7 @@ V_FUNCTION_END(__kernel_sigtramp_rt32) | |||
261 | .Lcie_start: | 261 | .Lcie_start: |
262 | .long 0 /* CIE ID */ | 262 | .long 0 /* CIE ID */ |
263 | .byte 1 /* Version number */ | 263 | .byte 1 /* Version number */ |
264 | .string "zR" /* NUL-terminated augmentation string */ | 264 | .string "zRS" /* NUL-terminated augmentation string */ |
265 | .uleb128 4 /* Code alignment factor */ | 265 | .uleb128 4 /* Code alignment factor */ |
266 | .sleb128 -4 /* Data alignment factor */ | 266 | .sleb128 -4 /* Data alignment factor */ |
267 | .byte 67 /* Return address register column, ap */ | 267 | .byte 67 /* Return address register column, ap */ |
diff --git a/arch/powerpc/kernel/vdso64/sigtramp.S b/arch/powerpc/kernel/vdso64/sigtramp.S index 31b604ab56de..7479edb101b8 100644 --- a/arch/powerpc/kernel/vdso64/sigtramp.S +++ b/arch/powerpc/kernel/vdso64/sigtramp.S | |||
@@ -263,7 +263,7 @@ V_FUNCTION_END(__kernel_sigtramp_rt64) | |||
263 | .Lcie_start: | 263 | .Lcie_start: |
264 | .long 0 /* CIE ID */ | 264 | .long 0 /* CIE ID */ |
265 | .byte 1 /* Version number */ | 265 | .byte 1 /* Version number */ |
266 | .string "zR" /* NUL-terminated augmentation string */ | 266 | .string "zRS" /* NUL-terminated augmentation string */ |
267 | .uleb128 4 /* Code alignment factor */ | 267 | .uleb128 4 /* Code alignment factor */ |
268 | .sleb128 -8 /* Data alignment factor */ | 268 | .sleb128 -8 /* Data alignment factor */ |
269 | .byte 67 /* Return address register column, ap */ | 269 | .byte 67 /* Return address register column, ap */ |
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 7fa7b15fd8e6..fe79c2584cb0 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
@@ -1,9 +1,11 @@ | |||
1 | #include <linux/config.h> | 1 | #include <linux/config.h> |
2 | #ifdef CONFIG_PPC64 | 2 | #ifdef CONFIG_PPC64 |
3 | #include <asm/page.h> | 3 | #include <asm/page.h> |
4 | #define PROVIDE32(x) PROVIDE(__unused__##x) | ||
4 | #else | 5 | #else |
5 | #define PAGE_SIZE 4096 | 6 | #define PAGE_SIZE 4096 |
6 | #define KERNELBASE CONFIG_KERNEL_START | 7 | #define KERNELBASE CONFIG_KERNEL_START |
8 | #define PROVIDE32(x) PROVIDE(x) | ||
7 | #endif | 9 | #endif |
8 | #include <asm-generic/vmlinux.lds.h> | 10 | #include <asm-generic/vmlinux.lds.h> |
9 | 11 | ||
@@ -18,43 +20,42 @@ jiffies = jiffies_64 + 4; | |||
18 | #endif | 20 | #endif |
19 | SECTIONS | 21 | SECTIONS |
20 | { | 22 | { |
21 | /* Sections to be discarded. */ | 23 | /* Sections to be discarded. */ |
22 | /DISCARD/ : { | 24 | /DISCARD/ : { |
23 | *(.exitcall.exit) | 25 | *(.exitcall.exit) |
24 | *(.exit.data) | 26 | *(.exit.data) |
25 | } | 27 | } |
26 | |||
27 | . = KERNELBASE; | ||
28 | |||
29 | /* Read-only sections, merged into text segment: */ | ||
30 | .text : { | ||
31 | *(.text .text.*) | ||
32 | SCHED_TEXT | ||
33 | LOCK_TEXT | ||
34 | KPROBES_TEXT | ||
35 | *(.fixup) | ||
36 | #ifdef CONFIG_PPC32 | ||
37 | *(.got1) | ||
38 | __got2_start = .; | ||
39 | *(.got2) | ||
40 | __got2_end = .; | ||
41 | #else | ||
42 | . = ALIGN(PAGE_SIZE); | ||
43 | _etext = .; | ||
44 | #endif | ||
45 | } | ||
46 | #ifdef CONFIG_PPC32 | ||
47 | _etext = .; | ||
48 | PROVIDE (etext = .); | ||
49 | 28 | ||
50 | RODATA | 29 | . = KERNELBASE; |
51 | .fini : { *(.fini) } =0 | ||
52 | .ctors : { *(.ctors) } | ||
53 | .dtors : { *(.dtors) } | ||
54 | 30 | ||
55 | .fixup : { *(.fixup) } | 31 | /* |
56 | #endif | 32 | * Text, read only data and other permanent read-only sections |
33 | */ | ||
34 | |||
35 | /* Text and gots */ | ||
36 | .text : { | ||
37 | *(.text .text.*) | ||
38 | SCHED_TEXT | ||
39 | LOCK_TEXT | ||
40 | KPROBES_TEXT | ||
41 | *(.fixup) | ||
57 | 42 | ||
43 | #ifdef CONFIG_PPC32 | ||
44 | *(.got1) | ||
45 | __got2_start = .; | ||
46 | *(.got2) | ||
47 | __got2_end = .; | ||
48 | #endif /* CONFIG_PPC32 */ | ||
49 | |||
50 | . = ALIGN(PAGE_SIZE); | ||
51 | _etext = .; | ||
52 | PROVIDE32 (etext = .); | ||
53 | } | ||
54 | |||
55 | /* Read-only data */ | ||
56 | RODATA | ||
57 | |||
58 | /* Exception & bug tables */ | ||
58 | __ex_table : { | 59 | __ex_table : { |
59 | __start___ex_table = .; | 60 | __start___ex_table = .; |
60 | *(__ex_table) | 61 | *(__ex_table) |
@@ -67,192 +68,172 @@ SECTIONS | |||
67 | __stop___bug_table = .; | 68 | __stop___bug_table = .; |
68 | } | 69 | } |
69 | 70 | ||
70 | #ifdef CONFIG_PPC64 | 71 | /* |
72 | * Init sections discarded at runtime | ||
73 | */ | ||
74 | . = ALIGN(PAGE_SIZE); | ||
75 | __init_begin = .; | ||
76 | |||
77 | .init.text : { | ||
78 | _sinittext = .; | ||
79 | *(.init.text) | ||
80 | _einittext = .; | ||
81 | } | ||
82 | |||
83 | /* .exit.text is discarded at runtime, not link time, | ||
84 | * to deal with references from __bug_table | ||
85 | */ | ||
86 | .exit.text : { *(.exit.text) } | ||
87 | |||
88 | .init.data : { | ||
89 | *(.init.data); | ||
90 | __vtop_table_begin = .; | ||
91 | *(.vtop_fixup); | ||
92 | __vtop_table_end = .; | ||
93 | __ptov_table_begin = .; | ||
94 | *(.ptov_fixup); | ||
95 | __ptov_table_end = .; | ||
96 | } | ||
97 | |||
98 | . = ALIGN(16); | ||
99 | .init.setup : { | ||
100 | __setup_start = .; | ||
101 | *(.init.setup) | ||
102 | __setup_end = .; | ||
103 | } | ||
104 | |||
105 | .initcall.init : { | ||
106 | __initcall_start = .; | ||
107 | *(.initcall1.init) | ||
108 | *(.initcall2.init) | ||
109 | *(.initcall3.init) | ||
110 | *(.initcall4.init) | ||
111 | *(.initcall5.init) | ||
112 | *(.initcall6.init) | ||
113 | *(.initcall7.init) | ||
114 | __initcall_end = .; | ||
115 | } | ||
116 | |||
117 | .con_initcall.init : { | ||
118 | __con_initcall_start = .; | ||
119 | *(.con_initcall.init) | ||
120 | __con_initcall_end = .; | ||
121 | } | ||
122 | |||
123 | SECURITY_INIT | ||
124 | |||
125 | . = ALIGN(8); | ||
71 | __ftr_fixup : { | 126 | __ftr_fixup : { |
72 | __start___ftr_fixup = .; | 127 | __start___ftr_fixup = .; |
73 | *(__ftr_fixup) | 128 | *(__ftr_fixup) |
74 | __stop___ftr_fixup = .; | 129 | __stop___ftr_fixup = .; |
75 | } | 130 | } |
76 | 131 | ||
77 | RODATA | 132 | . = ALIGN(PAGE_SIZE); |
78 | #endif | 133 | .init.ramfs : { |
134 | __initramfs_start = .; | ||
135 | *(.init.ramfs) | ||
136 | __initramfs_end = .; | ||
137 | } | ||
79 | 138 | ||
80 | #ifdef CONFIG_PPC32 | 139 | #ifdef CONFIG_PPC32 |
81 | /* Read-write section, merged into data segment: */ | 140 | . = ALIGN(32); |
82 | . = ALIGN(PAGE_SIZE); | 141 | #else |
83 | _sdata = .; | 142 | . = ALIGN(128); |
84 | .data : | ||
85 | { | ||
86 | *(.data) | ||
87 | *(.data1) | ||
88 | *(.sdata) | ||
89 | *(.sdata2) | ||
90 | *(.got.plt) *(.got) | ||
91 | *(.dynamic) | ||
92 | CONSTRUCTORS | ||
93 | } | ||
94 | |||
95 | . = ALIGN(PAGE_SIZE); | ||
96 | __nosave_begin = .; | ||
97 | .data_nosave : { *(.data.nosave) } | ||
98 | . = ALIGN(PAGE_SIZE); | ||
99 | __nosave_end = .; | ||
100 | |||
101 | . = ALIGN(32); | ||
102 | .data.cacheline_aligned : { *(.data.cacheline_aligned) } | ||
103 | |||
104 | _edata = .; | ||
105 | PROVIDE (edata = .); | ||
106 | |||
107 | . = ALIGN(8192); | ||
108 | .data.init_task : { *(.data.init_task) } | ||
109 | #endif | 143 | #endif |
144 | .data.percpu : { | ||
145 | __per_cpu_start = .; | ||
146 | *(.data.percpu) | ||
147 | __per_cpu_end = .; | ||
148 | } | ||
110 | 149 | ||
111 | /* will be freed after init */ | 150 | . = ALIGN(8); |
112 | . = ALIGN(PAGE_SIZE); | 151 | .machine.desc : { |
113 | __init_begin = .; | 152 | __machine_desc_start = . ; |
114 | .init.text : { | 153 | *(.machine.desc) |
115 | _sinittext = .; | 154 | __machine_desc_end = . ; |
116 | *(.init.text) | 155 | } |
117 | _einittext = .; | 156 | |
118 | } | 157 | /* freed after init ends here */ |
119 | #ifdef CONFIG_PPC32 | 158 | . = ALIGN(PAGE_SIZE); |
120 | /* .exit.text is discarded at runtime, not link time, | 159 | __init_end = .; |
121 | to deal with references from __bug_table */ | 160 | |
122 | .exit.text : { *(.exit.text) } | 161 | /* |
123 | #endif | 162 | * And now the various read/write data |
124 | .init.data : { | 163 | */ |
125 | *(.init.data); | 164 | |
126 | __vtop_table_begin = .; | 165 | . = ALIGN(PAGE_SIZE); |
127 | *(.vtop_fixup); | 166 | _sdata = .; |
128 | __vtop_table_end = .; | ||
129 | __ptov_table_begin = .; | ||
130 | *(.ptov_fixup); | ||
131 | __ptov_table_end = .; | ||
132 | } | ||
133 | |||
134 | . = ALIGN(16); | ||
135 | .init.setup : { | ||
136 | __setup_start = .; | ||
137 | *(.init.setup) | ||
138 | __setup_end = .; | ||
139 | } | ||
140 | |||
141 | .initcall.init : { | ||
142 | __initcall_start = .; | ||
143 | *(.initcall1.init) | ||
144 | *(.initcall2.init) | ||
145 | *(.initcall3.init) | ||
146 | *(.initcall4.init) | ||
147 | *(.initcall5.init) | ||
148 | *(.initcall6.init) | ||
149 | *(.initcall7.init) | ||
150 | __initcall_end = .; | ||
151 | } | ||
152 | |||
153 | .con_initcall.init : { | ||
154 | __con_initcall_start = .; | ||
155 | *(.con_initcall.init) | ||
156 | __con_initcall_end = .; | ||
157 | } | ||
158 | |||
159 | SECURITY_INIT | ||
160 | 167 | ||
161 | #ifdef CONFIG_PPC32 | 168 | #ifdef CONFIG_PPC32 |
162 | __start___ftr_fixup = .; | 169 | .data : |
163 | __ftr_fixup : { *(__ftr_fixup) } | 170 | { |
164 | __stop___ftr_fixup = .; | 171 | *(.data) |
172 | *(.sdata) | ||
173 | *(.got.plt) *(.got) | ||
174 | } | ||
165 | #else | 175 | #else |
166 | . = ALIGN(PAGE_SIZE); | 176 | .data : { |
167 | .init.ramfs : { | 177 | *(.data .data.rel* .toc1) |
168 | __initramfs_start = .; | 178 | *(.branch_lt) |
169 | *(.init.ramfs) | 179 | } |
170 | __initramfs_end = .; | ||
171 | } | ||
172 | #endif | ||
173 | 180 | ||
174 | #ifdef CONFIG_PPC32 | 181 | .opd : { |
175 | . = ALIGN(32); | 182 | *(.opd) |
183 | } | ||
184 | |||
185 | .got : { | ||
186 | __toc_start = .; | ||
187 | *(.got) | ||
188 | *(.toc) | ||
189 | } | ||
176 | #endif | 190 | #endif |
177 | .data.percpu : { | ||
178 | __per_cpu_start = .; | ||
179 | *(.data.percpu) | ||
180 | __per_cpu_end = .; | ||
181 | } | ||
182 | 191 | ||
183 | . = ALIGN(PAGE_SIZE); | 192 | . = ALIGN(PAGE_SIZE); |
184 | #ifdef CONFIG_PPC64 | 193 | _edata = .; |
185 | . = ALIGN(16384); | 194 | PROVIDE32 (edata = .); |
186 | __init_end = .; | 195 | |
187 | /* freed after init ends here */ | 196 | /* The initial task and kernel stack */ |
188 | 197 | #ifdef CONFIG_PPC32 | |
189 | /* Read/write sections */ | 198 | . = ALIGN(8192); |
190 | . = ALIGN(PAGE_SIZE); | ||
191 | . = ALIGN(16384); | ||
192 | _sdata = .; | ||
193 | /* The initial task and kernel stack */ | ||
194 | .data.init_task : { | ||
195 | *(.data.init_task) | ||
196 | } | ||
197 | |||
198 | . = ALIGN(PAGE_SIZE); | ||
199 | .data.page_aligned : { | ||
200 | *(.data.page_aligned) | ||
201 | } | ||
202 | |||
203 | .data.cacheline_aligned : { | ||
204 | *(.data.cacheline_aligned) | ||
205 | } | ||
206 | |||
207 | .data : { | ||
208 | *(.data .data.rel* .toc1) | ||
209 | *(.branch_lt) | ||
210 | } | ||
211 | |||
212 | .opd : { | ||
213 | *(.opd) | ||
214 | } | ||
215 | |||
216 | .got : { | ||
217 | __toc_start = .; | ||
218 | *(.got) | ||
219 | *(.toc) | ||
220 | . = ALIGN(PAGE_SIZE); | ||
221 | _edata = .; | ||
222 | } | ||
223 | |||
224 | . = ALIGN(PAGE_SIZE); | ||
225 | #else | 199 | #else |
226 | __initramfs_start = .; | 200 | . = ALIGN(16384); |
227 | .init.ramfs : { | 201 | #endif |
228 | *(.init.ramfs) | 202 | .data.init_task : { |
229 | } | 203 | *(.data.init_task) |
230 | __initramfs_end = .; | 204 | } |
231 | 205 | ||
232 | . = ALIGN(4096); | 206 | . = ALIGN(PAGE_SIZE); |
233 | __init_end = .; | 207 | .data.page_aligned : { |
208 | *(.data.page_aligned) | ||
209 | } | ||
234 | 210 | ||
235 | . = ALIGN(4096); | 211 | .data.cacheline_aligned : { |
236 | _sextratext = .; | 212 | *(.data.cacheline_aligned) |
237 | _eextratext = .; | 213 | } |
238 | 214 | ||
239 | __bss_start = .; | 215 | . = ALIGN(PAGE_SIZE); |
240 | #endif | 216 | __data_nosave : { |
217 | __nosave_begin = .; | ||
218 | *(.data.nosave) | ||
219 | . = ALIGN(PAGE_SIZE); | ||
220 | __nosave_end = .; | ||
221 | } | ||
241 | 222 | ||
242 | .bss : { | 223 | /* |
243 | __bss_start = .; | 224 | * And finally the bss |
244 | *(.sbss) *(.scommon) | 225 | */ |
245 | *(.dynbss) | 226 | |
246 | *(.bss) | 227 | .bss : { |
247 | *(COMMON) | 228 | __bss_start = .; |
248 | __bss_stop = .; | 229 | *(.sbss) *(.scommon) |
249 | } | 230 | *(.dynbss) |
231 | *(.bss) | ||
232 | *(COMMON) | ||
233 | __bss_stop = .; | ||
234 | } | ||
250 | 235 | ||
251 | #ifdef CONFIG_PPC64 | 236 | . = ALIGN(PAGE_SIZE); |
252 | . = ALIGN(PAGE_SIZE); | 237 | _end = . ; |
253 | #endif | 238 | PROVIDE32 (end = .); |
254 | _end = . ; | ||
255 | #ifdef CONFIG_PPC32 | ||
256 | PROVIDE (end = .); | ||
257 | #endif | ||
258 | } | 239 | } |
diff --git a/arch/powerpc/lib/copypage_64.S b/arch/powerpc/lib/copypage_64.S index 40523b140109..f9837f44ac0b 100644 --- a/arch/powerpc/lib/copypage_64.S +++ b/arch/powerpc/lib/copypage_64.S | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/lib/copypage.S | ||
3 | * | ||
4 | * Copyright (C) 2002 Paul Mackerras, IBM Corp. | 2 | * Copyright (C) 2002 Paul Mackerras, IBM Corp. |
5 | * | 3 | * |
6 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S index 6d69ef39b7df..a6b54cb97c49 100644 --- a/arch/powerpc/lib/copyuser_64.S +++ b/arch/powerpc/lib/copyuser_64.S | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/lib/copyuser.S | ||
3 | * | ||
4 | * Copyright (C) 2002 Paul Mackerras, IBM Corp. | 2 | * Copyright (C) 2002 Paul Mackerras, IBM Corp. |
5 | * | 3 | * |
6 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
diff --git a/arch/powerpc/lib/e2a.c b/arch/powerpc/lib/e2a.c index d2b834887920..4b72ed8fd50e 100644 --- a/arch/powerpc/lib/e2a.c +++ b/arch/powerpc/lib/e2a.c | |||
@@ -1,9 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/lib/e2a.c | ||
3 | * | ||
4 | * EBCDIC to ASCII conversion | 2 | * EBCDIC to ASCII conversion |
5 | * | 3 | * |
6 | * This function moved here from arch/ppc64/kernel/viopath.c | 4 | * This function moved here from arch/powerpc/platforms/iseries/viopath.c |
7 | * | 5 | * |
8 | * (C) Copyright 2000-2004 IBM Corporation | 6 | * (C) Copyright 2000-2004 IBM Corporation |
9 | * | 7 | * |
@@ -105,4 +103,14 @@ unsigned char e2a(unsigned char x) | |||
105 | } | 103 | } |
106 | EXPORT_SYMBOL(e2a); | 104 | EXPORT_SYMBOL(e2a); |
107 | 105 | ||
106 | unsigned char* strne2a(unsigned char *dest, const unsigned char *src, size_t n) | ||
107 | { | ||
108 | int i; | ||
109 | |||
110 | n = strnlen(src, n); | ||
108 | 111 | ||
112 | for (i = 0; i < n; i++) | ||
113 | dest[i] = e2a(src[i]); | ||
114 | |||
115 | return dest; | ||
116 | } | ||
diff --git a/arch/powerpc/lib/memcpy_64.S b/arch/powerpc/lib/memcpy_64.S index 9ccacdf5bcb9..fd66acfd3e3e 100644 --- a/arch/powerpc/lib/memcpy_64.S +++ b/arch/powerpc/lib/memcpy_64.S | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/lib/memcpy.S | ||
3 | * | ||
4 | * Copyright (C) 2002 Paul Mackerras, IBM Corp. | 2 | * Copyright (C) 2002 Paul Mackerras, IBM Corp. |
5 | * | 3 | * |
6 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c index 42c5de2c898f..31e511856dc5 100644 --- a/arch/powerpc/lib/rheap.c +++ b/arch/powerpc/lib/rheap.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/syslib/rheap.c | ||
3 | * | ||
4 | * A Remote Heap. Remote means that we don't touch the memory that the | 2 | * A Remote Heap. Remote means that we don't touch the memory that the |
5 | * heap points to. Normal heap implementations use the memory they manage | 3 | * heap points to. Normal heap implementations use the memory they manage |
6 | * to place their list. We cannot do that because the memory we manage may | 4 | * to place their list. We cannot do that because the memory we manage may |
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 666c2aa55016..c251d9936612 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c | |||
@@ -18,7 +18,7 @@ extern char system_call_common[]; | |||
18 | 18 | ||
19 | #ifdef CONFIG_PPC64 | 19 | #ifdef CONFIG_PPC64 |
20 | /* Bits in SRR1 that are copied from MSR */ | 20 | /* Bits in SRR1 that are copied from MSR */ |
21 | #define MSR_MASK 0xffffffff87c0ffff | 21 | #define MSR_MASK 0xffffffff87c0ffffUL |
22 | #else | 22 | #else |
23 | #define MSR_MASK 0x87c0ffff | 23 | #define MSR_MASK 0x87c0ffff |
24 | #endif | 24 | #endif |
diff --git a/arch/powerpc/lib/strcase.c b/arch/powerpc/lib/strcase.c index 36b521091bbc..f8ec1eba3fdd 100644 --- a/arch/powerpc/lib/strcase.c +++ b/arch/powerpc/lib/strcase.c | |||
@@ -1,4 +1,6 @@ | |||
1 | #include <linux/types.h> | ||
1 | #include <linux/ctype.h> | 2 | #include <linux/ctype.h> |
3 | #include <linux/string.h> | ||
2 | 4 | ||
3 | int strcasecmp(const char *s1, const char *s2) | 5 | int strcasecmp(const char *s1, const char *s2) |
4 | { | 6 | { |
@@ -11,7 +13,7 @@ int strcasecmp(const char *s1, const char *s2) | |||
11 | return c1 - c2; | 13 | return c1 - c2; |
12 | } | 14 | } |
13 | 15 | ||
14 | int strncasecmp(const char *s1, const char *s2, int n) | 16 | int strncasecmp(const char *s1, const char *s2, size_t n) |
15 | { | 17 | { |
16 | int c1, c2; | 18 | int c1, c2; |
17 | 19 | ||
diff --git a/arch/powerpc/math-emu/Makefile b/arch/powerpc/math-emu/Makefile new file mode 100644 index 000000000000..754143e8936b --- /dev/null +++ b/arch/powerpc/math-emu/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | |||
2 | obj-y := math.o fmr.o lfd.o stfd.o | ||
3 | |||
4 | obj-$(CONFIG_MATH_EMULATION) += fabs.o fadd.o fadds.o fcmpo.o fcmpu.o \ | ||
5 | fctiw.o fctiwz.o fdiv.o fdivs.o \ | ||
6 | fmadd.o fmadds.o fmsub.o fmsubs.o \ | ||
7 | fmul.o fmuls.o fnabs.o fneg.o types.o \ | ||
8 | fnmadd.o fnmadds.o fnmsub.o fnmsubs.o \ | ||
9 | fres.o frsp.o frsqrte.o fsel.o lfs.o \ | ||
10 | fsqrt.o fsqrts.o fsub.o fsubs.o \ | ||
11 | mcrfs.o mffs.o mtfsb0.o mtfsb1.o \ | ||
12 | mtfsf.o mtfsfi.o stfiwx.o stfs.o \ | ||
13 | udivmodti4.o | ||
diff --git a/arch/powerpc/math-emu/double.h b/arch/powerpc/math-emu/double.h new file mode 100644 index 000000000000..ffba8b67f059 --- /dev/null +++ b/arch/powerpc/math-emu/double.h | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Definitions for IEEE Double Precision | ||
3 | */ | ||
4 | |||
5 | #if _FP_W_TYPE_SIZE < 32 | ||
6 | #error "Here's a nickel kid. Go buy yourself a real computer." | ||
7 | #endif | ||
8 | |||
9 | #if _FP_W_TYPE_SIZE < 64 | ||
10 | #define _FP_FRACTBITS_D (2 * _FP_W_TYPE_SIZE) | ||
11 | #else | ||
12 | #define _FP_FRACTBITS_D _FP_W_TYPE_SIZE | ||
13 | #endif | ||
14 | |||
15 | #define _FP_FRACBITS_D 53 | ||
16 | #define _FP_FRACXBITS_D (_FP_FRACTBITS_D - _FP_FRACBITS_D) | ||
17 | #define _FP_WFRACBITS_D (_FP_WORKBITS + _FP_FRACBITS_D) | ||
18 | #define _FP_WFRACXBITS_D (_FP_FRACTBITS_D - _FP_WFRACBITS_D) | ||
19 | #define _FP_EXPBITS_D 11 | ||
20 | #define _FP_EXPBIAS_D 1023 | ||
21 | #define _FP_EXPMAX_D 2047 | ||
22 | |||
23 | #define _FP_QNANBIT_D \ | ||
24 | ((_FP_W_TYPE)1 << ((_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE)) | ||
25 | #define _FP_IMPLBIT_D \ | ||
26 | ((_FP_W_TYPE)1 << ((_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE)) | ||
27 | #define _FP_OVERFLOW_D \ | ||
28 | ((_FP_W_TYPE)1 << (_FP_WFRACBITS_D % _FP_W_TYPE_SIZE)) | ||
29 | |||
30 | #if _FP_W_TYPE_SIZE < 64 | ||
31 | |||
32 | union _FP_UNION_D | ||
33 | { | ||
34 | double flt; | ||
35 | struct { | ||
36 | #if __BYTE_ORDER == __BIG_ENDIAN | ||
37 | unsigned sign : 1; | ||
38 | unsigned exp : _FP_EXPBITS_D; | ||
39 | unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE; | ||
40 | unsigned frac0 : _FP_W_TYPE_SIZE; | ||
41 | #else | ||
42 | unsigned frac0 : _FP_W_TYPE_SIZE; | ||
43 | unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE; | ||
44 | unsigned exp : _FP_EXPBITS_D; | ||
45 | unsigned sign : 1; | ||
46 | #endif | ||
47 | } bits __attribute__((packed)); | ||
48 | }; | ||
49 | |||
50 | #define FP_DECL_D(X) _FP_DECL(2,X) | ||
51 | #define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_2(D,X,val) | ||
52 | #define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_2(D,val,X) | ||
53 | |||
54 | #define FP_UNPACK_D(X,val) \ | ||
55 | do { \ | ||
56 | _FP_UNPACK_RAW_2(D,X,val); \ | ||
57 | _FP_UNPACK_CANONICAL(D,2,X); \ | ||
58 | } while (0) | ||
59 | |||
60 | #define FP_PACK_D(val,X) \ | ||
61 | do { \ | ||
62 | _FP_PACK_CANONICAL(D,2,X); \ | ||
63 | _FP_PACK_RAW_2(D,val,X); \ | ||
64 | } while (0) | ||
65 | |||
66 | #define FP_NEG_D(R,X) _FP_NEG(D,2,R,X) | ||
67 | #define FP_ADD_D(R,X,Y) _FP_ADD(D,2,R,X,Y) | ||
68 | #define FP_SUB_D(R,X,Y) _FP_SUB(D,2,R,X,Y) | ||
69 | #define FP_MUL_D(R,X,Y) _FP_MUL(D,2,R,X,Y) | ||
70 | #define FP_DIV_D(R,X,Y) _FP_DIV(D,2,R,X,Y) | ||
71 | #define FP_SQRT_D(R,X) _FP_SQRT(D,2,R,X) | ||
72 | |||
73 | #define FP_CMP_D(r,X,Y,un) _FP_CMP(D,2,r,X,Y,un) | ||
74 | #define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,2,r,X,Y) | ||
75 | |||
76 | #define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,2,r,X,rsz,rsg) | ||
77 | #define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,2,X,r,rs,rt) | ||
78 | |||
79 | #else | ||
80 | |||
81 | union _FP_UNION_D | ||
82 | { | ||
83 | double flt; | ||
84 | struct { | ||
85 | #if __BYTE_ORDER == __BIG_ENDIAN | ||
86 | unsigned sign : 1; | ||
87 | unsigned exp : _FP_EXPBITS_D; | ||
88 | unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); | ||
89 | #else | ||
90 | unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); | ||
91 | unsigned exp : _FP_EXPBITS_D; | ||
92 | unsigned sign : 1; | ||
93 | #endif | ||
94 | } bits __attribute__((packed)); | ||
95 | }; | ||
96 | |||
97 | #define FP_DECL_D(X) _FP_DECL(1,X) | ||
98 | #define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_1(D,X,val) | ||
99 | #define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_1(D,val,X) | ||
100 | |||
101 | #define FP_UNPACK_D(X,val) \ | ||
102 | do { \ | ||
103 | _FP_UNPACK_RAW_1(D,X,val); \ | ||
104 | _FP_UNPACK_CANONICAL(D,1,X); \ | ||
105 | } while (0) | ||
106 | |||
107 | #define FP_PACK_D(val,X) \ | ||
108 | do { \ | ||
109 | _FP_PACK_CANONICAL(D,1,X); \ | ||
110 | _FP_PACK_RAW_1(D,val,X); \ | ||
111 | } while (0) | ||
112 | |||
113 | #define FP_NEG_D(R,X) _FP_NEG(D,1,R,X) | ||
114 | #define FP_ADD_D(R,X,Y) _FP_ADD(D,1,R,X,Y) | ||
115 | #define FP_SUB_D(R,X,Y) _FP_SUB(D,1,R,X,Y) | ||
116 | #define FP_MUL_D(R,X,Y) _FP_MUL(D,1,R,X,Y) | ||
117 | #define FP_DIV_D(R,X,Y) _FP_DIV(D,1,R,X,Y) | ||
118 | #define FP_SQRT_D(R,X) _FP_SQRT(D,1,R,X) | ||
119 | |||
120 | /* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by | ||
121 | the target machine. */ | ||
122 | |||
123 | #define FP_CMP_D(r,X,Y,un) _FP_CMP(D,1,r,X,Y,un) | ||
124 | #define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,1,r,X,Y) | ||
125 | |||
126 | #define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,1,r,X,rsz,rsg) | ||
127 | #define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,1,X,r,rs,rt) | ||
128 | |||
129 | #endif /* W_TYPE_SIZE < 64 */ | ||
diff --git a/arch/powerpc/math-emu/fabs.c b/arch/powerpc/math-emu/fabs.c new file mode 100644 index 000000000000..41f0617f3d3a --- /dev/null +++ b/arch/powerpc/math-emu/fabs.c | |||
@@ -0,0 +1,18 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | int | ||
6 | fabs(u32 *frD, u32 *frB) | ||
7 | { | ||
8 | frD[0] = frB[0] & 0x7fffffff; | ||
9 | frD[1] = frB[1]; | ||
10 | |||
11 | #ifdef DEBUG | ||
12 | printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB); | ||
13 | dump_double(frD); | ||
14 | printk("\n"); | ||
15 | #endif | ||
16 | |||
17 | return 0; | ||
18 | } | ||
diff --git a/arch/powerpc/math-emu/fadd.c b/arch/powerpc/math-emu/fadd.c new file mode 100644 index 000000000000..fc8836488b64 --- /dev/null +++ b/arch/powerpc/math-emu/fadd.c | |||
@@ -0,0 +1,38 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | |||
8 | int | ||
9 | fadd(void *frD, void *frA, void *frB) | ||
10 | { | ||
11 | FP_DECL_D(A); | ||
12 | FP_DECL_D(B); | ||
13 | FP_DECL_D(R); | ||
14 | int ret = 0; | ||
15 | |||
16 | #ifdef DEBUG | ||
17 | printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); | ||
18 | #endif | ||
19 | |||
20 | __FP_UNPACK_D(A, frA); | ||
21 | __FP_UNPACK_D(B, frB); | ||
22 | |||
23 | #ifdef DEBUG | ||
24 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
25 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
26 | #endif | ||
27 | |||
28 | if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF) | ||
29 | ret |= EFLAG_VXISI; | ||
30 | |||
31 | FP_ADD_D(R, A, B); | ||
32 | |||
33 | #ifdef DEBUG | ||
34 | printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
35 | #endif | ||
36 | |||
37 | return (ret | __FP_PACK_D(frD, R)); | ||
38 | } | ||
diff --git a/arch/powerpc/math-emu/fadds.c b/arch/powerpc/math-emu/fadds.c new file mode 100644 index 000000000000..93025b6c8f3c --- /dev/null +++ b/arch/powerpc/math-emu/fadds.c | |||
@@ -0,0 +1,39 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | #include "single.h" | ||
8 | |||
9 | int | ||
10 | fadds(void *frD, void *frA, void *frB) | ||
11 | { | ||
12 | FP_DECL_D(A); | ||
13 | FP_DECL_D(B); | ||
14 | FP_DECL_D(R); | ||
15 | int ret = 0; | ||
16 | |||
17 | #ifdef DEBUG | ||
18 | printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); | ||
19 | #endif | ||
20 | |||
21 | __FP_UNPACK_D(A, frA); | ||
22 | __FP_UNPACK_D(B, frB); | ||
23 | |||
24 | #ifdef DEBUG | ||
25 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
26 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
27 | #endif | ||
28 | |||
29 | if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF) | ||
30 | ret |= EFLAG_VXISI; | ||
31 | |||
32 | FP_ADD_D(R, A, B); | ||
33 | |||
34 | #ifdef DEBUG | ||
35 | printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
36 | #endif | ||
37 | |||
38 | return (ret | __FP_PACK_DS(frD, R)); | ||
39 | } | ||
diff --git a/arch/powerpc/math-emu/fcmpo.c b/arch/powerpc/math-emu/fcmpo.c new file mode 100644 index 000000000000..4efac394b4cb --- /dev/null +++ b/arch/powerpc/math-emu/fcmpo.c | |||
@@ -0,0 +1,46 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | |||
8 | int | ||
9 | fcmpo(u32 *ccr, int crfD, void *frA, void *frB) | ||
10 | { | ||
11 | FP_DECL_D(A); | ||
12 | FP_DECL_D(B); | ||
13 | int code[4] = { (1 << 3), (1 << 1), (1 << 2), (1 << 0) }; | ||
14 | long cmp; | ||
15 | int ret = 0; | ||
16 | |||
17 | #ifdef DEBUG | ||
18 | printk("%s: %p (%08x) %d %p %p\n", __FUNCTION__, ccr, *ccr, crfD, frA, frB); | ||
19 | #endif | ||
20 | |||
21 | __FP_UNPACK_D(A, frA); | ||
22 | __FP_UNPACK_D(B, frB); | ||
23 | |||
24 | #ifdef DEBUG | ||
25 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
26 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
27 | #endif | ||
28 | |||
29 | if (A_c == FP_CLS_NAN || B_c == FP_CLS_NAN) | ||
30 | ret |= EFLAG_VXVC; | ||
31 | |||
32 | FP_CMP_D(cmp, A, B, 2); | ||
33 | cmp = code[(cmp + 1) & 3]; | ||
34 | |||
35 | __FPU_FPSCR &= ~(0x1f000); | ||
36 | __FPU_FPSCR |= (cmp << 12); | ||
37 | |||
38 | *ccr &= ~(15 << ((7 - crfD) << 2)); | ||
39 | *ccr |= (cmp << ((7 - crfD) << 2)); | ||
40 | |||
41 | #ifdef DEBUG | ||
42 | printk("CR: %08x\n", *ccr); | ||
43 | #endif | ||
44 | |||
45 | return ret; | ||
46 | } | ||
diff --git a/arch/powerpc/math-emu/fcmpu.c b/arch/powerpc/math-emu/fcmpu.c new file mode 100644 index 000000000000..b7e33176e618 --- /dev/null +++ b/arch/powerpc/math-emu/fcmpu.c | |||
@@ -0,0 +1,42 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | |||
8 | int | ||
9 | fcmpu(u32 *ccr, int crfD, void *frA, void *frB) | ||
10 | { | ||
11 | FP_DECL_D(A); | ||
12 | FP_DECL_D(B); | ||
13 | int code[4] = { (1 << 3), (1 << 1), (1 << 2), (1 << 0) }; | ||
14 | long cmp; | ||
15 | |||
16 | #ifdef DEBUG | ||
17 | printk("%s: %p (%08x) %d %p %p\n", __FUNCTION__, ccr, *ccr, crfD, frA, frB); | ||
18 | #endif | ||
19 | |||
20 | __FP_UNPACK_D(A, frA); | ||
21 | __FP_UNPACK_D(B, frB); | ||
22 | |||
23 | #ifdef DEBUG | ||
24 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
25 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
26 | #endif | ||
27 | |||
28 | FP_CMP_D(cmp, A, B, 2); | ||
29 | cmp = code[(cmp + 1) & 3]; | ||
30 | |||
31 | __FPU_FPSCR &= ~(0x1f000); | ||
32 | __FPU_FPSCR |= (cmp << 12); | ||
33 | |||
34 | *ccr &= ~(15 << ((7 - crfD) << 2)); | ||
35 | *ccr |= (cmp << ((7 - crfD) << 2)); | ||
36 | |||
37 | #ifdef DEBUG | ||
38 | printk("CR: %08x\n", *ccr); | ||
39 | #endif | ||
40 | |||
41 | return 0; | ||
42 | } | ||
diff --git a/arch/powerpc/math-emu/fctiw.c b/arch/powerpc/math-emu/fctiw.c new file mode 100644 index 000000000000..3b3c98b840cf --- /dev/null +++ b/arch/powerpc/math-emu/fctiw.c | |||
@@ -0,0 +1,25 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | |||
8 | int | ||
9 | fctiw(u32 *frD, void *frB) | ||
10 | { | ||
11 | FP_DECL_D(B); | ||
12 | unsigned int r; | ||
13 | |||
14 | __FP_UNPACK_D(B, frB); | ||
15 | FP_TO_INT_D(r, B, 32, 1); | ||
16 | frD[1] = r; | ||
17 | |||
18 | #ifdef DEBUG | ||
19 | printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB); | ||
20 | dump_double(frD); | ||
21 | printk("\n"); | ||
22 | #endif | ||
23 | |||
24 | return 0; | ||
25 | } | ||
diff --git a/arch/powerpc/math-emu/fctiwz.c b/arch/powerpc/math-emu/fctiwz.c new file mode 100644 index 000000000000..7717eb6fcfb6 --- /dev/null +++ b/arch/powerpc/math-emu/fctiwz.c | |||
@@ -0,0 +1,32 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | |||
8 | int | ||
9 | fctiwz(u32 *frD, void *frB) | ||
10 | { | ||
11 | FP_DECL_D(B); | ||
12 | u32 fpscr; | ||
13 | unsigned int r; | ||
14 | |||
15 | fpscr = __FPU_FPSCR; | ||
16 | __FPU_FPSCR &= ~(3); | ||
17 | __FPU_FPSCR |= FP_RND_ZERO; | ||
18 | |||
19 | __FP_UNPACK_D(B, frB); | ||
20 | FP_TO_INT_D(r, B, 32, 1); | ||
21 | frD[1] = r; | ||
22 | |||
23 | __FPU_FPSCR = fpscr; | ||
24 | |||
25 | #ifdef DEBUG | ||
26 | printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB); | ||
27 | dump_double(frD); | ||
28 | printk("\n"); | ||
29 | #endif | ||
30 | |||
31 | return 0; | ||
32 | } | ||
diff --git a/arch/powerpc/math-emu/fdiv.c b/arch/powerpc/math-emu/fdiv.c new file mode 100644 index 000000000000..f2fba825b2d0 --- /dev/null +++ b/arch/powerpc/math-emu/fdiv.c | |||
@@ -0,0 +1,53 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | |||
8 | int | ||
9 | fdiv(void *frD, void *frA, void *frB) | ||
10 | { | ||
11 | FP_DECL_D(A); | ||
12 | FP_DECL_D(B); | ||
13 | FP_DECL_D(R); | ||
14 | int ret = 0; | ||
15 | |||
16 | #ifdef DEBUG | ||
17 | printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); | ||
18 | #endif | ||
19 | |||
20 | __FP_UNPACK_D(A, frA); | ||
21 | __FP_UNPACK_D(B, frB); | ||
22 | |||
23 | #ifdef DEBUG | ||
24 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
25 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
26 | #endif | ||
27 | |||
28 | if (A_c == FP_CLS_ZERO && B_c == FP_CLS_ZERO) { | ||
29 | ret |= EFLAG_VXZDZ; | ||
30 | #ifdef DEBUG | ||
31 | printk("%s: FPSCR_VXZDZ raised\n", __FUNCTION__); | ||
32 | #endif | ||
33 | } | ||
34 | if (A_c == FP_CLS_INF && B_c == FP_CLS_INF) { | ||
35 | ret |= EFLAG_VXIDI; | ||
36 | #ifdef DEBUG | ||
37 | printk("%s: FPSCR_VXIDI raised\n", __FUNCTION__); | ||
38 | #endif | ||
39 | } | ||
40 | |||
41 | if (B_c == FP_CLS_ZERO && A_c != FP_CLS_ZERO) { | ||
42 | ret |= EFLAG_DIVZERO; | ||
43 | if (__FPU_TRAP_P(EFLAG_DIVZERO)) | ||
44 | return ret; | ||
45 | } | ||
46 | FP_DIV_D(R, A, B); | ||
47 | |||
48 | #ifdef DEBUG | ||
49 | printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
50 | #endif | ||
51 | |||
52 | return (ret | __FP_PACK_D(frD, R)); | ||
53 | } | ||
diff --git a/arch/powerpc/math-emu/fdivs.c b/arch/powerpc/math-emu/fdivs.c new file mode 100644 index 000000000000..b971196e3175 --- /dev/null +++ b/arch/powerpc/math-emu/fdivs.c | |||
@@ -0,0 +1,55 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | #include "single.h" | ||
8 | |||
9 | int | ||
10 | fdivs(void *frD, void *frA, void *frB) | ||
11 | { | ||
12 | FP_DECL_D(A); | ||
13 | FP_DECL_D(B); | ||
14 | FP_DECL_D(R); | ||
15 | int ret = 0; | ||
16 | |||
17 | #ifdef DEBUG | ||
18 | printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); | ||
19 | #endif | ||
20 | |||
21 | __FP_UNPACK_D(A, frA); | ||
22 | __FP_UNPACK_D(B, frB); | ||
23 | |||
24 | #ifdef DEBUG | ||
25 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
26 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
27 | #endif | ||
28 | |||
29 | if (A_c == FP_CLS_ZERO && B_c == FP_CLS_ZERO) { | ||
30 | ret |= EFLAG_VXZDZ; | ||
31 | #ifdef DEBUG | ||
32 | printk("%s: FPSCR_VXZDZ raised\n", __FUNCTION__); | ||
33 | #endif | ||
34 | } | ||
35 | if (A_c == FP_CLS_INF && B_c == FP_CLS_INF) { | ||
36 | ret |= EFLAG_VXIDI; | ||
37 | #ifdef DEBUG | ||
38 | printk("%s: FPSCR_VXIDI raised\n", __FUNCTION__); | ||
39 | #endif | ||
40 | } | ||
41 | |||
42 | if (B_c == FP_CLS_ZERO && A_c != FP_CLS_ZERO) { | ||
43 | ret |= EFLAG_DIVZERO; | ||
44 | if (__FPU_TRAP_P(EFLAG_DIVZERO)) | ||
45 | return ret; | ||
46 | } | ||
47 | |||
48 | FP_DIV_D(R, A, B); | ||
49 | |||
50 | #ifdef DEBUG | ||
51 | printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
52 | #endif | ||
53 | |||
54 | return (ret | __FP_PACK_DS(frD, R)); | ||
55 | } | ||
diff --git a/arch/powerpc/math-emu/fmadd.c b/arch/powerpc/math-emu/fmadd.c new file mode 100644 index 000000000000..0a1dbce793e9 --- /dev/null +++ b/arch/powerpc/math-emu/fmadd.c | |||
@@ -0,0 +1,48 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | |||
8 | int | ||
9 | fmadd(void *frD, void *frA, void *frB, void *frC) | ||
10 | { | ||
11 | FP_DECL_D(R); | ||
12 | FP_DECL_D(A); | ||
13 | FP_DECL_D(B); | ||
14 | FP_DECL_D(C); | ||
15 | FP_DECL_D(T); | ||
16 | int ret = 0; | ||
17 | |||
18 | #ifdef DEBUG | ||
19 | printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); | ||
20 | #endif | ||
21 | |||
22 | __FP_UNPACK_D(A, frA); | ||
23 | __FP_UNPACK_D(B, frB); | ||
24 | __FP_UNPACK_D(C, frC); | ||
25 | |||
26 | #ifdef DEBUG | ||
27 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
28 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
29 | printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); | ||
30 | #endif | ||
31 | |||
32 | if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || | ||
33 | (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) | ||
34 | ret |= EFLAG_VXIMZ; | ||
35 | |||
36 | FP_MUL_D(T, A, C); | ||
37 | |||
38 | if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) | ||
39 | ret |= EFLAG_VXISI; | ||
40 | |||
41 | FP_ADD_D(R, T, B); | ||
42 | |||
43 | #ifdef DEBUG | ||
44 | printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
45 | #endif | ||
46 | |||
47 | return (ret | __FP_PACK_D(frD, R)); | ||
48 | } | ||
diff --git a/arch/powerpc/math-emu/fmadds.c b/arch/powerpc/math-emu/fmadds.c new file mode 100644 index 000000000000..0f70bba9445e --- /dev/null +++ b/arch/powerpc/math-emu/fmadds.c | |||
@@ -0,0 +1,49 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | #include "single.h" | ||
8 | |||
9 | int | ||
10 | fmadds(void *frD, void *frA, void *frB, void *frC) | ||
11 | { | ||
12 | FP_DECL_D(R); | ||
13 | FP_DECL_D(A); | ||
14 | FP_DECL_D(B); | ||
15 | FP_DECL_D(C); | ||
16 | FP_DECL_D(T); | ||
17 | int ret = 0; | ||
18 | |||
19 | #ifdef DEBUG | ||
20 | printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); | ||
21 | #endif | ||
22 | |||
23 | __FP_UNPACK_D(A, frA); | ||
24 | __FP_UNPACK_D(B, frB); | ||
25 | __FP_UNPACK_D(C, frC); | ||
26 | |||
27 | #ifdef DEBUG | ||
28 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
29 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
30 | printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); | ||
31 | #endif | ||
32 | |||
33 | if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || | ||
34 | (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) | ||
35 | ret |= EFLAG_VXIMZ; | ||
36 | |||
37 | FP_MUL_D(T, A, C); | ||
38 | |||
39 | if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) | ||
40 | ret |= EFLAG_VXISI; | ||
41 | |||
42 | FP_ADD_D(R, T, B); | ||
43 | |||
44 | #ifdef DEBUG | ||
45 | printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
46 | #endif | ||
47 | |||
48 | return (ret | __FP_PACK_DS(frD, R)); | ||
49 | } | ||
diff --git a/arch/powerpc/math-emu/fmr.c b/arch/powerpc/math-emu/fmr.c new file mode 100644 index 000000000000..28df700c0c7e --- /dev/null +++ b/arch/powerpc/math-emu/fmr.c | |||
@@ -0,0 +1,18 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | int | ||
6 | fmr(u32 *frD, u32 *frB) | ||
7 | { | ||
8 | frD[0] = frB[0]; | ||
9 | frD[1] = frB[1]; | ||
10 | |||
11 | #ifdef DEBUG | ||
12 | printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB); | ||
13 | dump_double(frD); | ||
14 | printk("\n"); | ||
15 | #endif | ||
16 | |||
17 | return 0; | ||
18 | } | ||
diff --git a/arch/powerpc/math-emu/fmsub.c b/arch/powerpc/math-emu/fmsub.c new file mode 100644 index 000000000000..203fd48a6fec --- /dev/null +++ b/arch/powerpc/math-emu/fmsub.c | |||
@@ -0,0 +1,51 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | |||
8 | int | ||
9 | fmsub(void *frD, void *frA, void *frB, void *frC) | ||
10 | { | ||
11 | FP_DECL_D(R); | ||
12 | FP_DECL_D(A); | ||
13 | FP_DECL_D(B); | ||
14 | FP_DECL_D(C); | ||
15 | FP_DECL_D(T); | ||
16 | int ret = 0; | ||
17 | |||
18 | #ifdef DEBUG | ||
19 | printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); | ||
20 | #endif | ||
21 | |||
22 | __FP_UNPACK_D(A, frA); | ||
23 | __FP_UNPACK_D(B, frB); | ||
24 | __FP_UNPACK_D(C, frC); | ||
25 | |||
26 | #ifdef DEBUG | ||
27 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
28 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
29 | printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); | ||
30 | #endif | ||
31 | |||
32 | if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || | ||
33 | (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) | ||
34 | ret |= EFLAG_VXIMZ; | ||
35 | |||
36 | FP_MUL_D(T, A, C); | ||
37 | |||
38 | if (B_c != FP_CLS_NAN) | ||
39 | B_s ^= 1; | ||
40 | |||
41 | if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) | ||
42 | ret |= EFLAG_VXISI; | ||
43 | |||
44 | FP_ADD_D(R, T, B); | ||
45 | |||
46 | #ifdef DEBUG | ||
47 | printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
48 | #endif | ||
49 | |||
50 | return (ret | __FP_PACK_D(frD, R)); | ||
51 | } | ||
diff --git a/arch/powerpc/math-emu/fmsubs.c b/arch/powerpc/math-emu/fmsubs.c new file mode 100644 index 000000000000..8ce68624c189 --- /dev/null +++ b/arch/powerpc/math-emu/fmsubs.c | |||
@@ -0,0 +1,52 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | #include "single.h" | ||
8 | |||
9 | int | ||
10 | fmsubs(void *frD, void *frA, void *frB, void *frC) | ||
11 | { | ||
12 | FP_DECL_D(R); | ||
13 | FP_DECL_D(A); | ||
14 | FP_DECL_D(B); | ||
15 | FP_DECL_D(C); | ||
16 | FP_DECL_D(T); | ||
17 | int ret = 0; | ||
18 | |||
19 | #ifdef DEBUG | ||
20 | printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); | ||
21 | #endif | ||
22 | |||
23 | __FP_UNPACK_D(A, frA); | ||
24 | __FP_UNPACK_D(B, frB); | ||
25 | __FP_UNPACK_D(C, frC); | ||
26 | |||
27 | #ifdef DEBUG | ||
28 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
29 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
30 | printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); | ||
31 | #endif | ||
32 | |||
33 | if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || | ||
34 | (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) | ||
35 | ret |= EFLAG_VXIMZ; | ||
36 | |||
37 | FP_MUL_D(T, A, C); | ||
38 | |||
39 | if (B_c != FP_CLS_NAN) | ||
40 | B_s ^= 1; | ||
41 | |||
42 | if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) | ||
43 | ret |= EFLAG_VXISI; | ||
44 | |||
45 | FP_ADD_D(R, T, B); | ||
46 | |||
47 | #ifdef DEBUG | ||
48 | printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
49 | #endif | ||
50 | |||
51 | return (ret | __FP_PACK_DS(frD, R)); | ||
52 | } | ||
diff --git a/arch/powerpc/math-emu/fmul.c b/arch/powerpc/math-emu/fmul.c new file mode 100644 index 000000000000..66c7e79aae2e --- /dev/null +++ b/arch/powerpc/math-emu/fmul.c | |||
@@ -0,0 +1,42 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | |||
8 | int | ||
9 | fmul(void *frD, void *frA, void *frB) | ||
10 | { | ||
11 | FP_DECL_D(A); | ||
12 | FP_DECL_D(B); | ||
13 | FP_DECL_D(R); | ||
14 | int ret = 0; | ||
15 | |||
16 | #ifdef DEBUG | ||
17 | printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); | ||
18 | #endif | ||
19 | |||
20 | __FP_UNPACK_D(A, frA); | ||
21 | __FP_UNPACK_D(B, frB); | ||
22 | |||
23 | #ifdef DEBUG | ||
24 | printk("A: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n", | ||
25 | A_s, A_f1, A_f0, A_e, A_c, A_f1, A_f0, A_e + 1023); | ||
26 | printk("B: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n", | ||
27 | B_s, B_f1, B_f0, B_e, B_c, B_f1, B_f0, B_e + 1023); | ||
28 | #endif | ||
29 | |||
30 | if ((A_c == FP_CLS_INF && B_c == FP_CLS_ZERO) || | ||
31 | (A_c == FP_CLS_ZERO && B_c == FP_CLS_INF)) | ||
32 | ret |= EFLAG_VXIMZ; | ||
33 | |||
34 | FP_MUL_D(R, A, B); | ||
35 | |||
36 | #ifdef DEBUG | ||
37 | printk("D: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n", | ||
38 | R_s, R_f1, R_f0, R_e, R_c, R_f1, R_f0, R_e + 1023); | ||
39 | #endif | ||
40 | |||
41 | return (ret | __FP_PACK_D(frD, R)); | ||
42 | } | ||
diff --git a/arch/powerpc/math-emu/fmuls.c b/arch/powerpc/math-emu/fmuls.c new file mode 100644 index 000000000000..26bc4278271c --- /dev/null +++ b/arch/powerpc/math-emu/fmuls.c | |||
@@ -0,0 +1,43 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | #include "single.h" | ||
8 | |||
9 | int | ||
10 | fmuls(void *frD, void *frA, void *frB) | ||
11 | { | ||
12 | FP_DECL_D(A); | ||
13 | FP_DECL_D(B); | ||
14 | FP_DECL_D(R); | ||
15 | int ret = 0; | ||
16 | |||
17 | #ifdef DEBUG | ||
18 | printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); | ||
19 | #endif | ||
20 | |||
21 | __FP_UNPACK_D(A, frA); | ||
22 | __FP_UNPACK_D(B, frB); | ||
23 | |||
24 | #ifdef DEBUG | ||
25 | printk("A: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n", | ||
26 | A_s, A_f1, A_f0, A_e, A_c, A_f1, A_f0, A_e + 1023); | ||
27 | printk("B: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n", | ||
28 | B_s, B_f1, B_f0, B_e, B_c, B_f1, B_f0, B_e + 1023); | ||
29 | #endif | ||
30 | |||
31 | if ((A_c == FP_CLS_INF && B_c == FP_CLS_ZERO) || | ||
32 | (A_c == FP_CLS_ZERO && B_c == FP_CLS_INF)) | ||
33 | ret |= EFLAG_VXIMZ; | ||
34 | |||
35 | FP_MUL_D(R, A, B); | ||
36 | |||
37 | #ifdef DEBUG | ||
38 | printk("D: %ld %lu %lu %ld (%ld) [%08lx.%08lx %lx]\n", | ||
39 | R_s, R_f1, R_f0, R_e, R_c, R_f1, R_f0, R_e + 1023); | ||
40 | #endif | ||
41 | |||
42 | return (ret | __FP_PACK_DS(frD, R)); | ||
43 | } | ||
diff --git a/arch/powerpc/math-emu/fnabs.c b/arch/powerpc/math-emu/fnabs.c new file mode 100644 index 000000000000..c6b913d179e0 --- /dev/null +++ b/arch/powerpc/math-emu/fnabs.c | |||
@@ -0,0 +1,18 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | int | ||
6 | fnabs(u32 *frD, u32 *frB) | ||
7 | { | ||
8 | frD[0] = frB[0] | 0x80000000; | ||
9 | frD[1] = frB[1]; | ||
10 | |||
11 | #ifdef DEBUG | ||
12 | printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB); | ||
13 | dump_double(frD); | ||
14 | printk("\n"); | ||
15 | #endif | ||
16 | |||
17 | return 0; | ||
18 | } | ||
diff --git a/arch/powerpc/math-emu/fneg.c b/arch/powerpc/math-emu/fneg.c new file mode 100644 index 000000000000..fe9a98deff69 --- /dev/null +++ b/arch/powerpc/math-emu/fneg.c | |||
@@ -0,0 +1,18 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | int | ||
6 | fneg(u32 *frD, u32 *frB) | ||
7 | { | ||
8 | frD[0] = frB[0] ^ 0x80000000; | ||
9 | frD[1] = frB[1]; | ||
10 | |||
11 | #ifdef DEBUG | ||
12 | printk("%s: D %p, B %p: ", __FUNCTION__, frD, frB); | ||
13 | dump_double(frD); | ||
14 | printk("\n"); | ||
15 | #endif | ||
16 | |||
17 | return 0; | ||
18 | } | ||
diff --git a/arch/powerpc/math-emu/fnmadd.c b/arch/powerpc/math-emu/fnmadd.c new file mode 100644 index 000000000000..7f312276d920 --- /dev/null +++ b/arch/powerpc/math-emu/fnmadd.c | |||
@@ -0,0 +1,51 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | |||
8 | int | ||
9 | fnmadd(void *frD, void *frA, void *frB, void *frC) | ||
10 | { | ||
11 | FP_DECL_D(R); | ||
12 | FP_DECL_D(A); | ||
13 | FP_DECL_D(B); | ||
14 | FP_DECL_D(C); | ||
15 | FP_DECL_D(T); | ||
16 | int ret = 0; | ||
17 | |||
18 | #ifdef DEBUG | ||
19 | printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); | ||
20 | #endif | ||
21 | |||
22 | __FP_UNPACK_D(A, frA); | ||
23 | __FP_UNPACK_D(B, frB); | ||
24 | __FP_UNPACK_D(C, frC); | ||
25 | |||
26 | #ifdef DEBUG | ||
27 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
28 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
29 | printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); | ||
30 | #endif | ||
31 | |||
32 | if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || | ||
33 | (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) | ||
34 | ret |= EFLAG_VXIMZ; | ||
35 | |||
36 | FP_MUL_D(T, A, C); | ||
37 | |||
38 | if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) | ||
39 | ret |= EFLAG_VXISI; | ||
40 | |||
41 | FP_ADD_D(R, T, B); | ||
42 | |||
43 | if (R_c != FP_CLS_NAN) | ||
44 | R_s ^= 1; | ||
45 | |||
46 | #ifdef DEBUG | ||
47 | printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
48 | #endif | ||
49 | |||
50 | return (ret | __FP_PACK_D(frD, R)); | ||
51 | } | ||
diff --git a/arch/powerpc/math-emu/fnmadds.c b/arch/powerpc/math-emu/fnmadds.c new file mode 100644 index 000000000000..65454c9c70bc --- /dev/null +++ b/arch/powerpc/math-emu/fnmadds.c | |||
@@ -0,0 +1,52 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | #include "single.h" | ||
8 | |||
9 | int | ||
10 | fnmadds(void *frD, void *frA, void *frB, void *frC) | ||
11 | { | ||
12 | FP_DECL_D(R); | ||
13 | FP_DECL_D(A); | ||
14 | FP_DECL_D(B); | ||
15 | FP_DECL_D(C); | ||
16 | FP_DECL_D(T); | ||
17 | int ret = 0; | ||
18 | |||
19 | #ifdef DEBUG | ||
20 | printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); | ||
21 | #endif | ||
22 | |||
23 | __FP_UNPACK_D(A, frA); | ||
24 | __FP_UNPACK_D(B, frB); | ||
25 | __FP_UNPACK_D(C, frC); | ||
26 | |||
27 | #ifdef DEBUG | ||
28 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
29 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
30 | printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); | ||
31 | #endif | ||
32 | |||
33 | if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || | ||
34 | (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) | ||
35 | ret |= EFLAG_VXIMZ; | ||
36 | |||
37 | FP_MUL_D(T, A, C); | ||
38 | |||
39 | if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) | ||
40 | ret |= EFLAG_VXISI; | ||
41 | |||
42 | FP_ADD_D(R, T, B); | ||
43 | |||
44 | if (R_c != FP_CLS_NAN) | ||
45 | R_s ^= 1; | ||
46 | |||
47 | #ifdef DEBUG | ||
48 | printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
49 | #endif | ||
50 | |||
51 | return (ret | __FP_PACK_DS(frD, R)); | ||
52 | } | ||
diff --git a/arch/powerpc/math-emu/fnmsub.c b/arch/powerpc/math-emu/fnmsub.c new file mode 100644 index 000000000000..f1ca7482b5f0 --- /dev/null +++ b/arch/powerpc/math-emu/fnmsub.c | |||
@@ -0,0 +1,54 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | |||
8 | int | ||
9 | fnmsub(void *frD, void *frA, void *frB, void *frC) | ||
10 | { | ||
11 | FP_DECL_D(R); | ||
12 | FP_DECL_D(A); | ||
13 | FP_DECL_D(B); | ||
14 | FP_DECL_D(C); | ||
15 | FP_DECL_D(T); | ||
16 | int ret = 0; | ||
17 | |||
18 | #ifdef DEBUG | ||
19 | printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); | ||
20 | #endif | ||
21 | |||
22 | __FP_UNPACK_D(A, frA); | ||
23 | __FP_UNPACK_D(B, frB); | ||
24 | __FP_UNPACK_D(C, frC); | ||
25 | |||
26 | #ifdef DEBUG | ||
27 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
28 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
29 | printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); | ||
30 | #endif | ||
31 | |||
32 | if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || | ||
33 | (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) | ||
34 | ret |= EFLAG_VXIMZ; | ||
35 | |||
36 | FP_MUL_D(T, A, C); | ||
37 | |||
38 | if (B_c != FP_CLS_NAN) | ||
39 | B_s ^= 1; | ||
40 | |||
41 | if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) | ||
42 | ret |= EFLAG_VXISI; | ||
43 | |||
44 | FP_ADD_D(R, T, B); | ||
45 | |||
46 | if (R_c != FP_CLS_NAN) | ||
47 | R_s ^= 1; | ||
48 | |||
49 | #ifdef DEBUG | ||
50 | printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
51 | #endif | ||
52 | |||
53 | return (ret | __FP_PACK_D(frD, R)); | ||
54 | } | ||
diff --git a/arch/powerpc/math-emu/fnmsubs.c b/arch/powerpc/math-emu/fnmsubs.c new file mode 100644 index 000000000000..5c9a09a87dc7 --- /dev/null +++ b/arch/powerpc/math-emu/fnmsubs.c | |||
@@ -0,0 +1,55 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | #include "single.h" | ||
8 | |||
9 | int | ||
10 | fnmsubs(void *frD, void *frA, void *frB, void *frC) | ||
11 | { | ||
12 | FP_DECL_D(R); | ||
13 | FP_DECL_D(A); | ||
14 | FP_DECL_D(B); | ||
15 | FP_DECL_D(C); | ||
16 | FP_DECL_D(T); | ||
17 | int ret = 0; | ||
18 | |||
19 | #ifdef DEBUG | ||
20 | printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); | ||
21 | #endif | ||
22 | |||
23 | __FP_UNPACK_D(A, frA); | ||
24 | __FP_UNPACK_D(B, frB); | ||
25 | __FP_UNPACK_D(C, frC); | ||
26 | |||
27 | #ifdef DEBUG | ||
28 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
29 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
30 | printk("C: %ld %lu %lu %ld (%ld)\n", C_s, C_f1, C_f0, C_e, C_c); | ||
31 | #endif | ||
32 | |||
33 | if ((A_c == FP_CLS_INF && C_c == FP_CLS_ZERO) || | ||
34 | (A_c == FP_CLS_ZERO && C_c == FP_CLS_INF)) | ||
35 | ret |= EFLAG_VXIMZ; | ||
36 | |||
37 | FP_MUL_D(T, A, C); | ||
38 | |||
39 | if (B_c != FP_CLS_NAN) | ||
40 | B_s ^= 1; | ||
41 | |||
42 | if (T_s != B_s && T_c == FP_CLS_INF && B_c == FP_CLS_INF) | ||
43 | ret |= EFLAG_VXISI; | ||
44 | |||
45 | FP_ADD_D(R, T, B); | ||
46 | |||
47 | if (R_c != FP_CLS_NAN) | ||
48 | R_s ^= 1; | ||
49 | |||
50 | #ifdef DEBUG | ||
51 | printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
52 | #endif | ||
53 | |||
54 | return (ret | __FP_PACK_DS(frD, R)); | ||
55 | } | ||
diff --git a/arch/powerpc/math-emu/fres.c b/arch/powerpc/math-emu/fres.c new file mode 100644 index 000000000000..ec11e46d20af --- /dev/null +++ b/arch/powerpc/math-emu/fres.c | |||
@@ -0,0 +1,12 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | int | ||
6 | fres(void *frD, void *frB) | ||
7 | { | ||
8 | #ifdef DEBUG | ||
9 | printk("%s: %p %p\n", __FUNCTION__, frD, frB); | ||
10 | #endif | ||
11 | return -ENOSYS; | ||
12 | } | ||
diff --git a/arch/powerpc/math-emu/frsp.c b/arch/powerpc/math-emu/frsp.c new file mode 100644 index 000000000000..d879b2a3d0c9 --- /dev/null +++ b/arch/powerpc/math-emu/frsp.c | |||
@@ -0,0 +1,25 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | #include "single.h" | ||
8 | |||
9 | int | ||
10 | frsp(void *frD, void *frB) | ||
11 | { | ||
12 | FP_DECL_D(B); | ||
13 | |||
14 | #ifdef DEBUG | ||
15 | printk("%s: D %p, B %p\n", __FUNCTION__, frD, frB); | ||
16 | #endif | ||
17 | |||
18 | __FP_UNPACK_D(B, frB); | ||
19 | |||
20 | #ifdef DEBUG | ||
21 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
22 | #endif | ||
23 | |||
24 | return __FP_PACK_DS(frD, B); | ||
25 | } | ||
diff --git a/arch/powerpc/math-emu/frsqrte.c b/arch/powerpc/math-emu/frsqrte.c new file mode 100644 index 000000000000..a11ae1829850 --- /dev/null +++ b/arch/powerpc/math-emu/frsqrte.c | |||
@@ -0,0 +1,12 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | int | ||
6 | frsqrte(void *frD, void *frB) | ||
7 | { | ||
8 | #ifdef DEBUG | ||
9 | printk("%s: %p %p\n", __FUNCTION__, frD, frB); | ||
10 | #endif | ||
11 | return 0; | ||
12 | } | ||
diff --git a/arch/powerpc/math-emu/fsel.c b/arch/powerpc/math-emu/fsel.c new file mode 100644 index 000000000000..e36e6e72819a --- /dev/null +++ b/arch/powerpc/math-emu/fsel.c | |||
@@ -0,0 +1,38 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | |||
8 | int | ||
9 | fsel(u32 *frD, void *frA, u32 *frB, u32 *frC) | ||
10 | { | ||
11 | FP_DECL_D(A); | ||
12 | |||
13 | #ifdef DEBUG | ||
14 | printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frA, frB, frC); | ||
15 | #endif | ||
16 | |||
17 | __FP_UNPACK_D(A, frA); | ||
18 | |||
19 | #ifdef DEBUG | ||
20 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
21 | printk("B: %08x %08x\n", frB[0], frB[1]); | ||
22 | printk("C: %08x %08x\n", frC[0], frC[1]); | ||
23 | #endif | ||
24 | |||
25 | if (A_c == FP_CLS_NAN || (A_c != FP_CLS_ZERO && A_s)) { | ||
26 | frD[0] = frB[0]; | ||
27 | frD[1] = frB[1]; | ||
28 | } else { | ||
29 | frD[0] = frC[0]; | ||
30 | frD[1] = frC[1]; | ||
31 | } | ||
32 | |||
33 | #ifdef DEBUG | ||
34 | printk("D: %08x.%08x\n", frD[0], frD[1]); | ||
35 | #endif | ||
36 | |||
37 | return 0; | ||
38 | } | ||
diff --git a/arch/powerpc/math-emu/fsqrt.c b/arch/powerpc/math-emu/fsqrt.c new file mode 100644 index 000000000000..6f8319f64a8a --- /dev/null +++ b/arch/powerpc/math-emu/fsqrt.c | |||
@@ -0,0 +1,37 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | |||
8 | int | ||
9 | fsqrt(void *frD, void *frB) | ||
10 | { | ||
11 | FP_DECL_D(B); | ||
12 | FP_DECL_D(R); | ||
13 | int ret = 0; | ||
14 | |||
15 | #ifdef DEBUG | ||
16 | printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frB); | ||
17 | #endif | ||
18 | |||
19 | __FP_UNPACK_D(B, frB); | ||
20 | |||
21 | #ifdef DEBUG | ||
22 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
23 | #endif | ||
24 | |||
25 | if (B_s && B_c != FP_CLS_ZERO) | ||
26 | ret |= EFLAG_VXSQRT; | ||
27 | if (B_c == FP_CLS_NAN) | ||
28 | ret |= EFLAG_VXSNAN; | ||
29 | |||
30 | FP_SQRT_D(R, B); | ||
31 | |||
32 | #ifdef DEBUG | ||
33 | printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
34 | #endif | ||
35 | |||
36 | return (ret | __FP_PACK_D(frD, R)); | ||
37 | } | ||
diff --git a/arch/powerpc/math-emu/fsqrts.c b/arch/powerpc/math-emu/fsqrts.c new file mode 100644 index 000000000000..3b2b1cf55c12 --- /dev/null +++ b/arch/powerpc/math-emu/fsqrts.c | |||
@@ -0,0 +1,38 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | #include "single.h" | ||
8 | |||
9 | int | ||
10 | fsqrts(void *frD, void *frB) | ||
11 | { | ||
12 | FP_DECL_D(B); | ||
13 | FP_DECL_D(R); | ||
14 | int ret = 0; | ||
15 | |||
16 | #ifdef DEBUG | ||
17 | printk("%s: %p %p %p %p\n", __FUNCTION__, frD, frB); | ||
18 | #endif | ||
19 | |||
20 | __FP_UNPACK_D(B, frB); | ||
21 | |||
22 | #ifdef DEBUG | ||
23 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
24 | #endif | ||
25 | |||
26 | if (B_s && B_c != FP_CLS_ZERO) | ||
27 | ret |= EFLAG_VXSQRT; | ||
28 | if (B_c == FP_CLS_NAN) | ||
29 | ret |= EFLAG_VXSNAN; | ||
30 | |||
31 | FP_SQRT_D(R, B); | ||
32 | |||
33 | #ifdef DEBUG | ||
34 | printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
35 | #endif | ||
36 | |||
37 | return (ret | __FP_PACK_DS(frD, R)); | ||
38 | } | ||
diff --git a/arch/powerpc/math-emu/fsub.c b/arch/powerpc/math-emu/fsub.c new file mode 100644 index 000000000000..956679042bb2 --- /dev/null +++ b/arch/powerpc/math-emu/fsub.c | |||
@@ -0,0 +1,41 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | |||
8 | int | ||
9 | fsub(void *frD, void *frA, void *frB) | ||
10 | { | ||
11 | FP_DECL_D(A); | ||
12 | FP_DECL_D(B); | ||
13 | FP_DECL_D(R); | ||
14 | int ret = 0; | ||
15 | |||
16 | #ifdef DEBUG | ||
17 | printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); | ||
18 | #endif | ||
19 | |||
20 | __FP_UNPACK_D(A, frA); | ||
21 | __FP_UNPACK_D(B, frB); | ||
22 | |||
23 | #ifdef DEBUG | ||
24 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
25 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
26 | #endif | ||
27 | |||
28 | if (B_c != FP_CLS_NAN) | ||
29 | B_s ^= 1; | ||
30 | |||
31 | if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF) | ||
32 | ret |= EFLAG_VXISI; | ||
33 | |||
34 | FP_ADD_D(R, A, B); | ||
35 | |||
36 | #ifdef DEBUG | ||
37 | printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
38 | #endif | ||
39 | |||
40 | return (ret | __FP_PACK_D(frD, R)); | ||
41 | } | ||
diff --git a/arch/powerpc/math-emu/fsubs.c b/arch/powerpc/math-emu/fsubs.c new file mode 100644 index 000000000000..3428117dfe8c --- /dev/null +++ b/arch/powerpc/math-emu/fsubs.c | |||
@@ -0,0 +1,42 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | #include "single.h" | ||
8 | |||
9 | int | ||
10 | fsubs(void *frD, void *frA, void *frB) | ||
11 | { | ||
12 | FP_DECL_D(A); | ||
13 | FP_DECL_D(B); | ||
14 | FP_DECL_D(R); | ||
15 | int ret = 0; | ||
16 | |||
17 | #ifdef DEBUG | ||
18 | printk("%s: %p %p %p\n", __FUNCTION__, frD, frA, frB); | ||
19 | #endif | ||
20 | |||
21 | __FP_UNPACK_D(A, frA); | ||
22 | __FP_UNPACK_D(B, frB); | ||
23 | |||
24 | #ifdef DEBUG | ||
25 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
26 | printk("B: %ld %lu %lu %ld (%ld)\n", B_s, B_f1, B_f0, B_e, B_c); | ||
27 | #endif | ||
28 | |||
29 | if (B_c != FP_CLS_NAN) | ||
30 | B_s ^= 1; | ||
31 | |||
32 | if (A_s != B_s && A_c == FP_CLS_INF && B_c == FP_CLS_INF) | ||
33 | ret |= EFLAG_VXISI; | ||
34 | |||
35 | FP_ADD_D(R, A, B); | ||
36 | |||
37 | #ifdef DEBUG | ||
38 | printk("D: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
39 | #endif | ||
40 | |||
41 | return (ret | __FP_PACK_DS(frD, R)); | ||
42 | } | ||
diff --git a/arch/powerpc/math-emu/lfd.c b/arch/powerpc/math-emu/lfd.c new file mode 100644 index 000000000000..7d38101c329b --- /dev/null +++ b/arch/powerpc/math-emu/lfd.c | |||
@@ -0,0 +1,19 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "sfp-machine.h" | ||
6 | #include "double.h" | ||
7 | |||
8 | int | ||
9 | lfd(void *frD, void *ea) | ||
10 | { | ||
11 | if (copy_from_user(frD, ea, sizeof(double))) | ||
12 | return -EFAULT; | ||
13 | #ifdef DEBUG | ||
14 | printk("%s: D %p, ea %p: ", __FUNCTION__, frD, ea); | ||
15 | dump_double(frD); | ||
16 | printk("\n"); | ||
17 | #endif | ||
18 | return 0; | ||
19 | } | ||
diff --git a/arch/powerpc/math-emu/lfs.c b/arch/powerpc/math-emu/lfs.c new file mode 100644 index 000000000000..c86dee3d7655 --- /dev/null +++ b/arch/powerpc/math-emu/lfs.c | |||
@@ -0,0 +1,37 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | #include "single.h" | ||
8 | |||
9 | int | ||
10 | lfs(void *frD, void *ea) | ||
11 | { | ||
12 | FP_DECL_D(R); | ||
13 | FP_DECL_S(A); | ||
14 | float f; | ||
15 | |||
16 | #ifdef DEBUG | ||
17 | printk("%s: D %p, ea %p\n", __FUNCTION__, frD, ea); | ||
18 | #endif | ||
19 | |||
20 | if (copy_from_user(&f, ea, sizeof(float))) | ||
21 | return -EFAULT; | ||
22 | |||
23 | __FP_UNPACK_S(A, &f); | ||
24 | |||
25 | #ifdef DEBUG | ||
26 | printk("A: %ld %lu %ld (%ld) [%08lx]\n", A_s, A_f, A_e, A_c, | ||
27 | *(unsigned long *)&f); | ||
28 | #endif | ||
29 | |||
30 | FP_CONV(D, S, 2, 1, R, A); | ||
31 | |||
32 | #ifdef DEBUG | ||
33 | printk("R: %ld %lu %lu %ld (%ld)\n", R_s, R_f1, R_f0, R_e, R_c); | ||
34 | #endif | ||
35 | |||
36 | return __FP_PACK_D(frD, R); | ||
37 | } | ||
diff --git a/arch/powerpc/math-emu/math.c b/arch/powerpc/math-emu/math.c new file mode 100644 index 000000000000..589153472761 --- /dev/null +++ b/arch/powerpc/math-emu/math.c | |||
@@ -0,0 +1,483 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1999 Eddie C. Dost (ecd@atecom.com) | ||
3 | */ | ||
4 | |||
5 | #include <linux/config.h> | ||
6 | #include <linux/types.h> | ||
7 | #include <linux/sched.h> | ||
8 | |||
9 | #include <asm/uaccess.h> | ||
10 | #include <asm/reg.h> | ||
11 | |||
12 | #include "sfp-machine.h" | ||
13 | #include "double.h" | ||
14 | |||
15 | #define FLOATFUNC(x) extern int x(void *, void *, void *, void *) | ||
16 | |||
17 | FLOATFUNC(fadd); | ||
18 | FLOATFUNC(fadds); | ||
19 | FLOATFUNC(fdiv); | ||
20 | FLOATFUNC(fdivs); | ||
21 | FLOATFUNC(fmul); | ||
22 | FLOATFUNC(fmuls); | ||
23 | FLOATFUNC(fsub); | ||
24 | FLOATFUNC(fsubs); | ||
25 | |||
26 | FLOATFUNC(fmadd); | ||
27 | FLOATFUNC(fmadds); | ||
28 | FLOATFUNC(fmsub); | ||
29 | FLOATFUNC(fmsubs); | ||
30 | FLOATFUNC(fnmadd); | ||
31 | FLOATFUNC(fnmadds); | ||
32 | FLOATFUNC(fnmsub); | ||
33 | FLOATFUNC(fnmsubs); | ||
34 | |||
35 | FLOATFUNC(fctiw); | ||
36 | FLOATFUNC(fctiwz); | ||
37 | FLOATFUNC(frsp); | ||
38 | |||
39 | FLOATFUNC(fcmpo); | ||
40 | FLOATFUNC(fcmpu); | ||
41 | |||
42 | FLOATFUNC(mcrfs); | ||
43 | FLOATFUNC(mffs); | ||
44 | FLOATFUNC(mtfsb0); | ||
45 | FLOATFUNC(mtfsb1); | ||
46 | FLOATFUNC(mtfsf); | ||
47 | FLOATFUNC(mtfsfi); | ||
48 | |||
49 | FLOATFUNC(lfd); | ||
50 | FLOATFUNC(lfs); | ||
51 | |||
52 | FLOATFUNC(stfd); | ||
53 | FLOATFUNC(stfs); | ||
54 | FLOATFUNC(stfiwx); | ||
55 | |||
56 | FLOATFUNC(fabs); | ||
57 | FLOATFUNC(fmr); | ||
58 | FLOATFUNC(fnabs); | ||
59 | FLOATFUNC(fneg); | ||
60 | |||
61 | /* Optional */ | ||
62 | FLOATFUNC(fres); | ||
63 | FLOATFUNC(frsqrte); | ||
64 | FLOATFUNC(fsel); | ||
65 | FLOATFUNC(fsqrt); | ||
66 | FLOATFUNC(fsqrts); | ||
67 | |||
68 | |||
69 | #define OP31 0x1f /* 31 */ | ||
70 | #define LFS 0x30 /* 48 */ | ||
71 | #define LFSU 0x31 /* 49 */ | ||
72 | #define LFD 0x32 /* 50 */ | ||
73 | #define LFDU 0x33 /* 51 */ | ||
74 | #define STFS 0x34 /* 52 */ | ||
75 | #define STFSU 0x35 /* 53 */ | ||
76 | #define STFD 0x36 /* 54 */ | ||
77 | #define STFDU 0x37 /* 55 */ | ||
78 | #define OP59 0x3b /* 59 */ | ||
79 | #define OP63 0x3f /* 63 */ | ||
80 | |||
81 | /* Opcode 31: */ | ||
82 | /* X-Form: */ | ||
83 | #define LFSX 0x217 /* 535 */ | ||
84 | #define LFSUX 0x237 /* 567 */ | ||
85 | #define LFDX 0x257 /* 599 */ | ||
86 | #define LFDUX 0x277 /* 631 */ | ||
87 | #define STFSX 0x297 /* 663 */ | ||
88 | #define STFSUX 0x2b7 /* 695 */ | ||
89 | #define STFDX 0x2d7 /* 727 */ | ||
90 | #define STFDUX 0x2f7 /* 759 */ | ||
91 | #define STFIWX 0x3d7 /* 983 */ | ||
92 | |||
93 | /* Opcode 59: */ | ||
94 | /* A-Form: */ | ||
95 | #define FDIVS 0x012 /* 18 */ | ||
96 | #define FSUBS 0x014 /* 20 */ | ||
97 | #define FADDS 0x015 /* 21 */ | ||
98 | #define FSQRTS 0x016 /* 22 */ | ||
99 | #define FRES 0x018 /* 24 */ | ||
100 | #define FMULS 0x019 /* 25 */ | ||
101 | #define FMSUBS 0x01c /* 28 */ | ||
102 | #define FMADDS 0x01d /* 29 */ | ||
103 | #define FNMSUBS 0x01e /* 30 */ | ||
104 | #define FNMADDS 0x01f /* 31 */ | ||
105 | |||
106 | /* Opcode 63: */ | ||
107 | /* A-Form: */ | ||
108 | #define FDIV 0x012 /* 18 */ | ||
109 | #define FSUB 0x014 /* 20 */ | ||
110 | #define FADD 0x015 /* 21 */ | ||
111 | #define FSQRT 0x016 /* 22 */ | ||
112 | #define FSEL 0x017 /* 23 */ | ||
113 | #define FMUL 0x019 /* 25 */ | ||
114 | #define FRSQRTE 0x01a /* 26 */ | ||
115 | #define FMSUB 0x01c /* 28 */ | ||
116 | #define FMADD 0x01d /* 29 */ | ||
117 | #define FNMSUB 0x01e /* 30 */ | ||
118 | #define FNMADD 0x01f /* 31 */ | ||
119 | |||
120 | /* X-Form: */ | ||
121 | #define FCMPU 0x000 /* 0 */ | ||
122 | #define FRSP 0x00c /* 12 */ | ||
123 | #define FCTIW 0x00e /* 14 */ | ||
124 | #define FCTIWZ 0x00f /* 15 */ | ||
125 | #define FCMPO 0x020 /* 32 */ | ||
126 | #define MTFSB1 0x026 /* 38 */ | ||
127 | #define FNEG 0x028 /* 40 */ | ||
128 | #define MCRFS 0x040 /* 64 */ | ||
129 | #define MTFSB0 0x046 /* 70 */ | ||
130 | #define FMR 0x048 /* 72 */ | ||
131 | #define MTFSFI 0x086 /* 134 */ | ||
132 | #define FNABS 0x088 /* 136 */ | ||
133 | #define FABS 0x108 /* 264 */ | ||
134 | #define MFFS 0x247 /* 583 */ | ||
135 | #define MTFSF 0x2c7 /* 711 */ | ||
136 | |||
137 | |||
138 | #define AB 2 | ||
139 | #define AC 3 | ||
140 | #define ABC 4 | ||
141 | #define D 5 | ||
142 | #define DU 6 | ||
143 | #define X 7 | ||
144 | #define XA 8 | ||
145 | #define XB 9 | ||
146 | #define XCR 11 | ||
147 | #define XCRB 12 | ||
148 | #define XCRI 13 | ||
149 | #define XCRL 16 | ||
150 | #define XE 14 | ||
151 | #define XEU 15 | ||
152 | #define XFLB 10 | ||
153 | |||
154 | #ifdef CONFIG_MATH_EMULATION | ||
155 | static int | ||
156 | record_exception(struct pt_regs *regs, int eflag) | ||
157 | { | ||
158 | u32 fpscr; | ||
159 | |||
160 | fpscr = __FPU_FPSCR; | ||
161 | |||
162 | if (eflag) { | ||
163 | fpscr |= FPSCR_FX; | ||
164 | if (eflag & EFLAG_OVERFLOW) | ||
165 | fpscr |= FPSCR_OX; | ||
166 | if (eflag & EFLAG_UNDERFLOW) | ||
167 | fpscr |= FPSCR_UX; | ||
168 | if (eflag & EFLAG_DIVZERO) | ||
169 | fpscr |= FPSCR_ZX; | ||
170 | if (eflag & EFLAG_INEXACT) | ||
171 | fpscr |= FPSCR_XX; | ||
172 | if (eflag & EFLAG_VXSNAN) | ||
173 | fpscr |= FPSCR_VXSNAN; | ||
174 | if (eflag & EFLAG_VXISI) | ||
175 | fpscr |= FPSCR_VXISI; | ||
176 | if (eflag & EFLAG_VXIDI) | ||
177 | fpscr |= FPSCR_VXIDI; | ||
178 | if (eflag & EFLAG_VXZDZ) | ||
179 | fpscr |= FPSCR_VXZDZ; | ||
180 | if (eflag & EFLAG_VXIMZ) | ||
181 | fpscr |= FPSCR_VXIMZ; | ||
182 | if (eflag & EFLAG_VXVC) | ||
183 | fpscr |= FPSCR_VXVC; | ||
184 | if (eflag & EFLAG_VXSOFT) | ||
185 | fpscr |= FPSCR_VXSOFT; | ||
186 | if (eflag & EFLAG_VXSQRT) | ||
187 | fpscr |= FPSCR_VXSQRT; | ||
188 | if (eflag & EFLAG_VXCVI) | ||
189 | fpscr |= FPSCR_VXCVI; | ||
190 | } | ||
191 | |||
192 | fpscr &= ~(FPSCR_VX); | ||
193 | if (fpscr & (FPSCR_VXSNAN | FPSCR_VXISI | FPSCR_VXIDI | | ||
194 | FPSCR_VXZDZ | FPSCR_VXIMZ | FPSCR_VXVC | | ||
195 | FPSCR_VXSOFT | FPSCR_VXSQRT | FPSCR_VXCVI)) | ||
196 | fpscr |= FPSCR_VX; | ||
197 | |||
198 | fpscr &= ~(FPSCR_FEX); | ||
199 | if (((fpscr & FPSCR_VX) && (fpscr & FPSCR_VE)) || | ||
200 | ((fpscr & FPSCR_OX) && (fpscr & FPSCR_OE)) || | ||
201 | ((fpscr & FPSCR_UX) && (fpscr & FPSCR_UE)) || | ||
202 | ((fpscr & FPSCR_ZX) && (fpscr & FPSCR_ZE)) || | ||
203 | ((fpscr & FPSCR_XX) && (fpscr & FPSCR_XE))) | ||
204 | fpscr |= FPSCR_FEX; | ||
205 | |||
206 | __FPU_FPSCR = fpscr; | ||
207 | |||
208 | return (fpscr & FPSCR_FEX) ? 1 : 0; | ||
209 | } | ||
210 | #endif /* CONFIG_MATH_EMULATION */ | ||
211 | |||
212 | int | ||
213 | do_mathemu(struct pt_regs *regs) | ||
214 | { | ||
215 | void *op0 = 0, *op1 = 0, *op2 = 0, *op3 = 0; | ||
216 | unsigned long pc = regs->nip; | ||
217 | signed short sdisp; | ||
218 | u32 insn = 0; | ||
219 | int idx = 0; | ||
220 | #ifdef CONFIG_MATH_EMULATION | ||
221 | int (*func)(void *, void *, void *, void *); | ||
222 | int type = 0; | ||
223 | int eflag, trap; | ||
224 | #endif | ||
225 | |||
226 | if (get_user(insn, (u32 *)pc)) | ||
227 | return -EFAULT; | ||
228 | |||
229 | #ifndef CONFIG_MATH_EMULATION | ||
230 | switch (insn >> 26) { | ||
231 | case LFD: | ||
232 | idx = (insn >> 16) & 0x1f; | ||
233 | sdisp = (insn & 0xffff); | ||
234 | op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; | ||
235 | op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); | ||
236 | lfd(op0, op1, op2, op3); | ||
237 | break; | ||
238 | case LFDU: | ||
239 | idx = (insn >> 16) & 0x1f; | ||
240 | sdisp = (insn & 0xffff); | ||
241 | op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; | ||
242 | op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); | ||
243 | lfd(op0, op1, op2, op3); | ||
244 | regs->gpr[idx] = (unsigned long)op1; | ||
245 | break; | ||
246 | case STFD: | ||
247 | idx = (insn >> 16) & 0x1f; | ||
248 | sdisp = (insn & 0xffff); | ||
249 | op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; | ||
250 | op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); | ||
251 | stfd(op0, op1, op2, op3); | ||
252 | break; | ||
253 | case STFDU: | ||
254 | idx = (insn >> 16) & 0x1f; | ||
255 | sdisp = (insn & 0xffff); | ||
256 | op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; | ||
257 | op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); | ||
258 | stfd(op0, op1, op2, op3); | ||
259 | regs->gpr[idx] = (unsigned long)op1; | ||
260 | break; | ||
261 | case OP63: | ||
262 | op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; | ||
263 | op1 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; | ||
264 | fmr(op0, op1, op2, op3); | ||
265 | break; | ||
266 | default: | ||
267 | goto illegal; | ||
268 | } | ||
269 | #else /* CONFIG_MATH_EMULATION */ | ||
270 | switch (insn >> 26) { | ||
271 | case LFS: func = lfs; type = D; break; | ||
272 | case LFSU: func = lfs; type = DU; break; | ||
273 | case LFD: func = lfd; type = D; break; | ||
274 | case LFDU: func = lfd; type = DU; break; | ||
275 | case STFS: func = stfs; type = D; break; | ||
276 | case STFSU: func = stfs; type = DU; break; | ||
277 | case STFD: func = stfd; type = D; break; | ||
278 | case STFDU: func = stfd; type = DU; break; | ||
279 | |||
280 | case OP31: | ||
281 | switch ((insn >> 1) & 0x3ff) { | ||
282 | case LFSX: func = lfs; type = XE; break; | ||
283 | case LFSUX: func = lfs; type = XEU; break; | ||
284 | case LFDX: func = lfd; type = XE; break; | ||
285 | case LFDUX: func = lfd; type = XEU; break; | ||
286 | case STFSX: func = stfs; type = XE; break; | ||
287 | case STFSUX: func = stfs; type = XEU; break; | ||
288 | case STFDX: func = stfd; type = XE; break; | ||
289 | case STFDUX: func = stfd; type = XEU; break; | ||
290 | case STFIWX: func = stfiwx; type = XE; break; | ||
291 | default: | ||
292 | goto illegal; | ||
293 | } | ||
294 | break; | ||
295 | |||
296 | case OP59: | ||
297 | switch ((insn >> 1) & 0x1f) { | ||
298 | case FDIVS: func = fdivs; type = AB; break; | ||
299 | case FSUBS: func = fsubs; type = AB; break; | ||
300 | case FADDS: func = fadds; type = AB; break; | ||
301 | case FSQRTS: func = fsqrts; type = AB; break; | ||
302 | case FRES: func = fres; type = AB; break; | ||
303 | case FMULS: func = fmuls; type = AC; break; | ||
304 | case FMSUBS: func = fmsubs; type = ABC; break; | ||
305 | case FMADDS: func = fmadds; type = ABC; break; | ||
306 | case FNMSUBS: func = fnmsubs; type = ABC; break; | ||
307 | case FNMADDS: func = fnmadds; type = ABC; break; | ||
308 | default: | ||
309 | goto illegal; | ||
310 | } | ||
311 | break; | ||
312 | |||
313 | case OP63: | ||
314 | if (insn & 0x20) { | ||
315 | switch ((insn >> 1) & 0x1f) { | ||
316 | case FDIV: func = fdiv; type = AB; break; | ||
317 | case FSUB: func = fsub; type = AB; break; | ||
318 | case FADD: func = fadd; type = AB; break; | ||
319 | case FSQRT: func = fsqrt; type = AB; break; | ||
320 | case FSEL: func = fsel; type = ABC; break; | ||
321 | case FMUL: func = fmul; type = AC; break; | ||
322 | case FRSQRTE: func = frsqrte; type = AB; break; | ||
323 | case FMSUB: func = fmsub; type = ABC; break; | ||
324 | case FMADD: func = fmadd; type = ABC; break; | ||
325 | case FNMSUB: func = fnmsub; type = ABC; break; | ||
326 | case FNMADD: func = fnmadd; type = ABC; break; | ||
327 | default: | ||
328 | goto illegal; | ||
329 | } | ||
330 | break; | ||
331 | } | ||
332 | |||
333 | switch ((insn >> 1) & 0x3ff) { | ||
334 | case FCMPU: func = fcmpu; type = XCR; break; | ||
335 | case FRSP: func = frsp; type = XB; break; | ||
336 | case FCTIW: func = fctiw; type = XB; break; | ||
337 | case FCTIWZ: func = fctiwz; type = XB; break; | ||
338 | case FCMPO: func = fcmpo; type = XCR; break; | ||
339 | case MTFSB1: func = mtfsb1; type = XCRB; break; | ||
340 | case FNEG: func = fneg; type = XB; break; | ||
341 | case MCRFS: func = mcrfs; type = XCRL; break; | ||
342 | case MTFSB0: func = mtfsb0; type = XCRB; break; | ||
343 | case FMR: func = fmr; type = XB; break; | ||
344 | case MTFSFI: func = mtfsfi; type = XCRI; break; | ||
345 | case FNABS: func = fnabs; type = XB; break; | ||
346 | case FABS: func = fabs; type = XB; break; | ||
347 | case MFFS: func = mffs; type = X; break; | ||
348 | case MTFSF: func = mtfsf; type = XFLB; break; | ||
349 | default: | ||
350 | goto illegal; | ||
351 | } | ||
352 | break; | ||
353 | |||
354 | default: | ||
355 | goto illegal; | ||
356 | } | ||
357 | |||
358 | switch (type) { | ||
359 | case AB: | ||
360 | op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; | ||
361 | op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f]; | ||
362 | op2 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; | ||
363 | break; | ||
364 | |||
365 | case AC: | ||
366 | op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; | ||
367 | op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f]; | ||
368 | op2 = (void *)¤t->thread.fpr[(insn >> 6) & 0x1f]; | ||
369 | break; | ||
370 | |||
371 | case ABC: | ||
372 | op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; | ||
373 | op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f]; | ||
374 | op2 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; | ||
375 | op3 = (void *)¤t->thread.fpr[(insn >> 6) & 0x1f]; | ||
376 | break; | ||
377 | |||
378 | case D: | ||
379 | idx = (insn >> 16) & 0x1f; | ||
380 | sdisp = (insn & 0xffff); | ||
381 | op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; | ||
382 | op1 = (void *)((idx ? regs->gpr[idx] : 0) + sdisp); | ||
383 | break; | ||
384 | |||
385 | case DU: | ||
386 | idx = (insn >> 16) & 0x1f; | ||
387 | if (!idx) | ||
388 | goto illegal; | ||
389 | |||
390 | sdisp = (insn & 0xffff); | ||
391 | op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; | ||
392 | op1 = (void *)(regs->gpr[idx] + sdisp); | ||
393 | break; | ||
394 | |||
395 | case X: | ||
396 | op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; | ||
397 | break; | ||
398 | |||
399 | case XA: | ||
400 | op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; | ||
401 | op1 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f]; | ||
402 | break; | ||
403 | |||
404 | case XB: | ||
405 | op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; | ||
406 | op1 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; | ||
407 | break; | ||
408 | |||
409 | case XE: | ||
410 | idx = (insn >> 16) & 0x1f; | ||
411 | if (!idx) | ||
412 | goto illegal; | ||
413 | |||
414 | op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; | ||
415 | op1 = (void *)(regs->gpr[idx] + regs->gpr[(insn >> 11) & 0x1f]); | ||
416 | break; | ||
417 | |||
418 | case XEU: | ||
419 | idx = (insn >> 16) & 0x1f; | ||
420 | op0 = (void *)¤t->thread.fpr[(insn >> 21) & 0x1f]; | ||
421 | op1 = (void *)((idx ? regs->gpr[idx] : 0) | ||
422 | + regs->gpr[(insn >> 11) & 0x1f]); | ||
423 | break; | ||
424 | |||
425 | case XCR: | ||
426 | op0 = (void *)®s->ccr; | ||
427 | op1 = (void *)((insn >> 23) & 0x7); | ||
428 | op2 = (void *)¤t->thread.fpr[(insn >> 16) & 0x1f]; | ||
429 | op3 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; | ||
430 | break; | ||
431 | |||
432 | case XCRL: | ||
433 | op0 = (void *)®s->ccr; | ||
434 | op1 = (void *)((insn >> 23) & 0x7); | ||
435 | op2 = (void *)((insn >> 18) & 0x7); | ||
436 | break; | ||
437 | |||
438 | case XCRB: | ||
439 | op0 = (void *)((insn >> 21) & 0x1f); | ||
440 | break; | ||
441 | |||
442 | case XCRI: | ||
443 | op0 = (void *)((insn >> 23) & 0x7); | ||
444 | op1 = (void *)((insn >> 12) & 0xf); | ||
445 | break; | ||
446 | |||
447 | case XFLB: | ||
448 | op0 = (void *)((insn >> 17) & 0xff); | ||
449 | op1 = (void *)¤t->thread.fpr[(insn >> 11) & 0x1f]; | ||
450 | break; | ||
451 | |||
452 | default: | ||
453 | goto illegal; | ||
454 | } | ||
455 | |||
456 | eflag = func(op0, op1, op2, op3); | ||
457 | |||
458 | if (insn & 1) { | ||
459 | regs->ccr &= ~(0x0f000000); | ||
460 | regs->ccr |= (__FPU_FPSCR >> 4) & 0x0f000000; | ||
461 | } | ||
462 | |||
463 | trap = record_exception(regs, eflag); | ||
464 | if (trap) | ||
465 | return 1; | ||
466 | |||
467 | switch (type) { | ||
468 | case DU: | ||
469 | case XEU: | ||
470 | regs->gpr[idx] = (unsigned long)op1; | ||
471 | break; | ||
472 | |||
473 | default: | ||
474 | break; | ||
475 | } | ||
476 | #endif /* CONFIG_MATH_EMULATION */ | ||
477 | |||
478 | regs->nip += 4; | ||
479 | return 0; | ||
480 | |||
481 | illegal: | ||
482 | return -ENOSYS; | ||
483 | } | ||
diff --git a/arch/powerpc/math-emu/mcrfs.c b/arch/powerpc/math-emu/mcrfs.c new file mode 100644 index 000000000000..106dd912914b --- /dev/null +++ b/arch/powerpc/math-emu/mcrfs.c | |||
@@ -0,0 +1,31 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | |||
7 | int | ||
8 | mcrfs(u32 *ccr, u32 crfD, u32 crfS) | ||
9 | { | ||
10 | u32 value, clear; | ||
11 | |||
12 | #ifdef DEBUG | ||
13 | printk("%s: %p (%08x) %d %d\n", __FUNCTION__, ccr, *ccr, crfD, crfS); | ||
14 | #endif | ||
15 | |||
16 | clear = 15 << ((7 - crfS) << 2); | ||
17 | if (!crfS) | ||
18 | clear = 0x90000000; | ||
19 | |||
20 | value = (__FPU_FPSCR >> ((7 - crfS) << 2)) & 15; | ||
21 | __FPU_FPSCR &= ~(clear); | ||
22 | |||
23 | *ccr &= ~(15 << ((7 - crfD) << 2)); | ||
24 | *ccr |= (value << ((7 - crfD) << 2)); | ||
25 | |||
26 | #ifdef DEBUG | ||
27 | printk("CR: %08x\n", __FUNCTION__, *ccr); | ||
28 | #endif | ||
29 | |||
30 | return 0; | ||
31 | } | ||
diff --git a/arch/powerpc/math-emu/mffs.c b/arch/powerpc/math-emu/mffs.c new file mode 100644 index 000000000000..f477c9170e75 --- /dev/null +++ b/arch/powerpc/math-emu/mffs.c | |||
@@ -0,0 +1,17 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | |||
7 | int | ||
8 | mffs(u32 *frD) | ||
9 | { | ||
10 | frD[1] = __FPU_FPSCR; | ||
11 | |||
12 | #ifdef DEBUG | ||
13 | printk("%s: frD %p: %08x.%08x\n", __FUNCTION__, frD, frD[0], frD[1]); | ||
14 | #endif | ||
15 | |||
16 | return 0; | ||
17 | } | ||
diff --git a/arch/powerpc/math-emu/mtfsb0.c b/arch/powerpc/math-emu/mtfsb0.c new file mode 100644 index 000000000000..99bfd80f4af3 --- /dev/null +++ b/arch/powerpc/math-emu/mtfsb0.c | |||
@@ -0,0 +1,18 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | |||
7 | int | ||
8 | mtfsb0(int crbD) | ||
9 | { | ||
10 | if ((crbD != 1) && (crbD != 2)) | ||
11 | __FPU_FPSCR &= ~(1 << (31 - crbD)); | ||
12 | |||
13 | #ifdef DEBUG | ||
14 | printk("%s: %d %08lx\n", __FUNCTION__, crbD, __FPU_FPSCR); | ||
15 | #endif | ||
16 | |||
17 | return 0; | ||
18 | } | ||
diff --git a/arch/powerpc/math-emu/mtfsb1.c b/arch/powerpc/math-emu/mtfsb1.c new file mode 100644 index 000000000000..3d9e7ed92d2b --- /dev/null +++ b/arch/powerpc/math-emu/mtfsb1.c | |||
@@ -0,0 +1,18 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | |||
7 | int | ||
8 | mtfsb1(int crbD) | ||
9 | { | ||
10 | if ((crbD != 1) && (crbD != 2)) | ||
11 | __FPU_FPSCR |= (1 << (31 - crbD)); | ||
12 | |||
13 | #ifdef DEBUG | ||
14 | printk("%s: %d %08lx\n", __FUNCTION__, crbD, __FPU_FPSCR); | ||
15 | #endif | ||
16 | |||
17 | return 0; | ||
18 | } | ||
diff --git a/arch/powerpc/math-emu/mtfsf.c b/arch/powerpc/math-emu/mtfsf.c new file mode 100644 index 000000000000..d70cf714994c --- /dev/null +++ b/arch/powerpc/math-emu/mtfsf.c | |||
@@ -0,0 +1,45 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | |||
7 | int | ||
8 | mtfsf(unsigned int FM, u32 *frB) | ||
9 | { | ||
10 | u32 mask; | ||
11 | |||
12 | if (FM == 0) | ||
13 | return 0; | ||
14 | |||
15 | if (FM == 0xff) | ||
16 | mask = 0x9fffffff; | ||
17 | else { | ||
18 | mask = 0; | ||
19 | if (FM & (1 << 0)) | ||
20 | mask |= 0x90000000; | ||
21 | if (FM & (1 << 1)) | ||
22 | mask |= 0x0f000000; | ||
23 | if (FM & (1 << 2)) | ||
24 | mask |= 0x00f00000; | ||
25 | if (FM & (1 << 3)) | ||
26 | mask |= 0x000f0000; | ||
27 | if (FM & (1 << 4)) | ||
28 | mask |= 0x0000f000; | ||
29 | if (FM & (1 << 5)) | ||
30 | mask |= 0x00000f00; | ||
31 | if (FM & (1 << 6)) | ||
32 | mask |= 0x000000f0; | ||
33 | if (FM & (1 << 7)) | ||
34 | mask |= 0x0000000f; | ||
35 | } | ||
36 | |||
37 | __FPU_FPSCR &= ~(mask); | ||
38 | __FPU_FPSCR |= (frB[1] & mask); | ||
39 | |||
40 | #ifdef DEBUG | ||
41 | printk("%s: %02x %p: %08lx\n", __FUNCTION__, FM, frB, __FPU_FPSCR); | ||
42 | #endif | ||
43 | |||
44 | return 0; | ||
45 | } | ||
diff --git a/arch/powerpc/math-emu/mtfsfi.c b/arch/powerpc/math-emu/mtfsfi.c new file mode 100644 index 000000000000..71df854baa7e --- /dev/null +++ b/arch/powerpc/math-emu/mtfsfi.c | |||
@@ -0,0 +1,23 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | |||
7 | int | ||
8 | mtfsfi(unsigned int crfD, unsigned int IMM) | ||
9 | { | ||
10 | u32 mask = 0xf; | ||
11 | |||
12 | if (!crfD) | ||
13 | mask = 9; | ||
14 | |||
15 | __FPU_FPSCR &= ~(mask << ((7 - crfD) << 2)); | ||
16 | __FPU_FPSCR |= (IMM & 0xf) << ((7 - crfD) << 2); | ||
17 | |||
18 | #ifdef DEBUG | ||
19 | printk("%s: %d %x: %08lx\n", __FUNCTION__, crfD, IMM, __FPU_FPSCR); | ||
20 | #endif | ||
21 | |||
22 | return 0; | ||
23 | } | ||
diff --git a/arch/powerpc/math-emu/op-1.h b/arch/powerpc/math-emu/op-1.h new file mode 100644 index 000000000000..c92fa95f562e --- /dev/null +++ b/arch/powerpc/math-emu/op-1.h | |||
@@ -0,0 +1,245 @@ | |||
1 | /* | ||
2 | * Basic one-word fraction declaration and manipulation. | ||
3 | */ | ||
4 | |||
5 | #define _FP_FRAC_DECL_1(X) _FP_W_TYPE X##_f | ||
6 | #define _FP_FRAC_COPY_1(D,S) (D##_f = S##_f) | ||
7 | #define _FP_FRAC_SET_1(X,I) (X##_f = I) | ||
8 | #define _FP_FRAC_HIGH_1(X) (X##_f) | ||
9 | #define _FP_FRAC_LOW_1(X) (X##_f) | ||
10 | #define _FP_FRAC_WORD_1(X,w) (X##_f) | ||
11 | |||
12 | #define _FP_FRAC_ADDI_1(X,I) (X##_f += I) | ||
13 | #define _FP_FRAC_SLL_1(X,N) \ | ||
14 | do { \ | ||
15 | if (__builtin_constant_p(N) && (N) == 1) \ | ||
16 | X##_f += X##_f; \ | ||
17 | else \ | ||
18 | X##_f <<= (N); \ | ||
19 | } while (0) | ||
20 | #define _FP_FRAC_SRL_1(X,N) (X##_f >>= N) | ||
21 | |||
22 | /* Right shift with sticky-lsb. */ | ||
23 | #define _FP_FRAC_SRS_1(X,N,sz) __FP_FRAC_SRS_1(X##_f, N, sz) | ||
24 | |||
25 | #define __FP_FRAC_SRS_1(X,N,sz) \ | ||
26 | (X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1 \ | ||
27 | ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0))) | ||
28 | |||
29 | #define _FP_FRAC_ADD_1(R,X,Y) (R##_f = X##_f + Y##_f) | ||
30 | #define _FP_FRAC_SUB_1(R,X,Y) (R##_f = X##_f - Y##_f) | ||
31 | #define _FP_FRAC_CLZ_1(z, X) __FP_CLZ(z, X##_f) | ||
32 | |||
33 | /* Predicates */ | ||
34 | #define _FP_FRAC_NEGP_1(X) ((_FP_WS_TYPE)X##_f < 0) | ||
35 | #define _FP_FRAC_ZEROP_1(X) (X##_f == 0) | ||
36 | #define _FP_FRAC_OVERP_1(fs,X) (X##_f & _FP_OVERFLOW_##fs) | ||
37 | #define _FP_FRAC_EQ_1(X, Y) (X##_f == Y##_f) | ||
38 | #define _FP_FRAC_GE_1(X, Y) (X##_f >= Y##_f) | ||
39 | #define _FP_FRAC_GT_1(X, Y) (X##_f > Y##_f) | ||
40 | |||
41 | #define _FP_ZEROFRAC_1 0 | ||
42 | #define _FP_MINFRAC_1 1 | ||
43 | |||
44 | /* | ||
45 | * Unpack the raw bits of a native fp value. Do not classify or | ||
46 | * normalize the data. | ||
47 | */ | ||
48 | |||
49 | #define _FP_UNPACK_RAW_1(fs, X, val) \ | ||
50 | do { \ | ||
51 | union _FP_UNION_##fs _flo; _flo.flt = (val); \ | ||
52 | \ | ||
53 | X##_f = _flo.bits.frac; \ | ||
54 | X##_e = _flo.bits.exp; \ | ||
55 | X##_s = _flo.bits.sign; \ | ||
56 | } while (0) | ||
57 | |||
58 | |||
59 | /* | ||
60 | * Repack the raw bits of a native fp value. | ||
61 | */ | ||
62 | |||
63 | #define _FP_PACK_RAW_1(fs, val, X) \ | ||
64 | do { \ | ||
65 | union _FP_UNION_##fs _flo; \ | ||
66 | \ | ||
67 | _flo.bits.frac = X##_f; \ | ||
68 | _flo.bits.exp = X##_e; \ | ||
69 | _flo.bits.sign = X##_s; \ | ||
70 | \ | ||
71 | (val) = _flo.flt; \ | ||
72 | } while (0) | ||
73 | |||
74 | |||
75 | /* | ||
76 | * Multiplication algorithms: | ||
77 | */ | ||
78 | |||
79 | /* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the | ||
80 | multiplication immediately. */ | ||
81 | |||
82 | #define _FP_MUL_MEAT_1_imm(fs, R, X, Y) \ | ||
83 | do { \ | ||
84 | R##_f = X##_f * Y##_f; \ | ||
85 | /* Normalize since we know where the msb of the multiplicands \ | ||
86 | were (bit B), we know that the msb of the of the product is \ | ||
87 | at either 2B or 2B-1. */ \ | ||
88 | _FP_FRAC_SRS_1(R, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \ | ||
89 | } while (0) | ||
90 | |||
91 | /* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ | ||
92 | |||
93 | #define _FP_MUL_MEAT_1_wide(fs, R, X, Y, doit) \ | ||
94 | do { \ | ||
95 | _FP_W_TYPE _Z_f0, _Z_f1; \ | ||
96 | doit(_Z_f1, _Z_f0, X##_f, Y##_f); \ | ||
97 | /* Normalize since we know where the msb of the multiplicands \ | ||
98 | were (bit B), we know that the msb of the of the product is \ | ||
99 | at either 2B or 2B-1. */ \ | ||
100 | _FP_FRAC_SRS_2(_Z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \ | ||
101 | R##_f = _Z_f0; \ | ||
102 | } while (0) | ||
103 | |||
104 | /* Finally, a simple widening multiply algorithm. What fun! */ | ||
105 | |||
106 | #define _FP_MUL_MEAT_1_hard(fs, R, X, Y) \ | ||
107 | do { \ | ||
108 | _FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1; \ | ||
109 | \ | ||
110 | /* split the words in half */ \ | ||
111 | _xh = X##_f >> (_FP_W_TYPE_SIZE/2); \ | ||
112 | _xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \ | ||
113 | _yh = Y##_f >> (_FP_W_TYPE_SIZE/2); \ | ||
114 | _yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \ | ||
115 | \ | ||
116 | /* multiply the pieces */ \ | ||
117 | _z_f0 = _xl * _yl; \ | ||
118 | _a_f0 = _xh * _yl; \ | ||
119 | _a_f1 = _xl * _yh; \ | ||
120 | _z_f1 = _xh * _yh; \ | ||
121 | \ | ||
122 | /* reassemble into two full words */ \ | ||
123 | if ((_a_f0 += _a_f1) < _a_f1) \ | ||
124 | _z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2); \ | ||
125 | _a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2); \ | ||
126 | _a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2); \ | ||
127 | _FP_FRAC_ADD_2(_z, _z, _a); \ | ||
128 | \ | ||
129 | /* normalize */ \ | ||
130 | _FP_FRAC_SRS_2(_z, _FP_WFRACBITS_##fs - 1, 2*_FP_WFRACBITS_##fs); \ | ||
131 | R##_f = _z_f0; \ | ||
132 | } while (0) | ||
133 | |||
134 | |||
135 | /* | ||
136 | * Division algorithms: | ||
137 | */ | ||
138 | |||
139 | /* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the | ||
140 | division immediately. Give this macro either _FP_DIV_HELP_imm for | ||
141 | C primitives or _FP_DIV_HELP_ldiv for the ISO function. Which you | ||
142 | choose will depend on what the compiler does with divrem4. */ | ||
143 | |||
144 | #define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit) \ | ||
145 | do { \ | ||
146 | _FP_W_TYPE _q, _r; \ | ||
147 | X##_f <<= (X##_f < Y##_f \ | ||
148 | ? R##_e--, _FP_WFRACBITS_##fs \ | ||
149 | : _FP_WFRACBITS_##fs - 1); \ | ||
150 | doit(_q, _r, X##_f, Y##_f); \ | ||
151 | R##_f = _q | (_r != 0); \ | ||
152 | } while (0) | ||
153 | |||
154 | /* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd | ||
155 | that may be useful in this situation. This first is for a primitive | ||
156 | that requires normalization, the second for one that does not. Look | ||
157 | for UDIV_NEEDS_NORMALIZATION to tell which your machine needs. */ | ||
158 | |||
159 | #define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y) \ | ||
160 | do { \ | ||
161 | _FP_W_TYPE _nh, _nl, _q, _r; \ | ||
162 | \ | ||
163 | /* Normalize Y -- i.e. make the most significant bit set. */ \ | ||
164 | Y##_f <<= _FP_WFRACXBITS_##fs - 1; \ | ||
165 | \ | ||
166 | /* Shift X op correspondingly high, that is, up one full word. */ \ | ||
167 | if (X##_f <= Y##_f) \ | ||
168 | { \ | ||
169 | _nl = 0; \ | ||
170 | _nh = X##_f; \ | ||
171 | } \ | ||
172 | else \ | ||
173 | { \ | ||
174 | R##_e++; \ | ||
175 | _nl = X##_f << (_FP_W_TYPE_SIZE-1); \ | ||
176 | _nh = X##_f >> 1; \ | ||
177 | } \ | ||
178 | \ | ||
179 | udiv_qrnnd(_q, _r, _nh, _nl, Y##_f); \ | ||
180 | R##_f = _q | (_r != 0); \ | ||
181 | } while (0) | ||
182 | |||
183 | #define _FP_DIV_MEAT_1_udiv(fs, R, X, Y) \ | ||
184 | do { \ | ||
185 | _FP_W_TYPE _nh, _nl, _q, _r; \ | ||
186 | if (X##_f < Y##_f) \ | ||
187 | { \ | ||
188 | R##_e--; \ | ||
189 | _nl = X##_f << _FP_WFRACBITS_##fs; \ | ||
190 | _nh = X##_f >> _FP_WFRACXBITS_##fs; \ | ||
191 | } \ | ||
192 | else \ | ||
193 | { \ | ||
194 | _nl = X##_f << (_FP_WFRACBITS_##fs - 1); \ | ||
195 | _nh = X##_f >> (_FP_WFRACXBITS_##fs + 1); \ | ||
196 | } \ | ||
197 | udiv_qrnnd(_q, _r, _nh, _nl, Y##_f); \ | ||
198 | R##_f = _q | (_r != 0); \ | ||
199 | } while (0) | ||
200 | |||
201 | |||
202 | /* | ||
203 | * Square root algorithms: | ||
204 | * We have just one right now, maybe Newton approximation | ||
205 | * should be added for those machines where division is fast. | ||
206 | */ | ||
207 | |||
208 | #define _FP_SQRT_MEAT_1(R, S, T, X, q) \ | ||
209 | do { \ | ||
210 | while (q) \ | ||
211 | { \ | ||
212 | T##_f = S##_f + q; \ | ||
213 | if (T##_f <= X##_f) \ | ||
214 | { \ | ||
215 | S##_f = T##_f + q; \ | ||
216 | X##_f -= T##_f; \ | ||
217 | R##_f += q; \ | ||
218 | } \ | ||
219 | _FP_FRAC_SLL_1(X, 1); \ | ||
220 | q >>= 1; \ | ||
221 | } \ | ||
222 | } while (0) | ||
223 | |||
224 | /* | ||
225 | * Assembly/disassembly for converting to/from integral types. | ||
226 | * No shifting or overflow handled here. | ||
227 | */ | ||
228 | |||
229 | #define _FP_FRAC_ASSEMBLE_1(r, X, rsize) (r = X##_f) | ||
230 | #define _FP_FRAC_DISASSEMBLE_1(X, r, rsize) (X##_f = r) | ||
231 | |||
232 | |||
233 | /* | ||
234 | * Convert FP values between word sizes | ||
235 | */ | ||
236 | |||
237 | #define _FP_FRAC_CONV_1_1(dfs, sfs, D, S) \ | ||
238 | do { \ | ||
239 | D##_f = S##_f; \ | ||
240 | if (_FP_WFRACBITS_##sfs > _FP_WFRACBITS_##dfs) \ | ||
241 | _FP_FRAC_SRS_1(D, (_FP_WFRACBITS_##sfs-_FP_WFRACBITS_##dfs), \ | ||
242 | _FP_WFRACBITS_##sfs); \ | ||
243 | else \ | ||
244 | D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs; \ | ||
245 | } while (0) | ||
diff --git a/arch/powerpc/math-emu/op-2.h b/arch/powerpc/math-emu/op-2.h new file mode 100644 index 000000000000..b9b06b4c6ea1 --- /dev/null +++ b/arch/powerpc/math-emu/op-2.h | |||
@@ -0,0 +1,433 @@ | |||
1 | /* | ||
2 | * Basic two-word fraction declaration and manipulation. | ||
3 | */ | ||
4 | |||
5 | #define _FP_FRAC_DECL_2(X) _FP_W_TYPE X##_f0, X##_f1 | ||
6 | #define _FP_FRAC_COPY_2(D,S) (D##_f0 = S##_f0, D##_f1 = S##_f1) | ||
7 | #define _FP_FRAC_SET_2(X,I) __FP_FRAC_SET_2(X, I) | ||
8 | #define _FP_FRAC_HIGH_2(X) (X##_f1) | ||
9 | #define _FP_FRAC_LOW_2(X) (X##_f0) | ||
10 | #define _FP_FRAC_WORD_2(X,w) (X##_f##w) | ||
11 | |||
12 | #define _FP_FRAC_SLL_2(X,N) \ | ||
13 | do { \ | ||
14 | if ((N) < _FP_W_TYPE_SIZE) \ | ||
15 | { \ | ||
16 | if (__builtin_constant_p(N) && (N) == 1) \ | ||
17 | { \ | ||
18 | X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0); \ | ||
19 | X##_f0 += X##_f0; \ | ||
20 | } \ | ||
21 | else \ | ||
22 | { \ | ||
23 | X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N)); \ | ||
24 | X##_f0 <<= (N); \ | ||
25 | } \ | ||
26 | } \ | ||
27 | else \ | ||
28 | { \ | ||
29 | X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE); \ | ||
30 | X##_f0 = 0; \ | ||
31 | } \ | ||
32 | } while (0) | ||
33 | |||
34 | #define _FP_FRAC_SRL_2(X,N) \ | ||
35 | do { \ | ||
36 | if ((N) < _FP_W_TYPE_SIZE) \ | ||
37 | { \ | ||
38 | X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N)); \ | ||
39 | X##_f1 >>= (N); \ | ||
40 | } \ | ||
41 | else \ | ||
42 | { \ | ||
43 | X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE); \ | ||
44 | X##_f1 = 0; \ | ||
45 | } \ | ||
46 | } while (0) | ||
47 | |||
48 | /* Right shift with sticky-lsb. */ | ||
49 | #define _FP_FRAC_SRS_2(X,N,sz) \ | ||
50 | do { \ | ||
51 | if ((N) < _FP_W_TYPE_SIZE) \ | ||
52 | { \ | ||
53 | X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) | \ | ||
54 | (__builtin_constant_p(N) && (N) == 1 \ | ||
55 | ? X##_f0 & 1 \ | ||
56 | : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0)); \ | ||
57 | X##_f1 >>= (N); \ | ||
58 | } \ | ||
59 | else \ | ||
60 | { \ | ||
61 | X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) | \ | ||
62 | (((X##_f1 << (sz - (N))) | X##_f0) != 0)); \ | ||
63 | X##_f1 = 0; \ | ||
64 | } \ | ||
65 | } while (0) | ||
66 | |||
67 | #define _FP_FRAC_ADDI_2(X,I) \ | ||
68 | __FP_FRAC_ADDI_2(X##_f1, X##_f0, I) | ||
69 | |||
70 | #define _FP_FRAC_ADD_2(R,X,Y) \ | ||
71 | __FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0) | ||
72 | |||
73 | #define _FP_FRAC_SUB_2(R,X,Y) \ | ||
74 | __FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0) | ||
75 | |||
76 | #define _FP_FRAC_CLZ_2(R,X) \ | ||
77 | do { \ | ||
78 | if (X##_f1) \ | ||
79 | __FP_CLZ(R,X##_f1); \ | ||
80 | else \ | ||
81 | { \ | ||
82 | __FP_CLZ(R,X##_f0); \ | ||
83 | R += _FP_W_TYPE_SIZE; \ | ||
84 | } \ | ||
85 | } while(0) | ||
86 | |||
87 | /* Predicates */ | ||
88 | #define _FP_FRAC_NEGP_2(X) ((_FP_WS_TYPE)X##_f1 < 0) | ||
89 | #define _FP_FRAC_ZEROP_2(X) ((X##_f1 | X##_f0) == 0) | ||
90 | #define _FP_FRAC_OVERP_2(fs,X) (X##_f1 & _FP_OVERFLOW_##fs) | ||
91 | #define _FP_FRAC_EQ_2(X, Y) (X##_f1 == Y##_f1 && X##_f0 == Y##_f0) | ||
92 | #define _FP_FRAC_GT_2(X, Y) \ | ||
93 | ((X##_f1 > Y##_f1) || (X##_f1 == Y##_f1 && X##_f0 > Y##_f0)) | ||
94 | #define _FP_FRAC_GE_2(X, Y) \ | ||
95 | ((X##_f1 > Y##_f1) || (X##_f1 == Y##_f1 && X##_f0 >= Y##_f0)) | ||
96 | |||
97 | #define _FP_ZEROFRAC_2 0, 0 | ||
98 | #define _FP_MINFRAC_2 0, 1 | ||
99 | |||
100 | /* | ||
101 | * Internals | ||
102 | */ | ||
103 | |||
104 | #define __FP_FRAC_SET_2(X,I1,I0) (X##_f0 = I0, X##_f1 = I1) | ||
105 | |||
106 | #define __FP_CLZ_2(R, xh, xl) \ | ||
107 | do { \ | ||
108 | if (xh) \ | ||
109 | __FP_CLZ(R,xl); \ | ||
110 | else \ | ||
111 | { \ | ||
112 | __FP_CLZ(R,xl); \ | ||
113 | R += _FP_W_TYPE_SIZE; \ | ||
114 | } \ | ||
115 | } while(0) | ||
116 | |||
117 | #if 0 | ||
118 | |||
119 | #ifndef __FP_FRAC_ADDI_2 | ||
120 | #define __FP_FRAC_ADDI_2(xh, xl, i) \ | ||
121 | (xh += ((xl += i) < i)) | ||
122 | #endif | ||
123 | #ifndef __FP_FRAC_ADD_2 | ||
124 | #define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \ | ||
125 | (rh = xh + yh + ((rl = xl + yl) < xl)) | ||
126 | #endif | ||
127 | #ifndef __FP_FRAC_SUB_2 | ||
128 | #define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \ | ||
129 | (rh = xh - yh - ((rl = xl - yl) > xl)) | ||
130 | #endif | ||
131 | |||
132 | #else | ||
133 | |||
134 | #undef __FP_FRAC_ADDI_2 | ||
135 | #define __FP_FRAC_ADDI_2(xh, xl, i) add_ssaaaa(xh, xl, xh, xl, 0, i) | ||
136 | #undef __FP_FRAC_ADD_2 | ||
137 | #define __FP_FRAC_ADD_2 add_ssaaaa | ||
138 | #undef __FP_FRAC_SUB_2 | ||
139 | #define __FP_FRAC_SUB_2 sub_ddmmss | ||
140 | |||
141 | #endif | ||
142 | |||
143 | /* | ||
144 | * Unpack the raw bits of a native fp value. Do not classify or | ||
145 | * normalize the data. | ||
146 | */ | ||
147 | |||
148 | #define _FP_UNPACK_RAW_2(fs, X, val) \ | ||
149 | do { \ | ||
150 | union _FP_UNION_##fs _flo; _flo.flt = (val); \ | ||
151 | \ | ||
152 | X##_f0 = _flo.bits.frac0; \ | ||
153 | X##_f1 = _flo.bits.frac1; \ | ||
154 | X##_e = _flo.bits.exp; \ | ||
155 | X##_s = _flo.bits.sign; \ | ||
156 | } while (0) | ||
157 | |||
158 | |||
159 | /* | ||
160 | * Repack the raw bits of a native fp value. | ||
161 | */ | ||
162 | |||
163 | #define _FP_PACK_RAW_2(fs, val, X) \ | ||
164 | do { \ | ||
165 | union _FP_UNION_##fs _flo; \ | ||
166 | \ | ||
167 | _flo.bits.frac0 = X##_f0; \ | ||
168 | _flo.bits.frac1 = X##_f1; \ | ||
169 | _flo.bits.exp = X##_e; \ | ||
170 | _flo.bits.sign = X##_s; \ | ||
171 | \ | ||
172 | (val) = _flo.flt; \ | ||
173 | } while (0) | ||
174 | |||
175 | |||
176 | /* | ||
177 | * Multiplication algorithms: | ||
178 | */ | ||
179 | |||
180 | /* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ | ||
181 | |||
182 | #define _FP_MUL_MEAT_2_wide(fs, R, X, Y, doit) \ | ||
183 | do { \ | ||
184 | _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \ | ||
185 | \ | ||
186 | doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \ | ||
187 | doit(_b_f1, _b_f0, X##_f0, Y##_f1); \ | ||
188 | doit(_c_f1, _c_f0, X##_f1, Y##_f0); \ | ||
189 | doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1); \ | ||
190 | \ | ||
191 | __FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ | ||
192 | _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0), \ | ||
193 | 0, _b_f1, _b_f0, 0, \ | ||
194 | _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ | ||
195 | _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0)); \ | ||
196 | __FP_FRAC_ADD_4(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ | ||
197 | _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0), \ | ||
198 | 0, _c_f1, _c_f0, 0, \ | ||
199 | _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ | ||
200 | _FP_FRAC_WORD_4(_z,1),_FP_FRAC_WORD_4(_z,0)); \ | ||
201 | \ | ||
202 | /* Normalize since we know where the msb of the multiplicands \ | ||
203 | were (bit B), we know that the msb of the of the product is \ | ||
204 | at either 2B or 2B-1. */ \ | ||
205 | _FP_FRAC_SRS_4(_z, _FP_WFRACBITS_##fs-1, 2*_FP_WFRACBITS_##fs); \ | ||
206 | R##_f0 = _FP_FRAC_WORD_4(_z,0); \ | ||
207 | R##_f1 = _FP_FRAC_WORD_4(_z,1); \ | ||
208 | } while (0) | ||
209 | |||
210 | /* This next macro appears to be totally broken. Fortunately nowhere | ||
211 | * seems to use it :-> The problem is that we define _z[4] but | ||
212 | * then use it in _FP_FRAC_SRS_4, which will attempt to access | ||
213 | * _z_f[n] which will cause an error. The fix probably involves | ||
214 | * declaring it with _FP_FRAC_DECL_4, see previous macro. -- PMM 02/1998 | ||
215 | */ | ||
216 | #define _FP_MUL_MEAT_2_gmp(fs, R, X, Y) \ | ||
217 | do { \ | ||
218 | _FP_W_TYPE _x[2], _y[2], _z[4]; \ | ||
219 | _x[0] = X##_f0; _x[1] = X##_f1; \ | ||
220 | _y[0] = Y##_f0; _y[1] = Y##_f1; \ | ||
221 | \ | ||
222 | mpn_mul_n(_z, _x, _y, 2); \ | ||
223 | \ | ||
224 | /* Normalize since we know where the msb of the multiplicands \ | ||
225 | were (bit B), we know that the msb of the of the product is \ | ||
226 | at either 2B or 2B-1. */ \ | ||
227 | _FP_FRAC_SRS_4(_z, _FP_WFRACBITS##_fs-1, 2*_FP_WFRACBITS_##fs); \ | ||
228 | R##_f0 = _z[0]; \ | ||
229 | R##_f1 = _z[1]; \ | ||
230 | } while (0) | ||
231 | |||
232 | |||
233 | /* | ||
234 | * Division algorithms: | ||
235 | * This seems to be giving me difficulties -- PMM | ||
236 | * Look, NetBSD seems to be able to comment algorithms. Can't you? | ||
237 | * I've thrown printks at the problem. | ||
238 | * This now appears to work, but I still don't really know why. | ||
239 | * Also, I don't think the result is properly normalised... | ||
240 | */ | ||
241 | |||
242 | #define _FP_DIV_MEAT_2_udiv_64(fs, R, X, Y) \ | ||
243 | do { \ | ||
244 | extern void _fp_udivmodti4(_FP_W_TYPE q[2], _FP_W_TYPE r[2], \ | ||
245 | _FP_W_TYPE n1, _FP_W_TYPE n0, \ | ||
246 | _FP_W_TYPE d1, _FP_W_TYPE d0); \ | ||
247 | _FP_W_TYPE _n_f3, _n_f2, _n_f1, _n_f0, _r_f1, _r_f0; \ | ||
248 | _FP_W_TYPE _q_f1, _q_f0, _m_f1, _m_f0; \ | ||
249 | _FP_W_TYPE _rmem[2], _qmem[2]; \ | ||
250 | /* I think this check is to ensure that the result is normalised. \ | ||
251 | * Assuming X,Y normalised (ie in [1.0,2.0)) X/Y will be in \ | ||
252 | * [0.5,2.0). Furthermore, it will be less than 1.0 iff X < Y. \ | ||
253 | * In this case we tweak things. (this is based on comments in \ | ||
254 | * the NetBSD FPU emulation code. ) \ | ||
255 | * We know X,Y are normalised because we ensure this as part of \ | ||
256 | * the unpacking process. -- PMM \ | ||
257 | */ \ | ||
258 | if (_FP_FRAC_GT_2(X, Y)) \ | ||
259 | { \ | ||
260 | /* R##_e++; */ \ | ||
261 | _n_f3 = X##_f1 >> 1; \ | ||
262 | _n_f2 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1; \ | ||
263 | _n_f1 = X##_f0 << (_FP_W_TYPE_SIZE - 1); \ | ||
264 | _n_f0 = 0; \ | ||
265 | } \ | ||
266 | else \ | ||
267 | { \ | ||
268 | R##_e--; \ | ||
269 | _n_f3 = X##_f1; \ | ||
270 | _n_f2 = X##_f0; \ | ||
271 | _n_f1 = _n_f0 = 0; \ | ||
272 | } \ | ||
273 | \ | ||
274 | /* Normalize, i.e. make the most significant bit of the \ | ||
275 | denominator set. CHANGED: - 1 to nothing -- PMM */ \ | ||
276 | _FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs /* -1 */); \ | ||
277 | \ | ||
278 | /* Do the 256/128 bit division given the 128-bit _fp_udivmodtf4 \ | ||
279 | primitive snagged from libgcc2.c. */ \ | ||
280 | \ | ||
281 | _fp_udivmodti4(_qmem, _rmem, _n_f3, _n_f2, 0, Y##_f1); \ | ||
282 | _q_f1 = _qmem[0]; \ | ||
283 | umul_ppmm(_m_f1, _m_f0, _q_f1, Y##_f0); \ | ||
284 | _r_f1 = _rmem[0]; \ | ||
285 | _r_f0 = _n_f1; \ | ||
286 | if (_FP_FRAC_GT_2(_m, _r)) \ | ||
287 | { \ | ||
288 | _q_f1--; \ | ||
289 | _FP_FRAC_ADD_2(_r, _r, Y); \ | ||
290 | if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \ | ||
291 | { \ | ||
292 | _q_f1--; \ | ||
293 | _FP_FRAC_ADD_2(_r, _r, Y); \ | ||
294 | } \ | ||
295 | } \ | ||
296 | _FP_FRAC_SUB_2(_r, _r, _m); \ | ||
297 | \ | ||
298 | _fp_udivmodti4(_qmem, _rmem, _r_f1, _r_f0, 0, Y##_f1); \ | ||
299 | _q_f0 = _qmem[0]; \ | ||
300 | umul_ppmm(_m_f1, _m_f0, _q_f0, Y##_f0); \ | ||
301 | _r_f1 = _rmem[0]; \ | ||
302 | _r_f0 = _n_f0; \ | ||
303 | if (_FP_FRAC_GT_2(_m, _r)) \ | ||
304 | { \ | ||
305 | _q_f0--; \ | ||
306 | _FP_FRAC_ADD_2(_r, _r, Y); \ | ||
307 | if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \ | ||
308 | { \ | ||
309 | _q_f0--; \ | ||
310 | _FP_FRAC_ADD_2(_r, _r, Y); \ | ||
311 | } \ | ||
312 | } \ | ||
313 | _FP_FRAC_SUB_2(_r, _r, _m); \ | ||
314 | \ | ||
315 | R##_f1 = _q_f1; \ | ||
316 | R##_f0 = _q_f0 | ((_r_f1 | _r_f0) != 0); \ | ||
317 | /* adjust so answer is normalized again. I'm not sure what the \ | ||
318 | * final sz param should be. In practice it's never used since \ | ||
319 | * N is 1 which is always going to be < _FP_W_TYPE_SIZE... \ | ||
320 | */ \ | ||
321 | /* _FP_FRAC_SRS_2(R,1,_FP_WFRACBITS_##fs); */ \ | ||
322 | } while (0) | ||
323 | |||
324 | |||
325 | #define _FP_DIV_MEAT_2_gmp(fs, R, X, Y) \ | ||
326 | do { \ | ||
327 | _FP_W_TYPE _x[4], _y[2], _z[4]; \ | ||
328 | _y[0] = Y##_f0; _y[1] = Y##_f1; \ | ||
329 | _x[0] = _x[3] = 0; \ | ||
330 | if (_FP_FRAC_GT_2(X, Y)) \ | ||
331 | { \ | ||
332 | R##_e++; \ | ||
333 | _x[1] = (X##_f0 << (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE) | \ | ||
334 | X##_f1 >> (_FP_W_TYPE_SIZE - \ | ||
335 | (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE))); \ | ||
336 | _x[2] = X##_f1 << (_FP_WFRACBITS-1 - _FP_W_TYPE_SIZE); \ | ||
337 | } \ | ||
338 | else \ | ||
339 | { \ | ||
340 | _x[1] = (X##_f0 << (_FP_WFRACBITS - _FP_W_TYPE_SIZE) | \ | ||
341 | X##_f1 >> (_FP_W_TYPE_SIZE - \ | ||
342 | (_FP_WFRACBITS - _FP_W_TYPE_SIZE))); \ | ||
343 | _x[2] = X##_f1 << (_FP_WFRACBITS - _FP_W_TYPE_SIZE); \ | ||
344 | } \ | ||
345 | \ | ||
346 | (void) mpn_divrem (_z, 0, _x, 4, _y, 2); \ | ||
347 | R##_f1 = _z[1]; \ | ||
348 | R##_f0 = _z[0] | ((_x[0] | _x[1]) != 0); \ | ||
349 | } while (0) | ||
350 | |||
351 | |||
352 | /* | ||
353 | * Square root algorithms: | ||
354 | * We have just one right now, maybe Newton approximation | ||
355 | * should be added for those machines where division is fast. | ||
356 | */ | ||
357 | |||
358 | #define _FP_SQRT_MEAT_2(R, S, T, X, q) \ | ||
359 | do { \ | ||
360 | while (q) \ | ||
361 | { \ | ||
362 | T##_f1 = S##_f1 + q; \ | ||
363 | if (T##_f1 <= X##_f1) \ | ||
364 | { \ | ||
365 | S##_f1 = T##_f1 + q; \ | ||
366 | X##_f1 -= T##_f1; \ | ||
367 | R##_f1 += q; \ | ||
368 | } \ | ||
369 | _FP_FRAC_SLL_2(X, 1); \ | ||
370 | q >>= 1; \ | ||
371 | } \ | ||
372 | q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ | ||
373 | while (q) \ | ||
374 | { \ | ||
375 | T##_f0 = S##_f0 + q; \ | ||
376 | T##_f1 = S##_f1; \ | ||
377 | if (T##_f1 < X##_f1 || \ | ||
378 | (T##_f1 == X##_f1 && T##_f0 < X##_f0)) \ | ||
379 | { \ | ||
380 | S##_f0 = T##_f0 + q; \ | ||
381 | if (((_FP_WS_TYPE)T##_f0) < 0 && \ | ||
382 | ((_FP_WS_TYPE)S##_f0) >= 0) \ | ||
383 | S##_f1++; \ | ||
384 | _FP_FRAC_SUB_2(X, X, T); \ | ||
385 | R##_f0 += q; \ | ||
386 | } \ | ||
387 | _FP_FRAC_SLL_2(X, 1); \ | ||
388 | q >>= 1; \ | ||
389 | } \ | ||
390 | } while (0) | ||
391 | |||
392 | |||
393 | /* | ||
394 | * Assembly/disassembly for converting to/from integral types. | ||
395 | * No shifting or overflow handled here. | ||
396 | */ | ||
397 | |||
398 | #define _FP_FRAC_ASSEMBLE_2(r, X, rsize) \ | ||
399 | do { \ | ||
400 | if (rsize <= _FP_W_TYPE_SIZE) \ | ||
401 | r = X##_f0; \ | ||
402 | else \ | ||
403 | { \ | ||
404 | r = X##_f1; \ | ||
405 | r <<= _FP_W_TYPE_SIZE; \ | ||
406 | r += X##_f0; \ | ||
407 | } \ | ||
408 | } while (0) | ||
409 | |||
410 | #define _FP_FRAC_DISASSEMBLE_2(X, r, rsize) \ | ||
411 | do { \ | ||
412 | X##_f0 = r; \ | ||
413 | X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \ | ||
414 | } while (0) | ||
415 | |||
416 | /* | ||
417 | * Convert FP values between word sizes | ||
418 | */ | ||
419 | |||
420 | #define _FP_FRAC_CONV_1_2(dfs, sfs, D, S) \ | ||
421 | do { \ | ||
422 | _FP_FRAC_SRS_2(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \ | ||
423 | _FP_WFRACBITS_##sfs); \ | ||
424 | D##_f = S##_f0; \ | ||
425 | } while (0) | ||
426 | |||
427 | #define _FP_FRAC_CONV_2_1(dfs, sfs, D, S) \ | ||
428 | do { \ | ||
429 | D##_f0 = S##_f; \ | ||
430 | D##_f1 = 0; \ | ||
431 | _FP_FRAC_SLL_2(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \ | ||
432 | } while (0) | ||
433 | |||
diff --git a/arch/powerpc/math-emu/op-4.h b/arch/powerpc/math-emu/op-4.h new file mode 100644 index 000000000000..fcdd6d064c54 --- /dev/null +++ b/arch/powerpc/math-emu/op-4.h | |||
@@ -0,0 +1,297 @@ | |||
1 | /* | ||
2 | * Basic four-word fraction declaration and manipulation. | ||
3 | * | ||
4 | * When adding quadword support for 32 bit machines, we need | ||
5 | * to be a little careful as double multiply uses some of these | ||
6 | * macros: (in op-2.h) | ||
7 | * _FP_MUL_MEAT_2_wide() uses _FP_FRAC_DECL_4, _FP_FRAC_WORD_4, | ||
8 | * _FP_FRAC_ADD_4, _FP_FRAC_SRS_4 | ||
9 | * _FP_MUL_MEAT_2_gmp() uses _FP_FRAC_SRS_4 (and should use | ||
10 | * _FP_FRAC_DECL_4: it appears to be broken and is not used | ||
11 | * anywhere anyway. ) | ||
12 | * | ||
13 | * I've now fixed all the macros that were here from the sparc64 code. | ||
14 | * [*none* of the shift macros were correct!] -- PMM 02/1998 | ||
15 | * | ||
16 | * The only quadword stuff that remains to be coded is: | ||
17 | * 1) the conversion to/from ints, which requires | ||
18 | * that we check (in op-common.h) that the following do the right thing | ||
19 | * for quadwords: _FP_TO_INT(Q,4,r,X,rsz,rsg), _FP_FROM_INT(Q,4,X,r,rs,rt) | ||
20 | * 2) multiply, divide and sqrt, which require: | ||
21 | * _FP_MUL_MEAT_4_*(R,X,Y), _FP_DIV_MEAT_4_*(R,X,Y), _FP_SQRT_MEAT_4(R,S,T,X,q), | ||
22 | * This also needs _FP_MUL_MEAT_Q and _FP_DIV_MEAT_Q to be defined to | ||
23 | * some suitable _FP_MUL_MEAT_4_* macros in sfp-machine.h. | ||
24 | * [we're free to choose whatever FP_MUL_MEAT_4_* macros we need for | ||
25 | * these; they are used nowhere else. ] | ||
26 | */ | ||
27 | |||
28 | #define _FP_FRAC_DECL_4(X) _FP_W_TYPE X##_f[4] | ||
29 | #define _FP_FRAC_COPY_4(D,S) \ | ||
30 | (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1], \ | ||
31 | D##_f[2] = S##_f[2], D##_f[3] = S##_f[3]) | ||
32 | /* The _FP_FRAC_SET_n(X,I) macro is intended for use with another | ||
33 | * macro such as _FP_ZEROFRAC_n which returns n comma separated values. | ||
34 | * The result is that we get an expansion of __FP_FRAC_SET_n(X,I0,I1,I2,I3) | ||
35 | * which just assigns the In values to the array X##_f[]. | ||
36 | * This is why the number of parameters doesn't appear to match | ||
37 | * at first glance... -- PMM | ||
38 | */ | ||
39 | #define _FP_FRAC_SET_4(X,I) __FP_FRAC_SET_4(X, I) | ||
40 | #define _FP_FRAC_HIGH_4(X) (X##_f[3]) | ||
41 | #define _FP_FRAC_LOW_4(X) (X##_f[0]) | ||
42 | #define _FP_FRAC_WORD_4(X,w) (X##_f[w]) | ||
43 | |||
44 | #define _FP_FRAC_SLL_4(X,N) \ | ||
45 | do { \ | ||
46 | _FP_I_TYPE _up, _down, _skip, _i; \ | ||
47 | _skip = (N) / _FP_W_TYPE_SIZE; \ | ||
48 | _up = (N) % _FP_W_TYPE_SIZE; \ | ||
49 | _down = _FP_W_TYPE_SIZE - _up; \ | ||
50 | for (_i = 3; _i > _skip; --_i) \ | ||
51 | X##_f[_i] = X##_f[_i-_skip] << _up | X##_f[_i-_skip-1] >> _down; \ | ||
52 | /* bugfixed: was X##_f[_i] <<= _up; -- PMM 02/1998 */ \ | ||
53 | X##_f[_i] = X##_f[0] << _up; \ | ||
54 | for (--_i; _i >= 0; --_i) \ | ||
55 | X##_f[_i] = 0; \ | ||
56 | } while (0) | ||
57 | |||
58 | /* This one was broken too */ | ||
59 | #define _FP_FRAC_SRL_4(X,N) \ | ||
60 | do { \ | ||
61 | _FP_I_TYPE _up, _down, _skip, _i; \ | ||
62 | _skip = (N) / _FP_W_TYPE_SIZE; \ | ||
63 | _down = (N) % _FP_W_TYPE_SIZE; \ | ||
64 | _up = _FP_W_TYPE_SIZE - _down; \ | ||
65 | for (_i = 0; _i < 3-_skip; ++_i) \ | ||
66 | X##_f[_i] = X##_f[_i+_skip] >> _down | X##_f[_i+_skip+1] << _up; \ | ||
67 | X##_f[_i] = X##_f[3] >> _down; \ | ||
68 | for (++_i; _i < 4; ++_i) \ | ||
69 | X##_f[_i] = 0; \ | ||
70 | } while (0) | ||
71 | |||
72 | |||
73 | /* Right shift with sticky-lsb. | ||
74 | * What this actually means is that we do a standard right-shift, | ||
75 | * but that if any of the bits that fall off the right hand side | ||
76 | * were one then we always set the LSbit. | ||
77 | */ | ||
78 | #define _FP_FRAC_SRS_4(X,N,size) \ | ||
79 | do { \ | ||
80 | _FP_I_TYPE _up, _down, _skip, _i; \ | ||
81 | _FP_W_TYPE _s; \ | ||
82 | _skip = (N) / _FP_W_TYPE_SIZE; \ | ||
83 | _down = (N) % _FP_W_TYPE_SIZE; \ | ||
84 | _up = _FP_W_TYPE_SIZE - _down; \ | ||
85 | for (_s = _i = 0; _i < _skip; ++_i) \ | ||
86 | _s |= X##_f[_i]; \ | ||
87 | _s |= X##_f[_i] << _up; \ | ||
88 | /* s is now != 0 if we want to set the LSbit */ \ | ||
89 | for (_i = 0; _i < 3-_skip; ++_i) \ | ||
90 | X##_f[_i] = X##_f[_i+_skip] >> _down | X##_f[_i+_skip+1] << _up; \ | ||
91 | X##_f[_i] = X##_f[3] >> _down; \ | ||
92 | for (++_i; _i < 4; ++_i) \ | ||
93 | X##_f[_i] = 0; \ | ||
94 | /* don't fix the LSB until the very end when we're sure f[0] is stable */ \ | ||
95 | X##_f[0] |= (_s != 0); \ | ||
96 | } while (0) | ||
97 | |||
98 | #define _FP_FRAC_ADD_4(R,X,Y) \ | ||
99 | __FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \ | ||
100 | X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ | ||
101 | Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) | ||
102 | |||
103 | #define _FP_FRAC_SUB_4(R,X,Y) \ | ||
104 | __FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \ | ||
105 | X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ | ||
106 | Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) | ||
107 | |||
108 | #define _FP_FRAC_ADDI_4(X,I) \ | ||
109 | __FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I) | ||
110 | |||
111 | #define _FP_ZEROFRAC_4 0,0,0,0 | ||
112 | #define _FP_MINFRAC_4 0,0,0,1 | ||
113 | |||
114 | #define _FP_FRAC_ZEROP_4(X) ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0) | ||
115 | #define _FP_FRAC_NEGP_4(X) ((_FP_WS_TYPE)X##_f[3] < 0) | ||
116 | #define _FP_FRAC_OVERP_4(fs,X) (X##_f[0] & _FP_OVERFLOW_##fs) | ||
117 | |||
118 | #define _FP_FRAC_EQ_4(X,Y) \ | ||
119 | (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1] \ | ||
120 | && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3]) | ||
121 | |||
122 | #define _FP_FRAC_GT_4(X,Y) \ | ||
123 | (X##_f[3] > Y##_f[3] || \ | ||
124 | (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \ | ||
125 | (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \ | ||
126 | (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0]) \ | ||
127 | )) \ | ||
128 | )) \ | ||
129 | ) | ||
130 | |||
131 | #define _FP_FRAC_GE_4(X,Y) \ | ||
132 | (X##_f[3] > Y##_f[3] || \ | ||
133 | (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \ | ||
134 | (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \ | ||
135 | (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0]) \ | ||
136 | )) \ | ||
137 | )) \ | ||
138 | ) | ||
139 | |||
140 | |||
141 | #define _FP_FRAC_CLZ_4(R,X) \ | ||
142 | do { \ | ||
143 | if (X##_f[3]) \ | ||
144 | { \ | ||
145 | __FP_CLZ(R,X##_f[3]); \ | ||
146 | } \ | ||
147 | else if (X##_f[2]) \ | ||
148 | { \ | ||
149 | __FP_CLZ(R,X##_f[2]); \ | ||
150 | R += _FP_W_TYPE_SIZE; \ | ||
151 | } \ | ||
152 | else if (X##_f[1]) \ | ||
153 | { \ | ||
154 | __FP_CLZ(R,X##_f[2]); \ | ||
155 | R += _FP_W_TYPE_SIZE*2; \ | ||
156 | } \ | ||
157 | else \ | ||
158 | { \ | ||
159 | __FP_CLZ(R,X##_f[0]); \ | ||
160 | R += _FP_W_TYPE_SIZE*3; \ | ||
161 | } \ | ||
162 | } while(0) | ||
163 | |||
164 | |||
165 | #define _FP_UNPACK_RAW_4(fs, X, val) \ | ||
166 | do { \ | ||
167 | union _FP_UNION_##fs _flo; _flo.flt = (val); \ | ||
168 | X##_f[0] = _flo.bits.frac0; \ | ||
169 | X##_f[1] = _flo.bits.frac1; \ | ||
170 | X##_f[2] = _flo.bits.frac2; \ | ||
171 | X##_f[3] = _flo.bits.frac3; \ | ||
172 | X##_e = _flo.bits.exp; \ | ||
173 | X##_s = _flo.bits.sign; \ | ||
174 | } while (0) | ||
175 | |||
176 | #define _FP_PACK_RAW_4(fs, val, X) \ | ||
177 | do { \ | ||
178 | union _FP_UNION_##fs _flo; \ | ||
179 | _flo.bits.frac0 = X##_f[0]; \ | ||
180 | _flo.bits.frac1 = X##_f[1]; \ | ||
181 | _flo.bits.frac2 = X##_f[2]; \ | ||
182 | _flo.bits.frac3 = X##_f[3]; \ | ||
183 | _flo.bits.exp = X##_e; \ | ||
184 | _flo.bits.sign = X##_s; \ | ||
185 | (val) = _flo.flt; \ | ||
186 | } while (0) | ||
187 | |||
188 | |||
189 | /* | ||
190 | * Internals | ||
191 | */ | ||
192 | |||
193 | #define __FP_FRAC_SET_4(X,I3,I2,I1,I0) \ | ||
194 | (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0) | ||
195 | |||
196 | #ifndef __FP_FRAC_ADD_4 | ||
197 | #define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ | ||
198 | (r0 = x0 + y0, \ | ||
199 | r1 = x1 + y1 + (r0 < x0), \ | ||
200 | r2 = x2 + y2 + (r1 < x1), \ | ||
201 | r3 = x3 + y3 + (r2 < x2)) | ||
202 | #endif | ||
203 | |||
204 | #ifndef __FP_FRAC_SUB_4 | ||
205 | #define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ | ||
206 | (r0 = x0 - y0, \ | ||
207 | r1 = x1 - y1 - (r0 > x0), \ | ||
208 | r2 = x2 - y2 - (r1 > x1), \ | ||
209 | r3 = x3 - y3 - (r2 > x2)) | ||
210 | #endif | ||
211 | |||
212 | #ifndef __FP_FRAC_ADDI_4 | ||
213 | /* I always wanted to be a lisp programmer :-> */ | ||
214 | #define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i) \ | ||
215 | (x3 += ((x2 += ((x1 += ((x0 += i) < x0)) < x1) < x2))) | ||
216 | #endif | ||
217 | |||
218 | /* Convert FP values between word sizes. This appears to be more | ||
219 | * complicated than I'd have expected it to be, so these might be | ||
220 | * wrong... These macros are in any case somewhat bogus because they | ||
221 | * use information about what various FRAC_n variables look like | ||
222 | * internally [eg, that 2 word vars are X_f0 and x_f1]. But so do | ||
223 | * the ones in op-2.h and op-1.h. | ||
224 | */ | ||
225 | #define _FP_FRAC_CONV_1_4(dfs, sfs, D, S) \ | ||
226 | do { \ | ||
227 | _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \ | ||
228 | _FP_WFRACBITS_##sfs); \ | ||
229 | D##_f = S##_f[0]; \ | ||
230 | } while (0) | ||
231 | |||
232 | #define _FP_FRAC_CONV_2_4(dfs, sfs, D, S) \ | ||
233 | do { \ | ||
234 | _FP_FRAC_SRS_4(S, (_FP_WFRACBITS_##sfs - _FP_WFRACBITS_##dfs), \ | ||
235 | _FP_WFRACBITS_##sfs); \ | ||
236 | D##_f0 = S##_f[0]; \ | ||
237 | D##_f1 = S##_f[1]; \ | ||
238 | } while (0) | ||
239 | |||
240 | /* Assembly/disassembly for converting to/from integral types. | ||
241 | * No shifting or overflow handled here. | ||
242 | */ | ||
243 | /* Put the FP value X into r, which is an integer of size rsize. */ | ||
244 | #define _FP_FRAC_ASSEMBLE_4(r, X, rsize) \ | ||
245 | do { \ | ||
246 | if (rsize <= _FP_W_TYPE_SIZE) \ | ||
247 | r = X##_f[0]; \ | ||
248 | else if (rsize <= 2*_FP_W_TYPE_SIZE) \ | ||
249 | { \ | ||
250 | r = X##_f[1]; \ | ||
251 | r <<= _FP_W_TYPE_SIZE; \ | ||
252 | r += X##_f[0]; \ | ||
253 | } \ | ||
254 | else \ | ||
255 | { \ | ||
256 | /* I'm feeling lazy so we deal with int == 3words (implausible)*/ \ | ||
257 | /* and int == 4words as a single case. */ \ | ||
258 | r = X##_f[3]; \ | ||
259 | r <<= _FP_W_TYPE_SIZE; \ | ||
260 | r += X##_f[2]; \ | ||
261 | r <<= _FP_W_TYPE_SIZE; \ | ||
262 | r += X##_f[1]; \ | ||
263 | r <<= _FP_W_TYPE_SIZE; \ | ||
264 | r += X##_f[0]; \ | ||
265 | } \ | ||
266 | } while (0) | ||
267 | |||
268 | /* "No disassemble Number Five!" */ | ||
269 | /* move an integer of size rsize into X's fractional part. We rely on | ||
270 | * the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid | ||
271 | * having to mask the values we store into it. | ||
272 | */ | ||
273 | #define _FP_FRAC_DISASSEMBLE_4(X, r, rsize) \ | ||
274 | do { \ | ||
275 | X##_f[0] = r; \ | ||
276 | X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \ | ||
277 | X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \ | ||
278 | X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \ | ||
279 | } while (0) | ||
280 | |||
281 | #define _FP_FRAC_CONV_4_1(dfs, sfs, D, S) \ | ||
282 | do { \ | ||
283 | D##_f[0] = S##_f; \ | ||
284 | D##_f[1] = D##_f[2] = D##_f[3] = 0; \ | ||
285 | _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \ | ||
286 | } while (0) | ||
287 | |||
288 | #define _FP_FRAC_CONV_4_2(dfs, sfs, D, S) \ | ||
289 | do { \ | ||
290 | D##_f[0] = S##_f0; \ | ||
291 | D##_f[1] = S##_f1; \ | ||
292 | D##_f[2] = D##_f[3] = 0; \ | ||
293 | _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs)); \ | ||
294 | } while (0) | ||
295 | |||
296 | /* FIXME! This has to be written */ | ||
297 | #define _FP_SQRT_MEAT_4(R, S, T, X, q) | ||
diff --git a/arch/powerpc/math-emu/op-common.h b/arch/powerpc/math-emu/op-common.h new file mode 100644 index 000000000000..afb82b6498ce --- /dev/null +++ b/arch/powerpc/math-emu/op-common.h | |||
@@ -0,0 +1,688 @@ | |||
1 | #define _FP_DECL(wc, X) \ | ||
2 | _FP_I_TYPE X##_c, X##_s, X##_e; \ | ||
3 | _FP_FRAC_DECL_##wc(X) | ||
4 | |||
5 | /* | ||
6 | * Finish truely unpacking a native fp value by classifying the kind | ||
7 | * of fp value and normalizing both the exponent and the fraction. | ||
8 | */ | ||
9 | |||
10 | #define _FP_UNPACK_CANONICAL(fs, wc, X) \ | ||
11 | do { \ | ||
12 | switch (X##_e) \ | ||
13 | { \ | ||
14 | default: \ | ||
15 | _FP_FRAC_HIGH_##wc(X) |= _FP_IMPLBIT_##fs; \ | ||
16 | _FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \ | ||
17 | X##_e -= _FP_EXPBIAS_##fs; \ | ||
18 | X##_c = FP_CLS_NORMAL; \ | ||
19 | break; \ | ||
20 | \ | ||
21 | case 0: \ | ||
22 | if (_FP_FRAC_ZEROP_##wc(X)) \ | ||
23 | X##_c = FP_CLS_ZERO; \ | ||
24 | else \ | ||
25 | { \ | ||
26 | /* a denormalized number */ \ | ||
27 | _FP_I_TYPE _shift; \ | ||
28 | _FP_FRAC_CLZ_##wc(_shift, X); \ | ||
29 | _shift -= _FP_FRACXBITS_##fs; \ | ||
30 | _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS)); \ | ||
31 | X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \ | ||
32 | X##_c = FP_CLS_NORMAL; \ | ||
33 | } \ | ||
34 | break; \ | ||
35 | \ | ||
36 | case _FP_EXPMAX_##fs: \ | ||
37 | if (_FP_FRAC_ZEROP_##wc(X)) \ | ||
38 | X##_c = FP_CLS_INF; \ | ||
39 | else \ | ||
40 | /* we don't differentiate between signaling and quiet nans */ \ | ||
41 | X##_c = FP_CLS_NAN; \ | ||
42 | break; \ | ||
43 | } \ | ||
44 | } while (0) | ||
45 | |||
46 | |||
47 | /* | ||
48 | * Before packing the bits back into the native fp result, take care | ||
49 | * of such mundane things as rounding and overflow. Also, for some | ||
50 | * kinds of fp values, the original parts may not have been fully | ||
51 | * extracted -- but that is ok, we can regenerate them now. | ||
52 | */ | ||
53 | |||
54 | #define _FP_PACK_CANONICAL(fs, wc, X) \ | ||
55 | ({int __ret = 0; \ | ||
56 | switch (X##_c) \ | ||
57 | { \ | ||
58 | case FP_CLS_NORMAL: \ | ||
59 | X##_e += _FP_EXPBIAS_##fs; \ | ||
60 | if (X##_e > 0) \ | ||
61 | { \ | ||
62 | __ret |= _FP_ROUND(wc, X); \ | ||
63 | if (_FP_FRAC_OVERP_##wc(fs, X)) \ | ||
64 | { \ | ||
65 | _FP_FRAC_SRL_##wc(X, (_FP_WORKBITS+1)); \ | ||
66 | X##_e++; \ | ||
67 | } \ | ||
68 | else \ | ||
69 | _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ | ||
70 | if (X##_e >= _FP_EXPMAX_##fs) \ | ||
71 | { \ | ||
72 | /* overflow to infinity */ \ | ||
73 | X##_e = _FP_EXPMAX_##fs; \ | ||
74 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
75 | __ret |= EFLAG_OVERFLOW; \ | ||
76 | } \ | ||
77 | } \ | ||
78 | else \ | ||
79 | { \ | ||
80 | /* we've got a denormalized number */ \ | ||
81 | X##_e = -X##_e + 1; \ | ||
82 | if (X##_e <= _FP_WFRACBITS_##fs) \ | ||
83 | { \ | ||
84 | _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \ | ||
85 | _FP_FRAC_SLL_##wc(X, 1); \ | ||
86 | if (_FP_FRAC_OVERP_##wc(fs, X)) \ | ||
87 | { \ | ||
88 | X##_e = 1; \ | ||
89 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
90 | } \ | ||
91 | else \ | ||
92 | { \ | ||
93 | X##_e = 0; \ | ||
94 | _FP_FRAC_SRL_##wc(X, _FP_WORKBITS+1); \ | ||
95 | __ret |= EFLAG_UNDERFLOW; \ | ||
96 | } \ | ||
97 | } \ | ||
98 | else \ | ||
99 | { \ | ||
100 | /* underflow to zero */ \ | ||
101 | X##_e = 0; \ | ||
102 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
103 | __ret |= EFLAG_UNDERFLOW; \ | ||
104 | } \ | ||
105 | } \ | ||
106 | break; \ | ||
107 | \ | ||
108 | case FP_CLS_ZERO: \ | ||
109 | X##_e = 0; \ | ||
110 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
111 | break; \ | ||
112 | \ | ||
113 | case FP_CLS_INF: \ | ||
114 | X##_e = _FP_EXPMAX_##fs; \ | ||
115 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
116 | break; \ | ||
117 | \ | ||
118 | case FP_CLS_NAN: \ | ||
119 | X##_e = _FP_EXPMAX_##fs; \ | ||
120 | if (!_FP_KEEPNANFRACP) \ | ||
121 | { \ | ||
122 | _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \ | ||
123 | X##_s = 0; \ | ||
124 | } \ | ||
125 | else \ | ||
126 | _FP_FRAC_HIGH_##wc(X) |= _FP_QNANBIT_##fs; \ | ||
127 | break; \ | ||
128 | } \ | ||
129 | __ret; \ | ||
130 | }) | ||
131 | |||
132 | |||
133 | /* | ||
134 | * Main addition routine. The input values should be cooked. | ||
135 | */ | ||
136 | |||
137 | #define _FP_ADD(fs, wc, R, X, Y) \ | ||
138 | do { \ | ||
139 | switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ | ||
140 | { \ | ||
141 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ | ||
142 | { \ | ||
143 | /* shift the smaller number so that its exponent matches the larger */ \ | ||
144 | _FP_I_TYPE diff = X##_e - Y##_e; \ | ||
145 | \ | ||
146 | if (diff < 0) \ | ||
147 | { \ | ||
148 | diff = -diff; \ | ||
149 | if (diff <= _FP_WFRACBITS_##fs) \ | ||
150 | _FP_FRAC_SRS_##wc(X, diff, _FP_WFRACBITS_##fs); \ | ||
151 | else if (!_FP_FRAC_ZEROP_##wc(X)) \ | ||
152 | _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \ | ||
153 | else \ | ||
154 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
155 | R##_e = Y##_e; \ | ||
156 | } \ | ||
157 | else \ | ||
158 | { \ | ||
159 | if (diff > 0) \ | ||
160 | { \ | ||
161 | if (diff <= _FP_WFRACBITS_##fs) \ | ||
162 | _FP_FRAC_SRS_##wc(Y, diff, _FP_WFRACBITS_##fs); \ | ||
163 | else if (!_FP_FRAC_ZEROP_##wc(Y)) \ | ||
164 | _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \ | ||
165 | else \ | ||
166 | _FP_FRAC_SET_##wc(Y, _FP_ZEROFRAC_##wc); \ | ||
167 | } \ | ||
168 | R##_e = X##_e; \ | ||
169 | } \ | ||
170 | \ | ||
171 | R##_c = FP_CLS_NORMAL; \ | ||
172 | \ | ||
173 | if (X##_s == Y##_s) \ | ||
174 | { \ | ||
175 | R##_s = X##_s; \ | ||
176 | _FP_FRAC_ADD_##wc(R, X, Y); \ | ||
177 | if (_FP_FRAC_OVERP_##wc(fs, R)) \ | ||
178 | { \ | ||
179 | _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \ | ||
180 | R##_e++; \ | ||
181 | } \ | ||
182 | } \ | ||
183 | else \ | ||
184 | { \ | ||
185 | R##_s = X##_s; \ | ||
186 | _FP_FRAC_SUB_##wc(R, X, Y); \ | ||
187 | if (_FP_FRAC_ZEROP_##wc(R)) \ | ||
188 | { \ | ||
189 | /* return an exact zero */ \ | ||
190 | if (FP_ROUNDMODE == FP_RND_MINF) \ | ||
191 | R##_s |= Y##_s; \ | ||
192 | else \ | ||
193 | R##_s &= Y##_s; \ | ||
194 | R##_c = FP_CLS_ZERO; \ | ||
195 | } \ | ||
196 | else \ | ||
197 | { \ | ||
198 | if (_FP_FRAC_NEGP_##wc(R)) \ | ||
199 | { \ | ||
200 | _FP_FRAC_SUB_##wc(R, Y, X); \ | ||
201 | R##_s = Y##_s; \ | ||
202 | } \ | ||
203 | \ | ||
204 | /* renormalize after subtraction */ \ | ||
205 | _FP_FRAC_CLZ_##wc(diff, R); \ | ||
206 | diff -= _FP_WFRACXBITS_##fs; \ | ||
207 | if (diff) \ | ||
208 | { \ | ||
209 | R##_e -= diff; \ | ||
210 | _FP_FRAC_SLL_##wc(R, diff); \ | ||
211 | } \ | ||
212 | } \ | ||
213 | } \ | ||
214 | break; \ | ||
215 | } \ | ||
216 | \ | ||
217 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ | ||
218 | _FP_CHOOSENAN(fs, wc, R, X, Y); \ | ||
219 | break; \ | ||
220 | \ | ||
221 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ | ||
222 | R##_e = X##_e; \ | ||
223 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ | ||
224 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ | ||
225 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ | ||
226 | _FP_FRAC_COPY_##wc(R, X); \ | ||
227 | R##_s = X##_s; \ | ||
228 | R##_c = X##_c; \ | ||
229 | break; \ | ||
230 | \ | ||
231 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ | ||
232 | R##_e = Y##_e; \ | ||
233 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ | ||
234 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ | ||
235 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ | ||
236 | _FP_FRAC_COPY_##wc(R, Y); \ | ||
237 | R##_s = Y##_s; \ | ||
238 | R##_c = Y##_c; \ | ||
239 | break; \ | ||
240 | \ | ||
241 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ | ||
242 | if (X##_s != Y##_s) \ | ||
243 | { \ | ||
244 | /* +INF + -INF => NAN */ \ | ||
245 | _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ | ||
246 | R##_s = X##_s ^ Y##_s; \ | ||
247 | R##_c = FP_CLS_NAN; \ | ||
248 | break; \ | ||
249 | } \ | ||
250 | /* FALLTHRU */ \ | ||
251 | \ | ||
252 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ | ||
253 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ | ||
254 | R##_s = X##_s; \ | ||
255 | R##_c = FP_CLS_INF; \ | ||
256 | break; \ | ||
257 | \ | ||
258 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ | ||
259 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ | ||
260 | R##_s = Y##_s; \ | ||
261 | R##_c = FP_CLS_INF; \ | ||
262 | break; \ | ||
263 | \ | ||
264 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ | ||
265 | /* make sure the sign is correct */ \ | ||
266 | if (FP_ROUNDMODE == FP_RND_MINF) \ | ||
267 | R##_s = X##_s | Y##_s; \ | ||
268 | else \ | ||
269 | R##_s = X##_s & Y##_s; \ | ||
270 | R##_c = FP_CLS_ZERO; \ | ||
271 | break; \ | ||
272 | \ | ||
273 | default: \ | ||
274 | abort(); \ | ||
275 | } \ | ||
276 | } while (0) | ||
277 | |||
278 | |||
279 | /* | ||
280 | * Main negation routine. FIXME -- when we care about setting exception | ||
281 | * bits reliably, this will not do. We should examine all of the fp classes. | ||
282 | */ | ||
283 | |||
284 | #define _FP_NEG(fs, wc, R, X) \ | ||
285 | do { \ | ||
286 | _FP_FRAC_COPY_##wc(R, X); \ | ||
287 | R##_c = X##_c; \ | ||
288 | R##_e = X##_e; \ | ||
289 | R##_s = 1 ^ X##_s; \ | ||
290 | } while (0) | ||
291 | |||
292 | |||
293 | /* | ||
294 | * Main multiplication routine. The input values should be cooked. | ||
295 | */ | ||
296 | |||
297 | #define _FP_MUL(fs, wc, R, X, Y) \ | ||
298 | do { \ | ||
299 | R##_s = X##_s ^ Y##_s; \ | ||
300 | switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ | ||
301 | { \ | ||
302 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ | ||
303 | R##_c = FP_CLS_NORMAL; \ | ||
304 | R##_e = X##_e + Y##_e + 1; \ | ||
305 | \ | ||
306 | _FP_MUL_MEAT_##fs(R,X,Y); \ | ||
307 | \ | ||
308 | if (_FP_FRAC_OVERP_##wc(fs, R)) \ | ||
309 | _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \ | ||
310 | else \ | ||
311 | R##_e--; \ | ||
312 | break; \ | ||
313 | \ | ||
314 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ | ||
315 | _FP_CHOOSENAN(fs, wc, R, X, Y); \ | ||
316 | break; \ | ||
317 | \ | ||
318 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ | ||
319 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ | ||
320 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ | ||
321 | R##_s = X##_s; \ | ||
322 | \ | ||
323 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ | ||
324 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ | ||
325 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ | ||
326 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ | ||
327 | _FP_FRAC_COPY_##wc(R, X); \ | ||
328 | R##_c = X##_c; \ | ||
329 | break; \ | ||
330 | \ | ||
331 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ | ||
332 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ | ||
333 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ | ||
334 | R##_s = Y##_s; \ | ||
335 | \ | ||
336 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ | ||
337 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ | ||
338 | _FP_FRAC_COPY_##wc(R, Y); \ | ||
339 | R##_c = Y##_c; \ | ||
340 | break; \ | ||
341 | \ | ||
342 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ | ||
343 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ | ||
344 | R##_c = FP_CLS_NAN; \ | ||
345 | _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ | ||
346 | break; \ | ||
347 | \ | ||
348 | default: \ | ||
349 | abort(); \ | ||
350 | } \ | ||
351 | } while (0) | ||
352 | |||
353 | |||
354 | /* | ||
355 | * Main division routine. The input values should be cooked. | ||
356 | */ | ||
357 | |||
358 | #define _FP_DIV(fs, wc, R, X, Y) \ | ||
359 | do { \ | ||
360 | R##_s = X##_s ^ Y##_s; \ | ||
361 | switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ | ||
362 | { \ | ||
363 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ | ||
364 | R##_c = FP_CLS_NORMAL; \ | ||
365 | R##_e = X##_e - Y##_e; \ | ||
366 | \ | ||
367 | _FP_DIV_MEAT_##fs(R,X,Y); \ | ||
368 | break; \ | ||
369 | \ | ||
370 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ | ||
371 | _FP_CHOOSENAN(fs, wc, R, X, Y); \ | ||
372 | break; \ | ||
373 | \ | ||
374 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ | ||
375 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ | ||
376 | case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ | ||
377 | R##_s = X##_s; \ | ||
378 | _FP_FRAC_COPY_##wc(R, X); \ | ||
379 | R##_c = X##_c; \ | ||
380 | break; \ | ||
381 | \ | ||
382 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ | ||
383 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ | ||
384 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ | ||
385 | R##_s = Y##_s; \ | ||
386 | _FP_FRAC_COPY_##wc(R, Y); \ | ||
387 | R##_c = Y##_c; \ | ||
388 | break; \ | ||
389 | \ | ||
390 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ | ||
391 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ | ||
392 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ | ||
393 | R##_c = FP_CLS_ZERO; \ | ||
394 | break; \ | ||
395 | \ | ||
396 | case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ | ||
397 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ | ||
398 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ | ||
399 | R##_c = FP_CLS_INF; \ | ||
400 | break; \ | ||
401 | \ | ||
402 | case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ | ||
403 | case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ | ||
404 | R##_c = FP_CLS_NAN; \ | ||
405 | _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ | ||
406 | break; \ | ||
407 | \ | ||
408 | default: \ | ||
409 | abort(); \ | ||
410 | } \ | ||
411 | } while (0) | ||
412 | |||
413 | |||
414 | /* | ||
415 | * Main differential comparison routine. The inputs should be raw not | ||
416 | * cooked. The return is -1,0,1 for normal values, 2 otherwise. | ||
417 | */ | ||
418 | |||
419 | #define _FP_CMP(fs, wc, ret, X, Y, un) \ | ||
420 | do { \ | ||
421 | /* NANs are unordered */ \ | ||
422 | if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \ | ||
423 | || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \ | ||
424 | { \ | ||
425 | ret = un; \ | ||
426 | } \ | ||
427 | else \ | ||
428 | { \ | ||
429 | int __x_zero = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \ | ||
430 | int __y_zero = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \ | ||
431 | \ | ||
432 | if (__x_zero && __y_zero) \ | ||
433 | ret = 0; \ | ||
434 | else if (__x_zero) \ | ||
435 | ret = Y##_s ? 1 : -1; \ | ||
436 | else if (__y_zero) \ | ||
437 | ret = X##_s ? -1 : 1; \ | ||
438 | else if (X##_s != Y##_s) \ | ||
439 | ret = X##_s ? -1 : 1; \ | ||
440 | else if (X##_e > Y##_e) \ | ||
441 | ret = X##_s ? -1 : 1; \ | ||
442 | else if (X##_e < Y##_e) \ | ||
443 | ret = X##_s ? 1 : -1; \ | ||
444 | else if (_FP_FRAC_GT_##wc(X, Y)) \ | ||
445 | ret = X##_s ? -1 : 1; \ | ||
446 | else if (_FP_FRAC_GT_##wc(Y, X)) \ | ||
447 | ret = X##_s ? 1 : -1; \ | ||
448 | else \ | ||
449 | ret = 0; \ | ||
450 | } \ | ||
451 | } while (0) | ||
452 | |||
453 | |||
454 | /* Simplification for strict equality. */ | ||
455 | |||
456 | #define _FP_CMP_EQ(fs, wc, ret, X, Y) \ | ||
457 | do { \ | ||
458 | /* NANs are unordered */ \ | ||
459 | if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \ | ||
460 | || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \ | ||
461 | { \ | ||
462 | ret = 1; \ | ||
463 | } \ | ||
464 | else \ | ||
465 | { \ | ||
466 | ret = !(X##_e == Y##_e \ | ||
467 | && _FP_FRAC_EQ_##wc(X, Y) \ | ||
468 | && (X##_s == Y##_s || !X##_e && _FP_FRAC_ZEROP_##wc(X))); \ | ||
469 | } \ | ||
470 | } while (0) | ||
471 | |||
472 | /* | ||
473 | * Main square root routine. The input value should be cooked. | ||
474 | */ | ||
475 | |||
476 | #define _FP_SQRT(fs, wc, R, X) \ | ||
477 | do { \ | ||
478 | _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \ | ||
479 | _FP_W_TYPE q; \ | ||
480 | switch (X##_c) \ | ||
481 | { \ | ||
482 | case FP_CLS_NAN: \ | ||
483 | R##_s = 0; \ | ||
484 | R##_c = FP_CLS_NAN; \ | ||
485 | _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ | ||
486 | break; \ | ||
487 | case FP_CLS_INF: \ | ||
488 | if (X##_s) \ | ||
489 | { \ | ||
490 | R##_s = 0; \ | ||
491 | R##_c = FP_CLS_NAN; /* sNAN */ \ | ||
492 | } \ | ||
493 | else \ | ||
494 | { \ | ||
495 | R##_s = 0; \ | ||
496 | R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \ | ||
497 | } \ | ||
498 | break; \ | ||
499 | case FP_CLS_ZERO: \ | ||
500 | R##_s = X##_s; \ | ||
501 | R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \ | ||
502 | break; \ | ||
503 | case FP_CLS_NORMAL: \ | ||
504 | R##_s = 0; \ | ||
505 | if (X##_s) \ | ||
506 | { \ | ||
507 | R##_c = FP_CLS_NAN; /* sNAN */ \ | ||
508 | break; \ | ||
509 | } \ | ||
510 | R##_c = FP_CLS_NORMAL; \ | ||
511 | if (X##_e & 1) \ | ||
512 | _FP_FRAC_SLL_##wc(X, 1); \ | ||
513 | R##_e = X##_e >> 1; \ | ||
514 | _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \ | ||
515 | _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \ | ||
516 | q = _FP_OVERFLOW_##fs; \ | ||
517 | _FP_FRAC_SLL_##wc(X, 1); \ | ||
518 | _FP_SQRT_MEAT_##wc(R, S, T, X, q); \ | ||
519 | _FP_FRAC_SRL_##wc(R, 1); \ | ||
520 | } \ | ||
521 | } while (0) | ||
522 | |||
523 | /* | ||
524 | * Convert from FP to integer | ||
525 | */ | ||
526 | |||
527 | /* "When a NaN, infinity, large positive argument >= 2147483648.0, or | ||
528 | * large negative argument <= -2147483649.0 is converted to an integer, | ||
529 | * the invalid_current bit...should be set and fp_exception_IEEE_754 should | ||
530 | * be raised. If the floating point invalid trap is disabled, no trap occurs | ||
531 | * and a numerical result is generated: if the sign bit of the operand | ||
532 | * is 0, the result is 2147483647; if the sign bit of the operand is 1, | ||
533 | * the result is -2147483648." | ||
534 | * Similarly for conversion to extended ints, except that the boundaries | ||
535 | * are >= 2^63, <= -(2^63 + 1), and the results are 2^63 + 1 for s=0 and | ||
536 | * -2^63 for s=1. | ||
537 | * -- SPARC Architecture Manual V9, Appendix B, which specifies how | ||
538 | * SPARCs resolve implementation dependencies in the IEEE-754 spec. | ||
539 | * I don't believe that the code below follows this. I'm not even sure | ||
540 | * it's right! | ||
541 | * It doesn't cope with needing to convert to an n bit integer when there | ||
542 | * is no n bit integer type. Fortunately gcc provides long long so this | ||
543 | * isn't a problem for sparc32. | ||
544 | * I have, however, fixed its NaN handling to conform as above. | ||
545 | * -- PMM 02/1998 | ||
546 | * NB: rsigned is not 'is r declared signed?' but 'should the value stored | ||
547 | * in r be signed or unsigned?'. r is always(?) declared unsigned. | ||
548 | * Comments below are mine, BTW -- PMM | ||
549 | */ | ||
550 | #define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \ | ||
551 | do { \ | ||
552 | switch (X##_c) \ | ||
553 | { \ | ||
554 | case FP_CLS_NORMAL: \ | ||
555 | if (X##_e < 0) \ | ||
556 | { \ | ||
557 | /* case FP_CLS_NAN: see above! */ \ | ||
558 | case FP_CLS_ZERO: \ | ||
559 | r = 0; \ | ||
560 | } \ | ||
561 | else if (X##_e >= rsize - (rsigned != 0)) \ | ||
562 | { /* overflow */ \ | ||
563 | case FP_CLS_NAN: \ | ||
564 | case FP_CLS_INF: \ | ||
565 | if (rsigned) \ | ||
566 | { \ | ||
567 | r = 1; \ | ||
568 | r <<= rsize - 1; \ | ||
569 | r -= 1 - X##_s; \ | ||
570 | } \ | ||
571 | else \ | ||
572 | { \ | ||
573 | r = 0; \ | ||
574 | if (!X##_s) \ | ||
575 | r = ~r; \ | ||
576 | } \ | ||
577 | } \ | ||
578 | else \ | ||
579 | { \ | ||
580 | if (_FP_W_TYPE_SIZE*wc < rsize) \ | ||
581 | { \ | ||
582 | _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ | ||
583 | r <<= X##_e - _FP_WFRACBITS_##fs; \ | ||
584 | } \ | ||
585 | else \ | ||
586 | { \ | ||
587 | if (X##_e >= _FP_WFRACBITS_##fs) \ | ||
588 | _FP_FRAC_SLL_##wc(X, (X##_e - _FP_WFRACBITS_##fs + 1));\ | ||
589 | else \ | ||
590 | _FP_FRAC_SRL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1));\ | ||
591 | _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ | ||
592 | } \ | ||
593 | if (rsigned && X##_s) \ | ||
594 | r = -r; \ | ||
595 | } \ | ||
596 | break; \ | ||
597 | } \ | ||
598 | } while (0) | ||
599 | |||
600 | #define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \ | ||
601 | do { \ | ||
602 | if (r) \ | ||
603 | { \ | ||
604 | X##_c = FP_CLS_NORMAL; \ | ||
605 | \ | ||
606 | if ((X##_s = (r < 0))) \ | ||
607 | r = -r; \ | ||
608 | /* Note that `r' is now considered unsigned, so we don't have \ | ||
609 | to worry about the single signed overflow case. */ \ | ||
610 | \ | ||
611 | if (rsize <= _FP_W_TYPE_SIZE) \ | ||
612 | __FP_CLZ(X##_e, r); \ | ||
613 | else \ | ||
614 | __FP_CLZ_2(X##_e, (_FP_W_TYPE)(r >> _FP_W_TYPE_SIZE), \ | ||
615 | (_FP_W_TYPE)r); \ | ||
616 | if (rsize < _FP_W_TYPE_SIZE) \ | ||
617 | X##_e -= (_FP_W_TYPE_SIZE - rsize); \ | ||
618 | X##_e = rsize - X##_e - 1; \ | ||
619 | \ | ||
620 | if (_FP_FRACBITS_##fs < rsize && _FP_WFRACBITS_##fs < X##_e) \ | ||
621 | __FP_FRAC_SRS_1(r, (X##_e - _FP_WFRACBITS_##fs), rsize); \ | ||
622 | r &= ~((_FP_W_TYPE)1 << X##_e); \ | ||
623 | _FP_FRAC_DISASSEMBLE_##wc(X, ((unsigned rtype)r), rsize); \ | ||
624 | _FP_FRAC_SLL_##wc(X, (_FP_WFRACBITS_##fs - X##_e - 1)); \ | ||
625 | } \ | ||
626 | else \ | ||
627 | { \ | ||
628 | X##_c = FP_CLS_ZERO, X##_s = 0; \ | ||
629 | } \ | ||
630 | } while (0) | ||
631 | |||
632 | |||
633 | #define FP_CONV(dfs,sfs,dwc,swc,D,S) \ | ||
634 | do { \ | ||
635 | _FP_FRAC_CONV_##dwc##_##swc(dfs, sfs, D, S); \ | ||
636 | D##_e = S##_e; \ | ||
637 | D##_c = S##_c; \ | ||
638 | D##_s = S##_s; \ | ||
639 | } while (0) | ||
640 | |||
641 | /* | ||
642 | * Helper primitives. | ||
643 | */ | ||
644 | |||
645 | /* Count leading zeros in a word. */ | ||
646 | |||
647 | #ifndef __FP_CLZ | ||
648 | #if _FP_W_TYPE_SIZE < 64 | ||
649 | /* this is just to shut the compiler up about shifts > word length -- PMM 02/1998 */ | ||
650 | #define __FP_CLZ(r, x) \ | ||
651 | do { \ | ||
652 | _FP_W_TYPE _t = (x); \ | ||
653 | r = _FP_W_TYPE_SIZE - 1; \ | ||
654 | if (_t > 0xffff) r -= 16; \ | ||
655 | if (_t > 0xffff) _t >>= 16; \ | ||
656 | if (_t > 0xff) r -= 8; \ | ||
657 | if (_t > 0xff) _t >>= 8; \ | ||
658 | if (_t & 0xf0) r -= 4; \ | ||
659 | if (_t & 0xf0) _t >>= 4; \ | ||
660 | if (_t & 0xc) r -= 2; \ | ||
661 | if (_t & 0xc) _t >>= 2; \ | ||
662 | if (_t & 0x2) r -= 1; \ | ||
663 | } while (0) | ||
664 | #else /* not _FP_W_TYPE_SIZE < 64 */ | ||
665 | #define __FP_CLZ(r, x) \ | ||
666 | do { \ | ||
667 | _FP_W_TYPE _t = (x); \ | ||
668 | r = _FP_W_TYPE_SIZE - 1; \ | ||
669 | if (_t > 0xffffffff) r -= 32; \ | ||
670 | if (_t > 0xffffffff) _t >>= 32; \ | ||
671 | if (_t > 0xffff) r -= 16; \ | ||
672 | if (_t > 0xffff) _t >>= 16; \ | ||
673 | if (_t > 0xff) r -= 8; \ | ||
674 | if (_t > 0xff) _t >>= 8; \ | ||
675 | if (_t & 0xf0) r -= 4; \ | ||
676 | if (_t & 0xf0) _t >>= 4; \ | ||
677 | if (_t & 0xc) r -= 2; \ | ||
678 | if (_t & 0xc) _t >>= 2; \ | ||
679 | if (_t & 0x2) r -= 1; \ | ||
680 | } while (0) | ||
681 | #endif /* not _FP_W_TYPE_SIZE < 64 */ | ||
682 | #endif /* ndef __FP_CLZ */ | ||
683 | |||
684 | #define _FP_DIV_HELP_imm(q, r, n, d) \ | ||
685 | do { \ | ||
686 | q = n / d, r = n % d; \ | ||
687 | } while (0) | ||
688 | |||
diff --git a/arch/powerpc/math-emu/sfp-machine.h b/arch/powerpc/math-emu/sfp-machine.h new file mode 100644 index 000000000000..4b17d83cfcdd --- /dev/null +++ b/arch/powerpc/math-emu/sfp-machine.h | |||
@@ -0,0 +1,377 @@ | |||
1 | /* Machine-dependent software floating-point definitions. PPC version. | ||
2 | Copyright (C) 1997 Free Software Foundation, Inc. | ||
3 | This file is part of the GNU C Library. | ||
4 | |||
5 | The GNU C Library is free software; you can redistribute it and/or | ||
6 | modify it under the terms of the GNU Library General Public License as | ||
7 | published by the Free Software Foundation; either version 2 of the | ||
8 | License, or (at your option) any later version. | ||
9 | |||
10 | The GNU C Library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Library General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Library General Public | ||
16 | License along with the GNU C Library; see the file COPYING.LIB. If | ||
17 | not, write to the Free Software Foundation, Inc., | ||
18 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | |||
20 | Actually, this is a PPC (32bit) version, written based on the | ||
21 | i386, sparc, and sparc64 versions, by me, | ||
22 | Peter Maydell (pmaydell@chiark.greenend.org.uk). | ||
23 | Comments are by and large also mine, although they may be inaccurate. | ||
24 | |||
25 | In picking out asm fragments I've gone with the lowest common | ||
26 | denominator, which also happens to be the hardware I have :-> | ||
27 | That is, a SPARC without hardware multiply and divide. | ||
28 | */ | ||
29 | |||
30 | /* basic word size definitions */ | ||
31 | #define _FP_W_TYPE_SIZE 32 | ||
32 | #define _FP_W_TYPE unsigned long | ||
33 | #define _FP_WS_TYPE signed long | ||
34 | #define _FP_I_TYPE long | ||
35 | |||
36 | #define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) | ||
37 | #define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) | ||
38 | #define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) | ||
39 | |||
40 | /* You can optionally code some things like addition in asm. For | ||
41 | * example, i386 defines __FP_FRAC_ADD_2 as asm. If you don't | ||
42 | * then you get a fragment of C code [if you change an #ifdef 0 | ||
43 | * in op-2.h] or a call to add_ssaaaa (see below). | ||
44 | * Good places to look for asm fragments to use are gcc and glibc. | ||
45 | * gcc's longlong.h is useful. | ||
46 | */ | ||
47 | |||
48 | /* We need to know how to multiply and divide. If the host word size | ||
49 | * is >= 2*fracbits you can use FP_MUL_MEAT_n_imm(t,R,X,Y) which | ||
50 | * codes the multiply with whatever gcc does to 'a * b'. | ||
51 | * _FP_MUL_MEAT_n_wide(t,R,X,Y,f) is used when you have an asm | ||
52 | * function that can multiply two 1W values and get a 2W result. | ||
53 | * Otherwise you're stuck with _FP_MUL_MEAT_n_hard(t,R,X,Y) which | ||
54 | * does bitshifting to avoid overflow. | ||
55 | * For division there is FP_DIV_MEAT_n_imm(t,R,X,Y,f) for word size | ||
56 | * >= 2*fracbits, where f is either _FP_DIV_HELP_imm or | ||
57 | * _FP_DIV_HELP_ldiv (see op-1.h). | ||
58 | * _FP_DIV_MEAT_udiv() is if you have asm to do 2W/1W => (1W, 1W). | ||
59 | * [GCC and glibc have longlong.h which has the asm macro udiv_qrnnd | ||
60 | * to do this.] | ||
61 | * In general, 'n' is the number of words required to hold the type, | ||
62 | * and 't' is either S, D or Q for single/double/quad. | ||
63 | * -- PMM | ||
64 | */ | ||
65 | /* Example: SPARC64: | ||
66 | * #define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_imm(S,R,X,Y) | ||
67 | * #define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_1_wide(D,R,X,Y,umul_ppmm) | ||
68 | * #define _FP_MUL_MEAT_Q(R,X,Y) _FP_MUL_MEAT_2_wide(Q,R,X,Y,umul_ppmm) | ||
69 | * | ||
70 | * #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm) | ||
71 | * #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_1_udiv(D,R,X,Y) | ||
72 | * #define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_2_udiv_64(Q,R,X,Y) | ||
73 | * | ||
74 | * Example: i386: | ||
75 | * #define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_wide(S,R,X,Y,_i386_mul_32_64) | ||
76 | * #define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_2_wide(D,R,X,Y,_i386_mul_32_64) | ||
77 | * | ||
78 | * #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv(S,R,X,Y,_i386_div_64_32) | ||
79 | * #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv_64(D,R,X,Y) | ||
80 | */ | ||
81 | |||
82 | #define _FP_MUL_MEAT_S(R,X,Y) _FP_MUL_MEAT_1_wide(S,R,X,Y,umul_ppmm) | ||
83 | #define _FP_MUL_MEAT_D(R,X,Y) _FP_MUL_MEAT_2_wide(D,R,X,Y,umul_ppmm) | ||
84 | |||
85 | #define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv(S,R,X,Y) | ||
86 | #define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv_64(D,R,X,Y) | ||
87 | |||
88 | /* These macros define what NaN looks like. They're supposed to expand to | ||
89 | * a comma-separated set of 32bit unsigned ints that encode NaN. | ||
90 | */ | ||
91 | #define _FP_NANFRAC_S _FP_QNANBIT_S | ||
92 | #define _FP_NANFRAC_D _FP_QNANBIT_D, 0 | ||
93 | #define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0, 0, 0 | ||
94 | |||
95 | #define _FP_KEEPNANFRACP 1 | ||
96 | |||
97 | /* This macro appears to be called when both X and Y are NaNs, and | ||
98 | * has to choose one and copy it to R. i386 goes for the larger of the | ||
99 | * two, sparc64 just picks Y. I don't understand this at all so I'll | ||
100 | * go with sparc64 because it's shorter :-> -- PMM | ||
101 | */ | ||
102 | #define _FP_CHOOSENAN(fs, wc, R, X, Y) \ | ||
103 | do { \ | ||
104 | R##_s = Y##_s; \ | ||
105 | _FP_FRAC_COPY_##wc(R,Y); \ | ||
106 | R##_c = FP_CLS_NAN; \ | ||
107 | } while (0) | ||
108 | |||
109 | |||
110 | extern void fp_unpack_d(long *, unsigned long *, unsigned long *, | ||
111 | long *, long *, void *); | ||
112 | extern int fp_pack_d(void *, long, unsigned long, unsigned long, long, long); | ||
113 | extern int fp_pack_ds(void *, long, unsigned long, unsigned long, long, long); | ||
114 | |||
115 | #define __FP_UNPACK_RAW_1(fs, X, val) \ | ||
116 | do { \ | ||
117 | union _FP_UNION_##fs *_flo = \ | ||
118 | (union _FP_UNION_##fs *)val; \ | ||
119 | \ | ||
120 | X##_f = _flo->bits.frac; \ | ||
121 | X##_e = _flo->bits.exp; \ | ||
122 | X##_s = _flo->bits.sign; \ | ||
123 | } while (0) | ||
124 | |||
125 | #define __FP_UNPACK_RAW_2(fs, X, val) \ | ||
126 | do { \ | ||
127 | union _FP_UNION_##fs *_flo = \ | ||
128 | (union _FP_UNION_##fs *)val; \ | ||
129 | \ | ||
130 | X##_f0 = _flo->bits.frac0; \ | ||
131 | X##_f1 = _flo->bits.frac1; \ | ||
132 | X##_e = _flo->bits.exp; \ | ||
133 | X##_s = _flo->bits.sign; \ | ||
134 | } while (0) | ||
135 | |||
136 | #define __FP_UNPACK_S(X,val) \ | ||
137 | do { \ | ||
138 | __FP_UNPACK_RAW_1(S,X,val); \ | ||
139 | _FP_UNPACK_CANONICAL(S,1,X); \ | ||
140 | } while (0) | ||
141 | |||
142 | #define __FP_UNPACK_D(X,val) \ | ||
143 | fp_unpack_d(&X##_s, &X##_f1, &X##_f0, &X##_e, &X##_c, val) | ||
144 | |||
145 | #define __FP_PACK_RAW_1(fs, val, X) \ | ||
146 | do { \ | ||
147 | union _FP_UNION_##fs *_flo = \ | ||
148 | (union _FP_UNION_##fs *)val; \ | ||
149 | \ | ||
150 | _flo->bits.frac = X##_f; \ | ||
151 | _flo->bits.exp = X##_e; \ | ||
152 | _flo->bits.sign = X##_s; \ | ||
153 | } while (0) | ||
154 | |||
155 | #define __FP_PACK_RAW_2(fs, val, X) \ | ||
156 | do { \ | ||
157 | union _FP_UNION_##fs *_flo = \ | ||
158 | (union _FP_UNION_##fs *)val; \ | ||
159 | \ | ||
160 | _flo->bits.frac0 = X##_f0; \ | ||
161 | _flo->bits.frac1 = X##_f1; \ | ||
162 | _flo->bits.exp = X##_e; \ | ||
163 | _flo->bits.sign = X##_s; \ | ||
164 | } while (0) | ||
165 | |||
166 | #include <linux/kernel.h> | ||
167 | #include <linux/sched.h> | ||
168 | |||
169 | #define __FPU_FPSCR (current->thread.fpscr.val) | ||
170 | |||
171 | /* We only actually write to the destination register | ||
172 | * if exceptions signalled (if any) will not trap. | ||
173 | */ | ||
174 | #define __FPU_ENABLED_EXC \ | ||
175 | ({ \ | ||
176 | (__FPU_FPSCR >> 3) & 0x1f; \ | ||
177 | }) | ||
178 | |||
179 | #define __FPU_TRAP_P(bits) \ | ||
180 | ((__FPU_ENABLED_EXC & (bits)) != 0) | ||
181 | |||
182 | #define __FP_PACK_S(val,X) \ | ||
183 | ({ int __exc = _FP_PACK_CANONICAL(S,1,X); \ | ||
184 | if(!__exc || !__FPU_TRAP_P(__exc)) \ | ||
185 | __FP_PACK_RAW_1(S,val,X); \ | ||
186 | __exc; \ | ||
187 | }) | ||
188 | |||
189 | #define __FP_PACK_D(val,X) \ | ||
190 | fp_pack_d(val, X##_s, X##_f1, X##_f0, X##_e, X##_c) | ||
191 | |||
192 | #define __FP_PACK_DS(val,X) \ | ||
193 | fp_pack_ds(val, X##_s, X##_f1, X##_f0, X##_e, X##_c) | ||
194 | |||
195 | /* Obtain the current rounding mode. */ | ||
196 | #define FP_ROUNDMODE \ | ||
197 | ({ \ | ||
198 | __FPU_FPSCR & 0x3; \ | ||
199 | }) | ||
200 | |||
201 | /* the asm fragments go here: all these are taken from glibc-2.0.5's | ||
202 | * stdlib/longlong.h | ||
203 | */ | ||
204 | |||
205 | #include <linux/types.h> | ||
206 | #include <asm/byteorder.h> | ||
207 | |||
208 | /* add_ssaaaa is used in op-2.h and should be equivalent to | ||
209 | * #define add_ssaaaa(sh,sl,ah,al,bh,bl) (sh = ah+bh+ (( sl = al+bl) < al)) | ||
210 | * add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, | ||
211 | * high_addend_2, low_addend_2) adds two UWtype integers, composed by | ||
212 | * HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 | ||
213 | * respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow | ||
214 | * (i.e. carry out) is not stored anywhere, and is lost. | ||
215 | */ | ||
216 | #define add_ssaaaa(sh, sl, ah, al, bh, bl) \ | ||
217 | do { \ | ||
218 | if (__builtin_constant_p (bh) && (bh) == 0) \ | ||
219 | __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ | ||
220 | : "=r" ((USItype)(sh)), \ | ||
221 | "=&r" ((USItype)(sl)) \ | ||
222 | : "%r" ((USItype)(ah)), \ | ||
223 | "%r" ((USItype)(al)), \ | ||
224 | "rI" ((USItype)(bl))); \ | ||
225 | else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ | ||
226 | __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ | ||
227 | : "=r" ((USItype)(sh)), \ | ||
228 | "=&r" ((USItype)(sl)) \ | ||
229 | : "%r" ((USItype)(ah)), \ | ||
230 | "%r" ((USItype)(al)), \ | ||
231 | "rI" ((USItype)(bl))); \ | ||
232 | else \ | ||
233 | __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ | ||
234 | : "=r" ((USItype)(sh)), \ | ||
235 | "=&r" ((USItype)(sl)) \ | ||
236 | : "%r" ((USItype)(ah)), \ | ||
237 | "r" ((USItype)(bh)), \ | ||
238 | "%r" ((USItype)(al)), \ | ||
239 | "rI" ((USItype)(bl))); \ | ||
240 | } while (0) | ||
241 | |||
242 | /* sub_ddmmss is used in op-2.h and udivmodti4.c and should be equivalent to | ||
243 | * #define sub_ddmmss(sh, sl, ah, al, bh, bl) (sh = ah-bh - ((sl = al-bl) > al)) | ||
244 | * sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, | ||
245 | * high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, | ||
246 | * composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and | ||
247 | * LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE | ||
248 | * and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, | ||
249 | * and is lost. | ||
250 | */ | ||
251 | #define sub_ddmmss(sh, sl, ah, al, bh, bl) \ | ||
252 | do { \ | ||
253 | if (__builtin_constant_p (ah) && (ah) == 0) \ | ||
254 | __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ | ||
255 | : "=r" ((USItype)(sh)), \ | ||
256 | "=&r" ((USItype)(sl)) \ | ||
257 | : "r" ((USItype)(bh)), \ | ||
258 | "rI" ((USItype)(al)), \ | ||
259 | "r" ((USItype)(bl))); \ | ||
260 | else if (__builtin_constant_p (ah) && (ah) ==~(USItype) 0) \ | ||
261 | __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ | ||
262 | : "=r" ((USItype)(sh)), \ | ||
263 | "=&r" ((USItype)(sl)) \ | ||
264 | : "r" ((USItype)(bh)), \ | ||
265 | "rI" ((USItype)(al)), \ | ||
266 | "r" ((USItype)(bl))); \ | ||
267 | else if (__builtin_constant_p (bh) && (bh) == 0) \ | ||
268 | __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ | ||
269 | : "=r" ((USItype)(sh)), \ | ||
270 | "=&r" ((USItype)(sl)) \ | ||
271 | : "r" ((USItype)(ah)), \ | ||
272 | "rI" ((USItype)(al)), \ | ||
273 | "r" ((USItype)(bl))); \ | ||
274 | else if (__builtin_constant_p (bh) && (bh) ==~(USItype) 0) \ | ||
275 | __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ | ||
276 | : "=r" ((USItype)(sh)), \ | ||
277 | "=&r" ((USItype)(sl)) \ | ||
278 | : "r" ((USItype)(ah)), \ | ||
279 | "rI" ((USItype)(al)), \ | ||
280 | "r" ((USItype)(bl))); \ | ||
281 | else \ | ||
282 | __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ | ||
283 | : "=r" ((USItype)(sh)), \ | ||
284 | "=&r" ((USItype)(sl)) \ | ||
285 | : "r" ((USItype)(ah)), \ | ||
286 | "r" ((USItype)(bh)), \ | ||
287 | "rI" ((USItype)(al)), \ | ||
288 | "r" ((USItype)(bl))); \ | ||
289 | } while (0) | ||
290 | |||
291 | /* asm fragments for mul and div */ | ||
292 | |||
293 | /* umul_ppmm(high_prod, low_prod, multipler, multiplicand) multiplies two | ||
294 | * UWtype integers MULTIPLER and MULTIPLICAND, and generates a two UWtype | ||
295 | * word product in HIGH_PROD and LOW_PROD. | ||
296 | */ | ||
297 | #define umul_ppmm(ph, pl, m0, m1) \ | ||
298 | do { \ | ||
299 | USItype __m0 = (m0), __m1 = (m1); \ | ||
300 | __asm__ ("mulhwu %0,%1,%2" \ | ||
301 | : "=r" ((USItype)(ph)) \ | ||
302 | : "%r" (__m0), \ | ||
303 | "r" (__m1)); \ | ||
304 | (pl) = __m0 * __m1; \ | ||
305 | } while (0) | ||
306 | |||
307 | /* udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, | ||
308 | * denominator) divides a UDWtype, composed by the UWtype integers | ||
309 | * HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient | ||
310 | * in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less | ||
311 | * than DENOMINATOR for correct operation. If, in addition, the most | ||
312 | * significant bit of DENOMINATOR must be 1, then the pre-processor symbol | ||
313 | * UDIV_NEEDS_NORMALIZATION is defined to 1. | ||
314 | */ | ||
315 | #define udiv_qrnnd(q, r, n1, n0, d) \ | ||
316 | do { \ | ||
317 | UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m; \ | ||
318 | __d1 = __ll_highpart (d); \ | ||
319 | __d0 = __ll_lowpart (d); \ | ||
320 | \ | ||
321 | __r1 = (n1) % __d1; \ | ||
322 | __q1 = (n1) / __d1; \ | ||
323 | __m = (UWtype) __q1 * __d0; \ | ||
324 | __r1 = __r1 * __ll_B | __ll_highpart (n0); \ | ||
325 | if (__r1 < __m) \ | ||
326 | { \ | ||
327 | __q1--, __r1 += (d); \ | ||
328 | if (__r1 >= (d)) /* we didn't get carry when adding to __r1 */ \ | ||
329 | if (__r1 < __m) \ | ||
330 | __q1--, __r1 += (d); \ | ||
331 | } \ | ||
332 | __r1 -= __m; \ | ||
333 | \ | ||
334 | __r0 = __r1 % __d1; \ | ||
335 | __q0 = __r1 / __d1; \ | ||
336 | __m = (UWtype) __q0 * __d0; \ | ||
337 | __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ | ||
338 | if (__r0 < __m) \ | ||
339 | { \ | ||
340 | __q0--, __r0 += (d); \ | ||
341 | if (__r0 >= (d)) \ | ||
342 | if (__r0 < __m) \ | ||
343 | __q0--, __r0 += (d); \ | ||
344 | } \ | ||
345 | __r0 -= __m; \ | ||
346 | \ | ||
347 | (q) = (UWtype) __q1 * __ll_B | __q0; \ | ||
348 | (r) = __r0; \ | ||
349 | } while (0) | ||
350 | |||
351 | #define UDIV_NEEDS_NORMALIZATION 1 | ||
352 | |||
353 | #define abort() \ | ||
354 | return 0 | ||
355 | |||
356 | #ifdef __BIG_ENDIAN | ||
357 | #define __BYTE_ORDER __BIG_ENDIAN | ||
358 | #else | ||
359 | #define __BYTE_ORDER __LITTLE_ENDIAN | ||
360 | #endif | ||
361 | |||
362 | /* Exception flags. */ | ||
363 | #define EFLAG_INVALID (1 << (31 - 2)) | ||
364 | #define EFLAG_OVERFLOW (1 << (31 - 3)) | ||
365 | #define EFLAG_UNDERFLOW (1 << (31 - 4)) | ||
366 | #define EFLAG_DIVZERO (1 << (31 - 5)) | ||
367 | #define EFLAG_INEXACT (1 << (31 - 6)) | ||
368 | |||
369 | #define EFLAG_VXSNAN (1 << (31 - 7)) | ||
370 | #define EFLAG_VXISI (1 << (31 - 8)) | ||
371 | #define EFLAG_VXIDI (1 << (31 - 9)) | ||
372 | #define EFLAG_VXZDZ (1 << (31 - 10)) | ||
373 | #define EFLAG_VXIMZ (1 << (31 - 11)) | ||
374 | #define EFLAG_VXVC (1 << (31 - 12)) | ||
375 | #define EFLAG_VXSOFT (1 << (31 - 21)) | ||
376 | #define EFLAG_VXSQRT (1 << (31 - 22)) | ||
377 | #define EFLAG_VXCVI (1 << (31 - 23)) | ||
diff --git a/arch/powerpc/math-emu/single.h b/arch/powerpc/math-emu/single.h new file mode 100644 index 000000000000..f19d99451815 --- /dev/null +++ b/arch/powerpc/math-emu/single.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * Definitions for IEEE Single Precision | ||
3 | */ | ||
4 | |||
5 | #if _FP_W_TYPE_SIZE < 32 | ||
6 | #error "Here's a nickel kid. Go buy yourself a real computer." | ||
7 | #endif | ||
8 | |||
9 | #define _FP_FRACBITS_S 24 | ||
10 | #define _FP_FRACXBITS_S (_FP_W_TYPE_SIZE - _FP_FRACBITS_S) | ||
11 | #define _FP_WFRACBITS_S (_FP_WORKBITS + _FP_FRACBITS_S) | ||
12 | #define _FP_WFRACXBITS_S (_FP_W_TYPE_SIZE - _FP_WFRACBITS_S) | ||
13 | #define _FP_EXPBITS_S 8 | ||
14 | #define _FP_EXPBIAS_S 127 | ||
15 | #define _FP_EXPMAX_S 255 | ||
16 | #define _FP_QNANBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2)) | ||
17 | #define _FP_IMPLBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1)) | ||
18 | #define _FP_OVERFLOW_S ((_FP_W_TYPE)1 << (_FP_WFRACBITS_S)) | ||
19 | |||
20 | /* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be | ||
21 | chosen by the target machine. */ | ||
22 | |||
23 | union _FP_UNION_S | ||
24 | { | ||
25 | float flt; | ||
26 | struct { | ||
27 | #if __BYTE_ORDER == __BIG_ENDIAN | ||
28 | unsigned sign : 1; | ||
29 | unsigned exp : _FP_EXPBITS_S; | ||
30 | unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0); | ||
31 | #else | ||
32 | unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0); | ||
33 | unsigned exp : _FP_EXPBITS_S; | ||
34 | unsigned sign : 1; | ||
35 | #endif | ||
36 | } bits __attribute__((packed)); | ||
37 | }; | ||
38 | |||
39 | #define FP_DECL_S(X) _FP_DECL(1,X) | ||
40 | #define FP_UNPACK_RAW_S(X,val) _FP_UNPACK_RAW_1(S,X,val) | ||
41 | #define FP_PACK_RAW_S(val,X) _FP_PACK_RAW_1(S,val,X) | ||
42 | |||
43 | #define FP_UNPACK_S(X,val) \ | ||
44 | do { \ | ||
45 | _FP_UNPACK_RAW_1(S,X,val); \ | ||
46 | _FP_UNPACK_CANONICAL(S,1,X); \ | ||
47 | } while (0) | ||
48 | |||
49 | #define FP_PACK_S(val,X) \ | ||
50 | do { \ | ||
51 | _FP_PACK_CANONICAL(S,1,X); \ | ||
52 | _FP_PACK_RAW_1(S,val,X); \ | ||
53 | } while (0) | ||
54 | |||
55 | #define FP_NEG_S(R,X) _FP_NEG(S,1,R,X) | ||
56 | #define FP_ADD_S(R,X,Y) _FP_ADD(S,1,R,X,Y) | ||
57 | #define FP_SUB_S(R,X,Y) _FP_SUB(S,1,R,X,Y) | ||
58 | #define FP_MUL_S(R,X,Y) _FP_MUL(S,1,R,X,Y) | ||
59 | #define FP_DIV_S(R,X,Y) _FP_DIV(S,1,R,X,Y) | ||
60 | #define FP_SQRT_S(R,X) _FP_SQRT(S,1,R,X) | ||
61 | |||
62 | #define FP_CMP_S(r,X,Y,un) _FP_CMP(S,1,r,X,Y,un) | ||
63 | #define FP_CMP_EQ_S(r,X,Y) _FP_CMP_EQ(S,1,r,X,Y) | ||
64 | |||
65 | #define FP_TO_INT_S(r,X,rsz,rsg) _FP_TO_INT(S,1,r,X,rsz,rsg) | ||
66 | #define FP_FROM_INT_S(X,r,rs,rt) _FP_FROM_INT(S,1,X,r,rs,rt) | ||
diff --git a/arch/powerpc/math-emu/soft-fp.h b/arch/powerpc/math-emu/soft-fp.h new file mode 100644 index 000000000000..cca39598f873 --- /dev/null +++ b/arch/powerpc/math-emu/soft-fp.h | |||
@@ -0,0 +1,104 @@ | |||
1 | #ifndef SOFT_FP_H | ||
2 | #define SOFT_FP_H | ||
3 | |||
4 | #include "sfp-machine.h" | ||
5 | |||
6 | #define _FP_WORKBITS 3 | ||
7 | #define _FP_WORK_LSB ((_FP_W_TYPE)1 << 3) | ||
8 | #define _FP_WORK_ROUND ((_FP_W_TYPE)1 << 2) | ||
9 | #define _FP_WORK_GUARD ((_FP_W_TYPE)1 << 1) | ||
10 | #define _FP_WORK_STICKY ((_FP_W_TYPE)1 << 0) | ||
11 | |||
12 | #ifndef FP_RND_NEAREST | ||
13 | # define FP_RND_NEAREST 0 | ||
14 | # define FP_RND_ZERO 1 | ||
15 | # define FP_RND_PINF 2 | ||
16 | # define FP_RND_MINF 3 | ||
17 | #ifndef FP_ROUNDMODE | ||
18 | # define FP_ROUNDMODE FP_RND_NEAREST | ||
19 | #endif | ||
20 | #endif | ||
21 | |||
22 | #define _FP_ROUND_NEAREST(wc, X) \ | ||
23 | ({ int __ret = 0; \ | ||
24 | int __frac = _FP_FRAC_LOW_##wc(X) & 15; \ | ||
25 | if (__frac & 7) { \ | ||
26 | __ret = EFLAG_INEXACT; \ | ||
27 | if ((__frac & 7) != _FP_WORK_ROUND) \ | ||
28 | _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \ | ||
29 | else if (__frac & _FP_WORK_LSB) \ | ||
30 | _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \ | ||
31 | } \ | ||
32 | __ret; \ | ||
33 | }) | ||
34 | |||
35 | #define _FP_ROUND_ZERO(wc, X) \ | ||
36 | ({ int __ret = 0; \ | ||
37 | if (_FP_FRAC_LOW_##wc(X) & 7) \ | ||
38 | __ret = EFLAG_INEXACT; \ | ||
39 | __ret; \ | ||
40 | }) | ||
41 | |||
42 | #define _FP_ROUND_PINF(wc, X) \ | ||
43 | ({ int __ret = EFLAG_INEXACT; \ | ||
44 | if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \ | ||
45 | _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \ | ||
46 | else __ret = 0; \ | ||
47 | __ret; \ | ||
48 | }) | ||
49 | |||
50 | #define _FP_ROUND_MINF(wc, X) \ | ||
51 | ({ int __ret = EFLAG_INEXACT; \ | ||
52 | if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \ | ||
53 | _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \ | ||
54 | else __ret = 0; \ | ||
55 | __ret; \ | ||
56 | }) | ||
57 | |||
58 | #define _FP_ROUND(wc, X) \ | ||
59 | ({ int __ret = 0; \ | ||
60 | switch (FP_ROUNDMODE) \ | ||
61 | { \ | ||
62 | case FP_RND_NEAREST: \ | ||
63 | __ret |= _FP_ROUND_NEAREST(wc,X); \ | ||
64 | break; \ | ||
65 | case FP_RND_ZERO: \ | ||
66 | __ret |= _FP_ROUND_ZERO(wc,X); \ | ||
67 | break; \ | ||
68 | case FP_RND_PINF: \ | ||
69 | __ret |= _FP_ROUND_PINF(wc,X); \ | ||
70 | break; \ | ||
71 | case FP_RND_MINF: \ | ||
72 | __ret |= _FP_ROUND_MINF(wc,X); \ | ||
73 | break; \ | ||
74 | }; \ | ||
75 | __ret; \ | ||
76 | }) | ||
77 | |||
78 | #define FP_CLS_NORMAL 0 | ||
79 | #define FP_CLS_ZERO 1 | ||
80 | #define FP_CLS_INF 2 | ||
81 | #define FP_CLS_NAN 3 | ||
82 | |||
83 | #define _FP_CLS_COMBINE(x,y) (((x) << 2) | (y)) | ||
84 | |||
85 | #include "op-1.h" | ||
86 | #include "op-2.h" | ||
87 | #include "op-4.h" | ||
88 | #include "op-common.h" | ||
89 | |||
90 | /* Sigh. Silly things longlong.h needs. */ | ||
91 | #define UWtype _FP_W_TYPE | ||
92 | #define W_TYPE_SIZE _FP_W_TYPE_SIZE | ||
93 | |||
94 | typedef int SItype __attribute__((mode(SI))); | ||
95 | typedef int DItype __attribute__((mode(DI))); | ||
96 | typedef unsigned int USItype __attribute__((mode(SI))); | ||
97 | typedef unsigned int UDItype __attribute__((mode(DI))); | ||
98 | #if _FP_W_TYPE_SIZE == 32 | ||
99 | typedef unsigned int UHWtype __attribute__((mode(HI))); | ||
100 | #elif _FP_W_TYPE_SIZE == 64 | ||
101 | typedef USItype UHWtype; | ||
102 | #endif | ||
103 | |||
104 | #endif | ||
diff --git a/arch/powerpc/math-emu/stfd.c b/arch/powerpc/math-emu/stfd.c new file mode 100644 index 000000000000..3f8c2558a9e8 --- /dev/null +++ b/arch/powerpc/math-emu/stfd.c | |||
@@ -0,0 +1,20 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | int | ||
6 | stfd(void *frS, void *ea) | ||
7 | { | ||
8 | #if 0 | ||
9 | #ifdef DEBUG | ||
10 | printk("%s: S %p, ea %p: ", __FUNCTION__, frS, ea); | ||
11 | dump_double(frS); | ||
12 | printk("\n"); | ||
13 | #endif | ||
14 | #endif | ||
15 | |||
16 | if (copy_to_user(ea, frS, sizeof(double))) | ||
17 | return -EFAULT; | ||
18 | |||
19 | return 0; | ||
20 | } | ||
diff --git a/arch/powerpc/math-emu/stfiwx.c b/arch/powerpc/math-emu/stfiwx.c new file mode 100644 index 000000000000..95caaeec6a08 --- /dev/null +++ b/arch/powerpc/math-emu/stfiwx.c | |||
@@ -0,0 +1,16 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | int | ||
6 | stfiwx(u32 *frS, void *ea) | ||
7 | { | ||
8 | #ifdef DEBUG | ||
9 | printk("%s: %p %p\n", __FUNCTION__, frS, ea); | ||
10 | #endif | ||
11 | |||
12 | if (copy_to_user(ea, &frS[1], sizeof(frS[1]))) | ||
13 | return -EFAULT; | ||
14 | |||
15 | return 0; | ||
16 | } | ||
diff --git a/arch/powerpc/math-emu/stfs.c b/arch/powerpc/math-emu/stfs.c new file mode 100644 index 000000000000..e87ca23c6dc3 --- /dev/null +++ b/arch/powerpc/math-emu/stfs.c | |||
@@ -0,0 +1,41 @@ | |||
1 | #include <linux/types.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <asm/uaccess.h> | ||
4 | |||
5 | #include "soft-fp.h" | ||
6 | #include "double.h" | ||
7 | #include "single.h" | ||
8 | |||
9 | int | ||
10 | stfs(void *frS, void *ea) | ||
11 | { | ||
12 | FP_DECL_D(A); | ||
13 | FP_DECL_S(R); | ||
14 | float f; | ||
15 | int err; | ||
16 | |||
17 | #ifdef DEBUG | ||
18 | printk("%s: S %p, ea %p\n", __FUNCTION__, frS, ea); | ||
19 | #endif | ||
20 | |||
21 | __FP_UNPACK_D(A, frS); | ||
22 | |||
23 | #ifdef DEBUG | ||
24 | printk("A: %ld %lu %lu %ld (%ld)\n", A_s, A_f1, A_f0, A_e, A_c); | ||
25 | #endif | ||
26 | |||
27 | FP_CONV(S, D, 1, 2, R, A); | ||
28 | |||
29 | #ifdef DEBUG | ||
30 | printk("R: %ld %lu %ld (%ld)\n", R_s, R_f, R_e, R_c); | ||
31 | #endif | ||
32 | |||
33 | err = _FP_PACK_CANONICAL(S, 1, R); | ||
34 | if (!err || !__FPU_TRAP_P(err)) { | ||
35 | __FP_PACK_RAW_1(S, &f, R); | ||
36 | if (copy_to_user(ea, &f, sizeof(float))) | ||
37 | return -EFAULT; | ||
38 | } | ||
39 | |||
40 | return err; | ||
41 | } | ||
diff --git a/arch/powerpc/math-emu/types.c b/arch/powerpc/math-emu/types.c new file mode 100644 index 000000000000..e1ed15d829db --- /dev/null +++ b/arch/powerpc/math-emu/types.c | |||
@@ -0,0 +1,51 @@ | |||
1 | #include "soft-fp.h" | ||
2 | #include "double.h" | ||
3 | #include "single.h" | ||
4 | |||
5 | void | ||
6 | fp_unpack_d(long *_s, unsigned long *_f1, unsigned long *_f0, | ||
7 | long *_e, long *_c, void *val) | ||
8 | { | ||
9 | FP_DECL_D(X); | ||
10 | |||
11 | __FP_UNPACK_RAW_2(D, X, val); | ||
12 | |||
13 | _FP_UNPACK_CANONICAL(D, 2, X); | ||
14 | |||
15 | *_s = X_s; | ||
16 | *_f1 = X_f1; | ||
17 | *_f0 = X_f0; | ||
18 | *_e = X_e; | ||
19 | *_c = X_c; | ||
20 | } | ||
21 | |||
22 | int | ||
23 | fp_pack_d(void *val, long X_s, unsigned long X_f1, | ||
24 | unsigned long X_f0, long X_e, long X_c) | ||
25 | { | ||
26 | int exc; | ||
27 | |||
28 | exc = _FP_PACK_CANONICAL(D, 2, X); | ||
29 | if (!exc || !__FPU_TRAP_P(exc)) | ||
30 | __FP_PACK_RAW_2(D, val, X); | ||
31 | return exc; | ||
32 | } | ||
33 | |||
34 | int | ||
35 | fp_pack_ds(void *val, long X_s, unsigned long X_f1, | ||
36 | unsigned long X_f0, long X_e, long X_c) | ||
37 | { | ||
38 | FP_DECL_S(__X); | ||
39 | int exc; | ||
40 | |||
41 | FP_CONV(S, D, 1, 2, __X, X); | ||
42 | exc = _FP_PACK_CANONICAL(S, 1, __X); | ||
43 | if (!exc || !__FPU_TRAP_P(exc)) { | ||
44 | _FP_UNPACK_CANONICAL(S, 1, __X); | ||
45 | FP_CONV(D, S, 2, 1, X, __X); | ||
46 | exc |= _FP_PACK_CANONICAL(D, 2, X); | ||
47 | if (!exc || !__FPU_TRAP_P(exc)) | ||
48 | __FP_PACK_RAW_2(D, val, X); | ||
49 | } | ||
50 | return exc; | ||
51 | } | ||
diff --git a/arch/powerpc/math-emu/udivmodti4.c b/arch/powerpc/math-emu/udivmodti4.c new file mode 100644 index 000000000000..7e112dc1e2f2 --- /dev/null +++ b/arch/powerpc/math-emu/udivmodti4.c | |||
@@ -0,0 +1,191 @@ | |||
1 | /* This has so very few changes over libgcc2's __udivmoddi4 it isn't funny. */ | ||
2 | |||
3 | #include "soft-fp.h" | ||
4 | |||
5 | #undef count_leading_zeros | ||
6 | #define count_leading_zeros __FP_CLZ | ||
7 | |||
8 | void | ||
9 | _fp_udivmodti4(_FP_W_TYPE q[2], _FP_W_TYPE r[2], | ||
10 | _FP_W_TYPE n1, _FP_W_TYPE n0, | ||
11 | _FP_W_TYPE d1, _FP_W_TYPE d0) | ||
12 | { | ||
13 | _FP_W_TYPE q0, q1, r0, r1; | ||
14 | _FP_I_TYPE b, bm; | ||
15 | |||
16 | if (d1 == 0) | ||
17 | { | ||
18 | #if !UDIV_NEEDS_NORMALIZATION | ||
19 | if (d0 > n1) | ||
20 | { | ||
21 | /* 0q = nn / 0D */ | ||
22 | |||
23 | udiv_qrnnd (q0, n0, n1, n0, d0); | ||
24 | q1 = 0; | ||
25 | |||
26 | /* Remainder in n0. */ | ||
27 | } | ||
28 | else | ||
29 | { | ||
30 | /* qq = NN / 0d */ | ||
31 | |||
32 | if (d0 == 0) | ||
33 | d0 = 1 / d0; /* Divide intentionally by zero. */ | ||
34 | |||
35 | udiv_qrnnd (q1, n1, 0, n1, d0); | ||
36 | udiv_qrnnd (q0, n0, n1, n0, d0); | ||
37 | |||
38 | /* Remainder in n0. */ | ||
39 | } | ||
40 | |||
41 | r0 = n0; | ||
42 | r1 = 0; | ||
43 | |||
44 | #else /* UDIV_NEEDS_NORMALIZATION */ | ||
45 | |||
46 | if (d0 > n1) | ||
47 | { | ||
48 | /* 0q = nn / 0D */ | ||
49 | |||
50 | count_leading_zeros (bm, d0); | ||
51 | |||
52 | if (bm != 0) | ||
53 | { | ||
54 | /* Normalize, i.e. make the most significant bit of the | ||
55 | denominator set. */ | ||
56 | |||
57 | d0 = d0 << bm; | ||
58 | n1 = (n1 << bm) | (n0 >> (_FP_W_TYPE_SIZE - bm)); | ||
59 | n0 = n0 << bm; | ||
60 | } | ||
61 | |||
62 | udiv_qrnnd (q0, n0, n1, n0, d0); | ||
63 | q1 = 0; | ||
64 | |||
65 | /* Remainder in n0 >> bm. */ | ||
66 | } | ||
67 | else | ||
68 | { | ||
69 | /* qq = NN / 0d */ | ||
70 | |||
71 | if (d0 == 0) | ||
72 | d0 = 1 / d0; /* Divide intentionally by zero. */ | ||
73 | |||
74 | count_leading_zeros (bm, d0); | ||
75 | |||
76 | if (bm == 0) | ||
77 | { | ||
78 | /* From (n1 >= d0) /\ (the most significant bit of d0 is set), | ||
79 | conclude (the most significant bit of n1 is set) /\ (the | ||
80 | leading quotient digit q1 = 1). | ||
81 | |||
82 | This special case is necessary, not an optimization. | ||
83 | (Shifts counts of SI_TYPE_SIZE are undefined.) */ | ||
84 | |||
85 | n1 -= d0; | ||
86 | q1 = 1; | ||
87 | } | ||
88 | else | ||
89 | { | ||
90 | _FP_W_TYPE n2; | ||
91 | |||
92 | /* Normalize. */ | ||
93 | |||
94 | b = _FP_W_TYPE_SIZE - bm; | ||
95 | |||
96 | d0 = d0 << bm; | ||
97 | n2 = n1 >> b; | ||
98 | n1 = (n1 << bm) | (n0 >> b); | ||
99 | n0 = n0 << bm; | ||
100 | |||
101 | udiv_qrnnd (q1, n1, n2, n1, d0); | ||
102 | } | ||
103 | |||
104 | /* n1 != d0... */ | ||
105 | |||
106 | udiv_qrnnd (q0, n0, n1, n0, d0); | ||
107 | |||
108 | /* Remainder in n0 >> bm. */ | ||
109 | } | ||
110 | |||
111 | r0 = n0 >> bm; | ||
112 | r1 = 0; | ||
113 | #endif /* UDIV_NEEDS_NORMALIZATION */ | ||
114 | } | ||
115 | else | ||
116 | { | ||
117 | if (d1 > n1) | ||
118 | { | ||
119 | /* 00 = nn / DD */ | ||
120 | |||
121 | q0 = 0; | ||
122 | q1 = 0; | ||
123 | |||
124 | /* Remainder in n1n0. */ | ||
125 | r0 = n0; | ||
126 | r1 = n1; | ||
127 | } | ||
128 | else | ||
129 | { | ||
130 | /* 0q = NN / dd */ | ||
131 | |||
132 | count_leading_zeros (bm, d1); | ||
133 | if (bm == 0) | ||
134 | { | ||
135 | /* From (n1 >= d1) /\ (the most significant bit of d1 is set), | ||
136 | conclude (the most significant bit of n1 is set) /\ (the | ||
137 | quotient digit q0 = 0 or 1). | ||
138 | |||
139 | This special case is necessary, not an optimization. */ | ||
140 | |||
141 | /* The condition on the next line takes advantage of that | ||
142 | n1 >= d1 (true due to program flow). */ | ||
143 | if (n1 > d1 || n0 >= d0) | ||
144 | { | ||
145 | q0 = 1; | ||
146 | sub_ddmmss (n1, n0, n1, n0, d1, d0); | ||
147 | } | ||
148 | else | ||
149 | q0 = 0; | ||
150 | |||
151 | q1 = 0; | ||
152 | |||
153 | r0 = n0; | ||
154 | r1 = n1; | ||
155 | } | ||
156 | else | ||
157 | { | ||
158 | _FP_W_TYPE m1, m0, n2; | ||
159 | |||
160 | /* Normalize. */ | ||
161 | |||
162 | b = _FP_W_TYPE_SIZE - bm; | ||
163 | |||
164 | d1 = (d1 << bm) | (d0 >> b); | ||
165 | d0 = d0 << bm; | ||
166 | n2 = n1 >> b; | ||
167 | n1 = (n1 << bm) | (n0 >> b); | ||
168 | n0 = n0 << bm; | ||
169 | |||
170 | udiv_qrnnd (q0, n1, n2, n1, d1); | ||
171 | umul_ppmm (m1, m0, q0, d0); | ||
172 | |||
173 | if (m1 > n1 || (m1 == n1 && m0 > n0)) | ||
174 | { | ||
175 | q0--; | ||
176 | sub_ddmmss (m1, m0, m1, m0, d1, d0); | ||
177 | } | ||
178 | |||
179 | q1 = 0; | ||
180 | |||
181 | /* Remainder in (n1n0 - m1m0) >> bm. */ | ||
182 | sub_ddmmss (n1, n0, n1, n0, m1, m0); | ||
183 | r0 = (n1 << b) | (n0 >> bm); | ||
184 | r1 = n1 >> bm; | ||
185 | } | ||
186 | } | ||
187 | } | ||
188 | |||
189 | q[0] = q0; q[1] = q1; | ||
190 | r[0] = r0, r[1] = r1; | ||
191 | } | ||
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index a4815d316722..5aea0909a5ec 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/mm/fault.c | ||
3 | * | ||
4 | * PowerPC version | 2 | * PowerPC version |
5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 3 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) |
6 | * | 4 | * |
@@ -269,25 +267,29 @@ good_area: | |||
269 | #endif | 267 | #endif |
270 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) | 268 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) |
271 | pte_t *ptep; | 269 | pte_t *ptep; |
270 | pmd_t *pmdp; | ||
272 | 271 | ||
273 | /* Since 4xx/Book-E supports per-page execute permission, | 272 | /* Since 4xx/Book-E supports per-page execute permission, |
274 | * we lazily flush dcache to icache. */ | 273 | * we lazily flush dcache to icache. */ |
275 | ptep = NULL; | 274 | ptep = NULL; |
276 | if (get_pteptr(mm, address, &ptep) && pte_present(*ptep)) { | 275 | if (get_pteptr(mm, address, &ptep, &pmdp)) { |
277 | struct page *page = pte_page(*ptep); | 276 | spinlock_t *ptl = pte_lockptr(mm, pmdp); |
278 | 277 | spin_lock(ptl); | |
279 | if (! test_bit(PG_arch_1, &page->flags)) { | 278 | if (pte_present(*ptep)) { |
280 | flush_dcache_icache_page(page); | 279 | struct page *page = pte_page(*ptep); |
281 | set_bit(PG_arch_1, &page->flags); | 280 | |
281 | if (!test_bit(PG_arch_1, &page->flags)) { | ||
282 | flush_dcache_icache_page(page); | ||
283 | set_bit(PG_arch_1, &page->flags); | ||
284 | } | ||
285 | pte_update(ptep, 0, _PAGE_HWEXEC); | ||
286 | _tlbie(address); | ||
287 | pte_unmap_unlock(ptep, ptl); | ||
288 | up_read(&mm->mmap_sem); | ||
289 | return 0; | ||
282 | } | 290 | } |
283 | pte_update(ptep, 0, _PAGE_HWEXEC); | 291 | pte_unmap_unlock(ptep, ptl); |
284 | _tlbie(address); | ||
285 | pte_unmap(ptep); | ||
286 | up_read(&mm->mmap_sem); | ||
287 | return 0; | ||
288 | } | 292 | } |
289 | if (ptep != NULL) | ||
290 | pte_unmap(ptep); | ||
291 | #endif | 293 | #endif |
292 | /* a write */ | 294 | /* a write */ |
293 | } else if (is_write) { | 295 | } else if (is_write) { |
diff --git a/arch/powerpc/mm/hash_low_32.S b/arch/powerpc/mm/hash_low_32.S index 12ccd7155bac..ea469eefa146 100644 --- a/arch/powerpc/mm/hash_low_32.S +++ b/arch/powerpc/mm/hash_low_32.S | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/kernel/hashtable.S | ||
3 | * | ||
4 | * $Id: hashtable.S,v 1.6 1999/10/08 01:56:15 paulus Exp $ | 2 | * $Id: hashtable.S,v 1.6 1999/10/08 01:56:15 paulus Exp $ |
5 | * | 3 | * |
6 | * PowerPC version | 4 | * PowerPC version |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index e9d589eefc14..c006d9039633 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -167,18 +167,18 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | |||
167 | * normal insert callback here. | 167 | * normal insert callback here. |
168 | */ | 168 | */ |
169 | #ifdef CONFIG_PPC_ISERIES | 169 | #ifdef CONFIG_PPC_ISERIES |
170 | if (_machine == PLATFORM_ISERIES_LPAR) | 170 | if (machine_is(iseries)) |
171 | ret = iSeries_hpte_insert(hpteg, va, | 171 | ret = iSeries_hpte_insert(hpteg, va, |
172 | __pa(vaddr), | 172 | paddr, |
173 | tmp_mode, | 173 | tmp_mode, |
174 | HPTE_V_BOLTED, | 174 | HPTE_V_BOLTED, |
175 | psize); | 175 | psize); |
176 | else | 176 | else |
177 | #endif | 177 | #endif |
178 | #ifdef CONFIG_PPC_PSERIES | 178 | #ifdef CONFIG_PPC_PSERIES |
179 | if (_machine & PLATFORM_LPAR) | 179 | if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR)) |
180 | ret = pSeries_lpar_hpte_insert(hpteg, va, | 180 | ret = pSeries_lpar_hpte_insert(hpteg, va, |
181 | virt_to_abs(paddr), | 181 | paddr, |
182 | tmp_mode, | 182 | tmp_mode, |
183 | HPTE_V_BOLTED, | 183 | HPTE_V_BOLTED, |
184 | psize); | 184 | psize); |
@@ -186,7 +186,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | |||
186 | #endif | 186 | #endif |
187 | #ifdef CONFIG_PPC_MULTIPLATFORM | 187 | #ifdef CONFIG_PPC_MULTIPLATFORM |
188 | ret = native_hpte_insert(hpteg, va, | 188 | ret = native_hpte_insert(hpteg, va, |
189 | virt_to_abs(paddr), | 189 | paddr, |
190 | tmp_mode, HPTE_V_BOLTED, | 190 | tmp_mode, HPTE_V_BOLTED, |
191 | psize); | 191 | psize); |
192 | #endif | 192 | #endif |
@@ -295,8 +295,7 @@ static void __init htab_init_page_sizes(void) | |||
295 | * Not in the device-tree, let's fallback on known size | 295 | * Not in the device-tree, let's fallback on known size |
296 | * list for 16M capable GP & GR | 296 | * list for 16M capable GP & GR |
297 | */ | 297 | */ |
298 | if ((_machine != PLATFORM_ISERIES_LPAR) && | 298 | if (cpu_has_feature(CPU_FTR_16M_PAGE) && !machine_is(iseries)) |
299 | cpu_has_feature(CPU_FTR_16M_PAGE)) | ||
300 | memcpy(mmu_psize_defs, mmu_psize_defaults_gp, | 299 | memcpy(mmu_psize_defs, mmu_psize_defaults_gp, |
301 | sizeof(mmu_psize_defaults_gp)); | 300 | sizeof(mmu_psize_defaults_gp)); |
302 | found: | 301 | found: |
@@ -392,7 +391,7 @@ static unsigned long __init htab_get_table_size(void) | |||
392 | #ifdef CONFIG_MEMORY_HOTPLUG | 391 | #ifdef CONFIG_MEMORY_HOTPLUG |
393 | void create_section_mapping(unsigned long start, unsigned long end) | 392 | void create_section_mapping(unsigned long start, unsigned long end) |
394 | { | 393 | { |
395 | BUG_ON(htab_bolt_mapping(start, end, start, | 394 | BUG_ON(htab_bolt_mapping(start, end, __pa(start), |
396 | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX, | 395 | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX, |
397 | mmu_linear_psize)); | 396 | mmu_linear_psize)); |
398 | } | 397 | } |
@@ -422,7 +421,7 @@ void __init htab_initialize(void) | |||
422 | 421 | ||
423 | htab_hash_mask = pteg_count - 1; | 422 | htab_hash_mask = pteg_count - 1; |
424 | 423 | ||
425 | if (platform_is_lpar()) { | 424 | if (firmware_has_feature(FW_FEATURE_LPAR)) { |
426 | /* Using a hypervisor which owns the htab */ | 425 | /* Using a hypervisor which owns the htab */ |
427 | htab_address = NULL; | 426 | htab_address = NULL; |
428 | _SDR1 = 0; | 427 | _SDR1 = 0; |
@@ -431,7 +430,6 @@ void __init htab_initialize(void) | |||
431 | * the absolute address space. | 430 | * the absolute address space. |
432 | */ | 431 | */ |
433 | table = lmb_alloc(htab_size_bytes, htab_size_bytes); | 432 | table = lmb_alloc(htab_size_bytes, htab_size_bytes); |
434 | BUG_ON(table == 0); | ||
435 | 433 | ||
436 | DBG("Hash table allocated at %lx, size: %lx\n", table, | 434 | DBG("Hash table allocated at %lx, size: %lx\n", table, |
437 | htab_size_bytes); | 435 | htab_size_bytes); |
@@ -474,21 +472,22 @@ void __init htab_initialize(void) | |||
474 | 472 | ||
475 | if (dart_tablebase != 0 && dart_tablebase >= base | 473 | if (dart_tablebase != 0 && dart_tablebase >= base |
476 | && dart_tablebase < (base + size)) { | 474 | && dart_tablebase < (base + size)) { |
475 | unsigned long dart_table_end = dart_tablebase + 16 * MB; | ||
477 | if (base != dart_tablebase) | 476 | if (base != dart_tablebase) |
478 | BUG_ON(htab_bolt_mapping(base, dart_tablebase, | 477 | BUG_ON(htab_bolt_mapping(base, dart_tablebase, |
479 | base, mode_rw, | 478 | __pa(base), mode_rw, |
480 | mmu_linear_psize)); | 479 | mmu_linear_psize)); |
481 | if ((base + size) > (dart_tablebase + 16*MB)) | 480 | if ((base + size) > dart_table_end) |
482 | BUG_ON(htab_bolt_mapping(dart_tablebase+16*MB, | 481 | BUG_ON(htab_bolt_mapping(dart_tablebase+16*MB, |
483 | base + size, | 482 | base + size, |
484 | dart_tablebase+16*MB, | 483 | __pa(dart_table_end), |
485 | mode_rw, | 484 | mode_rw, |
486 | mmu_linear_psize)); | 485 | mmu_linear_psize)); |
487 | continue; | 486 | continue; |
488 | } | 487 | } |
489 | #endif /* CONFIG_U3_DART */ | 488 | #endif /* CONFIG_U3_DART */ |
490 | BUG_ON(htab_bolt_mapping(base, base + size, base, | 489 | BUG_ON(htab_bolt_mapping(base, base + size, __pa(base), |
491 | mode_rw, mmu_linear_psize)); | 490 | mode_rw, mmu_linear_psize)); |
492 | } | 491 | } |
493 | 492 | ||
494 | /* | 493 | /* |
@@ -505,8 +504,8 @@ void __init htab_initialize(void) | |||
505 | if (base + size >= tce_alloc_start) | 504 | if (base + size >= tce_alloc_start) |
506 | tce_alloc_start = base + size + 1; | 505 | tce_alloc_start = base + size + 1; |
507 | 506 | ||
508 | BUG_ON(htab_bolt_mapping(tce_alloc_start, tce_alloc_end, | 507 | BUG_ON(htab_bolt_mapping(tce_alloc_start, tce_alloc_end, |
509 | tce_alloc_start, mode_rw, | 508 | __pa(tce_alloc_start), mode_rw, |
510 | mmu_linear_psize)); | 509 | mmu_linear_psize)); |
511 | } | 510 | } |
512 | 511 | ||
@@ -517,7 +516,7 @@ void __init htab_initialize(void) | |||
517 | 516 | ||
518 | void htab_initialize_secondary(void) | 517 | void htab_initialize_secondary(void) |
519 | { | 518 | { |
520 | if (!platform_is_lpar()) | 519 | if (!firmware_has_feature(FW_FEATURE_LPAR)) |
521 | mtspr(SPRN_SDR1, _SDR1); | 520 | mtspr(SPRN_SDR1, _SDR1); |
522 | } | 521 | } |
523 | 522 | ||
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index b51bb28c054b..7370f9f33e29 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
@@ -133,21 +133,6 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | |||
133 | return __pte(old); | 133 | return __pte(old); |
134 | } | 134 | } |
135 | 135 | ||
136 | /* | ||
137 | * This function checks for proper alignment of input addr and len parameters. | ||
138 | */ | ||
139 | int is_aligned_hugepage_range(unsigned long addr, unsigned long len) | ||
140 | { | ||
141 | if (len & ~HPAGE_MASK) | ||
142 | return -EINVAL; | ||
143 | if (addr & ~HPAGE_MASK) | ||
144 | return -EINVAL; | ||
145 | if (! (within_hugepage_low_range(addr, len) | ||
146 | || within_hugepage_high_range(addr, len)) ) | ||
147 | return -EINVAL; | ||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | struct slb_flush_info { | 136 | struct slb_flush_info { |
152 | struct mm_struct *mm; | 137 | struct mm_struct *mm; |
153 | u16 newareas; | 138 | u16 newareas; |
diff --git a/arch/powerpc/mm/imalloc.c b/arch/powerpc/mm/imalloc.c index 8b0c132bc163..add8c1a9af68 100644 --- a/arch/powerpc/mm/imalloc.c +++ b/arch/powerpc/mm/imalloc.c | |||
@@ -13,12 +13,12 @@ | |||
13 | #include <asm/uaccess.h> | 13 | #include <asm/uaccess.h> |
14 | #include <asm/pgalloc.h> | 14 | #include <asm/pgalloc.h> |
15 | #include <asm/pgtable.h> | 15 | #include <asm/pgtable.h> |
16 | #include <asm/semaphore.h> | 16 | #include <linux/mutex.h> |
17 | #include <asm/cacheflush.h> | 17 | #include <asm/cacheflush.h> |
18 | 18 | ||
19 | #include "mmu_decl.h" | 19 | #include "mmu_decl.h" |
20 | 20 | ||
21 | static DECLARE_MUTEX(imlist_sem); | 21 | static DEFINE_MUTEX(imlist_mutex); |
22 | struct vm_struct * imlist = NULL; | 22 | struct vm_struct * imlist = NULL; |
23 | 23 | ||
24 | static int get_free_im_addr(unsigned long size, unsigned long *im_addr) | 24 | static int get_free_im_addr(unsigned long size, unsigned long *im_addr) |
@@ -257,7 +257,7 @@ struct vm_struct * im_get_free_area(unsigned long size) | |||
257 | struct vm_struct *area; | 257 | struct vm_struct *area; |
258 | unsigned long addr; | 258 | unsigned long addr; |
259 | 259 | ||
260 | down(&imlist_sem); | 260 | mutex_lock(&imlist_mutex); |
261 | if (get_free_im_addr(size, &addr)) { | 261 | if (get_free_im_addr(size, &addr)) { |
262 | printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n", | 262 | printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n", |
263 | __FUNCTION__, size); | 263 | __FUNCTION__, size); |
@@ -272,7 +272,7 @@ struct vm_struct * im_get_free_area(unsigned long size) | |||
272 | __FUNCTION__, addr, size); | 272 | __FUNCTION__, addr, size); |
273 | } | 273 | } |
274 | next_im_done: | 274 | next_im_done: |
275 | up(&imlist_sem); | 275 | mutex_unlock(&imlist_mutex); |
276 | return area; | 276 | return area; |
277 | } | 277 | } |
278 | 278 | ||
@@ -281,9 +281,9 @@ struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, | |||
281 | { | 281 | { |
282 | struct vm_struct *area; | 282 | struct vm_struct *area; |
283 | 283 | ||
284 | down(&imlist_sem); | 284 | mutex_lock(&imlist_mutex); |
285 | area = __im_get_area(v_addr, size, criteria); | 285 | area = __im_get_area(v_addr, size, criteria); |
286 | up(&imlist_sem); | 286 | mutex_unlock(&imlist_mutex); |
287 | return area; | 287 | return area; |
288 | } | 288 | } |
289 | 289 | ||
@@ -297,17 +297,17 @@ void im_free(void * addr) | |||
297 | printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr); | 297 | printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr); |
298 | return; | 298 | return; |
299 | } | 299 | } |
300 | down(&imlist_sem); | 300 | mutex_lock(&imlist_mutex); |
301 | for (p = &imlist ; (tmp = *p) ; p = &tmp->next) { | 301 | for (p = &imlist ; (tmp = *p) ; p = &tmp->next) { |
302 | if (tmp->addr == addr) { | 302 | if (tmp->addr == addr) { |
303 | *p = tmp->next; | 303 | *p = tmp->next; |
304 | unmap_vm_area(tmp); | 304 | unmap_vm_area(tmp); |
305 | kfree(tmp); | 305 | kfree(tmp); |
306 | up(&imlist_sem); | 306 | mutex_unlock(&imlist_mutex); |
307 | return; | 307 | return; |
308 | } | 308 | } |
309 | } | 309 | } |
310 | up(&imlist_sem); | 310 | mutex_unlock(&imlist_mutex); |
311 | printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__, | 311 | printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__, |
312 | addr); | 312 | addr); |
313 | } | 313 | } |
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 7d0d75c11848..b57fb3a2b7bb 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c | |||
@@ -216,7 +216,7 @@ static void free_sec(unsigned long start, unsigned long end, const char *name) | |||
216 | 216 | ||
217 | while (start < end) { | 217 | while (start < end) { |
218 | ClearPageReserved(virt_to_page(start)); | 218 | ClearPageReserved(virt_to_page(start)); |
219 | set_page_count(virt_to_page(start), 1); | 219 | init_page_count(virt_to_page(start)); |
220 | free_page(start); | 220 | free_page(start); |
221 | cnt++; | 221 | cnt++; |
222 | start += PAGE_SIZE; | 222 | start += PAGE_SIZE; |
@@ -248,7 +248,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) | |||
248 | printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); | 248 | printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); |
249 | for (; start < end; start += PAGE_SIZE) { | 249 | for (; start < end; start += PAGE_SIZE) { |
250 | ClearPageReserved(virt_to_page(start)); | 250 | ClearPageReserved(virt_to_page(start)); |
251 | set_page_count(virt_to_page(start), 1); | 251 | init_page_count(virt_to_page(start)); |
252 | free_page(start); | 252 | free_page(start); |
253 | totalram_pages++; | 253 | totalram_pages++; |
254 | } | 254 | } |
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 81cfb0c2ec58..babebd15bdc4 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
@@ -84,54 +84,6 @@ | |||
84 | /* max amount of RAM to use */ | 84 | /* max amount of RAM to use */ |
85 | unsigned long __max_memory; | 85 | unsigned long __max_memory; |
86 | 86 | ||
87 | /* info on what we think the IO hole is */ | ||
88 | unsigned long io_hole_start; | ||
89 | unsigned long io_hole_size; | ||
90 | |||
91 | /* | ||
92 | * Do very early mm setup. | ||
93 | */ | ||
94 | void __init mm_init_ppc64(void) | ||
95 | { | ||
96 | #ifndef CONFIG_PPC_ISERIES | ||
97 | unsigned long i; | ||
98 | #endif | ||
99 | |||
100 | ppc64_boot_msg(0x100, "MM Init"); | ||
101 | |||
102 | /* This is the story of the IO hole... please, keep seated, | ||
103 | * unfortunately, we are out of oxygen masks at the moment. | ||
104 | * So we need some rough way to tell where your big IO hole | ||
105 | * is. On pmac, it's between 2G and 4G, on POWER3, it's around | ||
106 | * that area as well, on POWER4 we don't have one, etc... | ||
107 | * We need that as a "hint" when sizing the TCE table on POWER3 | ||
108 | * So far, the simplest way that seem work well enough for us it | ||
109 | * to just assume that the first discontinuity in our physical | ||
110 | * RAM layout is the IO hole. That may not be correct in the future | ||
111 | * (and isn't on iSeries but then we don't care ;) | ||
112 | */ | ||
113 | |||
114 | #ifndef CONFIG_PPC_ISERIES | ||
115 | for (i = 1; i < lmb.memory.cnt; i++) { | ||
116 | unsigned long base, prevbase, prevsize; | ||
117 | |||
118 | prevbase = lmb.memory.region[i-1].base; | ||
119 | prevsize = lmb.memory.region[i-1].size; | ||
120 | base = lmb.memory.region[i].base; | ||
121 | if (base > (prevbase + prevsize)) { | ||
122 | io_hole_start = prevbase + prevsize; | ||
123 | io_hole_size = base - (prevbase + prevsize); | ||
124 | break; | ||
125 | } | ||
126 | } | ||
127 | #endif /* CONFIG_PPC_ISERIES */ | ||
128 | if (io_hole_start) | ||
129 | printk("IO Hole assumed to be %lx -> %lx\n", | ||
130 | io_hole_start, io_hole_start + io_hole_size - 1); | ||
131 | |||
132 | ppc64_boot_msg(0x100, "MM Init Done"); | ||
133 | } | ||
134 | |||
135 | void free_initmem(void) | 87 | void free_initmem(void) |
136 | { | 88 | { |
137 | unsigned long addr; | 89 | unsigned long addr; |
@@ -140,7 +92,7 @@ void free_initmem(void) | |||
140 | for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) { | 92 | for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) { |
141 | memset((void *)addr, 0xcc, PAGE_SIZE); | 93 | memset((void *)addr, 0xcc, PAGE_SIZE); |
142 | ClearPageReserved(virt_to_page(addr)); | 94 | ClearPageReserved(virt_to_page(addr)); |
143 | set_page_count(virt_to_page(addr), 1); | 95 | init_page_count(virt_to_page(addr)); |
144 | free_page(addr); | 96 | free_page(addr); |
145 | totalram_pages++; | 97 | totalram_pages++; |
146 | } | 98 | } |
@@ -155,7 +107,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) | |||
155 | printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); | 107 | printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); |
156 | for (; start < end; start += PAGE_SIZE) { | 108 | for (; start < end; start += PAGE_SIZE) { |
157 | ClearPageReserved(virt_to_page(start)); | 109 | ClearPageReserved(virt_to_page(start)); |
158 | set_page_count(virt_to_page(start), 1); | 110 | init_page_count(virt_to_page(start)); |
159 | free_page(start); | 111 | free_page(start); |
160 | totalram_pages++; | 112 | totalram_pages++; |
161 | } | 113 | } |
diff --git a/arch/powerpc/mm/lmb.c b/arch/powerpc/mm/lmb.c index bbe3eac918e8..417d58518558 100644 --- a/arch/powerpc/mm/lmb.c +++ b/arch/powerpc/mm/lmb.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #define DBG(fmt...) | 31 | #define DBG(fmt...) |
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | #define LMB_ALLOC_ANYWHERE 0 | ||
35 | |||
34 | struct lmb lmb; | 36 | struct lmb lmb; |
35 | 37 | ||
36 | void lmb_dump_all(void) | 38 | void lmb_dump_all(void) |
@@ -226,6 +228,20 @@ unsigned long __init lmb_alloc(unsigned long size, unsigned long align) | |||
226 | unsigned long __init lmb_alloc_base(unsigned long size, unsigned long align, | 228 | unsigned long __init lmb_alloc_base(unsigned long size, unsigned long align, |
227 | unsigned long max_addr) | 229 | unsigned long max_addr) |
228 | { | 230 | { |
231 | unsigned long alloc; | ||
232 | |||
233 | alloc = __lmb_alloc_base(size, align, max_addr); | ||
234 | |||
235 | if (alloc == 0) | ||
236 | panic("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n", | ||
237 | size, max_addr); | ||
238 | |||
239 | return alloc; | ||
240 | } | ||
241 | |||
242 | unsigned long __init __lmb_alloc_base(unsigned long size, unsigned long align, | ||
243 | unsigned long max_addr) | ||
244 | { | ||
229 | long i, j; | 245 | long i, j; |
230 | unsigned long base = 0; | 246 | unsigned long base = 0; |
231 | 247 | ||
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 550517c2dd42..741dd8802d49 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -108,8 +108,8 @@ EXPORT_SYMBOL(phys_mem_access_prot); | |||
108 | void online_page(struct page *page) | 108 | void online_page(struct page *page) |
109 | { | 109 | { |
110 | ClearPageReserved(page); | 110 | ClearPageReserved(page); |
111 | set_page_count(page, 0); | 111 | init_page_count(page); |
112 | free_cold_page(page); | 112 | __free_page(page); |
113 | totalram_pages++; | 113 | totalram_pages++; |
114 | num_physpages++; | 114 | num_physpages++; |
115 | } | 115 | } |
@@ -125,7 +125,7 @@ int __devinit add_memory(u64 start, u64 size) | |||
125 | nid = hot_add_scn_to_nid(start); | 125 | nid = hot_add_scn_to_nid(start); |
126 | pgdata = NODE_DATA(nid); | 126 | pgdata = NODE_DATA(nid); |
127 | 127 | ||
128 | start = __va(start); | 128 | start = (unsigned long)__va(start); |
129 | create_section_mapping(start, start + size); | 129 | create_section_mapping(start, start + size); |
130 | 130 | ||
131 | /* this should work for most non-highmem platforms */ | 131 | /* this should work for most non-highmem platforms */ |
@@ -195,7 +195,7 @@ void show_mem(void) | |||
195 | printk("Mem-info:\n"); | 195 | printk("Mem-info:\n"); |
196 | show_free_areas(); | 196 | show_free_areas(); |
197 | printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); | 197 | printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); |
198 | for_each_pgdat(pgdat) { | 198 | for_each_online_pgdat(pgdat) { |
199 | unsigned long flags; | 199 | unsigned long flags; |
200 | pgdat_resize_lock(pgdat, &flags); | 200 | pgdat_resize_lock(pgdat, &flags); |
201 | for (i = 0; i < pgdat->node_spanned_pages; i++) { | 201 | for (i = 0; i < pgdat->node_spanned_pages; i++) { |
@@ -249,7 +249,6 @@ void __init do_init_bootmem(void) | |||
249 | bootmap_pages = bootmem_bootmap_pages(total_pages); | 249 | bootmap_pages = bootmem_bootmap_pages(total_pages); |
250 | 250 | ||
251 | start = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE); | 251 | start = lmb_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE); |
252 | BUG_ON(!start); | ||
253 | 252 | ||
254 | boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages); | 253 | boot_mapsize = init_bootmem(start >> PAGE_SHIFT, total_pages); |
255 | 254 | ||
@@ -343,7 +342,7 @@ void __init mem_init(void) | |||
343 | #ifdef CONFIG_NEED_MULTIPLE_NODES | 342 | #ifdef CONFIG_NEED_MULTIPLE_NODES |
344 | for_each_online_node(nid) { | 343 | for_each_online_node(nid) { |
345 | if (NODE_DATA(nid)->node_spanned_pages != 0) { | 344 | if (NODE_DATA(nid)->node_spanned_pages != 0) { |
346 | printk("freeing bootmem node %x\n", nid); | 345 | printk("freeing bootmem node %d\n", nid); |
347 | totalram_pages += | 346 | totalram_pages += |
348 | free_all_bootmem_node(NODE_DATA(nid)); | 347 | free_all_bootmem_node(NODE_DATA(nid)); |
349 | } | 348 | } |
@@ -352,7 +351,7 @@ void __init mem_init(void) | |||
352 | max_mapnr = max_pfn; | 351 | max_mapnr = max_pfn; |
353 | totalram_pages += free_all_bootmem(); | 352 | totalram_pages += free_all_bootmem(); |
354 | #endif | 353 | #endif |
355 | for_each_pgdat(pgdat) { | 354 | for_each_online_pgdat(pgdat) { |
356 | for (i = 0; i < pgdat->node_spanned_pages; i++) { | 355 | for (i = 0; i < pgdat->node_spanned_pages; i++) { |
357 | if (!pfn_valid(pgdat->node_start_pfn + i)) | 356 | if (!pfn_valid(pgdat->node_start_pfn + i)) |
358 | continue; | 357 | continue; |
@@ -376,7 +375,7 @@ void __init mem_init(void) | |||
376 | struct page *page = pfn_to_page(pfn); | 375 | struct page *page = pfn_to_page(pfn); |
377 | 376 | ||
378 | ClearPageReserved(page); | 377 | ClearPageReserved(page); |
379 | set_page_count(page, 1); | 378 | init_page_count(page); |
380 | __free_page(page); | 379 | __free_page(page); |
381 | totalhigh_pages++; | 380 | totalhigh_pages++; |
382 | } | 381 | } |
diff --git a/arch/powerpc/mm/mmap.c b/arch/powerpc/mm/mmap.c index fe65f522aff3..972a8e884b9a 100644 --- a/arch/powerpc/mm/mmap.c +++ b/arch/powerpc/mm/mmap.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/ppc64/mm/mmap.c | ||
3 | * | ||
4 | * flexible mmap layout support | 2 | * flexible mmap layout support |
5 | * | 3 | * |
6 | * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. | 4 | * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 2863a912bcd0..0a335f34974c 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -129,10 +129,12 @@ void __init get_region(unsigned int nid, unsigned long *start_pfn, | |||
129 | *start_pfn = 0; | 129 | *start_pfn = 0; |
130 | } | 130 | } |
131 | 131 | ||
132 | static inline void map_cpu_to_node(int cpu, int node) | 132 | static void __cpuinit map_cpu_to_node(int cpu, int node) |
133 | { | 133 | { |
134 | numa_cpu_lookup_table[cpu] = node; | 134 | numa_cpu_lookup_table[cpu] = node; |
135 | 135 | ||
136 | dbg("adding cpu %d to node %d\n", cpu, node); | ||
137 | |||
136 | if (!(cpu_isset(cpu, numa_cpumask_lookup_table[node]))) | 138 | if (!(cpu_isset(cpu, numa_cpumask_lookup_table[node]))) |
137 | cpu_set(cpu, numa_cpumask_lookup_table[node]); | 139 | cpu_set(cpu, numa_cpumask_lookup_table[node]); |
138 | } | 140 | } |
@@ -153,7 +155,7 @@ static void unmap_cpu_from_node(unsigned long cpu) | |||
153 | } | 155 | } |
154 | #endif /* CONFIG_HOTPLUG_CPU */ | 156 | #endif /* CONFIG_HOTPLUG_CPU */ |
155 | 157 | ||
156 | static struct device_node *find_cpu_node(unsigned int cpu) | 158 | static struct device_node * __cpuinit find_cpu_node(unsigned int cpu) |
157 | { | 159 | { |
158 | unsigned int hw_cpuid = get_hard_smp_processor_id(cpu); | 160 | unsigned int hw_cpuid = get_hard_smp_processor_id(cpu); |
159 | struct device_node *cpu_node = NULL; | 161 | struct device_node *cpu_node = NULL; |
@@ -189,23 +191,29 @@ static int *of_get_associativity(struct device_node *dev) | |||
189 | return (unsigned int *)get_property(dev, "ibm,associativity", NULL); | 191 | return (unsigned int *)get_property(dev, "ibm,associativity", NULL); |
190 | } | 192 | } |
191 | 193 | ||
192 | static int of_node_numa_domain(struct device_node *device) | 194 | /* Returns nid in the range [0..MAX_NUMNODES-1], or -1 if no useful numa |
195 | * info is found. | ||
196 | */ | ||
197 | static int of_node_to_nid(struct device_node *device) | ||
193 | { | 198 | { |
194 | int numa_domain; | 199 | int nid = -1; |
195 | unsigned int *tmp; | 200 | unsigned int *tmp; |
196 | 201 | ||
197 | if (min_common_depth == -1) | 202 | if (min_common_depth == -1) |
198 | return 0; | 203 | goto out; |
199 | 204 | ||
200 | tmp = of_get_associativity(device); | 205 | tmp = of_get_associativity(device); |
201 | if (tmp && (tmp[0] >= min_common_depth)) { | 206 | if (!tmp) |
202 | numa_domain = tmp[min_common_depth]; | 207 | goto out; |
203 | } else { | 208 | |
204 | dbg("WARNING: no NUMA information for %s\n", | 209 | if (tmp[0] >= min_common_depth) |
205 | device->full_name); | 210 | nid = tmp[min_common_depth]; |
206 | numa_domain = 0; | 211 | |
207 | } | 212 | /* POWER4 LPAR uses 0xffff as invalid node */ |
208 | return numa_domain; | 213 | if (nid == 0xffff || nid >= MAX_NUMNODES) |
214 | nid = -1; | ||
215 | out: | ||
216 | return nid; | ||
209 | } | 217 | } |
210 | 218 | ||
211 | /* | 219 | /* |
@@ -246,8 +254,7 @@ static int __init find_min_common_depth(void) | |||
246 | if ((len >= 1) && ref_points) { | 254 | if ((len >= 1) && ref_points) { |
247 | depth = ref_points[1]; | 255 | depth = ref_points[1]; |
248 | } else { | 256 | } else { |
249 | dbg("WARNING: could not find NUMA " | 257 | dbg("NUMA: ibm,associativity-reference-points not found.\n"); |
250 | "associativity reference point\n"); | ||
251 | depth = -1; | 258 | depth = -1; |
252 | } | 259 | } |
253 | of_node_put(rtas_root); | 260 | of_node_put(rtas_root); |
@@ -283,9 +290,9 @@ static unsigned long __devinit read_n_cells(int n, unsigned int **buf) | |||
283 | * Figure out to which domain a cpu belongs and stick it there. | 290 | * Figure out to which domain a cpu belongs and stick it there. |
284 | * Return the id of the domain used. | 291 | * Return the id of the domain used. |
285 | */ | 292 | */ |
286 | static int numa_setup_cpu(unsigned long lcpu) | 293 | static int __cpuinit numa_setup_cpu(unsigned long lcpu) |
287 | { | 294 | { |
288 | int numa_domain = 0; | 295 | int nid = 0; |
289 | struct device_node *cpu = find_cpu_node(lcpu); | 296 | struct device_node *cpu = find_cpu_node(lcpu); |
290 | 297 | ||
291 | if (!cpu) { | 298 | if (!cpu) { |
@@ -293,27 +300,16 @@ static int numa_setup_cpu(unsigned long lcpu) | |||
293 | goto out; | 300 | goto out; |
294 | } | 301 | } |
295 | 302 | ||
296 | numa_domain = of_node_numa_domain(cpu); | 303 | nid = of_node_to_nid(cpu); |
297 | 304 | ||
298 | if (numa_domain >= num_online_nodes()) { | 305 | if (nid < 0 || !node_online(nid)) |
299 | /* | 306 | nid = any_online_node(NODE_MASK_ALL); |
300 | * POWER4 LPAR uses 0xffff as invalid node, | ||
301 | * dont warn in this case. | ||
302 | */ | ||
303 | if (numa_domain != 0xffff) | ||
304 | printk(KERN_ERR "WARNING: cpu %ld " | ||
305 | "maps to invalid NUMA node %d\n", | ||
306 | lcpu, numa_domain); | ||
307 | numa_domain = 0; | ||
308 | } | ||
309 | out: | 307 | out: |
310 | node_set_online(numa_domain); | 308 | map_cpu_to_node(lcpu, nid); |
311 | |||
312 | map_cpu_to_node(lcpu, numa_domain); | ||
313 | 309 | ||
314 | of_node_put(cpu); | 310 | of_node_put(cpu); |
315 | 311 | ||
316 | return numa_domain; | 312 | return nid; |
317 | } | 313 | } |
318 | 314 | ||
319 | static int cpu_numa_callback(struct notifier_block *nfb, | 315 | static int cpu_numa_callback(struct notifier_block *nfb, |
@@ -325,10 +321,7 @@ static int cpu_numa_callback(struct notifier_block *nfb, | |||
325 | 321 | ||
326 | switch (action) { | 322 | switch (action) { |
327 | case CPU_UP_PREPARE: | 323 | case CPU_UP_PREPARE: |
328 | if (min_common_depth == -1 || !numa_enabled) | 324 | numa_setup_cpu(lcpu); |
329 | map_cpu_to_node(lcpu, 0); | ||
330 | else | ||
331 | numa_setup_cpu(lcpu); | ||
332 | ret = NOTIFY_OK; | 325 | ret = NOTIFY_OK; |
333 | break; | 326 | break; |
334 | #ifdef CONFIG_HOTPLUG_CPU | 327 | #ifdef CONFIG_HOTPLUG_CPU |
@@ -375,7 +368,7 @@ static int __init parse_numa_properties(void) | |||
375 | { | 368 | { |
376 | struct device_node *cpu = NULL; | 369 | struct device_node *cpu = NULL; |
377 | struct device_node *memory = NULL; | 370 | struct device_node *memory = NULL; |
378 | int max_domain; | 371 | int default_nid = 0; |
379 | unsigned long i; | 372 | unsigned long i; |
380 | 373 | ||
381 | if (numa_enabled == 0) { | 374 | if (numa_enabled == 0) { |
@@ -385,32 +378,32 @@ static int __init parse_numa_properties(void) | |||
385 | 378 | ||
386 | min_common_depth = find_min_common_depth(); | 379 | min_common_depth = find_min_common_depth(); |
387 | 380 | ||
388 | dbg("NUMA associativity depth for CPU/Memory: %d\n", min_common_depth); | ||
389 | if (min_common_depth < 0) | 381 | if (min_common_depth < 0) |
390 | return min_common_depth; | 382 | return min_common_depth; |
391 | 383 | ||
392 | max_domain = numa_setup_cpu(boot_cpuid); | 384 | dbg("NUMA associativity depth for CPU/Memory: %d\n", min_common_depth); |
393 | 385 | ||
394 | /* | 386 | /* |
395 | * Even though we connect cpus to numa domains later in SMP init, | 387 | * Even though we connect cpus to numa domains later in SMP |
396 | * we need to know the maximum node id now. This is because each | 388 | * init, we need to know the node ids now. This is because |
397 | * node id must have NODE_DATA etc backing it. | 389 | * each node to be onlined must have NODE_DATA etc backing it. |
398 | * As a result of hotplug we could still have cpus appear later on | ||
399 | * with larger node ids. In that case we force the cpu into node 0. | ||
400 | */ | 390 | */ |
401 | for_each_cpu(i) { | 391 | for_each_present_cpu(i) { |
402 | int numa_domain; | 392 | int nid; |
403 | 393 | ||
404 | cpu = find_cpu_node(i); | 394 | cpu = find_cpu_node(i); |
395 | BUG_ON(!cpu); | ||
396 | nid = of_node_to_nid(cpu); | ||
397 | of_node_put(cpu); | ||
405 | 398 | ||
406 | if (cpu) { | 399 | /* |
407 | numa_domain = of_node_numa_domain(cpu); | 400 | * Don't fall back to default_nid yet -- we will plug |
408 | of_node_put(cpu); | 401 | * cpus into nodes once the memory scan has discovered |
409 | 402 | * the topology. | |
410 | if (numa_domain < MAX_NUMNODES && | 403 | */ |
411 | max_domain < numa_domain) | 404 | if (nid < 0) |
412 | max_domain = numa_domain; | 405 | continue; |
413 | } | 406 | node_set_online(nid); |
414 | } | 407 | } |
415 | 408 | ||
416 | get_n_mem_cells(&n_mem_addr_cells, &n_mem_size_cells); | 409 | get_n_mem_cells(&n_mem_addr_cells, &n_mem_size_cells); |
@@ -418,7 +411,7 @@ static int __init parse_numa_properties(void) | |||
418 | while ((memory = of_find_node_by_type(memory, "memory")) != NULL) { | 411 | while ((memory = of_find_node_by_type(memory, "memory")) != NULL) { |
419 | unsigned long start; | 412 | unsigned long start; |
420 | unsigned long size; | 413 | unsigned long size; |
421 | int numa_domain; | 414 | int nid; |
422 | int ranges; | 415 | int ranges; |
423 | unsigned int *memcell_buf; | 416 | unsigned int *memcell_buf; |
424 | unsigned int len; | 417 | unsigned int len; |
@@ -439,18 +432,15 @@ new_range: | |||
439 | start = read_n_cells(n_mem_addr_cells, &memcell_buf); | 432 | start = read_n_cells(n_mem_addr_cells, &memcell_buf); |
440 | size = read_n_cells(n_mem_size_cells, &memcell_buf); | 433 | size = read_n_cells(n_mem_size_cells, &memcell_buf); |
441 | 434 | ||
442 | numa_domain = of_node_numa_domain(memory); | 435 | /* |
443 | 436 | * Assumption: either all memory nodes or none will | |
444 | if (numa_domain >= MAX_NUMNODES) { | 437 | * have associativity properties. If none, then |
445 | if (numa_domain != 0xffff) | 438 | * everything goes to default_nid. |
446 | printk(KERN_ERR "WARNING: memory at %lx maps " | 439 | */ |
447 | "to invalid NUMA node %d\n", start, | 440 | nid = of_node_to_nid(memory); |
448 | numa_domain); | 441 | if (nid < 0) |
449 | numa_domain = 0; | 442 | nid = default_nid; |
450 | } | 443 | node_set_online(nid); |
451 | |||
452 | if (max_domain < numa_domain) | ||
453 | max_domain = numa_domain; | ||
454 | 444 | ||
455 | if (!(size = numa_enforce_memory_limit(start, size))) { | 445 | if (!(size = numa_enforce_memory_limit(start, size))) { |
456 | if (--ranges) | 446 | if (--ranges) |
@@ -459,16 +449,13 @@ new_range: | |||
459 | continue; | 449 | continue; |
460 | } | 450 | } |
461 | 451 | ||
462 | add_region(numa_domain, start >> PAGE_SHIFT, | 452 | add_region(nid, start >> PAGE_SHIFT, |
463 | size >> PAGE_SHIFT); | 453 | size >> PAGE_SHIFT); |
464 | 454 | ||
465 | if (--ranges) | 455 | if (--ranges) |
466 | goto new_range; | 456 | goto new_range; |
467 | } | 457 | } |
468 | 458 | ||
469 | for (i = 0; i <= max_domain; i++) | ||
470 | node_set_online(i); | ||
471 | |||
472 | return 0; | 459 | return 0; |
473 | } | 460 | } |
474 | 461 | ||
@@ -483,7 +470,6 @@ static void __init setup_nonnuma(void) | |||
483 | printk(KERN_INFO "Memory hole size: %ldMB\n", | 470 | printk(KERN_INFO "Memory hole size: %ldMB\n", |
484 | (top_of_ram - total_ram) >> 20); | 471 | (top_of_ram - total_ram) >> 20); |
485 | 472 | ||
486 | map_cpu_to_node(boot_cpuid, 0); | ||
487 | for (i = 0; i < lmb.memory.cnt; ++i) | 473 | for (i = 0; i < lmb.memory.cnt; ++i) |
488 | add_region(0, lmb.memory.region[i].base >> PAGE_SHIFT, | 474 | add_region(0, lmb.memory.region[i].base >> PAGE_SHIFT, |
489 | lmb_size_pages(&lmb.memory, i)); | 475 | lmb_size_pages(&lmb.memory, i)); |
@@ -570,11 +556,11 @@ static void __init *careful_allocation(int nid, unsigned long size, | |||
570 | unsigned long end_pfn) | 556 | unsigned long end_pfn) |
571 | { | 557 | { |
572 | int new_nid; | 558 | int new_nid; |
573 | unsigned long ret = lmb_alloc_base(size, align, end_pfn << PAGE_SHIFT); | 559 | unsigned long ret = __lmb_alloc_base(size, align, end_pfn << PAGE_SHIFT); |
574 | 560 | ||
575 | /* retry over all memory */ | 561 | /* retry over all memory */ |
576 | if (!ret) | 562 | if (!ret) |
577 | ret = lmb_alloc_base(size, align, lmb_end_of_DRAM()); | 563 | ret = __lmb_alloc_base(size, align, lmb_end_of_DRAM()); |
578 | 564 | ||
579 | if (!ret) | 565 | if (!ret) |
580 | panic("numa.c: cannot allocate %lu bytes on node %d", | 566 | panic("numa.c: cannot allocate %lu bytes on node %d", |
@@ -620,6 +606,8 @@ void __init do_init_bootmem(void) | |||
620 | dump_numa_memory_topology(); | 606 | dump_numa_memory_topology(); |
621 | 607 | ||
622 | register_cpu_notifier(&ppc64_numa_nb); | 608 | register_cpu_notifier(&ppc64_numa_nb); |
609 | cpu_numa_callback(&ppc64_numa_nb, CPU_UP_PREPARE, | ||
610 | (void *)(unsigned long)boot_cpuid); | ||
623 | 611 | ||
624 | for_each_online_node(nid) { | 612 | for_each_online_node(nid) { |
625 | unsigned long start_pfn, end_pfn, pages_present; | 613 | unsigned long start_pfn, end_pfn, pages_present; |
@@ -767,10 +755,11 @@ int hot_add_scn_to_nid(unsigned long scn_addr) | |||
767 | { | 755 | { |
768 | struct device_node *memory = NULL; | 756 | struct device_node *memory = NULL; |
769 | nodemask_t nodes; | 757 | nodemask_t nodes; |
770 | int numa_domain = 0; | 758 | int default_nid = any_online_node(NODE_MASK_ALL); |
759 | int nid; | ||
771 | 760 | ||
772 | if (!numa_enabled || (min_common_depth < 0)) | 761 | if (!numa_enabled || (min_common_depth < 0)) |
773 | return numa_domain; | 762 | return default_nid; |
774 | 763 | ||
775 | while ((memory = of_find_node_by_type(memory, "memory")) != NULL) { | 764 | while ((memory = of_find_node_by_type(memory, "memory")) != NULL) { |
776 | unsigned long start, size; | 765 | unsigned long start, size; |
@@ -787,29 +776,30 @@ int hot_add_scn_to_nid(unsigned long scn_addr) | |||
787 | ha_new_range: | 776 | ha_new_range: |
788 | start = read_n_cells(n_mem_addr_cells, &memcell_buf); | 777 | start = read_n_cells(n_mem_addr_cells, &memcell_buf); |
789 | size = read_n_cells(n_mem_size_cells, &memcell_buf); | 778 | size = read_n_cells(n_mem_size_cells, &memcell_buf); |
790 | numa_domain = of_node_numa_domain(memory); | 779 | nid = of_node_to_nid(memory); |
791 | 780 | ||
792 | /* Domains not present at boot default to 0 */ | 781 | /* Domains not present at boot default to 0 */ |
793 | if (!node_online(numa_domain)) | 782 | if (nid < 0 || !node_online(nid)) |
794 | numa_domain = any_online_node(NODE_MASK_ALL); | 783 | nid = default_nid; |
795 | 784 | ||
796 | if ((scn_addr >= start) && (scn_addr < (start + size))) { | 785 | if ((scn_addr >= start) && (scn_addr < (start + size))) { |
797 | of_node_put(memory); | 786 | of_node_put(memory); |
798 | goto got_numa_domain; | 787 | goto got_nid; |
799 | } | 788 | } |
800 | 789 | ||
801 | if (--ranges) /* process all ranges in cell */ | 790 | if (--ranges) /* process all ranges in cell */ |
802 | goto ha_new_range; | 791 | goto ha_new_range; |
803 | } | 792 | } |
804 | BUG(); /* section address should be found above */ | 793 | BUG(); /* section address should be found above */ |
794 | return 0; | ||
805 | 795 | ||
806 | /* Temporary code to ensure that returned node is not empty */ | 796 | /* Temporary code to ensure that returned node is not empty */ |
807 | got_numa_domain: | 797 | got_nid: |
808 | nodes_setall(nodes); | 798 | nodes_setall(nodes); |
809 | while (NODE_DATA(numa_domain)->node_spanned_pages == 0) { | 799 | while (NODE_DATA(nid)->node_spanned_pages == 0) { |
810 | node_clear(numa_domain, nodes); | 800 | node_clear(nid, nodes); |
811 | numa_domain = any_online_node(nodes); | 801 | nid = any_online_node(nodes); |
812 | } | 802 | } |
813 | return numa_domain; | 803 | return nid; |
814 | } | 804 | } |
815 | #endif /* CONFIG_MEMORY_HOTPLUG */ | 805 | #endif /* CONFIG_MEMORY_HOTPLUG */ |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index f4e5ac122615..90628601fac7 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
@@ -37,6 +37,7 @@ | |||
37 | 37 | ||
38 | unsigned long ioremap_base; | 38 | unsigned long ioremap_base; |
39 | unsigned long ioremap_bot; | 39 | unsigned long ioremap_bot; |
40 | EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ | ||
40 | int io_bat_index; | 41 | int io_bat_index; |
41 | 42 | ||
42 | #if defined(CONFIG_6xx) || defined(CONFIG_POWER3) | 43 | #if defined(CONFIG_6xx) || defined(CONFIG_POWER3) |
@@ -153,6 +154,7 @@ ioremap64(unsigned long long addr, unsigned long size) | |||
153 | { | 154 | { |
154 | return __ioremap(addr, size, _PAGE_NO_CACHE); | 155 | return __ioremap(addr, size, _PAGE_NO_CACHE); |
155 | } | 156 | } |
157 | EXPORT_SYMBOL(ioremap64); | ||
156 | 158 | ||
157 | void __iomem * | 159 | void __iomem * |
158 | ioremap(phys_addr_t addr, unsigned long size) | 160 | ioremap(phys_addr_t addr, unsigned long size) |
@@ -162,6 +164,7 @@ ioremap(phys_addr_t addr, unsigned long size) | |||
162 | return ioremap64(addr64, size); | 164 | return ioremap64(addr64, size); |
163 | } | 165 | } |
164 | #endif /* CONFIG_PHYS_64BIT */ | 166 | #endif /* CONFIG_PHYS_64BIT */ |
167 | EXPORT_SYMBOL(ioremap); | ||
165 | 168 | ||
166 | void __iomem * | 169 | void __iomem * |
167 | __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) | 170 | __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) |
@@ -247,6 +250,7 @@ __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags) | |||
247 | out: | 250 | out: |
248 | return (void __iomem *) (v + ((unsigned long)addr & ~PAGE_MASK)); | 251 | return (void __iomem *) (v + ((unsigned long)addr & ~PAGE_MASK)); |
249 | } | 252 | } |
253 | EXPORT_SYMBOL(__ioremap); | ||
250 | 254 | ||
251 | void iounmap(volatile void __iomem *addr) | 255 | void iounmap(volatile void __iomem *addr) |
252 | { | 256 | { |
@@ -259,6 +263,7 @@ void iounmap(volatile void __iomem *addr) | |||
259 | if (addr > high_memory && (unsigned long) addr < ioremap_bot) | 263 | if (addr > high_memory && (unsigned long) addr < ioremap_bot) |
260 | vunmap((void *) (PAGE_MASK & (unsigned long)addr)); | 264 | vunmap((void *) (PAGE_MASK & (unsigned long)addr)); |
261 | } | 265 | } |
266 | EXPORT_SYMBOL(iounmap); | ||
262 | 267 | ||
263 | void __iomem *ioport_map(unsigned long port, unsigned int len) | 268 | void __iomem *ioport_map(unsigned long port, unsigned int len) |
264 | { | 269 | { |
@@ -367,7 +372,7 @@ void __init io_block_mapping(unsigned long virt, phys_addr_t phys, | |||
367 | * the PTE pointer is unmodified if PTE is not found. | 372 | * the PTE pointer is unmodified if PTE is not found. |
368 | */ | 373 | */ |
369 | int | 374 | int |
370 | get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep) | 375 | get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep, pmd_t **pmdp) |
371 | { | 376 | { |
372 | pgd_t *pgd; | 377 | pgd_t *pgd; |
373 | pmd_t *pmd; | 378 | pmd_t *pmd; |
@@ -382,6 +387,8 @@ get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep) | |||
382 | if (pte) { | 387 | if (pte) { |
383 | retval = 1; | 388 | retval = 1; |
384 | *ptep = pte; | 389 | *ptep = pte; |
390 | if (pmdp) | ||
391 | *pmdp = pmd; | ||
385 | /* XXX caller needs to do pte_unmap, yuck */ | 392 | /* XXX caller needs to do pte_unmap, yuck */ |
386 | } | 393 | } |
387 | } | 394 | } |
@@ -419,7 +426,7 @@ unsigned long iopa(unsigned long addr) | |||
419 | mm = &init_mm; | 426 | mm = &init_mm; |
420 | 427 | ||
421 | pa = 0; | 428 | pa = 0; |
422 | if (get_pteptr(mm, addr, &pte)) { | 429 | if (get_pteptr(mm, addr, &pte, NULL)) { |
423 | pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK); | 430 | pa = (pte_val(*pte) & PAGE_MASK) | (addr & ~PAGE_MASK); |
424 | pte_unmap(pte); | 431 | pte_unmap(pte); |
425 | } | 432 | } |
diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S index d1acee38f163..abfaabf667bf 100644 --- a/arch/powerpc/mm/slb_low.S +++ b/arch/powerpc/mm/slb_low.S | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/mm/slb_low.S | ||
3 | * | ||
4 | * Low-level SLB routines | 2 | * Low-level SLB routines |
5 | * | 3 | * |
6 | * Copyright (C) 2004 David Gibson <dwg@au.ibm.com>, IBM | 4 | * Copyright (C) 2004 David Gibson <dwg@au.ibm.com>, IBM |
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c index 82e4951826bc..4a9291d9fef8 100644 --- a/arch/powerpc/mm/stab.c +++ b/arch/powerpc/mm/stab.c | |||
@@ -239,7 +239,7 @@ void stabs_alloc(void) | |||
239 | if (cpu_has_feature(CPU_FTR_SLB)) | 239 | if (cpu_has_feature(CPU_FTR_SLB)) |
240 | return; | 240 | return; |
241 | 241 | ||
242 | for_each_cpu(cpu) { | 242 | for_each_possible_cpu(cpu) { |
243 | unsigned long newstab; | 243 | unsigned long newstab; |
244 | 244 | ||
245 | if (cpu == 0) | 245 | if (cpu == 0) |
@@ -247,10 +247,6 @@ void stabs_alloc(void) | |||
247 | 247 | ||
248 | newstab = lmb_alloc_base(HW_PAGE_SIZE, HW_PAGE_SIZE, | 248 | newstab = lmb_alloc_base(HW_PAGE_SIZE, HW_PAGE_SIZE, |
249 | 1<<SID_SHIFT); | 249 | 1<<SID_SHIFT); |
250 | if (! newstab) | ||
251 | panic("Unable to allocate segment table for CPU %d.\n", | ||
252 | cpu); | ||
253 | |||
254 | newstab = (unsigned long)__va(newstab); | 250 | newstab = (unsigned long)__va(newstab); |
255 | 251 | ||
256 | memset((void *)newstab, 0, HW_PAGE_SIZE); | 252 | memset((void *)newstab, 0, HW_PAGE_SIZE); |
diff --git a/arch/powerpc/mm/tlb_64.c b/arch/powerpc/mm/tlb_64.c index bb3afb6e6317..f734b11566c2 100644 --- a/arch/powerpc/mm/tlb_64.c +++ b/arch/powerpc/mm/tlb_64.c | |||
@@ -36,7 +36,7 @@ | |||
36 | DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); | 36 | DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); |
37 | 37 | ||
38 | /* This is declared as we are using the more or less generic | 38 | /* This is declared as we are using the more or less generic |
39 | * include/asm-ppc64/tlb.h file -- tgall | 39 | * include/asm-powerpc/tlb.h file -- tgall |
40 | */ | 40 | */ |
41 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); | 41 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
42 | DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); | 42 | DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); |
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index 554cd7c75321..f5f9859a8338 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile | |||
@@ -6,7 +6,7 @@ DRIVER_OBJS := $(addprefix ../../../drivers/oprofile/, \ | |||
6 | oprofilefs.o oprofile_stats.o \ | 6 | oprofilefs.o oprofile_stats.o \ |
7 | timer_int.o ) | 7 | timer_int.o ) |
8 | 8 | ||
9 | oprofile-y := $(DRIVER_OBJS) common.o | 9 | oprofile-y := $(DRIVER_OBJS) common.o backtrace.o |
10 | oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o | 10 | oprofile-$(CONFIG_PPC64) += op_model_rs64.o op_model_power4.o |
11 | oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o | 11 | oprofile-$(CONFIG_FSL_BOOKE) += op_model_fsl_booke.o |
12 | oprofile-$(CONFIG_PPC32) += op_model_7450.o | 12 | oprofile-$(CONFIG_PPC32) += op_model_7450.o |
diff --git a/arch/powerpc/oprofile/backtrace.c b/arch/powerpc/oprofile/backtrace.c new file mode 100644 index 000000000000..75f57bc96b40 --- /dev/null +++ b/arch/powerpc/oprofile/backtrace.c | |||
@@ -0,0 +1,126 @@ | |||
1 | /** | ||
2 | * Copyright (C) 2005 Brian Rogan <bcr6@cornell.edu>, IBM | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | **/ | ||
9 | |||
10 | #include <linux/oprofile.h> | ||
11 | #include <linux/sched.h> | ||
12 | #include <asm/processor.h> | ||
13 | #include <asm/uaccess.h> | ||
14 | |||
15 | #define STACK_SP(STACK) *(STACK) | ||
16 | |||
17 | #define STACK_LR64(STACK) *((unsigned long *)(STACK) + 2) | ||
18 | #define STACK_LR32(STACK) *((unsigned int *)(STACK) + 1) | ||
19 | |||
20 | #ifdef CONFIG_PPC64 | ||
21 | #define STACK_LR(STACK) STACK_LR64(STACK) | ||
22 | #else | ||
23 | #define STACK_LR(STACK) STACK_LR32(STACK) | ||
24 | #endif | ||
25 | |||
26 | static unsigned int user_getsp32(unsigned int sp, int is_first) | ||
27 | { | ||
28 | unsigned int stack_frame[2]; | ||
29 | |||
30 | if (!access_ok(VERIFY_READ, sp, sizeof(stack_frame))) | ||
31 | return 0; | ||
32 | |||
33 | /* | ||
34 | * The most likely reason for this is that we returned -EFAULT, | ||
35 | * which means that we've done all that we can do from | ||
36 | * interrupt context. | ||
37 | */ | ||
38 | if (__copy_from_user_inatomic(stack_frame, (void *)(long)sp, | ||
39 | sizeof(stack_frame))) | ||
40 | return 0; | ||
41 | |||
42 | if (!is_first) | ||
43 | oprofile_add_trace(STACK_LR32(stack_frame)); | ||
44 | |||
45 | /* | ||
46 | * We do not enforce increasing stack addresses here because | ||
47 | * we may transition to a different stack, eg a signal handler. | ||
48 | */ | ||
49 | return STACK_SP(stack_frame); | ||
50 | } | ||
51 | |||
52 | #ifdef CONFIG_PPC64 | ||
53 | static unsigned long user_getsp64(unsigned long sp, int is_first) | ||
54 | { | ||
55 | unsigned long stack_frame[3]; | ||
56 | |||
57 | if (!access_ok(VERIFY_READ, sp, sizeof(stack_frame))) | ||
58 | return 0; | ||
59 | |||
60 | if (__copy_from_user_inatomic(stack_frame, (void *)sp, | ||
61 | sizeof(stack_frame))) | ||
62 | return 0; | ||
63 | |||
64 | if (!is_first) | ||
65 | oprofile_add_trace(STACK_LR64(stack_frame)); | ||
66 | |||
67 | return STACK_SP(stack_frame); | ||
68 | } | ||
69 | #endif | ||
70 | |||
71 | static unsigned long kernel_getsp(unsigned long sp, int is_first) | ||
72 | { | ||
73 | unsigned long *stack_frame = (unsigned long *)sp; | ||
74 | |||
75 | if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD)) | ||
76 | return 0; | ||
77 | |||
78 | if (!is_first) | ||
79 | oprofile_add_trace(STACK_LR(stack_frame)); | ||
80 | |||
81 | /* | ||
82 | * We do not enforce increasing stack addresses here because | ||
83 | * we might be transitioning from an interrupt stack to a kernel | ||
84 | * stack. validate_sp() is designed to understand this, so just | ||
85 | * use it. | ||
86 | */ | ||
87 | return STACK_SP(stack_frame); | ||
88 | } | ||
89 | |||
90 | void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth) | ||
91 | { | ||
92 | unsigned long sp = regs->gpr[1]; | ||
93 | int first_frame = 1; | ||
94 | |||
95 | /* We ditch the top stackframe so need to loop through an extra time */ | ||
96 | depth += 1; | ||
97 | |||
98 | if (!user_mode(regs)) { | ||
99 | while (depth--) { | ||
100 | sp = kernel_getsp(sp, first_frame); | ||
101 | if (!sp) | ||
102 | break; | ||
103 | first_frame = 0; | ||
104 | } | ||
105 | } else { | ||
106 | #ifdef CONFIG_PPC64 | ||
107 | if (!test_thread_flag(TIF_32BIT)) { | ||
108 | while (depth--) { | ||
109 | sp = user_getsp64(sp, first_frame); | ||
110 | if (!sp) | ||
111 | break; | ||
112 | first_frame = 0; | ||
113 | } | ||
114 | |||
115 | return; | ||
116 | } | ||
117 | #endif | ||
118 | |||
119 | while (depth--) { | ||
120 | sp = user_getsp32(sp, first_frame); | ||
121 | if (!sp) | ||
122 | break; | ||
123 | first_frame = 0; | ||
124 | } | ||
125 | } | ||
126 | } | ||
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index cc2535be3a73..5b1de7e8041e 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c | |||
@@ -117,18 +117,10 @@ static int op_powerpc_create_files(struct super_block *sb, struct dentry *root) | |||
117 | 117 | ||
118 | oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel); | 118 | oprofilefs_create_ulong(sb, root, "enable_kernel", &sys.enable_kernel); |
119 | oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user); | 119 | oprofilefs_create_ulong(sb, root, "enable_user", &sys.enable_user); |
120 | #ifdef CONFIG_PPC64 | ||
121 | oprofilefs_create_ulong(sb, root, "backtrace_spinlocks", | ||
122 | &sys.backtrace_spinlocks); | ||
123 | #endif | ||
124 | 120 | ||
125 | /* Default to tracing both kernel and user */ | 121 | /* Default to tracing both kernel and user */ |
126 | sys.enable_kernel = 1; | 122 | sys.enable_kernel = 1; |
127 | sys.enable_user = 1; | 123 | sys.enable_user = 1; |
128 | #ifdef CONFIG_PPC64 | ||
129 | /* Turn on backtracing through spinlocks by default */ | ||
130 | sys.backtrace_spinlocks = 1; | ||
131 | #endif | ||
132 | 124 | ||
133 | return 0; | 125 | return 0; |
134 | } | 126 | } |
@@ -168,6 +160,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) | |||
168 | ops->shutdown = op_powerpc_shutdown; | 160 | ops->shutdown = op_powerpc_shutdown; |
169 | ops->start = op_powerpc_start; | 161 | ops->start = op_powerpc_start; |
170 | ops->stop = op_powerpc_stop; | 162 | ops->stop = op_powerpc_stop; |
163 | ops->backtrace = op_powerpc_backtrace; | ||
171 | 164 | ||
172 | printk(KERN_INFO "oprofile: using %s performance monitoring.\n", | 165 | printk(KERN_INFO "oprofile: using %s performance monitoring.\n", |
173 | ops->cpu_type); | 166 | ops->cpu_type); |
diff --git a/arch/powerpc/oprofile/op_model_7450.c b/arch/powerpc/oprofile/op_model_7450.c index 32abfdbb0eb1..e0491c3c71f1 100644 --- a/arch/powerpc/oprofile/op_model_7450.c +++ b/arch/powerpc/oprofile/op_model_7450.c | |||
@@ -176,13 +176,13 @@ static void fsl7450_handle_interrupt(struct pt_regs *regs, | |||
176 | mtmsr(mfmsr() | MSR_PMM); | 176 | mtmsr(mfmsr() | MSR_PMM); |
177 | 177 | ||
178 | pc = mfspr(SPRN_SIAR); | 178 | pc = mfspr(SPRN_SIAR); |
179 | is_kernel = (pc >= KERNELBASE); | 179 | is_kernel = is_kernel_addr(pc); |
180 | 180 | ||
181 | for (i = 0; i < NUM_CTRS; ++i) { | 181 | for (i = 0; i < NUM_CTRS; ++i) { |
182 | val = ctr_read(i); | 182 | val = ctr_read(i); |
183 | if (val < 0) { | 183 | if (val < 0) { |
184 | if (oprofile_running && ctr[i].enabled) { | 184 | if (oprofile_running && ctr[i].enabled) { |
185 | oprofile_add_pc(pc, is_kernel, i); | 185 | oprofile_add_ext_sample(pc, regs, i, is_kernel); |
186 | ctr_write(i, reset_value[i]); | 186 | ctr_write(i, reset_value[i]); |
187 | } else { | 187 | } else { |
188 | ctr_write(i, 0); | 188 | ctr_write(i, 0); |
diff --git a/arch/powerpc/oprofile/op_model_fsl_booke.c b/arch/powerpc/oprofile/op_model_fsl_booke.c index 26539cda6023..93d63e62662f 100644 --- a/arch/powerpc/oprofile/op_model_fsl_booke.c +++ b/arch/powerpc/oprofile/op_model_fsl_booke.c | |||
@@ -154,13 +154,13 @@ static void fsl_booke_handle_interrupt(struct pt_regs *regs, | |||
154 | mtmsr(mfmsr() | MSR_PMM); | 154 | mtmsr(mfmsr() | MSR_PMM); |
155 | 155 | ||
156 | pc = regs->nip; | 156 | pc = regs->nip; |
157 | is_kernel = (pc >= KERNELBASE); | 157 | is_kernel = is_kernel_addr(pc); |
158 | 158 | ||
159 | for (i = 0; i < num_counters; ++i) { | 159 | for (i = 0; i < num_counters; ++i) { |
160 | val = ctr_read(i); | 160 | val = ctr_read(i); |
161 | if (val < 0) { | 161 | if (val < 0) { |
162 | if (oprofile_running && ctr[i].enabled) { | 162 | if (oprofile_running && ctr[i].enabled) { |
163 | oprofile_add_pc(pc, is_kernel, i); | 163 | oprofile_add_ext_sample(pc, regs, i, is_kernel); |
164 | ctr_write(i, reset_value[i]); | 164 | ctr_write(i, reset_value[i]); |
165 | } else { | 165 | } else { |
166 | ctr_write(i, 0); | 166 | ctr_write(i, 0); |
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c index 659a021da0c7..4c2beab1fdc1 100644 --- a/arch/powerpc/oprofile/op_model_power4.c +++ b/arch/powerpc/oprofile/op_model_power4.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/oprofile.h> | 10 | #include <linux/oprofile.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/smp.h> | 12 | #include <linux/smp.h> |
13 | #include <asm/firmware.h> | ||
13 | #include <asm/ptrace.h> | 14 | #include <asm/ptrace.h> |
14 | #include <asm/system.h> | 15 | #include <asm/system.h> |
15 | #include <asm/processor.h> | 16 | #include <asm/processor.h> |
@@ -24,18 +25,14 @@ static unsigned long reset_value[OP_MAX_COUNTER]; | |||
24 | 25 | ||
25 | static int oprofile_running; | 26 | static int oprofile_running; |
26 | static int mmcra_has_sihv; | 27 | static int mmcra_has_sihv; |
28 | /* Unfortunately these bits vary between CPUs */ | ||
29 | static unsigned long mmcra_sihv = MMCRA_SIHV; | ||
30 | static unsigned long mmcra_sipr = MMCRA_SIPR; | ||
27 | 31 | ||
28 | /* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */ | 32 | /* mmcr values are set in power4_reg_setup, used in power4_cpu_setup */ |
29 | static u32 mmcr0_val; | 33 | static u32 mmcr0_val; |
30 | static u64 mmcr1_val; | 34 | static u64 mmcr1_val; |
31 | static u32 mmcra_val; | 35 | static u64 mmcra_val; |
32 | |||
33 | /* | ||
34 | * Since we do not have an NMI, backtracing through spinlocks is | ||
35 | * only a best guess. In light of this, allow it to be disabled at | ||
36 | * runtime. | ||
37 | */ | ||
38 | static int backtrace_spinlocks; | ||
39 | 36 | ||
40 | static void power4_reg_setup(struct op_counter_config *ctr, | 37 | static void power4_reg_setup(struct op_counter_config *ctr, |
41 | struct op_system_config *sys, | 38 | struct op_system_config *sys, |
@@ -62,8 +59,6 @@ static void power4_reg_setup(struct op_counter_config *ctr, | |||
62 | mmcr1_val = sys->mmcr1; | 59 | mmcr1_val = sys->mmcr1; |
63 | mmcra_val = sys->mmcra; | 60 | mmcra_val = sys->mmcra; |
64 | 61 | ||
65 | backtrace_spinlocks = sys->backtrace_spinlocks; | ||
66 | |||
67 | for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) | 62 | for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) |
68 | reset_value[i] = 0x80000000UL - ctr[i].count; | 63 | reset_value[i] = 0x80000000UL - ctr[i].count; |
69 | 64 | ||
@@ -196,25 +191,6 @@ static void __attribute_used__ kernel_unknown_bucket(void) | |||
196 | { | 191 | { |
197 | } | 192 | } |
198 | 193 | ||
199 | static unsigned long check_spinlock_pc(struct pt_regs *regs, | ||
200 | unsigned long profile_pc) | ||
201 | { | ||
202 | unsigned long pc = instruction_pointer(regs); | ||
203 | |||
204 | /* | ||
205 | * If both the SIAR (sampled instruction) and the perfmon exception | ||
206 | * occurred in a spinlock region then we account the sample to the | ||
207 | * calling function. This isnt 100% correct, we really need soft | ||
208 | * IRQ disable so we always get the perfmon exception at the | ||
209 | * point at which the SIAR is set. | ||
210 | */ | ||
211 | if (backtrace_spinlocks && in_lock_functions(pc) && | ||
212 | in_lock_functions(profile_pc)) | ||
213 | return regs->link; | ||
214 | else | ||
215 | return profile_pc; | ||
216 | } | ||
217 | |||
218 | /* | 194 | /* |
219 | * On GQ and newer the MMCRA stores the HV and PR bits at the time | 195 | * On GQ and newer the MMCRA stores the HV and PR bits at the time |
220 | * the SIAR was sampled. We use that to work out if the SIAR was sampled in | 196 | * the SIAR was sampled. We use that to work out if the SIAR was sampled in |
@@ -227,17 +203,17 @@ static unsigned long get_pc(struct pt_regs *regs) | |||
227 | 203 | ||
228 | /* Cant do much about it */ | 204 | /* Cant do much about it */ |
229 | if (!mmcra_has_sihv) | 205 | if (!mmcra_has_sihv) |
230 | return check_spinlock_pc(regs, pc); | 206 | return pc; |
231 | 207 | ||
232 | mmcra = mfspr(SPRN_MMCRA); | 208 | mmcra = mfspr(SPRN_MMCRA); |
233 | 209 | ||
234 | /* Were we in the hypervisor? */ | 210 | /* Were we in the hypervisor? */ |
235 | if (platform_is_lpar() && (mmcra & MMCRA_SIHV)) | 211 | if (firmware_has_feature(FW_FEATURE_LPAR) && (mmcra & mmcra_sihv)) |
236 | /* function descriptor madness */ | 212 | /* function descriptor madness */ |
237 | return *((unsigned long *)hypervisor_bucket); | 213 | return *((unsigned long *)hypervisor_bucket); |
238 | 214 | ||
239 | /* We were in userspace, nothing to do */ | 215 | /* We were in userspace, nothing to do */ |
240 | if (mmcra & MMCRA_SIPR) | 216 | if (mmcra & mmcra_sipr) |
241 | return pc; | 217 | return pc; |
242 | 218 | ||
243 | #ifdef CONFIG_PPC_RTAS | 219 | #ifdef CONFIG_PPC_RTAS |
@@ -256,7 +232,7 @@ static unsigned long get_pc(struct pt_regs *regs) | |||
256 | /* function descriptor madness */ | 232 | /* function descriptor madness */ |
257 | return *((unsigned long *)kernel_unknown_bucket); | 233 | return *((unsigned long *)kernel_unknown_bucket); |
258 | 234 | ||
259 | return check_spinlock_pc(regs, pc); | 235 | return pc; |
260 | } | 236 | } |
261 | 237 | ||
262 | static int get_kernel(unsigned long pc) | 238 | static int get_kernel(unsigned long pc) |
@@ -267,7 +243,7 @@ static int get_kernel(unsigned long pc) | |||
267 | is_kernel = is_kernel_addr(pc); | 243 | is_kernel = is_kernel_addr(pc); |
268 | } else { | 244 | } else { |
269 | unsigned long mmcra = mfspr(SPRN_MMCRA); | 245 | unsigned long mmcra = mfspr(SPRN_MMCRA); |
270 | is_kernel = ((mmcra & MMCRA_SIPR) == 0); | 246 | is_kernel = ((mmcra & mmcra_sipr) == 0); |
271 | } | 247 | } |
272 | 248 | ||
273 | return is_kernel; | 249 | return is_kernel; |
@@ -292,7 +268,7 @@ static void power4_handle_interrupt(struct pt_regs *regs, | |||
292 | val = ctr_read(i); | 268 | val = ctr_read(i); |
293 | if (val < 0) { | 269 | if (val < 0) { |
294 | if (oprofile_running && ctr[i].enabled) { | 270 | if (oprofile_running && ctr[i].enabled) { |
295 | oprofile_add_pc(pc, is_kernel, i); | 271 | oprofile_add_ext_sample(pc, regs, i, is_kernel); |
296 | ctr_write(i, reset_value[i]); | 272 | ctr_write(i, reset_value[i]); |
297 | } else { | 273 | } else { |
298 | ctr_write(i, 0); | 274 | ctr_write(i, 0); |
diff --git a/arch/powerpc/oprofile/op_model_rs64.c b/arch/powerpc/oprofile/op_model_rs64.c index 5c909ee609fe..042f8f4867ad 100644 --- a/arch/powerpc/oprofile/op_model_rs64.c +++ b/arch/powerpc/oprofile/op_model_rs64.c | |||
@@ -175,10 +175,13 @@ static void rs64_handle_interrupt(struct pt_regs *regs, | |||
175 | struct op_counter_config *ctr) | 175 | struct op_counter_config *ctr) |
176 | { | 176 | { |
177 | unsigned int mmcr0; | 177 | unsigned int mmcr0; |
178 | int is_kernel; | ||
178 | int val; | 179 | int val; |
179 | int i; | 180 | int i; |
180 | unsigned long pc = mfspr(SPRN_SIAR); | 181 | unsigned long pc = mfspr(SPRN_SIAR); |
181 | 182 | ||
183 | is_kernel = is_kernel_addr(pc); | ||
184 | |||
182 | /* set the PMM bit (see comment below) */ | 185 | /* set the PMM bit (see comment below) */ |
183 | mtmsrd(mfmsr() | MSR_PMM); | 186 | mtmsrd(mfmsr() | MSR_PMM); |
184 | 187 | ||
@@ -186,7 +189,7 @@ static void rs64_handle_interrupt(struct pt_regs *regs, | |||
186 | val = ctr_read(i); | 189 | val = ctr_read(i); |
187 | if (val < 0) { | 190 | if (val < 0) { |
188 | if (ctr[i].enabled) { | 191 | if (ctr[i].enabled) { |
189 | oprofile_add_pc(pc, is_kernel_addr(pc), i); | 192 | oprofile_add_ext_sample(pc, regs, i, is_kernel); |
190 | ctr_write(i, reset_value[i]); | 193 | ctr_write(i, reset_value[i]); |
191 | } else { | 194 | } else { |
192 | ctr_write(i, 0); | 195 | ctr_write(i, 0); |
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile index 9d8b28ef3343..5c72367441a8 100644 --- a/arch/powerpc/platforms/83xx/Makefile +++ b/arch/powerpc/platforms/83xx/Makefile | |||
@@ -1,4 +1,6 @@ | |||
1 | # | 1 | # |
2 | # Makefile for the PowerPC 83xx linux kernel. | 2 | # Makefile for the PowerPC 83xx linux kernel. |
3 | # | 3 | # |
4 | obj-$(CONFIG_MPC834x_SYS) += mpc834x_sys.o pci.o | 4 | obj-y := misc.o |
5 | obj-$(CONFIG_PCI) += pci.o | ||
6 | obj-$(CONFIG_MPC834x_SYS) += mpc834x_sys.o | ||
diff --git a/arch/powerpc/platforms/83xx/misc.c b/arch/powerpc/platforms/83xx/misc.c new file mode 100644 index 000000000000..1455bcef4892 --- /dev/null +++ b/arch/powerpc/platforms/83xx/misc.c | |||
@@ -0,0 +1,55 @@ | |||
1 | /* | ||
2 | * misc setup functions for MPC83xx | ||
3 | * | ||
4 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> | ||
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/config.h> | ||
13 | #include <linux/stddef.h> | ||
14 | #include <linux/kernel.h> | ||
15 | |||
16 | #include <asm/io.h> | ||
17 | #include <asm/hw_irq.h> | ||
18 | #include <sysdev/fsl_soc.h> | ||
19 | |||
20 | #include "mpc83xx.h" | ||
21 | |||
22 | void mpc83xx_restart(char *cmd) | ||
23 | { | ||
24 | #define RST_OFFSET 0x00000900 | ||
25 | #define RST_PROT_REG 0x00000018 | ||
26 | #define RST_CTRL_REG 0x0000001c | ||
27 | __be32 __iomem *reg; | ||
28 | |||
29 | /* map reset register space */ | ||
30 | reg = ioremap(get_immrbase() + 0x900, 0xff); | ||
31 | |||
32 | local_irq_disable(); | ||
33 | |||
34 | /* enable software reset "RSTE" */ | ||
35 | out_be32(reg + (RST_PROT_REG >> 2), 0x52535445); | ||
36 | |||
37 | /* set software hard reset */ | ||
38 | out_be32(reg + (RST_CTRL_REG >> 2), 0x2); | ||
39 | for (;;) ; | ||
40 | } | ||
41 | |||
42 | long __init mpc83xx_time_init(void) | ||
43 | { | ||
44 | #define SPCR_OFFSET 0x00000110 | ||
45 | #define SPCR_TBEN 0x00400000 | ||
46 | __be32 __iomem *spcr = ioremap(get_immrbase() + SPCR_OFFSET, 4); | ||
47 | __be32 tmp; | ||
48 | |||
49 | tmp = in_be32(spcr); | ||
50 | out_be32(spcr, tmp | SPCR_TBEN); | ||
51 | |||
52 | iounmap(spcr); | ||
53 | |||
54 | return 0; | ||
55 | } | ||
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c index 2098dd05a773..7c18b4cd5db4 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_sys.c +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c | |||
@@ -24,22 +24,15 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/seq_file.h> | 25 | #include <linux/seq_file.h> |
26 | #include <linux/root_dev.h> | 26 | #include <linux/root_dev.h> |
27 | #include <linux/module.h> | ||
28 | #include <linux/fsl_devices.h> | ||
29 | 27 | ||
30 | #include <asm/system.h> | 28 | #include <asm/system.h> |
31 | #include <asm/pgtable.h> | ||
32 | #include <asm/page.h> | ||
33 | #include <asm/atomic.h> | 29 | #include <asm/atomic.h> |
34 | #include <asm/time.h> | 30 | #include <asm/time.h> |
35 | #include <asm/io.h> | 31 | #include <asm/io.h> |
36 | #include <asm/machdep.h> | 32 | #include <asm/machdep.h> |
37 | #include <asm/ipic.h> | 33 | #include <asm/ipic.h> |
38 | #include <asm/bootinfo.h> | 34 | #include <asm/bootinfo.h> |
39 | #include <asm/pci-bridge.h> | ||
40 | #include <asm/mpc83xx.h> | ||
41 | #include <asm/irq.h> | 35 | #include <asm/irq.h> |
42 | #include <mm/mmu_decl.h> | ||
43 | #include <asm/prom.h> | 36 | #include <asm/prom.h> |
44 | #include <asm/udbg.h> | 37 | #include <asm/udbg.h> |
45 | #include <sysdev/fsl_soc.h> | 38 | #include <sysdev/fsl_soc.h> |
@@ -52,8 +45,6 @@ unsigned long isa_mem_base = 0; | |||
52 | #endif | 45 | #endif |
53 | 46 | ||
54 | #ifdef CONFIG_PCI | 47 | #ifdef CONFIG_PCI |
55 | extern int mpc83xx_pci2_busno; | ||
56 | |||
57 | static int | 48 | static int |
58 | mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | 49 | mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) |
59 | { | 50 | { |
@@ -78,26 +69,14 @@ mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | |||
78 | const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4; | 69 | const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4; |
79 | return PCI_IRQ_TABLE_LOOKUP; | 70 | return PCI_IRQ_TABLE_LOOKUP; |
80 | } | 71 | } |
81 | 72 | #endif /* CONFIG_PCI */ | |
82 | static int | ||
83 | mpc83xx_exclude_device(u_char bus, u_char devfn) | ||
84 | { | ||
85 | if (bus == 0 && PCI_SLOT(devfn) == 0) | ||
86 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
87 | if (mpc83xx_pci2_busno) | ||
88 | if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0) | ||
89 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
90 | return PCIBIOS_SUCCESSFUL; | ||
91 | } | ||
92 | #endif /* CONFIG_PCI */ | ||
93 | 73 | ||
94 | /* ************************************************************************ | 74 | /* ************************************************************************ |
95 | * | 75 | * |
96 | * Setup the architecture | 76 | * Setup the architecture |
97 | * | 77 | * |
98 | */ | 78 | */ |
99 | static void __init | 79 | static void __init mpc834x_sys_setup_arch(void) |
100 | mpc834x_sys_setup_arch(void) | ||
101 | { | 80 | { |
102 | struct device_node *np; | 81 | struct device_node *np; |
103 | 82 | ||
@@ -106,14 +85,14 @@ mpc834x_sys_setup_arch(void) | |||
106 | 85 | ||
107 | np = of_find_node_by_type(NULL, "cpu"); | 86 | np = of_find_node_by_type(NULL, "cpu"); |
108 | if (np != 0) { | 87 | if (np != 0) { |
109 | unsigned int *fp = (int *) get_property(np, "clock-frequency", NULL); | 88 | unsigned int *fp = |
89 | (int *)get_property(np, "clock-frequency", NULL); | ||
110 | if (fp != 0) | 90 | if (fp != 0) |
111 | loops_per_jiffy = *fp / HZ; | 91 | loops_per_jiffy = *fp / HZ; |
112 | else | 92 | else |
113 | loops_per_jiffy = 50000000 / HZ; | 93 | loops_per_jiffy = 50000000 / HZ; |
114 | of_node_put(np); | 94 | of_node_put(np); |
115 | } | 95 | } |
116 | |||
117 | #ifdef CONFIG_PCI | 96 | #ifdef CONFIG_PCI |
118 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | 97 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) |
119 | add_bridge(np); | 98 | add_bridge(np); |
@@ -124,14 +103,13 @@ mpc834x_sys_setup_arch(void) | |||
124 | #endif | 103 | #endif |
125 | 104 | ||
126 | #ifdef CONFIG_ROOT_NFS | 105 | #ifdef CONFIG_ROOT_NFS |
127 | ROOT_DEV = Root_NFS; | 106 | ROOT_DEV = Root_NFS; |
128 | #else | 107 | #else |
129 | ROOT_DEV = Root_HDA1; | 108 | ROOT_DEV = Root_HDA1; |
130 | #endif | 109 | #endif |
131 | } | 110 | } |
132 | 111 | ||
133 | void __init | 112 | void __init mpc834x_sys_init_IRQ(void) |
134 | mpc834x_sys_init_IRQ(void) | ||
135 | { | 113 | { |
136 | u8 senses[8] = { | 114 | u8 senses[8] = { |
137 | 0, /* EXT 0 */ | 115 | 0, /* EXT 0 */ |
@@ -160,64 +138,27 @@ mpc834x_sys_init_IRQ(void) | |||
160 | } | 138 | } |
161 | 139 | ||
162 | #if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374) | 140 | #if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374) |
163 | extern ulong ds1374_get_rtc_time(void); | 141 | extern ulong ds1374_get_rtc_time(void); |
164 | extern int ds1374_set_rtc_time(ulong); | 142 | extern int ds1374_set_rtc_time(ulong); |
165 | 143 | ||
166 | static int __init | 144 | static int __init mpc834x_rtc_hookup(void) |
167 | mpc834x_rtc_hookup(void) | ||
168 | { | 145 | { |
169 | struct timespec tv; | 146 | struct timespec tv; |
170 | 147 | ||
171 | ppc_md.get_rtc_time = ds1374_get_rtc_time; | 148 | ppc_md.get_rtc_time = ds1374_get_rtc_time; |
172 | ppc_md.set_rtc_time = ds1374_set_rtc_time; | 149 | ppc_md.set_rtc_time = ds1374_set_rtc_time; |
173 | 150 | ||
174 | tv.tv_nsec = 0; | 151 | tv.tv_nsec = 0; |
175 | tv.tv_sec = (ppc_md.get_rtc_time)(); | 152 | tv.tv_sec = (ppc_md.get_rtc_time) (); |
176 | do_settimeofday(&tv); | 153 | do_settimeofday(&tv); |
177 | 154 | ||
178 | return 0; | 155 | return 0; |
179 | } | 156 | } |
157 | |||
180 | late_initcall(mpc834x_rtc_hookup); | 158 | late_initcall(mpc834x_rtc_hookup); |
181 | #endif | 159 | #endif |
182 | 160 | ||
183 | static void | 161 | void __init platform_init(void) |
184 | mpc83xx_restart(char *cmd) | ||
185 | { | ||
186 | #define RST_OFFSET 0x00000900 | ||
187 | #define RST_PROT_REG 0x00000018 | ||
188 | #define RST_CTRL_REG 0x0000001c | ||
189 | __be32 __iomem *reg; | ||
190 | |||
191 | // map reset register space | ||
192 | reg = ioremap(get_immrbase() + 0x900, 0xff); | ||
193 | |||
194 | local_irq_disable(); | ||
195 | |||
196 | /* enable software reset "RSTE" */ | ||
197 | out_be32(reg + (RST_PROT_REG >> 2), 0x52535445); | ||
198 | |||
199 | /* set software hard reset */ | ||
200 | out_be32(reg + (RST_CTRL_REG >> 2), 0x52535445); | ||
201 | for(;;); | ||
202 | } | ||
203 | |||
204 | static long __init | ||
205 | mpc83xx_time_init(void) | ||
206 | { | ||
207 | #define SPCR_OFFSET 0x00000110 | ||
208 | #define SPCR_TBEN 0x00400000 | ||
209 | __be32 __iomem *spcr = ioremap(get_immrbase() + SPCR_OFFSET, 4); | ||
210 | __be32 tmp; | ||
211 | |||
212 | tmp = in_be32(spcr); | ||
213 | out_be32(spcr, tmp|SPCR_TBEN); | ||
214 | |||
215 | iounmap(spcr); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | void __init | ||
220 | platform_init(void) | ||
221 | { | 162 | { |
222 | /* setup the PowerPC module struct */ | 163 | /* setup the PowerPC module struct */ |
223 | ppc_md.setup_arch = mpc834x_sys_setup_arch; | 164 | ppc_md.setup_arch = mpc834x_sys_setup_arch; |
@@ -239,5 +180,3 @@ platform_init(void) | |||
239 | 180 | ||
240 | return; | 181 | return; |
241 | } | 182 | } |
242 | |||
243 | |||
diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.h b/arch/powerpc/platforms/83xx/mpc834x_sys.h index e4ca39f6a862..fedecb73f7ff 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_sys.h +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.h | |||
@@ -20,4 +20,4 @@ | |||
20 | #define PIRQC MPC83xx_IRQ_EXT6 | 20 | #define PIRQC MPC83xx_IRQ_EXT6 |
21 | #define PIRQD MPC83xx_IRQ_EXT7 | 21 | #define PIRQD MPC83xx_IRQ_EXT7 |
22 | 22 | ||
23 | #endif /* __MACH_MPC83XX_SYS_H__ */ | 23 | #endif /* __MACH_MPC83XX_SYS_H__ */ |
diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h index ce9e66abef24..01cae106912b 100644 --- a/arch/powerpc/platforms/83xx/mpc83xx.h +++ b/arch/powerpc/platforms/83xx/mpc83xx.h | |||
@@ -10,5 +10,8 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | extern int add_bridge(struct device_node *dev); | 12 | extern int add_bridge(struct device_node *dev); |
13 | extern int mpc83xx_exclude_device(u_char bus, u_char devfn); | ||
14 | extern void mpc83xx_restart(char *cmd); | ||
15 | extern long mpc83xx_time_init(void); | ||
13 | 16 | ||
14 | #endif /* __MPC83XX_H__ */ | 17 | #endif /* __MPC83XX_H__ */ |
diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c index 469cdacc5bd4..16f7d3b30e1d 100644 --- a/arch/powerpc/platforms/83xx/pci.c +++ b/arch/powerpc/platforms/83xx/pci.c | |||
@@ -36,7 +36,16 @@ | |||
36 | 36 | ||
37 | int mpc83xx_pci2_busno; | 37 | int mpc83xx_pci2_busno; |
38 | 38 | ||
39 | #ifdef CONFIG_PCI | 39 | int mpc83xx_exclude_device(u_char bus, u_char devfn) |
40 | { | ||
41 | if (bus == 0 && PCI_SLOT(devfn) == 0) | ||
42 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
43 | if (mpc83xx_pci2_busno) | ||
44 | if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0) | ||
45 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
46 | return PCIBIOS_SUCCESSFUL; | ||
47 | } | ||
48 | |||
40 | int __init add_bridge(struct device_node *dev) | 49 | int __init add_bridge(struct device_node *dev) |
41 | { | 50 | { |
42 | int len; | 51 | int len; |
@@ -52,7 +61,7 @@ int __init add_bridge(struct device_node *dev) | |||
52 | has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); | 61 | has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); |
53 | 62 | ||
54 | /* Get bus range if any */ | 63 | /* Get bus range if any */ |
55 | bus_range = (int *) get_property(dev, "bus-range", &len); | 64 | bus_range = (int *)get_property(dev, "bus-range", &len); |
56 | if (bus_range == NULL || len < 2 * sizeof(int)) { | 65 | if (bus_range == NULL || len < 2 * sizeof(int)) { |
57 | printk(KERN_WARNING "Can't get bus-range for %s, assume" | 66 | printk(KERN_WARNING "Can't get bus-range for %s, assume" |
58 | " bus 0\n", dev->full_name); | 67 | " bus 0\n", dev->full_name); |
@@ -74,7 +83,7 @@ int __init add_bridge(struct device_node *dev) | |||
74 | if ((rsrc.start & 0xfffff) == 0x8500) { | 83 | if ((rsrc.start & 0xfffff) == 0x8500) { |
75 | setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304); | 84 | setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304); |
76 | } | 85 | } |
77 | /* PCI 2*/ | 86 | /* PCI 2 */ |
78 | if ((rsrc.start & 0xfffff) == 0x8600) { | 87 | if ((rsrc.start & 0xfffff) == 0x8600) { |
79 | setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384); | 88 | setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384); |
80 | primary = 0; | 89 | primary = 0; |
@@ -84,10 +93,10 @@ int __init add_bridge(struct device_node *dev) | |||
84 | 93 | ||
85 | printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%08lx. " | 94 | printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%08lx. " |
86 | "Firmware bus number: %d->%d\n", | 95 | "Firmware bus number: %d->%d\n", |
87 | rsrc.start, hose->first_busno, hose->last_busno); | 96 | rsrc.start, hose->first_busno, hose->last_busno); |
88 | 97 | ||
89 | DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", | 98 | DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", |
90 | hose, hose->cfg_addr, hose->cfg_data); | 99 | hose, hose->cfg_addr, hose->cfg_data); |
91 | 100 | ||
92 | /* Interpret the "ranges" property */ | 101 | /* Interpret the "ranges" property */ |
93 | /* This also maps the I/O region and sets isa_io/mem_base */ | 102 | /* This also maps the I/O region and sets isa_io/mem_base */ |
@@ -95,5 +104,3 @@ int __init add_bridge(struct device_node *dev) | |||
95 | 104 | ||
96 | return 0; | 105 | return 0; |
97 | } | 106 | } |
98 | |||
99 | #endif | ||
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index c5bc2821d991..06e371282f57 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig | |||
@@ -1,86 +1,31 @@ | |||
1 | config 85xx | 1 | menu "Platform support" |
2 | bool | 2 | depends on PPC_85xx |
3 | depends on E500 | ||
4 | default y | ||
5 | |||
6 | config PPC_INDIRECT_PCI_BE | ||
7 | bool | ||
8 | depends on 85xx | ||
9 | default y | ||
10 | |||
11 | menu "Freescale 85xx options" | ||
12 | depends on E500 | ||
13 | 3 | ||
14 | choice | 4 | choice |
15 | prompt "Machine Type" | 5 | prompt "Machine Type" |
16 | depends on 85xx | ||
17 | default MPC8540_ADS | 6 | default MPC8540_ADS |
18 | 7 | ||
19 | config MPC8540_ADS | 8 | config MPC8540_ADS |
20 | bool "Freescale MPC8540 ADS" | 9 | bool "Freescale MPC8540 ADS" |
10 | select DEFAULT_UIMAGE | ||
21 | help | 11 | help |
22 | This option enables support for the MPC 8540 ADS evaluation board. | 12 | This option enables support for the MPC 8540 ADS board |
23 | |||
24 | config MPC8548_CDS | ||
25 | bool "Freescale MPC8548 CDS" | ||
26 | help | ||
27 | This option enablese support for the MPC8548 CDS evaluation board. | ||
28 | |||
29 | config MPC8555_CDS | ||
30 | bool "Freescale MPC8555 CDS" | ||
31 | help | ||
32 | This option enablese support for the MPC8555 CDS evaluation board. | ||
33 | |||
34 | config MPC8560_ADS | ||
35 | bool "Freescale MPC8560 ADS" | ||
36 | help | ||
37 | This option enables support for the MPC 8560 ADS evaluation board. | ||
38 | |||
39 | config SBC8560 | ||
40 | bool "WindRiver PowerQUICC III SBC8560" | ||
41 | help | ||
42 | This option enables support for the WindRiver PowerQUICC III | ||
43 | SBC8560 board. | ||
44 | |||
45 | config STX_GP3 | ||
46 | bool "Silicon Turnkey Express GP3" | ||
47 | help | ||
48 | This option enables support for the Silicon Turnkey Express GP3 | ||
49 | board. | ||
50 | 13 | ||
51 | endchoice | 14 | endchoice |
52 | 15 | ||
53 | # It's often necessary to know the specific 85xx processor type. | ||
54 | # Fortunately, it is implied (so far) from the board type, so we | ||
55 | # don't need to ask more redundant questions. | ||
56 | config MPC8540 | 16 | config MPC8540 |
57 | bool | 17 | bool |
58 | depends on MPC8540_ADS | 18 | select PPC_UDBG_16550 |
59 | default y | 19 | select PPC_INDIRECT_PCI |
60 | 20 | default y if MPC8540_ADS | |
61 | config MPC8548 | ||
62 | bool | ||
63 | depends on MPC8548_CDS | ||
64 | default y | ||
65 | 21 | ||
66 | config MPC8555 | 22 | config PPC_INDIRECT_PCI_BE |
67 | bool | ||
68 | depends on MPC8555_CDS | ||
69 | default y | ||
70 | |||
71 | config MPC8560 | ||
72 | bool | 23 | bool |
73 | depends on SBC8560 || MPC8560_ADS || STX_GP3 | 24 | depends on PPC_85xx |
74 | default y | ||
75 | |||
76 | config 85xx_PCI2 | ||
77 | bool "Supprt for 2nd PCI host controller" | ||
78 | depends on MPC8555_CDS | ||
79 | default y | 25 | default y |
80 | 26 | ||
81 | config PPC_GEN550 | 27 | config MPIC |
82 | bool | 28 | bool |
83 | depends on MPC8540 || SBC8560 || MPC8555 | ||
84 | default y | 29 | default y |
85 | 30 | ||
86 | endmenu | 31 | endmenu |
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 6407197ffd89..ffc4139cb214 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile | |||
@@ -1 +1,5 @@ | |||
1 | # empty makefile so make clean works | 1 | # |
2 | # Makefile for the PowerPC 85xx linux kernel. | ||
3 | # | ||
4 | obj-$(CONFIG_PPC_85xx) += misc.o pci.o | ||
5 | obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o | ||
diff --git a/arch/powerpc/platforms/85xx/misc.c b/arch/powerpc/platforms/85xx/misc.c new file mode 100644 index 000000000000..26c5e822c7c8 --- /dev/null +++ b/arch/powerpc/platforms/85xx/misc.c | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * MPC85xx generic code. | ||
3 | * | ||
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
5 | * | ||
6 | * Copyright 2005 Freescale Semiconductor Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | #include <linux/irq.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <asm/irq.h> | ||
16 | |||
17 | extern void abort(void); | ||
18 | |||
19 | void mpc85xx_restart(char *cmd) | ||
20 | { | ||
21 | local_irq_disable(); | ||
22 | abort(); | ||
23 | } | ||
24 | |||
25 | /* For now this is a pass through */ | ||
26 | phys_addr_t fixup_bigphys_addr(phys_addr_t addr, phys_addr_t size) | ||
27 | { | ||
28 | return addr; | ||
29 | }; | ||
30 | |||
31 | EXPORT_SYMBOL(fixup_bigphys_addr); | ||
diff --git a/arch/powerpc/platforms/85xx/mpc8540_ads.h b/arch/powerpc/platforms/85xx/mpc8540_ads.h new file mode 100644 index 000000000000..f770cadb2080 --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc8540_ads.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/85xx/mpc8540_ads.h | ||
3 | * | ||
4 | * MPC8540ADS board definitions | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2004 Freescale Semiconductor Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __MACH_MPC8540ADS_H__ | ||
18 | #define __MACH_MPC8540ADS_H__ | ||
19 | |||
20 | #include <linux/config.h> | ||
21 | #include <linux/initrd.h> | ||
22 | |||
23 | #define BOARD_CCSRBAR ((uint)0xe0000000) | ||
24 | #define BCSR_ADDR ((uint)0xf8000000) | ||
25 | #define BCSR_SIZE ((uint)(32 * 1024)) | ||
26 | |||
27 | /* PCI interrupt controller */ | ||
28 | #define PIRQA MPC85xx_IRQ_EXT1 | ||
29 | #define PIRQB MPC85xx_IRQ_EXT2 | ||
30 | #define PIRQC MPC85xx_IRQ_EXT3 | ||
31 | #define PIRQD MPC85xx_IRQ_EXT4 | ||
32 | |||
33 | /* Offset of CPM register space */ | ||
34 | #define CPM_MAP_ADDR (CCSRBAR + MPC85xx_CPM_OFFSET) | ||
35 | |||
36 | #endif /* __MACH_MPC8540ADS_H__ */ | ||
diff --git a/arch/powerpc/platforms/85xx/mpc85xx.h b/arch/powerpc/platforms/85xx/mpc85xx.h new file mode 100644 index 000000000000..b44db6268f3d --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc85xx.h | |||
@@ -0,0 +1,18 @@ | |||
1 | /* | ||
2 | * arch/ppc/platforms/85xx/mpc85xx.h | ||
3 | * | ||
4 | * MPC85xx soc definitions/function decls | ||
5 | * | ||
6 | * Maintainer: Kumar Gala <kumar.gala@freescale.com> | ||
7 | * | ||
8 | * Copyright 2005 Freescale Semiconductor Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | extern void mpc85xx_restart(char *); | ||
18 | extern int add_bridge(struct device_node *dev); | ||
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c new file mode 100644 index 000000000000..b7821dbae00d --- /dev/null +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c | |||
@@ -0,0 +1,244 @@ | |||
1 | /* | ||
2 | * MPC85xx setup and early boot code plus other random bits. | ||
3 | * | ||
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
5 | * | ||
6 | * Copyright 2005 Freescale Semiconductor Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/config.h> | ||
15 | #include <linux/stddef.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/kdev_t.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/seq_file.h> | ||
21 | #include <linux/root_dev.h> | ||
22 | |||
23 | #include <asm/system.h> | ||
24 | #include <asm/time.h> | ||
25 | #include <asm/machdep.h> | ||
26 | #include <asm/pci-bridge.h> | ||
27 | #include <asm/mpc85xx.h> | ||
28 | #include <asm/prom.h> | ||
29 | #include <asm/mpic.h> | ||
30 | #include <mm/mmu_decl.h> | ||
31 | #include <asm/udbg.h> | ||
32 | |||
33 | #include <sysdev/fsl_soc.h> | ||
34 | #include "mpc85xx.h" | ||
35 | |||
36 | #ifndef CONFIG_PCI | ||
37 | unsigned long isa_io_base = 0; | ||
38 | unsigned long isa_mem_base = 0; | ||
39 | #endif | ||
40 | |||
41 | /* | ||
42 | * Internal interrupts are all Level Sensitive, and Positive Polarity | ||
43 | * | ||
44 | * Note: Likely, this table and the following function should be | ||
45 | * obtained and derived from the OF Device Tree. | ||
46 | */ | ||
47 | static u_char mpc85xx_ads_openpic_initsenses[] __initdata = { | ||
48 | MPC85XX_INTERNAL_IRQ_SENSES, | ||
49 | 0x0, /* External 0: */ | ||
50 | #if defined(CONFIG_PCI) | ||
51 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 1: PCI slot 0 */ | ||
52 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 2: PCI slot 1 */ | ||
53 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 3: PCI slot 2 */ | ||
54 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* Ext 4: PCI slot 3 */ | ||
55 | #else | ||
56 | 0x0, /* External 1: */ | ||
57 | 0x0, /* External 2: */ | ||
58 | 0x0, /* External 3: */ | ||
59 | 0x0, /* External 4: */ | ||
60 | #endif | ||
61 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 5: PHY */ | ||
62 | 0x0, /* External 6: */ | ||
63 | (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 7: PHY */ | ||
64 | 0x0, /* External 8: */ | ||
65 | 0x0, /* External 9: */ | ||
66 | 0x0, /* External 10: */ | ||
67 | 0x0, /* External 11: */ | ||
68 | }; | ||
69 | |||
70 | #ifdef CONFIG_PCI | ||
71 | /* | ||
72 | * interrupt routing | ||
73 | */ | ||
74 | |||
75 | int | ||
76 | mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
77 | { | ||
78 | static char pci_irq_table[][4] = | ||
79 | /* | ||
80 | * This is little evil, but works around the fact | ||
81 | * that revA boards have IDSEL starting at 18 | ||
82 | * and others boards (older) start at 12 | ||
83 | * | ||
84 | * PCI IDSEL/INTPIN->INTLINE | ||
85 | * A B C D | ||
86 | */ | ||
87 | { | ||
88 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 2 */ | ||
89 | {PIRQD, PIRQA, PIRQB, PIRQC}, | ||
90 | {PIRQC, PIRQD, PIRQA, PIRQB}, | ||
91 | {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 5 */ | ||
92 | {0, 0, 0, 0}, /* -- */ | ||
93 | {0, 0, 0, 0}, /* -- */ | ||
94 | {0, 0, 0, 0}, /* -- */ | ||
95 | {0, 0, 0, 0}, /* -- */ | ||
96 | {0, 0, 0, 0}, /* -- */ | ||
97 | {0, 0, 0, 0}, /* -- */ | ||
98 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 12 */ | ||
99 | {PIRQD, PIRQA, PIRQB, PIRQC}, | ||
100 | {PIRQC, PIRQD, PIRQA, PIRQB}, | ||
101 | {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 15 */ | ||
102 | {0, 0, 0, 0}, /* -- */ | ||
103 | {0, 0, 0, 0}, /* -- */ | ||
104 | {PIRQA, PIRQB, PIRQC, PIRQD}, /* IDSEL 18 */ | ||
105 | {PIRQD, PIRQA, PIRQB, PIRQC}, | ||
106 | {PIRQC, PIRQD, PIRQA, PIRQB}, | ||
107 | {PIRQB, PIRQC, PIRQD, PIRQA}, /* IDSEL 21 */ | ||
108 | }; | ||
109 | |||
110 | const long min_idsel = 2, max_idsel = 21, irqs_per_slot = 4; | ||
111 | return PCI_IRQ_TABLE_LOOKUP; | ||
112 | } | ||
113 | |||
114 | int | ||
115 | mpc85xx_exclude_device(u_char bus, u_char devfn) | ||
116 | { | ||
117 | if (bus == 0 && PCI_SLOT(devfn) == 0) | ||
118 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
119 | else | ||
120 | return PCIBIOS_SUCCESSFUL; | ||
121 | } | ||
122 | |||
123 | #endif /* CONFIG_PCI */ | ||
124 | |||
125 | |||
126 | void __init mpc85xx_ads_pic_init(void) | ||
127 | { | ||
128 | struct mpic *mpic1; | ||
129 | phys_addr_t OpenPIC_PAddr; | ||
130 | |||
131 | /* Determine the Physical Address of the OpenPIC regs */ | ||
132 | OpenPIC_PAddr = get_immrbase() + MPC85xx_OPENPIC_OFFSET; | ||
133 | |||
134 | mpic1 = mpic_alloc(OpenPIC_PAddr, | ||
135 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | ||
136 | 4, MPC85xx_OPENPIC_IRQ_OFFSET, 0, 250, | ||
137 | mpc85xx_ads_openpic_initsenses, | ||
138 | sizeof(mpc85xx_ads_openpic_initsenses), | ||
139 | " OpenPIC "); | ||
140 | BUG_ON(mpic1 == NULL); | ||
141 | mpic_assign_isu(mpic1, 0, OpenPIC_PAddr + 0x10200); | ||
142 | mpic_assign_isu(mpic1, 1, OpenPIC_PAddr + 0x10280); | ||
143 | mpic_assign_isu(mpic1, 2, OpenPIC_PAddr + 0x10300); | ||
144 | mpic_assign_isu(mpic1, 3, OpenPIC_PAddr + 0x10380); | ||
145 | mpic_assign_isu(mpic1, 4, OpenPIC_PAddr + 0x10400); | ||
146 | mpic_assign_isu(mpic1, 5, OpenPIC_PAddr + 0x10480); | ||
147 | mpic_assign_isu(mpic1, 6, OpenPIC_PAddr + 0x10500); | ||
148 | mpic_assign_isu(mpic1, 7, OpenPIC_PAddr + 0x10580); | ||
149 | |||
150 | /* dummy mappings to get to 48 */ | ||
151 | mpic_assign_isu(mpic1, 8, OpenPIC_PAddr + 0x10600); | ||
152 | mpic_assign_isu(mpic1, 9, OpenPIC_PAddr + 0x10680); | ||
153 | mpic_assign_isu(mpic1, 10, OpenPIC_PAddr + 0x10700); | ||
154 | mpic_assign_isu(mpic1, 11, OpenPIC_PAddr + 0x10780); | ||
155 | |||
156 | /* External ints */ | ||
157 | mpic_assign_isu(mpic1, 12, OpenPIC_PAddr + 0x10000); | ||
158 | mpic_assign_isu(mpic1, 13, OpenPIC_PAddr + 0x10080); | ||
159 | mpic_assign_isu(mpic1, 14, OpenPIC_PAddr + 0x10100); | ||
160 | mpic_init(mpic1); | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * Setup the architecture | ||
165 | */ | ||
166 | static void __init mpc85xx_ads_setup_arch(void) | ||
167 | { | ||
168 | struct device_node *cpu; | ||
169 | struct device_node *np; | ||
170 | |||
171 | if (ppc_md.progress) | ||
172 | ppc_md.progress("mpc85xx_ads_setup_arch()", 0); | ||
173 | |||
174 | cpu = of_find_node_by_type(NULL, "cpu"); | ||
175 | if (cpu != 0) { | ||
176 | unsigned int *fp; | ||
177 | |||
178 | fp = (int *)get_property(cpu, "clock-frequency", NULL); | ||
179 | if (fp != 0) | ||
180 | loops_per_jiffy = *fp / HZ; | ||
181 | else | ||
182 | loops_per_jiffy = 50000000 / HZ; | ||
183 | of_node_put(cpu); | ||
184 | } | ||
185 | |||
186 | #ifdef CONFIG_PCI | ||
187 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | ||
188 | add_bridge(np); | ||
189 | |||
190 | ppc_md.pci_swizzle = common_swizzle; | ||
191 | ppc_md.pci_map_irq = mpc85xx_map_irq; | ||
192 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; | ||
193 | #endif | ||
194 | |||
195 | #ifdef CONFIG_ROOT_NFS | ||
196 | ROOT_DEV = Root_NFS; | ||
197 | #else | ||
198 | ROOT_DEV = Root_HDA1; | ||
199 | #endif | ||
200 | } | ||
201 | |||
202 | void mpc85xx_ads_show_cpuinfo(struct seq_file *m) | ||
203 | { | ||
204 | uint pvid, svid, phid1; | ||
205 | uint memsize = total_memory; | ||
206 | |||
207 | pvid = mfspr(SPRN_PVR); | ||
208 | svid = mfspr(SPRN_SVR); | ||
209 | |||
210 | seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); | ||
211 | seq_printf(m, "Machine\t\t: mpc85xx\n"); | ||
212 | seq_printf(m, "PVR\t\t: 0x%x\n", pvid); | ||
213 | seq_printf(m, "SVR\t\t: 0x%x\n", svid); | ||
214 | |||
215 | /* Display cpu Pll setting */ | ||
216 | phid1 = mfspr(SPRN_HID1); | ||
217 | seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); | ||
218 | |||
219 | /* Display the amount of memory */ | ||
220 | seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); | ||
221 | } | ||
222 | |||
223 | void __init platform_init(void) | ||
224 | { | ||
225 | ppc_md.setup_arch = mpc85xx_ads_setup_arch; | ||
226 | ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo; | ||
227 | |||
228 | ppc_md.init_IRQ = mpc85xx_ads_pic_init; | ||
229 | ppc_md.get_irq = mpic_get_irq; | ||
230 | |||
231 | ppc_md.restart = mpc85xx_restart; | ||
232 | ppc_md.power_off = NULL; | ||
233 | ppc_md.halt = NULL; | ||
234 | |||
235 | ppc_md.time_init = NULL; | ||
236 | ppc_md.set_rtc_time = NULL; | ||
237 | ppc_md.get_rtc_time = NULL; | ||
238 | ppc_md.calibrate_decr = generic_calibrate_decr; | ||
239 | |||
240 | ppc_md.progress = udbg_progress; | ||
241 | |||
242 | if (ppc_md.progress) | ||
243 | ppc_md.progress("mpc85xx_ads platform_init(): exit", 0); | ||
244 | } | ||
diff --git a/arch/powerpc/platforms/85xx/pci.c b/arch/powerpc/platforms/85xx/pci.c new file mode 100644 index 000000000000..bad290110ed1 --- /dev/null +++ b/arch/powerpc/platforms/85xx/pci.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * FSL SoC setup code | ||
3 | * | ||
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
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/config.h> | ||
13 | #include <linux/stddef.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/irq.h> | ||
20 | #include <linux/module.h> | ||
21 | |||
22 | #include <asm/system.h> | ||
23 | #include <asm/atomic.h> | ||
24 | #include <asm/io.h> | ||
25 | #include <asm/pci-bridge.h> | ||
26 | #include <asm/prom.h> | ||
27 | #include <sysdev/fsl_soc.h> | ||
28 | |||
29 | #undef DEBUG | ||
30 | |||
31 | #ifdef DEBUG | ||
32 | #define DBG(x...) printk(x) | ||
33 | #else | ||
34 | #define DBG(x...) | ||
35 | #endif | ||
36 | |||
37 | int mpc85xx_pci2_busno = 0; | ||
38 | |||
39 | #ifdef CONFIG_PCI | ||
40 | int __init add_bridge(struct device_node *dev) | ||
41 | { | ||
42 | int len; | ||
43 | struct pci_controller *hose; | ||
44 | struct resource rsrc; | ||
45 | int *bus_range; | ||
46 | int primary = 1, has_address = 0; | ||
47 | phys_addr_t immr = get_immrbase(); | ||
48 | |||
49 | DBG("Adding PCI host bridge %s\n", dev->full_name); | ||
50 | |||
51 | /* Fetch host bridge registers address */ | ||
52 | has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); | ||
53 | |||
54 | /* Get bus range if any */ | ||
55 | bus_range = (int *) get_property(dev, "bus-range", &len); | ||
56 | if (bus_range == NULL || len < 2 * sizeof(int)) { | ||
57 | printk(KERN_WARNING "Can't get bus-range for %s, assume" | ||
58 | " bus 0\n", dev->full_name); | ||
59 | } | ||
60 | |||
61 | hose = pcibios_alloc_controller(); | ||
62 | if (!hose) | ||
63 | return -ENOMEM; | ||
64 | hose->arch_data = dev; | ||
65 | hose->set_cfg_type = 1; | ||
66 | |||
67 | hose->first_busno = bus_range ? bus_range[0] : 0; | ||
68 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | ||
69 | |||
70 | /* PCI 1 */ | ||
71 | if ((rsrc.start & 0xfffff) == 0x8000) { | ||
72 | setup_indirect_pci(hose, immr + 0x8000, immr + 0x8004); | ||
73 | } | ||
74 | /* PCI 2 */ | ||
75 | if ((rsrc.start & 0xfffff) == 0x9000) { | ||
76 | setup_indirect_pci(hose, immr + 0x9000, immr + 0x9004); | ||
77 | primary = 0; | ||
78 | hose->bus_offset = hose->first_busno; | ||
79 | mpc85xx_pci2_busno = hose->first_busno; | ||
80 | } | ||
81 | |||
82 | printk(KERN_INFO "Found MPC85xx PCI host bridge at 0x%08lx. " | ||
83 | "Firmware bus number: %d->%d\n", | ||
84 | rsrc.start, hose->first_busno, hose->last_busno); | ||
85 | |||
86 | DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", | ||
87 | hose, hose->cfg_addr, hose->cfg_data); | ||
88 | |||
89 | /* Interpret the "ranges" property */ | ||
90 | /* This also maps the I/O region and sets isa_io/mem_base */ | ||
91 | pci_process_bridge_OF_ranges(hose, dev, primary); | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | #endif | ||
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile index 04073fd987ec..c4f6b0d2d140 100644 --- a/arch/powerpc/platforms/Makefile +++ b/arch/powerpc/platforms/Makefile | |||
@@ -8,7 +8,7 @@ endif | |||
8 | obj-$(CONFIG_PPC_CHRP) += chrp/ | 8 | obj-$(CONFIG_PPC_CHRP) += chrp/ |
9 | obj-$(CONFIG_4xx) += 4xx/ | 9 | obj-$(CONFIG_4xx) += 4xx/ |
10 | obj-$(CONFIG_PPC_83xx) += 83xx/ | 10 | obj-$(CONFIG_PPC_83xx) += 83xx/ |
11 | obj-$(CONFIG_85xx) += 85xx/ | 11 | obj-$(CONFIG_PPC_85xx) += 85xx/ |
12 | obj-$(CONFIG_PPC_PSERIES) += pseries/ | 12 | obj-$(CONFIG_PPC_PSERIES) += pseries/ |
13 | obj-$(CONFIG_PPC_ISERIES) += iseries/ | 13 | obj-$(CONFIG_PPC_ISERIES) += iseries/ |
14 | obj-$(CONFIG_PPC_MAPLE) += maple/ | 14 | obj-$(CONFIG_PPC_MAPLE) += maple/ |
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig index 3157071e241c..c2a3db8edb0c 100644 --- a/arch/powerpc/platforms/cell/Kconfig +++ b/arch/powerpc/platforms/cell/Kconfig | |||
@@ -10,4 +10,9 @@ config SPU_FS | |||
10 | Units on machines implementing the Broadband Processor | 10 | Units on machines implementing the Broadband Processor |
11 | Architecture. | 11 | Architecture. |
12 | 12 | ||
13 | config SPUFS_MMAP | ||
14 | bool | ||
15 | depends on SPU_FS && SPARSEMEM && !PPC_64K_PAGES | ||
16 | default y | ||
17 | |||
13 | endmenu | 18 | endmenu |
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile index 3b998a393e3f..e570bad06394 100644 --- a/arch/powerpc/platforms/cell/Makefile +++ b/arch/powerpc/platforms/cell/Makefile | |||
@@ -6,5 +6,11 @@ obj-$(CONFIG_SPU_FS) += spu-base.o spufs/ | |||
6 | 6 | ||
7 | spu-base-y += spu_base.o spu_priv1.o | 7 | spu-base-y += spu_base.o spu_priv1.o |
8 | 8 | ||
9 | builtin-spufs-$(CONFIG_SPU_FS) += spu_syscalls.o | 9 | # needed only when building loadable spufs.ko |
10 | obj-y += $(builtin-spufs-m) | 10 | spufs-modular-$(CONFIG_SPU_FS) += spu_syscalls.o |
11 | obj-y += $(spufs-modular-m) | ||
12 | |||
13 | # always needed in kernel | ||
14 | spufs-builtin-$(CONFIG_SPU_FS) += spu_callbacks.o | ||
15 | obj-y += $(spufs-builtin-y) $(spufs-builtin-m) | ||
16 | |||
diff --git a/arch/powerpc/platforms/cell/interrupt.c b/arch/powerpc/platforms/cell/interrupt.c index 63aa52acf441..978be1c30c1b 100644 --- a/arch/powerpc/platforms/cell/interrupt.c +++ b/arch/powerpc/platforms/cell/interrupt.c | |||
@@ -63,7 +63,24 @@ static DEFINE_PER_CPU(struct iic, iic); | |||
63 | 63 | ||
64 | void iic_local_enable(void) | 64 | void iic_local_enable(void) |
65 | { | 65 | { |
66 | out_be64(&__get_cpu_var(iic).regs->prio, 0xff); | 66 | struct iic *iic = &__get_cpu_var(iic); |
67 | u64 tmp; | ||
68 | |||
69 | /* | ||
70 | * There seems to be a bug that is present in DD2.x CPUs | ||
71 | * and still only partially fixed in DD3.1. | ||
72 | * This bug causes a value written to the priority register | ||
73 | * not to make it there, resulting in a system hang unless we | ||
74 | * write it again. | ||
75 | * Masking with 0xf0 is done because the Cell BE does not | ||
76 | * implement the lower four bits of the interrupt priority, | ||
77 | * they always read back as zeroes, although future CPUs | ||
78 | * might implement different bits. | ||
79 | */ | ||
80 | do { | ||
81 | out_be64(&iic->regs->prio, 0xff); | ||
82 | tmp = in_be64(&iic->regs->prio); | ||
83 | } while ((tmp & 0xf0) != 0xf0); | ||
67 | } | 84 | } |
68 | 85 | ||
69 | void iic_local_disable(void) | 86 | void iic_local_disable(void) |
@@ -123,7 +140,7 @@ static int iic_external_get_irq(struct iic_pending_bits pending) | |||
123 | pending.class != 2) | 140 | pending.class != 2) |
124 | break; | 141 | break; |
125 | irq = IIC_EXT_OFFSET | 142 | irq = IIC_EXT_OFFSET |
126 | + spider_get_irq(pending.prio + node * IIC_NODE_STRIDE) | 143 | + spider_get_irq(node) |
127 | + node * IIC_NODE_STRIDE; | 144 | + node * IIC_NODE_STRIDE; |
128 | break; | 145 | break; |
129 | case 0x01 ... 0x04: | 146 | case 0x01 ... 0x04: |
@@ -174,38 +191,98 @@ int iic_get_irq(struct pt_regs *regs) | |||
174 | return irq; | 191 | return irq; |
175 | } | 192 | } |
176 | 193 | ||
177 | static int setup_iic(int cpu, struct iic *iic) | 194 | /* hardcoded part to be compatible with older firmware */ |
195 | |||
196 | static int setup_iic_hardcoded(void) | ||
178 | { | 197 | { |
179 | struct device_node *np; | 198 | struct device_node *np; |
180 | int nodeid = cpu / 2; | 199 | int nodeid, cpu; |
181 | unsigned long regs; | 200 | unsigned long regs; |
201 | struct iic *iic; | ||
182 | 202 | ||
183 | for (np = of_find_node_by_type(NULL, "cpu"); | 203 | for_each_cpu(cpu) { |
184 | np; | 204 | iic = &per_cpu(iic, cpu); |
185 | np = of_find_node_by_type(np, "cpu")) { | 205 | nodeid = cpu/2; |
186 | if (nodeid == *(int *)get_property(np, "node-id", NULL)) | 206 | |
187 | break; | 207 | for (np = of_find_node_by_type(NULL, "cpu"); |
208 | np; | ||
209 | np = of_find_node_by_type(np, "cpu")) { | ||
210 | if (nodeid == *(int *)get_property(np, "node-id", NULL)) | ||
211 | break; | ||
212 | } | ||
213 | |||
214 | if (!np) { | ||
215 | printk(KERN_WARNING "IIC: CPU %d not found\n", cpu); | ||
216 | iic->regs = NULL; | ||
217 | iic->target_id = 0xff; | ||
218 | return -ENODEV; | ||
219 | } | ||
220 | |||
221 | regs = *(long *)get_property(np, "iic", NULL); | ||
222 | |||
223 | /* hack until we have decided on the devtree info */ | ||
224 | regs += 0x400; | ||
225 | if (cpu & 1) | ||
226 | regs += 0x20; | ||
227 | |||
228 | printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs); | ||
229 | iic->regs = ioremap(regs, sizeof(struct iic_regs)); | ||
230 | iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe); | ||
188 | } | 231 | } |
189 | 232 | ||
190 | if (!np) { | 233 | return 0; |
191 | printk(KERN_WARNING "IIC: CPU %d not found\n", cpu); | 234 | } |
192 | iic->regs = NULL; | ||
193 | iic->target_id = 0xff; | ||
194 | return -ENODEV; | ||
195 | } | ||
196 | 235 | ||
197 | regs = *(long *)get_property(np, "iic", NULL); | 236 | static int setup_iic(void) |
237 | { | ||
238 | struct device_node *dn; | ||
239 | unsigned long *regs; | ||
240 | char *compatible; | ||
241 | unsigned *np, found = 0; | ||
242 | struct iic *iic = NULL; | ||
243 | |||
244 | for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) { | ||
245 | compatible = (char *)get_property(dn, "compatible", NULL); | ||
246 | |||
247 | if (!compatible) { | ||
248 | printk(KERN_WARNING "no compatible property found !\n"); | ||
249 | continue; | ||
250 | } | ||
198 | 251 | ||
199 | /* hack until we have decided on the devtree info */ | 252 | if (strstr(compatible, "IBM,CBEA-Internal-Interrupt-Controller")) |
200 | regs += 0x400; | 253 | regs = (unsigned long *)get_property(dn,"reg", NULL); |
201 | if (cpu & 1) | 254 | else |
202 | regs += 0x20; | 255 | continue; |
203 | 256 | ||
204 | printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs); | 257 | if (!regs) |
205 | iic->regs = __ioremap(regs, sizeof(struct iic_regs), | 258 | printk(KERN_WARNING "IIC: no reg property\n"); |
206 | _PAGE_NO_CACHE); | 259 | |
207 | iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe); | 260 | np = (unsigned int *)get_property(dn, "ibm,interrupt-server-ranges", NULL); |
208 | return 0; | 261 | |
262 | if (!np) { | ||
263 | printk(KERN_WARNING "IIC: CPU association not found\n"); | ||
264 | iic->regs = NULL; | ||
265 | iic->target_id = 0xff; | ||
266 | return -ENODEV; | ||
267 | } | ||
268 | |||
269 | iic = &per_cpu(iic, np[0]); | ||
270 | iic->regs = ioremap(regs[0], sizeof(struct iic_regs)); | ||
271 | iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe); | ||
272 | printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs); | ||
273 | |||
274 | iic = &per_cpu(iic, np[1]); | ||
275 | iic->regs = ioremap(regs[2], sizeof(struct iic_regs)); | ||
276 | iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe); | ||
277 | printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs); | ||
278 | |||
279 | found++; | ||
280 | } | ||
281 | |||
282 | if (found) | ||
283 | return 0; | ||
284 | else | ||
285 | return -ENODEV; | ||
209 | } | 286 | } |
210 | 287 | ||
211 | #ifdef CONFIG_SMP | 288 | #ifdef CONFIG_SMP |
@@ -283,10 +360,12 @@ void iic_init_IRQ(void) | |||
283 | int cpu, irq_offset; | 360 | int cpu, irq_offset; |
284 | struct iic *iic; | 361 | struct iic *iic; |
285 | 362 | ||
363 | if (setup_iic() < 0) | ||
364 | setup_iic_hardcoded(); | ||
365 | |||
286 | irq_offset = 0; | 366 | irq_offset = 0; |
287 | for_each_cpu(cpu) { | 367 | for_each_possible_cpu(cpu) { |
288 | iic = &per_cpu(iic, cpu); | 368 | iic = &per_cpu(iic, cpu); |
289 | setup_iic(cpu, iic); | ||
290 | if (iic->regs) | 369 | if (iic->regs) |
291 | out_be64(&iic->regs->prio, 0xff); | 370 | out_be64(&iic->regs->prio, 0xff); |
292 | } | 371 | } |
diff --git a/arch/powerpc/platforms/cell/interrupt.h b/arch/powerpc/platforms/cell/interrupt.h index a14bd38791c0..799f77d98f96 100644 --- a/arch/powerpc/platforms/cell/interrupt.h +++ b/arch/powerpc/platforms/cell/interrupt.h | |||
@@ -57,7 +57,7 @@ extern void iic_local_disable(void); | |||
57 | extern u8 iic_get_target_id(int cpu); | 57 | extern u8 iic_get_target_id(int cpu); |
58 | 58 | ||
59 | extern void spider_init_IRQ(void); | 59 | extern void spider_init_IRQ(void); |
60 | extern int spider_get_irq(unsigned long int_pending); | 60 | extern int spider_get_irq(int node); |
61 | 61 | ||
62 | #endif | 62 | #endif |
63 | #endif /* ASM_CELL_PIC_H */ | 63 | #endif /* ASM_CELL_PIC_H */ |
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index 46e7cb9c3e64..a49ceb799a8e 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c | |||
@@ -289,7 +289,7 @@ static void cell_do_map_iommu(struct cell_iommu *iommu, | |||
289 | ioc_base = iommu->mapped_base; | 289 | ioc_base = iommu->mapped_base; |
290 | ioc_mmio_base = iommu->mapped_mmio_base; | 290 | ioc_mmio_base = iommu->mapped_mmio_base; |
291 | 291 | ||
292 | for (real_address = 0, io_address = 0; | 292 | for (real_address = 0, io_address = map_start; |
293 | io_address <= map_start + map_size; | 293 | io_address <= map_start + map_size; |
294 | real_address += io_page_size, io_address += io_page_size) { | 294 | real_address += io_page_size, io_address += io_page_size) { |
295 | ioste = get_iost_entry(fake_iopt, io_address, io_page_size); | 295 | ioste = get_iost_entry(fake_iopt, io_address, io_page_size); |
@@ -302,7 +302,7 @@ static void cell_do_map_iommu(struct cell_iommu *iommu, | |||
302 | set_iopt_cache(ioc_mmio_base, | 302 | set_iopt_cache(ioc_mmio_base, |
303 | get_ioc_hash_1way(ioste, io_address), | 303 | get_ioc_hash_1way(ioste, io_address), |
304 | get_ioc_tag(ioste, io_address), | 304 | get_ioc_tag(ioste, io_address), |
305 | get_iopt_entry(real_address-map_start, ioid, IOPT_PROT_RW)); | 305 | get_iopt_entry(real_address, ioid, IOPT_PROT_RW)); |
306 | } | 306 | } |
307 | } | 307 | } |
308 | 308 | ||
@@ -344,8 +344,8 @@ static int cell_map_iommu_hardcoded(int num_nodes) | |||
344 | 344 | ||
345 | /* node 0 */ | 345 | /* node 0 */ |
346 | iommu = &cell_iommus[0]; | 346 | iommu = &cell_iommus[0]; |
347 | iommu->mapped_base = __ioremap(0x20000511000, 0x1000, _PAGE_NO_CACHE); | 347 | iommu->mapped_base = ioremap(0x20000511000, 0x1000); |
348 | iommu->mapped_mmio_base = __ioremap(0x20000510000, 0x1000, _PAGE_NO_CACHE); | 348 | iommu->mapped_mmio_base = ioremap(0x20000510000, 0x1000); |
349 | 349 | ||
350 | enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base); | 350 | enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base); |
351 | 351 | ||
@@ -357,8 +357,8 @@ static int cell_map_iommu_hardcoded(int num_nodes) | |||
357 | 357 | ||
358 | /* node 1 */ | 358 | /* node 1 */ |
359 | iommu = &cell_iommus[1]; | 359 | iommu = &cell_iommus[1]; |
360 | iommu->mapped_base = __ioremap(0x30000511000, 0x1000, _PAGE_NO_CACHE); | 360 | iommu->mapped_base = ioremap(0x30000511000, 0x1000); |
361 | iommu->mapped_mmio_base = __ioremap(0x30000510000, 0x1000, _PAGE_NO_CACHE); | 361 | iommu->mapped_mmio_base = ioremap(0x30000510000, 0x1000); |
362 | 362 | ||
363 | enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base); | 363 | enable_mapping(iommu->mapped_base, iommu->mapped_mmio_base); |
364 | 364 | ||
@@ -407,8 +407,8 @@ static int cell_map_iommu(void) | |||
407 | iommu->base = *base; | 407 | iommu->base = *base; |
408 | iommu->mmio_base = *mmio_base; | 408 | iommu->mmio_base = *mmio_base; |
409 | 409 | ||
410 | iommu->mapped_base = __ioremap(*base, 0x1000, _PAGE_NO_CACHE); | 410 | iommu->mapped_base = ioremap(*base, 0x1000); |
411 | iommu->mapped_mmio_base = __ioremap(*mmio_base, 0x1000, _PAGE_NO_CACHE); | 411 | iommu->mapped_mmio_base = ioremap(*mmio_base, 0x1000); |
412 | 412 | ||
413 | enable_mapping(iommu->mapped_base, | 413 | enable_mapping(iommu->mapped_base, |
414 | iommu->mapped_mmio_base); | 414 | iommu->mapped_mmio_base); |
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c index e0e051c675dd..7eed8c624517 100644 --- a/arch/powerpc/platforms/cell/pervasive.c +++ b/arch/powerpc/platforms/cell/pervasive.c | |||
@@ -203,7 +203,7 @@ found: | |||
203 | 203 | ||
204 | pr_debug("pervasive area for CPU %d at %lx, size %x\n", | 204 | pr_debug("pervasive area for CPU %d at %lx, size %x\n", |
205 | cpu, real_address, size); | 205 | cpu, real_address, size); |
206 | p->regs = __ioremap(real_address, size, _PAGE_NO_CACHE); | 206 | p->regs = ioremap(real_address, size); |
207 | p->thread = thread; | 207 | p->thread = thread; |
208 | return 0; | 208 | return 0; |
209 | } | 209 | } |
@@ -217,7 +217,7 @@ void __init cell_pervasive_init(void) | |||
217 | if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) | 217 | if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO)) |
218 | return; | 218 | return; |
219 | 219 | ||
220 | for_each_cpu(cpu) { | 220 | for_each_possible_cpu(cpu) { |
221 | p = &cbe_pervasive[cpu]; | 221 | p = &cbe_pervasive[cpu]; |
222 | ret = cbe_find_pmd_mmio(cpu, p); | 222 | ret = cbe_find_pmd_mmio(cpu, p); |
223 | if (ret) | 223 | if (ret) |
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c index b33a4443f5a9..dac5d0365fde 100644 --- a/arch/powerpc/platforms/cell/setup.c +++ b/arch/powerpc/platforms/cell/setup.c | |||
@@ -115,7 +115,7 @@ static void __init cell_spuprop_present(struct device_node *spe, | |||
115 | for (pfn = start_pfn; pfn < end_pfn; pfn++) { | 115 | for (pfn = start_pfn; pfn < end_pfn; pfn++) { |
116 | struct page *page = pfn_to_page(pfn); | 116 | struct page *page = pfn_to_page(pfn); |
117 | set_page_links(page, ZONE_DMA, node_id, pfn); | 117 | set_page_links(page, ZONE_DMA, node_id, pfn); |
118 | set_page_count(page, 1); | 118 | init_page_count(page); |
119 | reset_page_mapcount(page); | 119 | reset_page_mapcount(page); |
120 | SetPageReserved(page); | 120 | SetPageReserved(page); |
121 | INIT_LIST_HEAD(&page->lru); | 121 | INIT_LIST_HEAD(&page->lru); |
@@ -195,9 +195,13 @@ static void __init cell_init_early(void) | |||
195 | } | 195 | } |
196 | 196 | ||
197 | 197 | ||
198 | static int __init cell_probe(int platform) | 198 | static int __init cell_probe(void) |
199 | { | 199 | { |
200 | if (platform != PLATFORM_CELL) | 200 | /* XXX This is temporary, the Cell maintainer will come up with |
201 | * more appropriate detection logic | ||
202 | */ | ||
203 | unsigned long root = of_get_flat_dt_root(); | ||
204 | if (!of_flat_dt_is_compatible(root, "IBM,CPBW-1.0")) | ||
201 | return 0; | 205 | return 0; |
202 | 206 | ||
203 | return 1; | 207 | return 1; |
@@ -212,7 +216,8 @@ static int cell_check_legacy_ioport(unsigned int baseport) | |||
212 | return -ENODEV; | 216 | return -ENODEV; |
213 | } | 217 | } |
214 | 218 | ||
215 | struct machdep_calls __initdata cell_md = { | 219 | define_machine(cell) { |
220 | .name = "Cell", | ||
216 | .probe = cell_probe, | 221 | .probe = cell_probe, |
217 | .setup_arch = cell_setup_arch, | 222 | .setup_arch = cell_setup_arch, |
218 | .init_early = cell_init_early, | 223 | .init_early = cell_init_early, |
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index e74132188bdf..55cbdd77a62d 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c | |||
@@ -84,10 +84,11 @@ static void __iomem *spider_get_irq_config(int irq) | |||
84 | 84 | ||
85 | static void spider_enable_irq(unsigned int irq) | 85 | static void spider_enable_irq(unsigned int irq) |
86 | { | 86 | { |
87 | int nodeid = (irq / IIC_NODE_STRIDE) * 0x10; | ||
87 | void __iomem *cfg = spider_get_irq_config(irq); | 88 | void __iomem *cfg = spider_get_irq_config(irq); |
88 | irq = spider_get_nr(irq); | 89 | irq = spider_get_nr(irq); |
89 | 90 | ||
90 | out_be32(cfg, in_be32(cfg) | 0x3107000eu); | 91 | out_be32(cfg, (in_be32(cfg) & ~0xf0)| 0x3107000eu | nodeid); |
91 | out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); | 92 | out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq); |
92 | } | 93 | } |
93 | 94 | ||
@@ -131,61 +132,108 @@ static struct hw_interrupt_type spider_pic = { | |||
131 | .end = spider_end_irq, | 132 | .end = spider_end_irq, |
132 | }; | 133 | }; |
133 | 134 | ||
134 | 135 | int spider_get_irq(int node) | |
135 | int spider_get_irq(unsigned long int_pending) | ||
136 | { | 136 | { |
137 | void __iomem *regs = spider_get_pic(int_pending); | ||
138 | unsigned long cs; | 137 | unsigned long cs; |
139 | int irq; | 138 | void __iomem *regs = spider_pics[node]; |
140 | |||
141 | cs = in_be32(regs + TIR_CS); | ||
142 | 139 | ||
143 | irq = cs >> 24; | 140 | cs = in_be32(regs + TIR_CS) >> 24; |
144 | if (irq != 63) | ||
145 | return irq; | ||
146 | 141 | ||
147 | return -1; | 142 | if (cs == 63) |
143 | return -1; | ||
144 | else | ||
145 | return cs; | ||
148 | } | 146 | } |
149 | 147 | ||
150 | void spider_init_IRQ(void) | 148 | /* hardcoded part to be compatible with older firmware */ |
149 | |||
150 | void spider_init_IRQ_hardcoded(void) | ||
151 | { | 151 | { |
152 | int node; | 152 | int node; |
153 | struct device_node *dn; | ||
154 | unsigned int *property; | ||
155 | long spiderpic; | 153 | long spiderpic; |
154 | long pics[] = { 0x24000008000, 0x34000008000 }; | ||
156 | int n; | 155 | int n; |
157 | 156 | ||
158 | /* FIXME: detect multiple PICs as soon as the device tree has them */ | 157 | pr_debug("%s(%d): Using hardcoded defaults\n", __FUNCTION__, __LINE__); |
159 | for (node = 0; node < 1; node++) { | ||
160 | dn = of_find_node_by_path("/"); | ||
161 | n = prom_n_addr_cells(dn); | ||
162 | property = (unsigned int *) get_property(dn, | ||
163 | "platform-spider-pic", NULL); | ||
164 | 158 | ||
165 | if (!property) | 159 | for (node = 0; node < num_present_cpus()/2; node++) { |
166 | continue; | 160 | spiderpic = pics[node]; |
167 | for (spiderpic = 0; n > 0; --n) | ||
168 | spiderpic = (spiderpic << 32) + *property++; | ||
169 | printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic); | 161 | printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic); |
170 | spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE); | 162 | spider_pics[node] = ioremap(spiderpic, 0x800); |
171 | for (n = 0; n < IIC_NUM_EXT; n++) { | 163 | for (n = 0; n < IIC_NUM_EXT; n++) { |
172 | int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; | 164 | int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; |
173 | get_irq_desc(irq)->handler = &spider_pic; | 165 | get_irq_desc(irq)->handler = &spider_pic; |
166 | } | ||
174 | 167 | ||
175 | /* do not mask any interrupts because of level */ | 168 | /* do not mask any interrupts because of level */ |
176 | out_be32(spider_pics[node] + TIR_MSK, 0x0); | 169 | out_be32(spider_pics[node] + TIR_MSK, 0x0); |
177 | 170 | ||
178 | /* disable edge detection clear */ | 171 | /* disable edge detection clear */ |
179 | /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ | 172 | /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ |
180 | 173 | ||
181 | /* enable interrupt packets to be output */ | 174 | /* enable interrupt packets to be output */ |
182 | out_be32(spider_pics[node] + TIR_PIEN, | 175 | out_be32(spider_pics[node] + TIR_PIEN, |
183 | in_be32(spider_pics[node] + TIR_PIEN) | 0x1); | 176 | in_be32(spider_pics[node] + TIR_PIEN) | 0x1); |
184 | 177 | ||
185 | /* Enable the interrupt detection enable bit. Do this last! */ | 178 | /* Enable the interrupt detection enable bit. Do this last! */ |
186 | out_be32(spider_pics[node] + TIR_DEN, | 179 | out_be32(spider_pics[node] + TIR_DEN, |
187 | in_be32(spider_pics[node] +TIR_DEN) | 0x1); | 180 | in_be32(spider_pics[node] + TIR_DEN) | 0x1); |
181 | } | ||
182 | } | ||
183 | |||
184 | void spider_init_IRQ(void) | ||
185 | { | ||
186 | long spider_reg; | ||
187 | struct device_node *dn; | ||
188 | char *compatible; | ||
189 | int n, node = 0; | ||
190 | |||
191 | for (dn = NULL; (dn = of_find_node_by_name(dn, "interrupt-controller"));) { | ||
192 | compatible = (char *)get_property(dn, "compatible", NULL); | ||
188 | 193 | ||
194 | if (!compatible) | ||
195 | continue; | ||
196 | |||
197 | if (strstr(compatible, "CBEA,platform-spider-pic")) | ||
198 | spider_reg = *(long *)get_property(dn,"reg", NULL); | ||
199 | else if (strstr(compatible, "sti,platform-spider-pic")) { | ||
200 | spider_init_IRQ_hardcoded(); | ||
201 | return; | ||
202 | } else | ||
203 | continue; | ||
204 | |||
205 | if (!spider_reg) | ||
206 | printk("interrupt controller does not have reg property !\n"); | ||
207 | |||
208 | n = prom_n_addr_cells(dn); | ||
209 | |||
210 | if ( n != 2) | ||
211 | printk("reg property with invalid number of elements \n"); | ||
212 | |||
213 | spider_pics[node] = ioremap(spider_reg, 0x800); | ||
214 | |||
215 | printk("SPIDER addr: %lx with %i addr_cells mapped to %p\n", | ||
216 | spider_reg, n, spider_pics[node]); | ||
217 | |||
218 | for (n = 0; n < IIC_NUM_EXT; n++) { | ||
219 | int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE; | ||
220 | get_irq_desc(irq)->handler = &spider_pic; | ||
189 | } | 221 | } |
222 | |||
223 | /* do not mask any interrupts because of level */ | ||
224 | out_be32(spider_pics[node] + TIR_MSK, 0x0); | ||
225 | |||
226 | /* disable edge detection clear */ | ||
227 | /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */ | ||
228 | |||
229 | /* enable interrupt packets to be output */ | ||
230 | out_be32(spider_pics[node] + TIR_PIEN, | ||
231 | in_be32(spider_pics[node] + TIR_PIEN) | 0x1); | ||
232 | |||
233 | /* Enable the interrupt detection enable bit. Do this last! */ | ||
234 | out_be32(spider_pics[node] + TIR_DEN, | ||
235 | in_be32(spider_pics[node] + TIR_DEN) | 0x1); | ||
236 | |||
237 | node++; | ||
190 | } | 238 | } |
191 | } | 239 | } |
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index d75ae03df686..269dda4fd0b4 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c | |||
@@ -32,7 +32,7 @@ | |||
32 | 32 | ||
33 | #include <asm/io.h> | 33 | #include <asm/io.h> |
34 | #include <asm/prom.h> | 34 | #include <asm/prom.h> |
35 | #include <asm/semaphore.h> | 35 | #include <linux/mutex.h> |
36 | #include <asm/spu.h> | 36 | #include <asm/spu.h> |
37 | #include <asm/mmu_context.h> | 37 | #include <asm/mmu_context.h> |
38 | 38 | ||
@@ -111,7 +111,7 @@ static int __spu_trap_data_seg(struct spu *spu, unsigned long ea) | |||
111 | extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX | 111 | extern int hash_page(unsigned long ea, unsigned long access, unsigned long trap); //XXX |
112 | static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) | 112 | static int __spu_trap_data_map(struct spu *spu, unsigned long ea, u64 dsisr) |
113 | { | 113 | { |
114 | pr_debug("%s\n", __FUNCTION__); | 114 | pr_debug("%s, %lx, %lx\n", __FUNCTION__, dsisr, ea); |
115 | 115 | ||
116 | /* Handle kernel space hash faults immediately. | 116 | /* Handle kernel space hash faults immediately. |
117 | User hash faults need to be deferred to process context. */ | 117 | User hash faults need to be deferred to process context. */ |
@@ -168,7 +168,7 @@ static int __spu_trap_halt(struct spu *spu) | |||
168 | static int __spu_trap_tag_group(struct spu *spu) | 168 | static int __spu_trap_tag_group(struct spu *spu) |
169 | { | 169 | { |
170 | pr_debug("%s\n", __FUNCTION__); | 170 | pr_debug("%s\n", __FUNCTION__); |
171 | /* wake_up(&spu->dma_wq); */ | 171 | spu->mfc_callback(spu); |
172 | return 0; | 172 | return 0; |
173 | } | 173 | } |
174 | 174 | ||
@@ -242,6 +242,8 @@ spu_irq_class_1(int irq, void *data, struct pt_regs *regs) | |||
242 | spu_mfc_dsisr_set(spu, 0ul); | 242 | spu_mfc_dsisr_set(spu, 0ul); |
243 | spu_int_stat_clear(spu, 1, stat); | 243 | spu_int_stat_clear(spu, 1, stat); |
244 | spin_unlock(&spu->register_lock); | 244 | spin_unlock(&spu->register_lock); |
245 | pr_debug("%s: %lx %lx %lx %lx\n", __FUNCTION__, mask, stat, | ||
246 | dar, dsisr); | ||
245 | 247 | ||
246 | if (stat & 1) /* segment fault */ | 248 | if (stat & 1) /* segment fault */ |
247 | __spu_trap_data_seg(spu, dar); | 249 | __spu_trap_data_seg(spu, dar); |
@@ -342,7 +344,7 @@ spu_free_irqs(struct spu *spu) | |||
342 | } | 344 | } |
343 | 345 | ||
344 | static LIST_HEAD(spu_list); | 346 | static LIST_HEAD(spu_list); |
345 | static DECLARE_MUTEX(spu_mutex); | 347 | static DEFINE_MUTEX(spu_mutex); |
346 | 348 | ||
347 | static void spu_init_channels(struct spu *spu) | 349 | static void spu_init_channels(struct spu *spu) |
348 | { | 350 | { |
@@ -382,7 +384,7 @@ struct spu *spu_alloc(void) | |||
382 | { | 384 | { |
383 | struct spu *spu; | 385 | struct spu *spu; |
384 | 386 | ||
385 | down(&spu_mutex); | 387 | mutex_lock(&spu_mutex); |
386 | if (!list_empty(&spu_list)) { | 388 | if (!list_empty(&spu_list)) { |
387 | spu = list_entry(spu_list.next, struct spu, list); | 389 | spu = list_entry(spu_list.next, struct spu, list); |
388 | list_del_init(&spu->list); | 390 | list_del_init(&spu->list); |
@@ -391,7 +393,7 @@ struct spu *spu_alloc(void) | |||
391 | pr_debug("No SPU left\n"); | 393 | pr_debug("No SPU left\n"); |
392 | spu = NULL; | 394 | spu = NULL; |
393 | } | 395 | } |
394 | up(&spu_mutex); | 396 | mutex_unlock(&spu_mutex); |
395 | 397 | ||
396 | if (spu) | 398 | if (spu) |
397 | spu_init_channels(spu); | 399 | spu_init_channels(spu); |
@@ -402,9 +404,9 @@ EXPORT_SYMBOL_GPL(spu_alloc); | |||
402 | 404 | ||
403 | void spu_free(struct spu *spu) | 405 | void spu_free(struct spu *spu) |
404 | { | 406 | { |
405 | down(&spu_mutex); | 407 | mutex_lock(&spu_mutex); |
406 | list_add_tail(&spu->list, &spu_list); | 408 | list_add_tail(&spu->list, &spu_list); |
407 | up(&spu_mutex); | 409 | mutex_unlock(&spu_mutex); |
408 | } | 410 | } |
409 | EXPORT_SYMBOL_GPL(spu_free); | 411 | EXPORT_SYMBOL_GPL(spu_free); |
410 | 412 | ||
@@ -484,14 +486,13 @@ int spu_irq_class_1_bottom(struct spu *spu) | |||
484 | 486 | ||
485 | ea = spu->dar; | 487 | ea = spu->dar; |
486 | dsisr = spu->dsisr; | 488 | dsisr = spu->dsisr; |
487 | if (dsisr & MFC_DSISR_PTE_NOT_FOUND) { | 489 | if (dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)) { |
488 | access = (_PAGE_PRESENT | _PAGE_USER); | 490 | access = (_PAGE_PRESENT | _PAGE_USER); |
489 | access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL; | 491 | access |= (dsisr & MFC_DSISR_ACCESS_PUT) ? _PAGE_RW : 0UL; |
490 | if (hash_page(ea, access, 0x300) != 0) | 492 | if (hash_page(ea, access, 0x300) != 0) |
491 | error |= CLASS1_ENABLE_STORAGE_FAULT_INTR; | 493 | error |= CLASS1_ENABLE_STORAGE_FAULT_INTR; |
492 | } | 494 | } |
493 | if ((error & CLASS1_ENABLE_STORAGE_FAULT_INTR) || | 495 | if (error & CLASS1_ENABLE_STORAGE_FAULT_INTR) { |
494 | (dsisr & MFC_DSISR_ACCESS_DENIED)) { | ||
495 | if ((ret = spu_handle_mm_fault(spu)) != 0) | 496 | if ((ret = spu_handle_mm_fault(spu)) != 0) |
496 | error |= CLASS1_ENABLE_STORAGE_FAULT_INTR; | 497 | error |= CLASS1_ENABLE_STORAGE_FAULT_INTR; |
497 | else | 498 | else |
@@ -568,6 +569,11 @@ static int __init spu_map_device(struct spu *spu, struct device_node *spe) | |||
568 | if (!spu->local_store) | 569 | if (!spu->local_store) |
569 | goto out; | 570 | goto out; |
570 | 571 | ||
572 | prop = get_property(spe, "problem", NULL); | ||
573 | if (!prop) | ||
574 | goto out_unmap; | ||
575 | spu->problem_phys = *(unsigned long *)prop; | ||
576 | |||
571 | spu->problem= map_spe_prop(spe, "problem"); | 577 | spu->problem= map_spe_prop(spe, "problem"); |
572 | if (!spu->problem) | 578 | if (!spu->problem) |
573 | goto out_unmap; | 579 | goto out_unmap; |
@@ -632,15 +638,16 @@ static int __init create_spu(struct device_node *spe) | |||
632 | spu->ibox_callback = NULL; | 638 | spu->ibox_callback = NULL; |
633 | spu->wbox_callback = NULL; | 639 | spu->wbox_callback = NULL; |
634 | spu->stop_callback = NULL; | 640 | spu->stop_callback = NULL; |
641 | spu->mfc_callback = NULL; | ||
635 | 642 | ||
636 | down(&spu_mutex); | 643 | mutex_lock(&spu_mutex); |
637 | spu->number = number++; | 644 | spu->number = number++; |
638 | ret = spu_request_irqs(spu); | 645 | ret = spu_request_irqs(spu); |
639 | if (ret) | 646 | if (ret) |
640 | goto out_unmap; | 647 | goto out_unmap; |
641 | 648 | ||
642 | list_add(&spu->list, &spu_list); | 649 | list_add(&spu->list, &spu_list); |
643 | up(&spu_mutex); | 650 | mutex_unlock(&spu_mutex); |
644 | 651 | ||
645 | pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n", | 652 | pr_debug(KERN_DEBUG "Using SPE %s %02x %p %p %p %p %d\n", |
646 | spu->name, spu->isrc, spu->local_store, | 653 | spu->name, spu->isrc, spu->local_store, |
@@ -648,7 +655,7 @@ static int __init create_spu(struct device_node *spe) | |||
648 | goto out; | 655 | goto out; |
649 | 656 | ||
650 | out_unmap: | 657 | out_unmap: |
651 | up(&spu_mutex); | 658 | mutex_unlock(&spu_mutex); |
652 | spu_unmap(spu); | 659 | spu_unmap(spu); |
653 | out_free: | 660 | out_free: |
654 | kfree(spu); | 661 | kfree(spu); |
@@ -668,10 +675,10 @@ static void destroy_spu(struct spu *spu) | |||
668 | static void cleanup_spu_base(void) | 675 | static void cleanup_spu_base(void) |
669 | { | 676 | { |
670 | struct spu *spu, *tmp; | 677 | struct spu *spu, *tmp; |
671 | down(&spu_mutex); | 678 | mutex_lock(&spu_mutex); |
672 | list_for_each_entry_safe(spu, tmp, &spu_list, list) | 679 | list_for_each_entry_safe(spu, tmp, &spu_list, list) |
673 | destroy_spu(spu); | 680 | destroy_spu(spu); |
674 | up(&spu_mutex); | 681 | mutex_unlock(&spu_mutex); |
675 | } | 682 | } |
676 | module_exit(cleanup_spu_base); | 683 | module_exit(cleanup_spu_base); |
677 | 684 | ||
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c new file mode 100644 index 000000000000..3a4245c926ad --- /dev/null +++ b/arch/powerpc/platforms/cell/spu_callbacks.c | |||
@@ -0,0 +1,345 @@ | |||
1 | /* | ||
2 | * System call callback functions for SPUs | ||
3 | */ | ||
4 | |||
5 | #define DEBUG | ||
6 | |||
7 | #include <linux/kallsyms.h> | ||
8 | #include <linux/module.h> | ||
9 | #include <linux/syscalls.h> | ||
10 | |||
11 | #include <asm/spu.h> | ||
12 | #include <asm/syscalls.h> | ||
13 | #include <asm/unistd.h> | ||
14 | |||
15 | /* | ||
16 | * This table defines the system calls that an SPU can call. | ||
17 | * It is currently a subset of the 64 bit powerpc system calls, | ||
18 | * with the exact semantics. | ||
19 | * | ||
20 | * The reasons for disabling some of the system calls are: | ||
21 | * 1. They interact with the way SPU syscalls are handled | ||
22 | * and we can't let them execute ever: | ||
23 | * restart_syscall, exit, for, execve, ptrace, ... | ||
24 | * 2. They are deprecated and replaced by other means: | ||
25 | * uselib, pciconfig_*, sysfs, ... | ||
26 | * 3. They are somewhat interacting with the system in a way | ||
27 | * we don't want an SPU to: | ||
28 | * reboot, init_module, mount, kexec_load | ||
29 | * 4. They are optional and we can't rely on them being | ||
30 | * linked into the kernel. Unfortunately, the cond_syscall | ||
31 | * helper does not work here as it does not add the necessary | ||
32 | * opd symbols: | ||
33 | * mbind, mq_open, ipc, ... | ||
34 | */ | ||
35 | |||
36 | void *spu_syscall_table[] = { | ||
37 | [__NR_restart_syscall] sys_ni_syscall, /* sys_restart_syscall */ | ||
38 | [__NR_exit] sys_ni_syscall, /* sys_exit */ | ||
39 | [__NR_fork] sys_ni_syscall, /* ppc_fork */ | ||
40 | [__NR_read] sys_read, | ||
41 | [__NR_write] sys_write, | ||
42 | [__NR_open] sys_open, | ||
43 | [__NR_close] sys_close, | ||
44 | [__NR_waitpid] sys_waitpid, | ||
45 | [__NR_creat] sys_creat, | ||
46 | [__NR_link] sys_link, | ||
47 | [__NR_unlink] sys_unlink, | ||
48 | [__NR_execve] sys_ni_syscall, /* sys_execve */ | ||
49 | [__NR_chdir] sys_chdir, | ||
50 | [__NR_time] sys_time, | ||
51 | [__NR_mknod] sys_mknod, | ||
52 | [__NR_chmod] sys_chmod, | ||
53 | [__NR_lchown] sys_lchown, | ||
54 | [__NR_break] sys_ni_syscall, | ||
55 | [__NR_oldstat] sys_ni_syscall, | ||
56 | [__NR_lseek] sys_lseek, | ||
57 | [__NR_getpid] sys_getpid, | ||
58 | [__NR_mount] sys_ni_syscall, /* sys_mount */ | ||
59 | [__NR_umount] sys_ni_syscall, | ||
60 | [__NR_setuid] sys_setuid, | ||
61 | [__NR_getuid] sys_getuid, | ||
62 | [__NR_stime] sys_stime, | ||
63 | [__NR_ptrace] sys_ni_syscall, /* sys_ptrace */ | ||
64 | [__NR_alarm] sys_alarm, | ||
65 | [__NR_oldfstat] sys_ni_syscall, | ||
66 | [__NR_pause] sys_ni_syscall, /* sys_pause */ | ||
67 | [__NR_utime] sys_ni_syscall, /* sys_utime */ | ||
68 | [__NR_stty] sys_ni_syscall, | ||
69 | [__NR_gtty] sys_ni_syscall, | ||
70 | [__NR_access] sys_access, | ||
71 | [__NR_nice] sys_nice, | ||
72 | [__NR_ftime] sys_ni_syscall, | ||
73 | [__NR_sync] sys_sync, | ||
74 | [__NR_kill] sys_kill, | ||
75 | [__NR_rename] sys_rename, | ||
76 | [__NR_mkdir] sys_mkdir, | ||
77 | [__NR_rmdir] sys_rmdir, | ||
78 | [__NR_dup] sys_dup, | ||
79 | [__NR_pipe] sys_pipe, | ||
80 | [__NR_times] sys_times, | ||
81 | [__NR_prof] sys_ni_syscall, | ||
82 | [__NR_brk] sys_brk, | ||
83 | [__NR_setgid] sys_setgid, | ||
84 | [__NR_getgid] sys_getgid, | ||
85 | [__NR_signal] sys_ni_syscall, /* sys_signal */ | ||
86 | [__NR_geteuid] sys_geteuid, | ||
87 | [__NR_getegid] sys_getegid, | ||
88 | [__NR_acct] sys_ni_syscall, /* sys_acct */ | ||
89 | [__NR_umount2] sys_ni_syscall, /* sys_umount */ | ||
90 | [__NR_lock] sys_ni_syscall, | ||
91 | [__NR_ioctl] sys_ioctl, | ||
92 | [__NR_fcntl] sys_fcntl, | ||
93 | [__NR_mpx] sys_ni_syscall, | ||
94 | [__NR_setpgid] sys_setpgid, | ||
95 | [__NR_ulimit] sys_ni_syscall, | ||
96 | [__NR_oldolduname] sys_ni_syscall, | ||
97 | [__NR_umask] sys_umask, | ||
98 | [__NR_chroot] sys_chroot, | ||
99 | [__NR_ustat] sys_ni_syscall, /* sys_ustat */ | ||
100 | [__NR_dup2] sys_dup2, | ||
101 | [__NR_getppid] sys_getppid, | ||
102 | [__NR_getpgrp] sys_getpgrp, | ||
103 | [__NR_setsid] sys_setsid, | ||
104 | [__NR_sigaction] sys_ni_syscall, | ||
105 | [__NR_sgetmask] sys_sgetmask, | ||
106 | [__NR_ssetmask] sys_ssetmask, | ||
107 | [__NR_setreuid] sys_setreuid, | ||
108 | [__NR_setregid] sys_setregid, | ||
109 | [__NR_sigsuspend] sys_ni_syscall, | ||
110 | [__NR_sigpending] sys_ni_syscall, | ||
111 | [__NR_sethostname] sys_sethostname, | ||
112 | [__NR_setrlimit] sys_setrlimit, | ||
113 | [__NR_getrlimit] sys_ni_syscall, | ||
114 | [__NR_getrusage] sys_getrusage, | ||
115 | [__NR_gettimeofday] sys_gettimeofday, | ||
116 | [__NR_settimeofday] sys_settimeofday, | ||
117 | [__NR_getgroups] sys_getgroups, | ||
118 | [__NR_setgroups] sys_setgroups, | ||
119 | [__NR_select] sys_ni_syscall, | ||
120 | [__NR_symlink] sys_symlink, | ||
121 | [__NR_oldlstat] sys_ni_syscall, | ||
122 | [__NR_readlink] sys_readlink, | ||
123 | [__NR_uselib] sys_ni_syscall, /* sys_uselib */ | ||
124 | [__NR_swapon] sys_ni_syscall, /* sys_swapon */ | ||
125 | [__NR_reboot] sys_ni_syscall, /* sys_reboot */ | ||
126 | [__NR_readdir] sys_ni_syscall, | ||
127 | [__NR_mmap] sys_mmap, | ||
128 | [__NR_munmap] sys_munmap, | ||
129 | [__NR_truncate] sys_truncate, | ||
130 | [__NR_ftruncate] sys_ftruncate, | ||
131 | [__NR_fchmod] sys_fchmod, | ||
132 | [__NR_fchown] sys_fchown, | ||
133 | [__NR_getpriority] sys_getpriority, | ||
134 | [__NR_setpriority] sys_setpriority, | ||
135 | [__NR_profil] sys_ni_syscall, | ||
136 | [__NR_statfs] sys_ni_syscall, /* sys_statfs */ | ||
137 | [__NR_fstatfs] sys_ni_syscall, /* sys_fstatfs */ | ||
138 | [__NR_ioperm] sys_ni_syscall, | ||
139 | [__NR_socketcall] sys_socketcall, | ||
140 | [__NR_syslog] sys_syslog, | ||
141 | [__NR_setitimer] sys_setitimer, | ||
142 | [__NR_getitimer] sys_getitimer, | ||
143 | [__NR_stat] sys_newstat, | ||
144 | [__NR_lstat] sys_newlstat, | ||
145 | [__NR_fstat] sys_newfstat, | ||
146 | [__NR_olduname] sys_ni_syscall, | ||
147 | [__NR_iopl] sys_ni_syscall, | ||
148 | [__NR_vhangup] sys_vhangup, | ||
149 | [__NR_idle] sys_ni_syscall, | ||
150 | [__NR_vm86] sys_ni_syscall, | ||
151 | [__NR_wait4] sys_wait4, | ||
152 | [__NR_swapoff] sys_ni_syscall, /* sys_swapoff */ | ||
153 | [__NR_sysinfo] sys_sysinfo, | ||
154 | [__NR_ipc] sys_ni_syscall, /* sys_ipc */ | ||
155 | [__NR_fsync] sys_fsync, | ||
156 | [__NR_sigreturn] sys_ni_syscall, | ||
157 | [__NR_clone] sys_ni_syscall, /* ppc_clone */ | ||
158 | [__NR_setdomainname] sys_setdomainname, | ||
159 | [__NR_uname] ppc_newuname, | ||
160 | [__NR_modify_ldt] sys_ni_syscall, | ||
161 | [__NR_adjtimex] sys_adjtimex, | ||
162 | [__NR_mprotect] sys_mprotect, | ||
163 | [__NR_sigprocmask] sys_ni_syscall, | ||
164 | [__NR_create_module] sys_ni_syscall, | ||
165 | [__NR_init_module] sys_ni_syscall, /* sys_init_module */ | ||
166 | [__NR_delete_module] sys_ni_syscall, /* sys_delete_module */ | ||
167 | [__NR_get_kernel_syms] sys_ni_syscall, | ||
168 | [__NR_quotactl] sys_ni_syscall, /* sys_quotactl */ | ||
169 | [__NR_getpgid] sys_getpgid, | ||
170 | [__NR_fchdir] sys_fchdir, | ||
171 | [__NR_bdflush] sys_bdflush, | ||
172 | [__NR_sysfs] sys_ni_syscall, /* sys_sysfs */ | ||
173 | [__NR_personality] ppc64_personality, | ||
174 | [__NR_afs_syscall] sys_ni_syscall, | ||
175 | [__NR_setfsuid] sys_setfsuid, | ||
176 | [__NR_setfsgid] sys_setfsgid, | ||
177 | [__NR__llseek] sys_llseek, | ||
178 | [__NR_getdents] sys_getdents, | ||
179 | [__NR__newselect] sys_select, | ||
180 | [__NR_flock] sys_flock, | ||
181 | [__NR_msync] sys_msync, | ||
182 | [__NR_readv] sys_readv, | ||
183 | [__NR_writev] sys_writev, | ||
184 | [__NR_getsid] sys_getsid, | ||
185 | [__NR_fdatasync] sys_fdatasync, | ||
186 | [__NR__sysctl] sys_ni_syscall, /* sys_sysctl */ | ||
187 | [__NR_mlock] sys_mlock, | ||
188 | [__NR_munlock] sys_munlock, | ||
189 | [__NR_mlockall] sys_mlockall, | ||
190 | [__NR_munlockall] sys_munlockall, | ||
191 | [__NR_sched_setparam] sys_sched_setparam, | ||
192 | [__NR_sched_getparam] sys_sched_getparam, | ||
193 | [__NR_sched_setscheduler] sys_sched_setscheduler, | ||
194 | [__NR_sched_getscheduler] sys_sched_getscheduler, | ||
195 | [__NR_sched_yield] sys_sched_yield, | ||
196 | [__NR_sched_get_priority_max] sys_sched_get_priority_max, | ||
197 | [__NR_sched_get_priority_min] sys_sched_get_priority_min, | ||
198 | [__NR_sched_rr_get_interval] sys_sched_rr_get_interval, | ||
199 | [__NR_nanosleep] sys_nanosleep, | ||
200 | [__NR_mremap] sys_mremap, | ||
201 | [__NR_setresuid] sys_setresuid, | ||
202 | [__NR_getresuid] sys_getresuid, | ||
203 | [__NR_query_module] sys_ni_syscall, | ||
204 | [__NR_poll] sys_poll, | ||
205 | [__NR_nfsservctl] sys_ni_syscall, /* sys_nfsservctl */ | ||
206 | [__NR_setresgid] sys_setresgid, | ||
207 | [__NR_getresgid] sys_getresgid, | ||
208 | [__NR_prctl] sys_prctl, | ||
209 | [__NR_rt_sigreturn] sys_ni_syscall, /* ppc64_rt_sigreturn */ | ||
210 | [__NR_rt_sigaction] sys_ni_syscall, /* sys_rt_sigaction */ | ||
211 | [__NR_rt_sigprocmask] sys_ni_syscall, /* sys_rt_sigprocmask */ | ||
212 | [__NR_rt_sigpending] sys_ni_syscall, /* sys_rt_sigpending */ | ||
213 | [__NR_rt_sigtimedwait] sys_ni_syscall, /* sys_rt_sigtimedwait */ | ||
214 | [__NR_rt_sigqueueinfo] sys_ni_syscall, /* sys_rt_sigqueueinfo */ | ||
215 | [__NR_rt_sigsuspend] sys_ni_syscall, /* sys_rt_sigsuspend */ | ||
216 | [__NR_pread64] sys_pread64, | ||
217 | [__NR_pwrite64] sys_pwrite64, | ||
218 | [__NR_chown] sys_chown, | ||
219 | [__NR_getcwd] sys_getcwd, | ||
220 | [__NR_capget] sys_capget, | ||
221 | [__NR_capset] sys_capset, | ||
222 | [__NR_sigaltstack] sys_ni_syscall, /* sys_sigaltstack */ | ||
223 | [__NR_sendfile] sys_sendfile64, | ||
224 | [__NR_getpmsg] sys_ni_syscall, | ||
225 | [__NR_putpmsg] sys_ni_syscall, | ||
226 | [__NR_vfork] sys_ni_syscall, /* ppc_vfork */ | ||
227 | [__NR_ugetrlimit] sys_getrlimit, | ||
228 | [__NR_readahead] sys_readahead, | ||
229 | [192] sys_ni_syscall, | ||
230 | [193] sys_ni_syscall, | ||
231 | [194] sys_ni_syscall, | ||
232 | [195] sys_ni_syscall, | ||
233 | [196] sys_ni_syscall, | ||
234 | [197] sys_ni_syscall, | ||
235 | [__NR_pciconfig_read] sys_ni_syscall, /* sys_pciconfig_read */ | ||
236 | [__NR_pciconfig_write] sys_ni_syscall, /* sys_pciconfig_write */ | ||
237 | [__NR_pciconfig_iobase] sys_ni_syscall, /* sys_pciconfig_iobase */ | ||
238 | [__NR_multiplexer] sys_ni_syscall, | ||
239 | [__NR_getdents64] sys_getdents64, | ||
240 | [__NR_pivot_root] sys_pivot_root, | ||
241 | [204] sys_ni_syscall, | ||
242 | [__NR_madvise] sys_madvise, | ||
243 | [__NR_mincore] sys_mincore, | ||
244 | [__NR_gettid] sys_gettid, | ||
245 | [__NR_tkill] sys_tkill, | ||
246 | [__NR_setxattr] sys_setxattr, | ||
247 | [__NR_lsetxattr] sys_lsetxattr, | ||
248 | [__NR_fsetxattr] sys_fsetxattr, | ||
249 | [__NR_getxattr] sys_getxattr, | ||
250 | [__NR_lgetxattr] sys_lgetxattr, | ||
251 | [__NR_fgetxattr] sys_fgetxattr, | ||
252 | [__NR_listxattr] sys_listxattr, | ||
253 | [__NR_llistxattr] sys_llistxattr, | ||
254 | [__NR_flistxattr] sys_flistxattr, | ||
255 | [__NR_removexattr] sys_removexattr, | ||
256 | [__NR_lremovexattr] sys_lremovexattr, | ||
257 | [__NR_fremovexattr] sys_fremovexattr, | ||
258 | [__NR_futex] sys_futex, | ||
259 | [__NR_sched_setaffinity] sys_sched_setaffinity, | ||
260 | [__NR_sched_getaffinity] sys_sched_getaffinity, | ||
261 | [__NR_tuxcall] sys_ni_syscall, | ||
262 | [226] sys_ni_syscall, | ||
263 | [__NR_io_setup] sys_io_setup, | ||
264 | [__NR_io_destroy] sys_io_destroy, | ||
265 | [__NR_io_getevents] sys_io_getevents, | ||
266 | [__NR_io_submit] sys_io_submit, | ||
267 | [__NR_io_cancel] sys_io_cancel, | ||
268 | [__NR_set_tid_address] sys_ni_syscall, /* sys_set_tid_address */ | ||
269 | [__NR_fadvise64] sys_fadvise64, | ||
270 | [__NR_exit_group] sys_ni_syscall, /* sys_exit_group */ | ||
271 | [__NR_lookup_dcookie] sys_ni_syscall, /* sys_lookup_dcookie */ | ||
272 | [__NR_epoll_create] sys_epoll_create, | ||
273 | [__NR_epoll_ctl] sys_epoll_ctl, | ||
274 | [__NR_epoll_wait] sys_epoll_wait, | ||
275 | [__NR_remap_file_pages] sys_remap_file_pages, | ||
276 | [__NR_timer_create] sys_timer_create, | ||
277 | [__NR_timer_settime] sys_timer_settime, | ||
278 | [__NR_timer_gettime] sys_timer_gettime, | ||
279 | [__NR_timer_getoverrun] sys_timer_getoverrun, | ||
280 | [__NR_timer_delete] sys_timer_delete, | ||
281 | [__NR_clock_settime] sys_clock_settime, | ||
282 | [__NR_clock_gettime] sys_clock_gettime, | ||
283 | [__NR_clock_getres] sys_clock_getres, | ||
284 | [__NR_clock_nanosleep] sys_clock_nanosleep, | ||
285 | [__NR_swapcontext] sys_ni_syscall, /* ppc64_swapcontext */ | ||
286 | [__NR_tgkill] sys_tgkill, | ||
287 | [__NR_utimes] sys_utimes, | ||
288 | [__NR_statfs64] sys_statfs64, | ||
289 | [__NR_fstatfs64] sys_fstatfs64, | ||
290 | [254] sys_ni_syscall, | ||
291 | [__NR_rtas] ppc_rtas, | ||
292 | [256] sys_ni_syscall, | ||
293 | [257] sys_ni_syscall, | ||
294 | [258] sys_ni_syscall, | ||
295 | [__NR_mbind] sys_ni_syscall, /* sys_mbind */ | ||
296 | [__NR_get_mempolicy] sys_ni_syscall, /* sys_get_mempolicy */ | ||
297 | [__NR_set_mempolicy] sys_ni_syscall, /* sys_set_mempolicy */ | ||
298 | [__NR_mq_open] sys_ni_syscall, /* sys_mq_open */ | ||
299 | [__NR_mq_unlink] sys_ni_syscall, /* sys_mq_unlink */ | ||
300 | [__NR_mq_timedsend] sys_ni_syscall, /* sys_mq_timedsend */ | ||
301 | [__NR_mq_timedreceive] sys_ni_syscall, /* sys_mq_timedreceive */ | ||
302 | [__NR_mq_notify] sys_ni_syscall, /* sys_mq_notify */ | ||
303 | [__NR_mq_getsetattr] sys_ni_syscall, /* sys_mq_getsetattr */ | ||
304 | [__NR_kexec_load] sys_ni_syscall, /* sys_kexec_load */ | ||
305 | [__NR_add_key] sys_ni_syscall, /* sys_add_key */ | ||
306 | [__NR_request_key] sys_ni_syscall, /* sys_request_key */ | ||
307 | [__NR_keyctl] sys_ni_syscall, /* sys_keyctl */ | ||
308 | [__NR_waitid] sys_ni_syscall, /* sys_waitid */ | ||
309 | [__NR_ioprio_set] sys_ni_syscall, /* sys_ioprio_set */ | ||
310 | [__NR_ioprio_get] sys_ni_syscall, /* sys_ioprio_get */ | ||
311 | [__NR_inotify_init] sys_ni_syscall, /* sys_inotify_init */ | ||
312 | [__NR_inotify_add_watch] sys_ni_syscall, /* sys_inotify_add_watch */ | ||
313 | [__NR_inotify_rm_watch] sys_ni_syscall, /* sys_inotify_rm_watch */ | ||
314 | [__NR_spu_run] sys_ni_syscall, /* sys_spu_run */ | ||
315 | [__NR_spu_create] sys_ni_syscall, /* sys_spu_create */ | ||
316 | [__NR_pselect6] sys_ni_syscall, /* sys_pselect */ | ||
317 | [__NR_ppoll] sys_ni_syscall, /* sys_ppoll */ | ||
318 | [__NR_unshare] sys_unshare, | ||
319 | }; | ||
320 | |||
321 | long spu_sys_callback(struct spu_syscall_block *s) | ||
322 | { | ||
323 | long (*syscall)(u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6); | ||
324 | |||
325 | BUILD_BUG_ON(ARRAY_SIZE(spu_syscall_table) != __NR_syscalls); | ||
326 | |||
327 | syscall = spu_syscall_table[s->nr_ret]; | ||
328 | |||
329 | if (s->nr_ret >= __NR_syscalls) { | ||
330 | pr_debug("%s: invalid syscall #%ld", __FUNCTION__, s->nr_ret); | ||
331 | return -ENOSYS; | ||
332 | } | ||
333 | |||
334 | #ifdef DEBUG | ||
335 | print_symbol(KERN_DEBUG "SPU-syscall %s:", (unsigned long)syscall); | ||
336 | printk("syscall%ld(%lx, %lx, %lx, %lx, %lx, %lx)\n", | ||
337 | s->nr_ret, | ||
338 | s->parm[0], s->parm[1], s->parm[2], | ||
339 | s->parm[3], s->parm[4], s->parm[5]); | ||
340 | #endif | ||
341 | |||
342 | return syscall(s->parm[0], s->parm[1], s->parm[2], | ||
343 | s->parm[3], s->parm[4], s->parm[5]); | ||
344 | } | ||
345 | EXPORT_SYMBOL_GPL(spu_sys_callback); | ||
diff --git a/arch/powerpc/platforms/cell/spufs/backing_ops.c b/arch/powerpc/platforms/cell/spufs/backing_ops.c index a5c489a53c61..f1d35ddc9df3 100644 --- a/arch/powerpc/platforms/cell/spufs/backing_ops.c +++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c | |||
@@ -285,6 +285,49 @@ static void spu_backing_runcntl_stop(struct spu_context *ctx) | |||
285 | spu_backing_runcntl_write(ctx, SPU_RUNCNTL_STOP); | 285 | spu_backing_runcntl_write(ctx, SPU_RUNCNTL_STOP); |
286 | } | 286 | } |
287 | 287 | ||
288 | static int spu_backing_set_mfc_query(struct spu_context * ctx, u32 mask, | ||
289 | u32 mode) | ||
290 | { | ||
291 | struct spu_problem_collapsed *prob = &ctx->csa.prob; | ||
292 | int ret; | ||
293 | |||
294 | spin_lock(&ctx->csa.register_lock); | ||
295 | ret = -EAGAIN; | ||
296 | if (prob->dma_querytype_RW) | ||
297 | goto out; | ||
298 | ret = 0; | ||
299 | /* FIXME: what are the side-effects of this? */ | ||
300 | prob->dma_querymask_RW = mask; | ||
301 | prob->dma_querytype_RW = mode; | ||
302 | out: | ||
303 | spin_unlock(&ctx->csa.register_lock); | ||
304 | |||
305 | return ret; | ||
306 | } | ||
307 | |||
308 | static u32 spu_backing_read_mfc_tagstatus(struct spu_context * ctx) | ||
309 | { | ||
310 | return ctx->csa.prob.dma_tagstatus_R; | ||
311 | } | ||
312 | |||
313 | static u32 spu_backing_get_mfc_free_elements(struct spu_context *ctx) | ||
314 | { | ||
315 | return ctx->csa.prob.dma_qstatus_R; | ||
316 | } | ||
317 | |||
318 | static int spu_backing_send_mfc_command(struct spu_context *ctx, | ||
319 | struct mfc_dma_command *cmd) | ||
320 | { | ||
321 | int ret; | ||
322 | |||
323 | spin_lock(&ctx->csa.register_lock); | ||
324 | ret = -EAGAIN; | ||
325 | /* FIXME: set up priv2->puq */ | ||
326 | spin_unlock(&ctx->csa.register_lock); | ||
327 | |||
328 | return ret; | ||
329 | } | ||
330 | |||
288 | struct spu_context_ops spu_backing_ops = { | 331 | struct spu_context_ops spu_backing_ops = { |
289 | .mbox_read = spu_backing_mbox_read, | 332 | .mbox_read = spu_backing_mbox_read, |
290 | .mbox_stat_read = spu_backing_mbox_stat_read, | 333 | .mbox_stat_read = spu_backing_mbox_stat_read, |
@@ -305,4 +348,8 @@ struct spu_context_ops spu_backing_ops = { | |||
305 | .get_ls = spu_backing_get_ls, | 348 | .get_ls = spu_backing_get_ls, |
306 | .runcntl_write = spu_backing_runcntl_write, | 349 | .runcntl_write = spu_backing_runcntl_write, |
307 | .runcntl_stop = spu_backing_runcntl_stop, | 350 | .runcntl_stop = spu_backing_runcntl_stop, |
351 | .set_mfc_query = spu_backing_set_mfc_query, | ||
352 | .read_mfc_tagstatus = spu_backing_read_mfc_tagstatus, | ||
353 | .get_mfc_free_elements = spu_backing_get_mfc_free_elements, | ||
354 | .send_mfc_command = spu_backing_send_mfc_command, | ||
308 | }; | 355 | }; |
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c index 336f238102fd..8bb33abfad17 100644 --- a/arch/powerpc/platforms/cell/spufs/context.c +++ b/arch/powerpc/platforms/cell/spufs/context.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include <asm/spu_csa.h> | 27 | #include <asm/spu_csa.h> |
28 | #include "spufs.h" | 28 | #include "spufs.h" |
29 | 29 | ||
30 | struct spu_context *alloc_spu_context(struct address_space *local_store) | 30 | struct spu_context *alloc_spu_context(void) |
31 | { | 31 | { |
32 | struct spu_context *ctx; | 32 | struct spu_context *ctx; |
33 | ctx = kmalloc(sizeof *ctx, GFP_KERNEL); | 33 | ctx = kmalloc(sizeof *ctx, GFP_KERNEL); |
@@ -47,10 +47,17 @@ struct spu_context *alloc_spu_context(struct address_space *local_store) | |||
47 | init_waitqueue_head(&ctx->ibox_wq); | 47 | init_waitqueue_head(&ctx->ibox_wq); |
48 | init_waitqueue_head(&ctx->wbox_wq); | 48 | init_waitqueue_head(&ctx->wbox_wq); |
49 | init_waitqueue_head(&ctx->stop_wq); | 49 | init_waitqueue_head(&ctx->stop_wq); |
50 | init_waitqueue_head(&ctx->mfc_wq); | ||
50 | ctx->ibox_fasync = NULL; | 51 | ctx->ibox_fasync = NULL; |
51 | ctx->wbox_fasync = NULL; | 52 | ctx->wbox_fasync = NULL; |
53 | ctx->mfc_fasync = NULL; | ||
54 | ctx->mfc = NULL; | ||
55 | ctx->tagwait = 0; | ||
52 | ctx->state = SPU_STATE_SAVED; | 56 | ctx->state = SPU_STATE_SAVED; |
53 | ctx->local_store = local_store; | 57 | ctx->local_store = NULL; |
58 | ctx->cntl = NULL; | ||
59 | ctx->signal1 = NULL; | ||
60 | ctx->signal2 = NULL; | ||
54 | ctx->spu = NULL; | 61 | ctx->spu = NULL; |
55 | ctx->ops = &spu_backing_ops; | 62 | ctx->ops = &spu_backing_ops; |
56 | ctx->owner = get_task_mm(current); | 63 | ctx->owner = get_task_mm(current); |
@@ -68,8 +75,6 @@ void destroy_spu_context(struct kref *kref) | |||
68 | ctx = container_of(kref, struct spu_context, kref); | 75 | ctx = container_of(kref, struct spu_context, kref); |
69 | down_write(&ctx->state_sema); | 76 | down_write(&ctx->state_sema); |
70 | spu_deactivate(ctx); | 77 | spu_deactivate(ctx); |
71 | ctx->ibox_fasync = NULL; | ||
72 | ctx->wbox_fasync = NULL; | ||
73 | up_write(&ctx->state_sema); | 78 | up_write(&ctx->state_sema); |
74 | spu_fini_csa(&ctx->csa); | 79 | spu_fini_csa(&ctx->csa); |
75 | kfree(ctx); | 80 | kfree(ctx); |
@@ -109,7 +114,16 @@ void spu_release(struct spu_context *ctx) | |||
109 | 114 | ||
110 | void spu_unmap_mappings(struct spu_context *ctx) | 115 | void spu_unmap_mappings(struct spu_context *ctx) |
111 | { | 116 | { |
112 | unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1); | 117 | if (ctx->local_store) |
118 | unmap_mapping_range(ctx->local_store, 0, LS_SIZE, 1); | ||
119 | if (ctx->mfc) | ||
120 | unmap_mapping_range(ctx->mfc, 0, 0x4000, 1); | ||
121 | if (ctx->cntl) | ||
122 | unmap_mapping_range(ctx->cntl, 0, 0x4000, 1); | ||
123 | if (ctx->signal1) | ||
124 | unmap_mapping_range(ctx->signal1, 0, 0x4000, 1); | ||
125 | if (ctx->signal2) | ||
126 | unmap_mapping_range(ctx->signal2, 0, 0x4000, 1); | ||
113 | } | 127 | } |
114 | 128 | ||
115 | int spu_acquire_runnable(struct spu_context *ctx) | 129 | int spu_acquire_runnable(struct spu_context *ctx) |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index dfa649c9b956..366185e92667 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -20,6 +20,8 @@ | |||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #undef DEBUG | ||
24 | |||
23 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
24 | #include <linux/ioctl.h> | 26 | #include <linux/ioctl.h> |
25 | #include <linux/module.h> | 27 | #include <linux/module.h> |
@@ -39,8 +41,10 @@ static int | |||
39 | spufs_mem_open(struct inode *inode, struct file *file) | 41 | spufs_mem_open(struct inode *inode, struct file *file) |
40 | { | 42 | { |
41 | struct spufs_inode_info *i = SPUFS_I(inode); | 43 | struct spufs_inode_info *i = SPUFS_I(inode); |
42 | file->private_data = i->i_ctx; | 44 | struct spu_context *ctx = i->i_ctx; |
43 | file->f_mapping = i->i_ctx->local_store; | 45 | file->private_data = ctx; |
46 | file->f_mapping = inode->i_mapping; | ||
47 | ctx->local_store = inode->i_mapping; | ||
44 | return 0; | 48 | return 0; |
45 | } | 49 | } |
46 | 50 | ||
@@ -84,7 +88,7 @@ spufs_mem_write(struct file *file, const char __user *buffer, | |||
84 | return ret; | 88 | return ret; |
85 | } | 89 | } |
86 | 90 | ||
87 | #ifdef CONFIG_SPARSEMEM | 91 | #ifdef CONFIG_SPUFS_MMAP |
88 | static struct page * | 92 | static struct page * |
89 | spufs_mem_mmap_nopage(struct vm_area_struct *vma, | 93 | spufs_mem_mmap_nopage(struct vm_area_struct *vma, |
90 | unsigned long address, int *type) | 94 | unsigned long address, int *type) |
@@ -136,11 +140,113 @@ static struct file_operations spufs_mem_fops = { | |||
136 | .read = spufs_mem_read, | 140 | .read = spufs_mem_read, |
137 | .write = spufs_mem_write, | 141 | .write = spufs_mem_write, |
138 | .llseek = generic_file_llseek, | 142 | .llseek = generic_file_llseek, |
139 | #ifdef CONFIG_SPARSEMEM | 143 | #ifdef CONFIG_SPUFS_MMAP |
140 | .mmap = spufs_mem_mmap, | 144 | .mmap = spufs_mem_mmap, |
141 | #endif | 145 | #endif |
142 | }; | 146 | }; |
143 | 147 | ||
148 | #ifdef CONFIG_SPUFS_MMAP | ||
149 | static struct page *spufs_ps_nopage(struct vm_area_struct *vma, | ||
150 | unsigned long address, | ||
151 | int *type, unsigned long ps_offs) | ||
152 | { | ||
153 | struct page *page = NOPAGE_SIGBUS; | ||
154 | int fault_type = VM_FAULT_SIGBUS; | ||
155 | struct spu_context *ctx = vma->vm_file->private_data; | ||
156 | unsigned long offset = address - vma->vm_start; | ||
157 | unsigned long area; | ||
158 | int ret; | ||
159 | |||
160 | offset += vma->vm_pgoff << PAGE_SHIFT; | ||
161 | if (offset >= 0x4000) | ||
162 | goto out; | ||
163 | |||
164 | ret = spu_acquire_runnable(ctx); | ||
165 | if (ret) | ||
166 | goto out; | ||
167 | |||
168 | area = ctx->spu->problem_phys + ps_offs; | ||
169 | page = pfn_to_page((area + offset) >> PAGE_SHIFT); | ||
170 | fault_type = VM_FAULT_MINOR; | ||
171 | page_cache_get(page); | ||
172 | |||
173 | spu_release(ctx); | ||
174 | |||
175 | out: | ||
176 | if (type) | ||
177 | *type = fault_type; | ||
178 | |||
179 | return page; | ||
180 | } | ||
181 | |||
182 | static struct page *spufs_cntl_mmap_nopage(struct vm_area_struct *vma, | ||
183 | unsigned long address, int *type) | ||
184 | { | ||
185 | return spufs_ps_nopage(vma, address, type, 0x4000); | ||
186 | } | ||
187 | |||
188 | static struct vm_operations_struct spufs_cntl_mmap_vmops = { | ||
189 | .nopage = spufs_cntl_mmap_nopage, | ||
190 | }; | ||
191 | |||
192 | /* | ||
193 | * mmap support for problem state control area [0x4000 - 0x4fff]. | ||
194 | * Mapping this area requires that the application have CAP_SYS_RAWIO, | ||
195 | * as these registers require special care when read/writing. | ||
196 | */ | ||
197 | static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma) | ||
198 | { | ||
199 | if (!(vma->vm_flags & VM_SHARED)) | ||
200 | return -EINVAL; | ||
201 | |||
202 | if (!capable(CAP_SYS_RAWIO)) | ||
203 | return -EPERM; | ||
204 | |||
205 | vma->vm_flags |= VM_RESERVED; | ||
206 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) | ||
207 | | _PAGE_NO_CACHE); | ||
208 | |||
209 | vma->vm_ops = &spufs_cntl_mmap_vmops; | ||
210 | return 0; | ||
211 | } | ||
212 | #endif | ||
213 | |||
214 | static int spufs_cntl_open(struct inode *inode, struct file *file) | ||
215 | { | ||
216 | struct spufs_inode_info *i = SPUFS_I(inode); | ||
217 | struct spu_context *ctx = i->i_ctx; | ||
218 | |||
219 | file->private_data = ctx; | ||
220 | file->f_mapping = inode->i_mapping; | ||
221 | ctx->cntl = inode->i_mapping; | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static ssize_t | ||
226 | spufs_cntl_read(struct file *file, char __user *buffer, | ||
227 | size_t size, loff_t *pos) | ||
228 | { | ||
229 | /* FIXME: read from spu status */ | ||
230 | return -EINVAL; | ||
231 | } | ||
232 | |||
233 | static ssize_t | ||
234 | spufs_cntl_write(struct file *file, const char __user *buffer, | ||
235 | size_t size, loff_t *pos) | ||
236 | { | ||
237 | /* FIXME: write to runctl bit */ | ||
238 | return -EINVAL; | ||
239 | } | ||
240 | |||
241 | static struct file_operations spufs_cntl_fops = { | ||
242 | .open = spufs_cntl_open, | ||
243 | .read = spufs_cntl_read, | ||
244 | .write = spufs_cntl_write, | ||
245 | #ifdef CONFIG_SPUFS_MMAP | ||
246 | .mmap = spufs_cntl_mmap, | ||
247 | #endif | ||
248 | }; | ||
249 | |||
144 | static int | 250 | static int |
145 | spufs_regs_open(struct inode *inode, struct file *file) | 251 | spufs_regs_open(struct inode *inode, struct file *file) |
146 | { | 252 | { |
@@ -501,6 +607,16 @@ static struct file_operations spufs_wbox_stat_fops = { | |||
501 | .read = spufs_wbox_stat_read, | 607 | .read = spufs_wbox_stat_read, |
502 | }; | 608 | }; |
503 | 609 | ||
610 | static int spufs_signal1_open(struct inode *inode, struct file *file) | ||
611 | { | ||
612 | struct spufs_inode_info *i = SPUFS_I(inode); | ||
613 | struct spu_context *ctx = i->i_ctx; | ||
614 | file->private_data = ctx; | ||
615 | file->f_mapping = inode->i_mapping; | ||
616 | ctx->signal1 = inode->i_mapping; | ||
617 | return nonseekable_open(inode, file); | ||
618 | } | ||
619 | |||
504 | static ssize_t spufs_signal1_read(struct file *file, char __user *buf, | 620 | static ssize_t spufs_signal1_read(struct file *file, char __user *buf, |
505 | size_t len, loff_t *pos) | 621 | size_t len, loff_t *pos) |
506 | { | 622 | { |
@@ -541,12 +657,50 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf, | |||
541 | return 4; | 657 | return 4; |
542 | } | 658 | } |
543 | 659 | ||
660 | #ifdef CONFIG_SPUFS_MMAP | ||
661 | static struct page *spufs_signal1_mmap_nopage(struct vm_area_struct *vma, | ||
662 | unsigned long address, int *type) | ||
663 | { | ||
664 | return spufs_ps_nopage(vma, address, type, 0x14000); | ||
665 | } | ||
666 | |||
667 | static struct vm_operations_struct spufs_signal1_mmap_vmops = { | ||
668 | .nopage = spufs_signal1_mmap_nopage, | ||
669 | }; | ||
670 | |||
671 | static int spufs_signal1_mmap(struct file *file, struct vm_area_struct *vma) | ||
672 | { | ||
673 | if (!(vma->vm_flags & VM_SHARED)) | ||
674 | return -EINVAL; | ||
675 | |||
676 | vma->vm_flags |= VM_RESERVED; | ||
677 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) | ||
678 | | _PAGE_NO_CACHE); | ||
679 | |||
680 | vma->vm_ops = &spufs_signal1_mmap_vmops; | ||
681 | return 0; | ||
682 | } | ||
683 | #endif | ||
684 | |||
544 | static struct file_operations spufs_signal1_fops = { | 685 | static struct file_operations spufs_signal1_fops = { |
545 | .open = spufs_pipe_open, | 686 | .open = spufs_signal1_open, |
546 | .read = spufs_signal1_read, | 687 | .read = spufs_signal1_read, |
547 | .write = spufs_signal1_write, | 688 | .write = spufs_signal1_write, |
689 | #ifdef CONFIG_SPUFS_MMAP | ||
690 | .mmap = spufs_signal1_mmap, | ||
691 | #endif | ||
548 | }; | 692 | }; |
549 | 693 | ||
694 | static int spufs_signal2_open(struct inode *inode, struct file *file) | ||
695 | { | ||
696 | struct spufs_inode_info *i = SPUFS_I(inode); | ||
697 | struct spu_context *ctx = i->i_ctx; | ||
698 | file->private_data = ctx; | ||
699 | file->f_mapping = inode->i_mapping; | ||
700 | ctx->signal2 = inode->i_mapping; | ||
701 | return nonseekable_open(inode, file); | ||
702 | } | ||
703 | |||
550 | static ssize_t spufs_signal2_read(struct file *file, char __user *buf, | 704 | static ssize_t spufs_signal2_read(struct file *file, char __user *buf, |
551 | size_t len, loff_t *pos) | 705 | size_t len, loff_t *pos) |
552 | { | 706 | { |
@@ -589,10 +743,39 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf, | |||
589 | return 4; | 743 | return 4; |
590 | } | 744 | } |
591 | 745 | ||
746 | #ifdef CONFIG_SPUFS_MMAP | ||
747 | static struct page *spufs_signal2_mmap_nopage(struct vm_area_struct *vma, | ||
748 | unsigned long address, int *type) | ||
749 | { | ||
750 | return spufs_ps_nopage(vma, address, type, 0x1c000); | ||
751 | } | ||
752 | |||
753 | static struct vm_operations_struct spufs_signal2_mmap_vmops = { | ||
754 | .nopage = spufs_signal2_mmap_nopage, | ||
755 | }; | ||
756 | |||
757 | static int spufs_signal2_mmap(struct file *file, struct vm_area_struct *vma) | ||
758 | { | ||
759 | if (!(vma->vm_flags & VM_SHARED)) | ||
760 | return -EINVAL; | ||
761 | |||
762 | /* FIXME: */ | ||
763 | vma->vm_flags |= VM_RESERVED; | ||
764 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) | ||
765 | | _PAGE_NO_CACHE); | ||
766 | |||
767 | vma->vm_ops = &spufs_signal2_mmap_vmops; | ||
768 | return 0; | ||
769 | } | ||
770 | #endif | ||
771 | |||
592 | static struct file_operations spufs_signal2_fops = { | 772 | static struct file_operations spufs_signal2_fops = { |
593 | .open = spufs_pipe_open, | 773 | .open = spufs_signal2_open, |
594 | .read = spufs_signal2_read, | 774 | .read = spufs_signal2_read, |
595 | .write = spufs_signal2_write, | 775 | .write = spufs_signal2_write, |
776 | #ifdef CONFIG_SPUFS_MMAP | ||
777 | .mmap = spufs_signal2_mmap, | ||
778 | #endif | ||
596 | }; | 779 | }; |
597 | 780 | ||
598 | static void spufs_signal1_type_set(void *data, u64 val) | 781 | static void spufs_signal1_type_set(void *data, u64 val) |
@@ -641,6 +824,332 @@ static u64 spufs_signal2_type_get(void *data) | |||
641 | DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get, | 824 | DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get, |
642 | spufs_signal2_type_set, "%llu"); | 825 | spufs_signal2_type_set, "%llu"); |
643 | 826 | ||
827 | #ifdef CONFIG_SPUFS_MMAP | ||
828 | static struct page *spufs_mfc_mmap_nopage(struct vm_area_struct *vma, | ||
829 | unsigned long address, int *type) | ||
830 | { | ||
831 | return spufs_ps_nopage(vma, address, type, 0x3000); | ||
832 | } | ||
833 | |||
834 | static struct vm_operations_struct spufs_mfc_mmap_vmops = { | ||
835 | .nopage = spufs_mfc_mmap_nopage, | ||
836 | }; | ||
837 | |||
838 | /* | ||
839 | * mmap support for problem state MFC DMA area [0x0000 - 0x0fff]. | ||
840 | * Mapping this area requires that the application have CAP_SYS_RAWIO, | ||
841 | * as these registers require special care when read/writing. | ||
842 | */ | ||
843 | static int spufs_mfc_mmap(struct file *file, struct vm_area_struct *vma) | ||
844 | { | ||
845 | if (!(vma->vm_flags & VM_SHARED)) | ||
846 | return -EINVAL; | ||
847 | |||
848 | if (!capable(CAP_SYS_RAWIO)) | ||
849 | return -EPERM; | ||
850 | |||
851 | vma->vm_flags |= VM_RESERVED; | ||
852 | vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot) | ||
853 | | _PAGE_NO_CACHE); | ||
854 | |||
855 | vma->vm_ops = &spufs_mfc_mmap_vmops; | ||
856 | return 0; | ||
857 | } | ||
858 | #endif | ||
859 | |||
860 | static int spufs_mfc_open(struct inode *inode, struct file *file) | ||
861 | { | ||
862 | struct spufs_inode_info *i = SPUFS_I(inode); | ||
863 | struct spu_context *ctx = i->i_ctx; | ||
864 | |||
865 | /* we don't want to deal with DMA into other processes */ | ||
866 | if (ctx->owner != current->mm) | ||
867 | return -EINVAL; | ||
868 | |||
869 | if (atomic_read(&inode->i_count) != 1) | ||
870 | return -EBUSY; | ||
871 | |||
872 | file->private_data = ctx; | ||
873 | return nonseekable_open(inode, file); | ||
874 | } | ||
875 | |||
876 | /* interrupt-level mfc callback function. */ | ||
877 | void spufs_mfc_callback(struct spu *spu) | ||
878 | { | ||
879 | struct spu_context *ctx = spu->ctx; | ||
880 | |||
881 | wake_up_all(&ctx->mfc_wq); | ||
882 | |||
883 | pr_debug("%s %s\n", __FUNCTION__, spu->name); | ||
884 | if (ctx->mfc_fasync) { | ||
885 | u32 free_elements, tagstatus; | ||
886 | unsigned int mask; | ||
887 | |||
888 | /* no need for spu_acquire in interrupt context */ | ||
889 | free_elements = ctx->ops->get_mfc_free_elements(ctx); | ||
890 | tagstatus = ctx->ops->read_mfc_tagstatus(ctx); | ||
891 | |||
892 | mask = 0; | ||
893 | if (free_elements & 0xffff) | ||
894 | mask |= POLLOUT; | ||
895 | if (tagstatus & ctx->tagwait) | ||
896 | mask |= POLLIN; | ||
897 | |||
898 | kill_fasync(&ctx->mfc_fasync, SIGIO, mask); | ||
899 | } | ||
900 | } | ||
901 | |||
902 | static int spufs_read_mfc_tagstatus(struct spu_context *ctx, u32 *status) | ||
903 | { | ||
904 | /* See if there is one tag group is complete */ | ||
905 | /* FIXME we need locking around tagwait */ | ||
906 | *status = ctx->ops->read_mfc_tagstatus(ctx) & ctx->tagwait; | ||
907 | ctx->tagwait &= ~*status; | ||
908 | if (*status) | ||
909 | return 1; | ||
910 | |||
911 | /* enable interrupt waiting for any tag group, | ||
912 | may silently fail if interrupts are already enabled */ | ||
913 | ctx->ops->set_mfc_query(ctx, ctx->tagwait, 1); | ||
914 | return 0; | ||
915 | } | ||
916 | |||
917 | static ssize_t spufs_mfc_read(struct file *file, char __user *buffer, | ||
918 | size_t size, loff_t *pos) | ||
919 | { | ||
920 | struct spu_context *ctx = file->private_data; | ||
921 | int ret = -EINVAL; | ||
922 | u32 status; | ||
923 | |||
924 | if (size != 4) | ||
925 | goto out; | ||
926 | |||
927 | spu_acquire(ctx); | ||
928 | if (file->f_flags & O_NONBLOCK) { | ||
929 | status = ctx->ops->read_mfc_tagstatus(ctx); | ||
930 | if (!(status & ctx->tagwait)) | ||
931 | ret = -EAGAIN; | ||
932 | else | ||
933 | ctx->tagwait &= ~status; | ||
934 | } else { | ||
935 | ret = spufs_wait(ctx->mfc_wq, | ||
936 | spufs_read_mfc_tagstatus(ctx, &status)); | ||
937 | } | ||
938 | spu_release(ctx); | ||
939 | |||
940 | if (ret) | ||
941 | goto out; | ||
942 | |||
943 | ret = 4; | ||
944 | if (copy_to_user(buffer, &status, 4)) | ||
945 | ret = -EFAULT; | ||
946 | |||
947 | out: | ||
948 | return ret; | ||
949 | } | ||
950 | |||
951 | static int spufs_check_valid_dma(struct mfc_dma_command *cmd) | ||
952 | { | ||
953 | pr_debug("queueing DMA %x %lx %x %x %x\n", cmd->lsa, | ||
954 | cmd->ea, cmd->size, cmd->tag, cmd->cmd); | ||
955 | |||
956 | switch (cmd->cmd) { | ||
957 | case MFC_PUT_CMD: | ||
958 | case MFC_PUTF_CMD: | ||
959 | case MFC_PUTB_CMD: | ||
960 | case MFC_GET_CMD: | ||
961 | case MFC_GETF_CMD: | ||
962 | case MFC_GETB_CMD: | ||
963 | break; | ||
964 | default: | ||
965 | pr_debug("invalid DMA opcode %x\n", cmd->cmd); | ||
966 | return -EIO; | ||
967 | } | ||
968 | |||
969 | if ((cmd->lsa & 0xf) != (cmd->ea &0xf)) { | ||
970 | pr_debug("invalid DMA alignment, ea %lx lsa %x\n", | ||
971 | cmd->ea, cmd->lsa); | ||
972 | return -EIO; | ||
973 | } | ||
974 | |||
975 | switch (cmd->size & 0xf) { | ||
976 | case 1: | ||
977 | break; | ||
978 | case 2: | ||
979 | if (cmd->lsa & 1) | ||
980 | goto error; | ||
981 | break; | ||
982 | case 4: | ||
983 | if (cmd->lsa & 3) | ||
984 | goto error; | ||
985 | break; | ||
986 | case 8: | ||
987 | if (cmd->lsa & 7) | ||
988 | goto error; | ||
989 | break; | ||
990 | case 0: | ||
991 | if (cmd->lsa & 15) | ||
992 | goto error; | ||
993 | break; | ||
994 | error: | ||
995 | default: | ||
996 | pr_debug("invalid DMA alignment %x for size %x\n", | ||
997 | cmd->lsa & 0xf, cmd->size); | ||
998 | return -EIO; | ||
999 | } | ||
1000 | |||
1001 | if (cmd->size > 16 * 1024) { | ||
1002 | pr_debug("invalid DMA size %x\n", cmd->size); | ||
1003 | return -EIO; | ||
1004 | } | ||
1005 | |||
1006 | if (cmd->tag & 0xfff0) { | ||
1007 | /* we reserve the higher tag numbers for kernel use */ | ||
1008 | pr_debug("invalid DMA tag\n"); | ||
1009 | return -EIO; | ||
1010 | } | ||
1011 | |||
1012 | if (cmd->class) { | ||
1013 | /* not supported in this version */ | ||
1014 | pr_debug("invalid DMA class\n"); | ||
1015 | return -EIO; | ||
1016 | } | ||
1017 | |||
1018 | return 0; | ||
1019 | } | ||
1020 | |||
1021 | static int spu_send_mfc_command(struct spu_context *ctx, | ||
1022 | struct mfc_dma_command cmd, | ||
1023 | int *error) | ||
1024 | { | ||
1025 | *error = ctx->ops->send_mfc_command(ctx, &cmd); | ||
1026 | if (*error == -EAGAIN) { | ||
1027 | /* wait for any tag group to complete | ||
1028 | so we have space for the new command */ | ||
1029 | ctx->ops->set_mfc_query(ctx, ctx->tagwait, 1); | ||
1030 | /* try again, because the queue might be | ||
1031 | empty again */ | ||
1032 | *error = ctx->ops->send_mfc_command(ctx, &cmd); | ||
1033 | if (*error == -EAGAIN) | ||
1034 | return 0; | ||
1035 | } | ||
1036 | return 1; | ||
1037 | } | ||
1038 | |||
1039 | static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer, | ||
1040 | size_t size, loff_t *pos) | ||
1041 | { | ||
1042 | struct spu_context *ctx = file->private_data; | ||
1043 | struct mfc_dma_command cmd; | ||
1044 | int ret = -EINVAL; | ||
1045 | |||
1046 | if (size != sizeof cmd) | ||
1047 | goto out; | ||
1048 | |||
1049 | ret = -EFAULT; | ||
1050 | if (copy_from_user(&cmd, buffer, sizeof cmd)) | ||
1051 | goto out; | ||
1052 | |||
1053 | ret = spufs_check_valid_dma(&cmd); | ||
1054 | if (ret) | ||
1055 | goto out; | ||
1056 | |||
1057 | spu_acquire_runnable(ctx); | ||
1058 | if (file->f_flags & O_NONBLOCK) { | ||
1059 | ret = ctx->ops->send_mfc_command(ctx, &cmd); | ||
1060 | } else { | ||
1061 | int status; | ||
1062 | ret = spufs_wait(ctx->mfc_wq, | ||
1063 | spu_send_mfc_command(ctx, cmd, &status)); | ||
1064 | if (status) | ||
1065 | ret = status; | ||
1066 | } | ||
1067 | spu_release(ctx); | ||
1068 | |||
1069 | if (ret) | ||
1070 | goto out; | ||
1071 | |||
1072 | ctx->tagwait |= 1 << cmd.tag; | ||
1073 | |||
1074 | out: | ||
1075 | return ret; | ||
1076 | } | ||
1077 | |||
1078 | static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait) | ||
1079 | { | ||
1080 | struct spu_context *ctx = file->private_data; | ||
1081 | u32 free_elements, tagstatus; | ||
1082 | unsigned int mask; | ||
1083 | |||
1084 | spu_acquire(ctx); | ||
1085 | ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2); | ||
1086 | free_elements = ctx->ops->get_mfc_free_elements(ctx); | ||
1087 | tagstatus = ctx->ops->read_mfc_tagstatus(ctx); | ||
1088 | spu_release(ctx); | ||
1089 | |||
1090 | poll_wait(file, &ctx->mfc_wq, wait); | ||
1091 | |||
1092 | mask = 0; | ||
1093 | if (free_elements & 0xffff) | ||
1094 | mask |= POLLOUT | POLLWRNORM; | ||
1095 | if (tagstatus & ctx->tagwait) | ||
1096 | mask |= POLLIN | POLLRDNORM; | ||
1097 | |||
1098 | pr_debug("%s: free %d tagstatus %d tagwait %d\n", __FUNCTION__, | ||
1099 | free_elements, tagstatus, ctx->tagwait); | ||
1100 | |||
1101 | return mask; | ||
1102 | } | ||
1103 | |||
1104 | static int spufs_mfc_flush(struct file *file) | ||
1105 | { | ||
1106 | struct spu_context *ctx = file->private_data; | ||
1107 | int ret; | ||
1108 | |||
1109 | spu_acquire(ctx); | ||
1110 | #if 0 | ||
1111 | /* this currently hangs */ | ||
1112 | ret = spufs_wait(ctx->mfc_wq, | ||
1113 | ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2)); | ||
1114 | if (ret) | ||
1115 | goto out; | ||
1116 | ret = spufs_wait(ctx->mfc_wq, | ||
1117 | ctx->ops->read_mfc_tagstatus(ctx) == ctx->tagwait); | ||
1118 | out: | ||
1119 | #else | ||
1120 | ret = 0; | ||
1121 | #endif | ||
1122 | spu_release(ctx); | ||
1123 | |||
1124 | return ret; | ||
1125 | } | ||
1126 | |||
1127 | static int spufs_mfc_fsync(struct file *file, struct dentry *dentry, | ||
1128 | int datasync) | ||
1129 | { | ||
1130 | return spufs_mfc_flush(file); | ||
1131 | } | ||
1132 | |||
1133 | static int spufs_mfc_fasync(int fd, struct file *file, int on) | ||
1134 | { | ||
1135 | struct spu_context *ctx = file->private_data; | ||
1136 | |||
1137 | return fasync_helper(fd, file, on, &ctx->mfc_fasync); | ||
1138 | } | ||
1139 | |||
1140 | static struct file_operations spufs_mfc_fops = { | ||
1141 | .open = spufs_mfc_open, | ||
1142 | .read = spufs_mfc_read, | ||
1143 | .write = spufs_mfc_write, | ||
1144 | .poll = spufs_mfc_poll, | ||
1145 | .flush = spufs_mfc_flush, | ||
1146 | .fsync = spufs_mfc_fsync, | ||
1147 | .fasync = spufs_mfc_fasync, | ||
1148 | #ifdef CONFIG_SPUFS_MMAP | ||
1149 | .mmap = spufs_mfc_mmap, | ||
1150 | #endif | ||
1151 | }; | ||
1152 | |||
644 | static void spufs_npc_set(void *data, u64 val) | 1153 | static void spufs_npc_set(void *data, u64 val) |
645 | { | 1154 | { |
646 | struct spu_context *ctx = data; | 1155 | struct spu_context *ctx = data; |
@@ -783,6 +1292,8 @@ struct tree_descr spufs_dir_contents[] = { | |||
783 | { "signal2", &spufs_signal2_fops, 0666, }, | 1292 | { "signal2", &spufs_signal2_fops, 0666, }, |
784 | { "signal1_type", &spufs_signal1_type, 0666, }, | 1293 | { "signal1_type", &spufs_signal1_type, 0666, }, |
785 | { "signal2_type", &spufs_signal2_type, 0666, }, | 1294 | { "signal2_type", &spufs_signal2_type, 0666, }, |
1295 | { "mfc", &spufs_mfc_fops, 0666, }, | ||
1296 | { "cntl", &spufs_cntl_fops, 0666, }, | ||
786 | { "npc", &spufs_npc_ops, 0666, }, | 1297 | { "npc", &spufs_npc_ops, 0666, }, |
787 | { "fpcr", &spufs_fpcr_fops, 0666, }, | 1298 | { "fpcr", &spufs_fpcr_fops, 0666, }, |
788 | { "decr", &spufs_decr_ops, 0666, }, | 1299 | { "decr", &spufs_decr_ops, 0666, }, |
diff --git a/arch/powerpc/platforms/cell/spufs/hw_ops.c b/arch/powerpc/platforms/cell/spufs/hw_ops.c index 5445719bff79..a13a8b5a014d 100644 --- a/arch/powerpc/platforms/cell/spufs/hw_ops.c +++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c | |||
@@ -232,6 +232,59 @@ static void spu_hw_runcntl_stop(struct spu_context *ctx) | |||
232 | spin_unlock_irq(&ctx->spu->register_lock); | 232 | spin_unlock_irq(&ctx->spu->register_lock); |
233 | } | 233 | } |
234 | 234 | ||
235 | static int spu_hw_set_mfc_query(struct spu_context * ctx, u32 mask, u32 mode) | ||
236 | { | ||
237 | struct spu_problem *prob = ctx->spu->problem; | ||
238 | int ret; | ||
239 | |||
240 | spin_lock_irq(&ctx->spu->register_lock); | ||
241 | ret = -EAGAIN; | ||
242 | if (in_be32(&prob->dma_querytype_RW)) | ||
243 | goto out; | ||
244 | ret = 0; | ||
245 | out_be32(&prob->dma_querymask_RW, mask); | ||
246 | out_be32(&prob->dma_querytype_RW, mode); | ||
247 | out: | ||
248 | spin_unlock_irq(&ctx->spu->register_lock); | ||
249 | return ret; | ||
250 | } | ||
251 | |||
252 | static u32 spu_hw_read_mfc_tagstatus(struct spu_context * ctx) | ||
253 | { | ||
254 | return in_be32(&ctx->spu->problem->dma_tagstatus_R); | ||
255 | } | ||
256 | |||
257 | static u32 spu_hw_get_mfc_free_elements(struct spu_context *ctx) | ||
258 | { | ||
259 | return in_be32(&ctx->spu->problem->dma_qstatus_R); | ||
260 | } | ||
261 | |||
262 | static int spu_hw_send_mfc_command(struct spu_context *ctx, | ||
263 | struct mfc_dma_command *cmd) | ||
264 | { | ||
265 | u32 status; | ||
266 | struct spu_problem *prob = ctx->spu->problem; | ||
267 | |||
268 | spin_lock_irq(&ctx->spu->register_lock); | ||
269 | out_be32(&prob->mfc_lsa_W, cmd->lsa); | ||
270 | out_be64(&prob->mfc_ea_W, cmd->ea); | ||
271 | out_be32(&prob->mfc_union_W.by32.mfc_size_tag32, | ||
272 | cmd->size << 16 | cmd->tag); | ||
273 | out_be32(&prob->mfc_union_W.by32.mfc_class_cmd32, | ||
274 | cmd->class << 16 | cmd->cmd); | ||
275 | status = in_be32(&prob->mfc_union_W.by32.mfc_class_cmd32); | ||
276 | spin_unlock_irq(&ctx->spu->register_lock); | ||
277 | |||
278 | switch (status & 0xffff) { | ||
279 | case 0: | ||
280 | return 0; | ||
281 | case 2: | ||
282 | return -EAGAIN; | ||
283 | default: | ||
284 | return -EINVAL; | ||
285 | } | ||
286 | } | ||
287 | |||
235 | struct spu_context_ops spu_hw_ops = { | 288 | struct spu_context_ops spu_hw_ops = { |
236 | .mbox_read = spu_hw_mbox_read, | 289 | .mbox_read = spu_hw_mbox_read, |
237 | .mbox_stat_read = spu_hw_mbox_stat_read, | 290 | .mbox_stat_read = spu_hw_mbox_stat_read, |
@@ -252,4 +305,8 @@ struct spu_context_ops spu_hw_ops = { | |||
252 | .get_ls = spu_hw_get_ls, | 305 | .get_ls = spu_hw_get_ls, |
253 | .runcntl_write = spu_hw_runcntl_write, | 306 | .runcntl_write = spu_hw_runcntl_write, |
254 | .runcntl_stop = spu_hw_runcntl_stop, | 307 | .runcntl_stop = spu_hw_runcntl_stop, |
308 | .set_mfc_query = spu_hw_set_mfc_query, | ||
309 | .read_mfc_tagstatus = spu_hw_read_mfc_tagstatus, | ||
310 | .get_mfc_free_elements = spu_hw_get_mfc_free_elements, | ||
311 | .send_mfc_command = spu_hw_send_mfc_command, | ||
255 | }; | 312 | }; |
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index b3962c3a0348..d9554199afa7 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
@@ -103,7 +103,7 @@ spufs_setattr(struct dentry *dentry, struct iattr *attr) | |||
103 | 103 | ||
104 | static int | 104 | static int |
105 | spufs_new_file(struct super_block *sb, struct dentry *dentry, | 105 | spufs_new_file(struct super_block *sb, struct dentry *dentry, |
106 | struct file_operations *fops, int mode, | 106 | const struct file_operations *fops, int mode, |
107 | struct spu_context *ctx) | 107 | struct spu_context *ctx) |
108 | { | 108 | { |
109 | static struct inode_operations spufs_file_iops = { | 109 | static struct inode_operations spufs_file_iops = { |
@@ -241,7 +241,7 @@ spufs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
241 | inode->i_gid = dir->i_gid; | 241 | inode->i_gid = dir->i_gid; |
242 | inode->i_mode &= S_ISGID; | 242 | inode->i_mode &= S_ISGID; |
243 | } | 243 | } |
244 | ctx = alloc_spu_context(inode->i_mapping); | 244 | ctx = alloc_spu_context(); |
245 | SPUFS_I(inode)->i_ctx = ctx; | 245 | SPUFS_I(inode)->i_ctx = ctx; |
246 | if (!ctx) | 246 | if (!ctx) |
247 | goto out_iput; | 247 | goto out_iput; |
@@ -442,7 +442,7 @@ static struct file_system_type spufs_type = { | |||
442 | .kill_sb = kill_litter_super, | 442 | .kill_sb = kill_litter_super, |
443 | }; | 443 | }; |
444 | 444 | ||
445 | static int spufs_init(void) | 445 | static int __init spufs_init(void) |
446 | { | 446 | { |
447 | int ret; | 447 | int ret; |
448 | ret = -ENOMEM; | 448 | ret = -ENOMEM; |
@@ -472,7 +472,7 @@ out: | |||
472 | } | 472 | } |
473 | module_init(spufs_init); | 473 | module_init(spufs_init); |
474 | 474 | ||
475 | static void spufs_exit(void) | 475 | static void __exit spufs_exit(void) |
476 | { | 476 | { |
477 | spu_sched_exit(); | 477 | spu_sched_exit(); |
478 | unregister_spu_syscalls(&spufs_calls); | 478 | unregister_spu_syscalls(&spufs_calls); |
diff --git a/arch/powerpc/platforms/cell/spufs/run.c b/arch/powerpc/platforms/cell/spufs/run.c index 18ea8866c61a..c04e078c0fe5 100644 --- a/arch/powerpc/platforms/cell/spufs/run.c +++ b/arch/powerpc/platforms/cell/spufs/run.c | |||
@@ -76,6 +76,90 @@ static inline int spu_reacquire_runnable(struct spu_context *ctx, u32 *npc, | |||
76 | return 0; | 76 | return 0; |
77 | } | 77 | } |
78 | 78 | ||
79 | /* | ||
80 | * SPU syscall restarting is tricky because we violate the basic | ||
81 | * assumption that the signal handler is running on the interrupted | ||
82 | * thread. Here instead, the handler runs on PowerPC user space code, | ||
83 | * while the syscall was called from the SPU. | ||
84 | * This means we can only do a very rough approximation of POSIX | ||
85 | * signal semantics. | ||
86 | */ | ||
87 | int spu_handle_restartsys(struct spu_context *ctx, long *spu_ret, | ||
88 | unsigned int *npc) | ||
89 | { | ||
90 | int ret; | ||
91 | |||
92 | switch (*spu_ret) { | ||
93 | case -ERESTARTSYS: | ||
94 | case -ERESTARTNOINTR: | ||
95 | /* | ||
96 | * Enter the regular syscall restarting for | ||
97 | * sys_spu_run, then restart the SPU syscall | ||
98 | * callback. | ||
99 | */ | ||
100 | *npc -= 8; | ||
101 | ret = -ERESTARTSYS; | ||
102 | break; | ||
103 | case -ERESTARTNOHAND: | ||
104 | case -ERESTART_RESTARTBLOCK: | ||
105 | /* | ||
106 | * Restart block is too hard for now, just return -EINTR | ||
107 | * to the SPU. | ||
108 | * ERESTARTNOHAND comes from sys_pause, we also return | ||
109 | * -EINTR from there. | ||
110 | * Assume that we need to be restarted ourselves though. | ||
111 | */ | ||
112 | *spu_ret = -EINTR; | ||
113 | ret = -ERESTARTSYS; | ||
114 | break; | ||
115 | default: | ||
116 | printk(KERN_WARNING "%s: unexpected return code %ld\n", | ||
117 | __FUNCTION__, *spu_ret); | ||
118 | ret = 0; | ||
119 | } | ||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | int spu_process_callback(struct spu_context *ctx) | ||
124 | { | ||
125 | struct spu_syscall_block s; | ||
126 | u32 ls_pointer, npc; | ||
127 | char *ls; | ||
128 | long spu_ret; | ||
129 | int ret; | ||
130 | |||
131 | /* get syscall block from local store */ | ||
132 | npc = ctx->ops->npc_read(ctx); | ||
133 | ls = ctx->ops->get_ls(ctx); | ||
134 | ls_pointer = *(u32*)(ls + npc); | ||
135 | if (ls_pointer > (LS_SIZE - sizeof(s))) | ||
136 | return -EFAULT; | ||
137 | memcpy(&s, ls + ls_pointer, sizeof (s)); | ||
138 | |||
139 | /* do actual syscall without pinning the spu */ | ||
140 | ret = 0; | ||
141 | spu_ret = -ENOSYS; | ||
142 | npc += 4; | ||
143 | |||
144 | if (s.nr_ret < __NR_syscalls) { | ||
145 | spu_release(ctx); | ||
146 | /* do actual system call from here */ | ||
147 | spu_ret = spu_sys_callback(&s); | ||
148 | if (spu_ret <= -ERESTARTSYS) { | ||
149 | ret = spu_handle_restartsys(ctx, &spu_ret, &npc); | ||
150 | } | ||
151 | spu_acquire(ctx); | ||
152 | if (ret == -ERESTARTSYS) | ||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | /* write result, jump over indirect pointer */ | ||
157 | memcpy(ls + ls_pointer, &spu_ret, sizeof (spu_ret)); | ||
158 | ctx->ops->npc_write(ctx, npc); | ||
159 | ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE); | ||
160 | return ret; | ||
161 | } | ||
162 | |||
79 | static inline int spu_process_events(struct spu_context *ctx) | 163 | static inline int spu_process_events(struct spu_context *ctx) |
80 | { | 164 | { |
81 | struct spu *spu = ctx->spu; | 165 | struct spu *spu = ctx->spu; |
@@ -107,6 +191,13 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx, | |||
107 | ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status)); | 191 | ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, status)); |
108 | if (unlikely(ret)) | 192 | if (unlikely(ret)) |
109 | break; | 193 | break; |
194 | if ((*status & SPU_STATUS_STOPPED_BY_STOP) && | ||
195 | (*status >> SPU_STOP_STATUS_SHIFT == 0x2104)) { | ||
196 | ret = spu_process_callback(ctx); | ||
197 | if (ret) | ||
198 | break; | ||
199 | *status &= ~SPU_STATUS_STOPPED_BY_STOP; | ||
200 | } | ||
110 | if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { | 201 | if (unlikely(ctx->state != SPU_STATE_RUNNABLE)) { |
111 | ret = spu_reacquire_runnable(ctx, npc, status); | 202 | ret = spu_reacquire_runnable(ctx, npc, status); |
112 | if (ret) | 203 | if (ret) |
diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 963182fbd1aa..bf652cd77000 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c | |||
@@ -180,6 +180,7 @@ static inline void bind_context(struct spu *spu, struct spu_context *ctx) | |||
180 | spu->ibox_callback = spufs_ibox_callback; | 180 | spu->ibox_callback = spufs_ibox_callback; |
181 | spu->wbox_callback = spufs_wbox_callback; | 181 | spu->wbox_callback = spufs_wbox_callback; |
182 | spu->stop_callback = spufs_stop_callback; | 182 | spu->stop_callback = spufs_stop_callback; |
183 | spu->mfc_callback = spufs_mfc_callback; | ||
183 | mb(); | 184 | mb(); |
184 | spu_unmap_mappings(ctx); | 185 | spu_unmap_mappings(ctx); |
185 | spu_restore(&ctx->csa, spu); | 186 | spu_restore(&ctx->csa, spu); |
@@ -197,6 +198,7 @@ static inline void unbind_context(struct spu *spu, struct spu_context *ctx) | |||
197 | spu->ibox_callback = NULL; | 198 | spu->ibox_callback = NULL; |
198 | spu->wbox_callback = NULL; | 199 | spu->wbox_callback = NULL; |
199 | spu->stop_callback = NULL; | 200 | spu->stop_callback = NULL; |
201 | spu->mfc_callback = NULL; | ||
200 | spu->mm = NULL; | 202 | spu->mm = NULL; |
201 | spu->pid = 0; | 203 | spu->pid = 0; |
202 | spu->prio = MAX_PRIO; | 204 | spu->prio = MAX_PRIO; |
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index db2601f0abd5..4485738e2102 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -43,7 +43,11 @@ struct spu_context { | |||
43 | struct spu *spu; /* pointer to a physical SPU */ | 43 | struct spu *spu; /* pointer to a physical SPU */ |
44 | struct spu_state csa; /* SPU context save area. */ | 44 | struct spu_state csa; /* SPU context save area. */ |
45 | spinlock_t mmio_lock; /* protects mmio access */ | 45 | spinlock_t mmio_lock; /* protects mmio access */ |
46 | struct address_space *local_store;/* local store backing store */ | 46 | struct address_space *local_store; /* local store mapping. */ |
47 | struct address_space *mfc; /* 'mfc' area mappings. */ | ||
48 | struct address_space *cntl; /* 'control' area mappings. */ | ||
49 | struct address_space *signal1; /* 'signal1' area mappings. */ | ||
50 | struct address_space *signal2; /* 'signal2' area mappings. */ | ||
47 | 51 | ||
48 | enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; | 52 | enum { SPU_STATE_RUNNABLE, SPU_STATE_SAVED } state; |
49 | struct rw_semaphore state_sema; | 53 | struct rw_semaphore state_sema; |
@@ -55,13 +59,27 @@ struct spu_context { | |||
55 | wait_queue_head_t ibox_wq; | 59 | wait_queue_head_t ibox_wq; |
56 | wait_queue_head_t wbox_wq; | 60 | wait_queue_head_t wbox_wq; |
57 | wait_queue_head_t stop_wq; | 61 | wait_queue_head_t stop_wq; |
62 | wait_queue_head_t mfc_wq; | ||
58 | struct fasync_struct *ibox_fasync; | 63 | struct fasync_struct *ibox_fasync; |
59 | struct fasync_struct *wbox_fasync; | 64 | struct fasync_struct *wbox_fasync; |
65 | struct fasync_struct *mfc_fasync; | ||
66 | u32 tagwait; | ||
60 | struct spu_context_ops *ops; | 67 | struct spu_context_ops *ops; |
61 | struct work_struct reap_work; | 68 | struct work_struct reap_work; |
62 | u64 flags; | 69 | u64 flags; |
63 | }; | 70 | }; |
64 | 71 | ||
72 | struct mfc_dma_command { | ||
73 | int32_t pad; /* reserved */ | ||
74 | uint32_t lsa; /* local storage address */ | ||
75 | uint64_t ea; /* effective address */ | ||
76 | uint16_t size; /* transfer size */ | ||
77 | uint16_t tag; /* command tag */ | ||
78 | uint16_t class; /* class ID */ | ||
79 | uint16_t cmd; /* command opcode */ | ||
80 | }; | ||
81 | |||
82 | |||
65 | /* SPU context query/set operations. */ | 83 | /* SPU context query/set operations. */ |
66 | struct spu_context_ops { | 84 | struct spu_context_ops { |
67 | int (*mbox_read) (struct spu_context * ctx, u32 * data); | 85 | int (*mbox_read) (struct spu_context * ctx, u32 * data); |
@@ -84,6 +102,11 @@ struct spu_context_ops { | |||
84 | char*(*get_ls) (struct spu_context * ctx); | 102 | char*(*get_ls) (struct spu_context * ctx); |
85 | void (*runcntl_write) (struct spu_context * ctx, u32 data); | 103 | void (*runcntl_write) (struct spu_context * ctx, u32 data); |
86 | void (*runcntl_stop) (struct spu_context * ctx); | 104 | void (*runcntl_stop) (struct spu_context * ctx); |
105 | int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode); | ||
106 | u32 (*read_mfc_tagstatus)(struct spu_context * ctx); | ||
107 | u32 (*get_mfc_free_elements)(struct spu_context *ctx); | ||
108 | int (*send_mfc_command)(struct spu_context *ctx, | ||
109 | struct mfc_dma_command *cmd); | ||
87 | }; | 110 | }; |
88 | 111 | ||
89 | extern struct spu_context_ops spu_hw_ops; | 112 | extern struct spu_context_ops spu_hw_ops; |
@@ -106,7 +129,7 @@ long spufs_create_thread(struct nameidata *nd, | |||
106 | extern struct file_operations spufs_context_fops; | 129 | extern struct file_operations spufs_context_fops; |
107 | 130 | ||
108 | /* context management */ | 131 | /* context management */ |
109 | struct spu_context * alloc_spu_context(struct address_space *local_store); | 132 | struct spu_context * alloc_spu_context(void); |
110 | void destroy_spu_context(struct kref *kref); | 133 | void destroy_spu_context(struct kref *kref); |
111 | struct spu_context * get_spu_context(struct spu_context *ctx); | 134 | struct spu_context * get_spu_context(struct spu_context *ctx); |
112 | int put_spu_context(struct spu_context *ctx); | 135 | int put_spu_context(struct spu_context *ctx); |
@@ -159,5 +182,6 @@ size_t spu_ibox_read(struct spu_context *ctx, u32 *data); | |||
159 | void spufs_ibox_callback(struct spu *spu); | 182 | void spufs_ibox_callback(struct spu *spu); |
160 | void spufs_wbox_callback(struct spu *spu); | 183 | void spufs_wbox_callback(struct spu *spu); |
161 | void spufs_stop_callback(struct spu *spu); | 184 | void spufs_stop_callback(struct spu *spu); |
185 | void spufs_mfc_callback(struct spu *spu); | ||
162 | 186 | ||
163 | #endif | 187 | #endif |
diff --git a/arch/powerpc/platforms/cell/spufs/switch.c b/arch/powerpc/platforms/cell/spufs/switch.c index 212db28531fa..97898d5d34e5 100644 --- a/arch/powerpc/platforms/cell/spufs/switch.c +++ b/arch/powerpc/platforms/cell/spufs/switch.c | |||
@@ -2145,7 +2145,8 @@ static void init_priv1(struct spu_state *csa) | |||
2145 | csa->priv1.int_mask_class1_RW = CLASS1_ENABLE_SEGMENT_FAULT_INTR | | 2145 | csa->priv1.int_mask_class1_RW = CLASS1_ENABLE_SEGMENT_FAULT_INTR | |
2146 | CLASS1_ENABLE_STORAGE_FAULT_INTR; | 2146 | CLASS1_ENABLE_STORAGE_FAULT_INTR; |
2147 | csa->priv1.int_mask_class2_RW = CLASS2_ENABLE_SPU_STOP_INTR | | 2147 | csa->priv1.int_mask_class2_RW = CLASS2_ENABLE_SPU_STOP_INTR | |
2148 | CLASS2_ENABLE_SPU_HALT_INTR; | 2148 | CLASS2_ENABLE_SPU_HALT_INTR | |
2149 | CLASS2_ENABLE_SPU_DMA_TAG_GROUP_COMPLETE_INTR; | ||
2149 | } | 2150 | } |
2150 | 2151 | ||
2151 | static void init_priv2(struct spu_state *csa) | 2152 | static void init_priv2(struct spu_state *csa) |
diff --git a/arch/powerpc/platforms/chrp/chrp.h b/arch/powerpc/platforms/chrp/chrp.h index 814f54742e0f..63f0aee4c158 100644 --- a/arch/powerpc/platforms/chrp/chrp.h +++ b/arch/powerpc/platforms/chrp/chrp.h | |||
@@ -8,4 +8,4 @@ extern int chrp_set_rtc_time(struct rtc_time *); | |||
8 | extern long chrp_time_init(void); | 8 | extern long chrp_time_init(void); |
9 | 9 | ||
10 | extern void chrp_find_bridges(void); | 10 | extern void chrp_find_bridges(void); |
11 | extern void chrp_event_scan(void); | 11 | extern void chrp_event_scan(unsigned long); |
diff --git a/arch/powerpc/platforms/chrp/pegasos_eth.c b/arch/powerpc/platforms/chrp/pegasos_eth.c index 29c86781c493..6ad4b1a72c96 100644 --- a/arch/powerpc/platforms/chrp/pegasos_eth.c +++ b/arch/powerpc/platforms/chrp/pegasos_eth.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/platforms/chrp_pegasos_eth.c | ||
3 | * | ||
4 | * Copyright (C) 2005 Sven Luther <sl@bplan-gmbh.de> | 2 | * Copyright (C) 2005 Sven Luther <sl@bplan-gmbh.de> |
5 | * Thanks to : | 3 | * Thanks to : |
6 | * Dale Farnsworth <dale@farnsworth.org> | 4 | * Dale Farnsworth <dale@farnsworth.org> |
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index e1fadbf49150..23a201718704 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/platforms/setup.c | ||
3 | * | ||
4 | * Copyright (C) 1995 Linus Torvalds | 2 | * Copyright (C) 1995 Linus Torvalds |
5 | * Adapted from 'alpha' version by Gary Thomas | 3 | * Adapted from 'alpha' version by Gary Thomas |
6 | * Modified by Cort Dougan (cort@cs.nmt.edu) | 4 | * Modified by Cort Dougan (cort@cs.nmt.edu) |
@@ -37,6 +35,7 @@ | |||
37 | #include <linux/root_dev.h> | 35 | #include <linux/root_dev.h> |
38 | #include <linux/initrd.h> | 36 | #include <linux/initrd.h> |
39 | #include <linux/module.h> | 37 | #include <linux/module.h> |
38 | #include <linux/timer.h> | ||
40 | 39 | ||
41 | #include <asm/io.h> | 40 | #include <asm/io.h> |
42 | #include <asm/pgtable.h> | 41 | #include <asm/pgtable.h> |
@@ -63,6 +62,10 @@ EXPORT_SYMBOL(_chrp_type); | |||
63 | 62 | ||
64 | struct mpic *chrp_mpic; | 63 | struct mpic *chrp_mpic; |
65 | 64 | ||
65 | /* Used for doing CHRP event-scans */ | ||
66 | DEFINE_PER_CPU(struct timer_list, heartbeat_timer); | ||
67 | unsigned long event_scan_interval; | ||
68 | |||
66 | /* | 69 | /* |
67 | * XXX this should be in xmon.h, but putting it there means xmon.h | 70 | * XXX this should be in xmon.h, but putting it there means xmon.h |
68 | * has to include <linux/interrupt.h> (to get irqreturn_t), which | 71 | * has to include <linux/interrupt.h> (to get irqreturn_t), which |
@@ -231,8 +234,6 @@ void __init chrp_setup_arch(void) | |||
231 | { | 234 | { |
232 | struct device_node *root = find_path_device ("/"); | 235 | struct device_node *root = find_path_device ("/"); |
233 | char *machine = NULL; | 236 | char *machine = NULL; |
234 | struct device_node *device; | ||
235 | unsigned int *p = NULL; | ||
236 | 237 | ||
237 | /* init to some ~sane value until calibrate_delay() runs */ | 238 | /* init to some ~sane value until calibrate_delay() runs */ |
238 | loops_per_jiffy = 50000000/HZ; | 239 | loops_per_jiffy = 50000000/HZ; |
@@ -289,23 +290,12 @@ void __init chrp_setup_arch(void) | |||
289 | */ | 290 | */ |
290 | sio_init(); | 291 | sio_init(); |
291 | 292 | ||
292 | /* Get the event scan rate for the rtas so we know how | ||
293 | * often it expects a heartbeat. -- Cort | ||
294 | */ | ||
295 | device = find_devices("rtas"); | ||
296 | if (device) | ||
297 | p = (unsigned int *) get_property | ||
298 | (device, "rtas-event-scan-rate", NULL); | ||
299 | if (p && *p) { | ||
300 | ppc_md.heartbeat = chrp_event_scan; | ||
301 | ppc_md.heartbeat_reset = HZ / (*p * 30) - 1; | ||
302 | ppc_md.heartbeat_count = 1; | ||
303 | printk("RTAS Event Scan Rate: %u (%lu jiffies)\n", | ||
304 | *p, ppc_md.heartbeat_reset); | ||
305 | } | ||
306 | |||
307 | pci_create_OF_bus_map(); | 293 | pci_create_OF_bus_map(); |
308 | 294 | ||
295 | #ifdef CONFIG_SMP | ||
296 | smp_ops = &chrp_smp_ops; | ||
297 | #endif /* CONFIG_SMP */ | ||
298 | |||
309 | /* | 299 | /* |
310 | * Print the banner, then scroll down so boot progress | 300 | * Print the banner, then scroll down so boot progress |
311 | * can be printed. -- Cort | 301 | * can be printed. -- Cort |
@@ -314,7 +304,7 @@ void __init chrp_setup_arch(void) | |||
314 | } | 304 | } |
315 | 305 | ||
316 | void | 306 | void |
317 | chrp_event_scan(void) | 307 | chrp_event_scan(unsigned long unused) |
318 | { | 308 | { |
319 | unsigned char log[1024]; | 309 | unsigned char log[1024]; |
320 | int ret = 0; | 310 | int ret = 0; |
@@ -322,7 +312,8 @@ chrp_event_scan(void) | |||
322 | /* XXX: we should loop until the hardware says no more error logs -- Cort */ | 312 | /* XXX: we should loop until the hardware says no more error logs -- Cort */ |
323 | rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0, | 313 | rtas_call(rtas_token("event-scan"), 4, 1, &ret, 0xffffffff, 0, |
324 | __pa(log), 1024); | 314 | __pa(log), 1024); |
325 | ppc_md.heartbeat_count = ppc_md.heartbeat_reset; | 315 | mod_timer(&__get_cpu_var(heartbeat_timer), |
316 | jiffies + event_scan_interval); | ||
326 | } | 317 | } |
327 | 318 | ||
328 | /* | 319 | /* |
@@ -467,6 +458,9 @@ void __init chrp_init_IRQ(void) | |||
467 | void __init | 458 | void __init |
468 | chrp_init2(void) | 459 | chrp_init2(void) |
469 | { | 460 | { |
461 | struct device_node *device; | ||
462 | unsigned int *p = NULL; | ||
463 | |||
470 | #ifdef CONFIG_NVRAM | 464 | #ifdef CONFIG_NVRAM |
471 | chrp_nvram_init(); | 465 | chrp_nvram_init(); |
472 | #endif | 466 | #endif |
@@ -478,12 +472,53 @@ chrp_init2(void) | |||
478 | request_region(0x80,0x10,"dma page reg"); | 472 | request_region(0x80,0x10,"dma page reg"); |
479 | request_region(0xc0,0x20,"dma2"); | 473 | request_region(0xc0,0x20,"dma2"); |
480 | 474 | ||
475 | /* Get the event scan rate for the rtas so we know how | ||
476 | * often it expects a heartbeat. -- Cort | ||
477 | */ | ||
478 | device = find_devices("rtas"); | ||
479 | if (device) | ||
480 | p = (unsigned int *) get_property | ||
481 | (device, "rtas-event-scan-rate", NULL); | ||
482 | if (p && *p) { | ||
483 | /* | ||
484 | * Arrange to call chrp_event_scan at least *p times | ||
485 | * per minute. We use 59 rather than 60 here so that | ||
486 | * the rate will be slightly higher than the minimum. | ||
487 | * This all assumes we don't do hotplug CPU on any | ||
488 | * machine that needs the event scans done. | ||
489 | */ | ||
490 | unsigned long interval, offset; | ||
491 | int cpu, ncpus; | ||
492 | struct timer_list *timer; | ||
493 | |||
494 | interval = HZ * 59 / *p; | ||
495 | offset = HZ; | ||
496 | ncpus = num_online_cpus(); | ||
497 | event_scan_interval = ncpus * interval; | ||
498 | for (cpu = 0; cpu < ncpus; ++cpu) { | ||
499 | timer = &per_cpu(heartbeat_timer, cpu); | ||
500 | setup_timer(timer, chrp_event_scan, 0); | ||
501 | timer->expires = jiffies + offset; | ||
502 | add_timer_on(timer, cpu); | ||
503 | offset += interval; | ||
504 | } | ||
505 | printk("RTAS Event Scan Rate: %u (%lu jiffies)\n", | ||
506 | *p, interval); | ||
507 | } | ||
508 | |||
481 | if (ppc_md.progress) | 509 | if (ppc_md.progress) |
482 | ppc_md.progress(" Have fun! ", 0x7777); | 510 | ppc_md.progress(" Have fun! ", 0x7777); |
483 | } | 511 | } |
484 | 512 | ||
485 | void __init chrp_init(void) | 513 | static int __init chrp_probe(void) |
486 | { | 514 | { |
515 | char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(), | ||
516 | "device_type", NULL); | ||
517 | if (dtype == NULL) | ||
518 | return 0; | ||
519 | if (strcmp(dtype, "chrp")) | ||
520 | return 0; | ||
521 | |||
487 | ISA_DMA_THRESHOLD = ~0L; | 522 | ISA_DMA_THRESHOLD = ~0L; |
488 | DMA_MODE_READ = 0x44; | 523 | DMA_MODE_READ = 0x44; |
489 | DMA_MODE_WRITE = 0x48; | 524 | DMA_MODE_WRITE = 0x48; |
diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 78df2e7ca88a..7d7889026936 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/platforms/chrp_time.c | ||
3 | * | ||
4 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | 2 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds |
5 | * | 3 | * |
6 | * Adapted for PowerPC (PReP) by Gary Thomas | 4 | * Adapted for PowerPC (PReP) by Gary Thomas |
@@ -122,33 +120,15 @@ int chrp_set_rtc_time(struct rtc_time *tmarg) | |||
122 | void chrp_get_rtc_time(struct rtc_time *tm) | 120 | void chrp_get_rtc_time(struct rtc_time *tm) |
123 | { | 121 | { |
124 | unsigned int year, mon, day, hour, min, sec; | 122 | unsigned int year, mon, day, hour, min, sec; |
125 | int uip, i; | ||
126 | |||
127 | /* The Linux interpretation of the CMOS clock register contents: | ||
128 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the | ||
129 | * RTC registers show the second which has precisely just started. | ||
130 | * Let's hope other operating systems interpret the RTC the same way. | ||
131 | */ | ||
132 | 123 | ||
133 | /* Since the UIP flag is set for about 2.2 ms and the clock | 124 | do { |
134 | * is typically written with a precision of 1 jiffy, trying | ||
135 | * to obtain a precision better than a few milliseconds is | ||
136 | * an illusion. Only consistency is interesting, this also | ||
137 | * allows to use the routine for /dev/rtc without a potential | ||
138 | * 1 second kernel busy loop triggered by any reader of /dev/rtc. | ||
139 | */ | ||
140 | |||
141 | for ( i = 0; i<1000000; i++) { | ||
142 | uip = chrp_cmos_clock_read(RTC_FREQ_SELECT); | ||
143 | sec = chrp_cmos_clock_read(RTC_SECONDS); | 125 | sec = chrp_cmos_clock_read(RTC_SECONDS); |
144 | min = chrp_cmos_clock_read(RTC_MINUTES); | 126 | min = chrp_cmos_clock_read(RTC_MINUTES); |
145 | hour = chrp_cmos_clock_read(RTC_HOURS); | 127 | hour = chrp_cmos_clock_read(RTC_HOURS); |
146 | day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH); | 128 | day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH); |
147 | mon = chrp_cmos_clock_read(RTC_MONTH); | 129 | mon = chrp_cmos_clock_read(RTC_MONTH); |
148 | year = chrp_cmos_clock_read(RTC_YEAR); | 130 | year = chrp_cmos_clock_read(RTC_YEAR); |
149 | uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT); | 131 | } while (sec != chrp_cmos_clock_read(RTC_SECONDS)); |
150 | if ((uip & RTC_UIP)==0) break; | ||
151 | } | ||
152 | 132 | ||
153 | if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | 133 | if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
154 | BCD_TO_BIN(sec); | 134 | BCD_TO_BIN(sec); |
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index a41d8b78c0cd..d771b8ee857d 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include "setup.h" | 46 | #include "setup.h" |
47 | 47 | ||
48 | extern int piranha_simulator; | 48 | extern int piranha_simulator; |
49 | static int mf_initialized; | ||
49 | 50 | ||
50 | /* | 51 | /* |
51 | * This is the structure layout for the Machine Facilites LPAR event | 52 | * This is the structure layout for the Machine Facilites LPAR event |
@@ -143,7 +144,8 @@ static spinlock_t pending_event_spinlock; | |||
143 | static struct pending_event *pending_event_head; | 144 | static struct pending_event *pending_event_head; |
144 | static struct pending_event *pending_event_tail; | 145 | static struct pending_event *pending_event_tail; |
145 | static struct pending_event *pending_event_avail; | 146 | static struct pending_event *pending_event_avail; |
146 | static struct pending_event pending_event_prealloc[16]; | 147 | #define PENDING_EVENT_PREALLOC_LEN 16 |
148 | static struct pending_event pending_event_prealloc[PENDING_EVENT_PREALLOC_LEN]; | ||
147 | 149 | ||
148 | /* | 150 | /* |
149 | * Put a pending event onto the available queue, so it can get reused. | 151 | * Put a pending event onto the available queue, so it can get reused. |
@@ -597,7 +599,7 @@ void mf_power_off(void) | |||
597 | * Global kernel interface to tell the VSP object in the primary | 599 | * Global kernel interface to tell the VSP object in the primary |
598 | * partition to reboot this partition. | 600 | * partition to reboot this partition. |
599 | */ | 601 | */ |
600 | void mf_reboot(void) | 602 | void mf_reboot(char *cmd) |
601 | { | 603 | { |
602 | printk(KERN_INFO "mf.c: Preparing to bounce...\n"); | 604 | printk(KERN_INFO "mf.c: Preparing to bounce...\n"); |
603 | signal_ce_msg_simple(0x4e, NULL); | 605 | signal_ce_msg_simple(0x4e, NULL); |
@@ -625,7 +627,7 @@ void mf_display_src(u32 word) | |||
625 | /* | 627 | /* |
626 | * Display a single word SRC of the form "PROGXXXX" on the VSP control panel. | 628 | * Display a single word SRC of the form "PROGXXXX" on the VSP control panel. |
627 | */ | 629 | */ |
628 | void mf_display_progress(u16 value) | 630 | static __init void mf_display_progress_src(u16 value) |
629 | { | 631 | { |
630 | u8 ce[12]; | 632 | u8 ce[12]; |
631 | u8 src[72]; | 633 | u8 src[72]; |
@@ -649,30 +651,42 @@ void mf_display_progress(u16 value) | |||
649 | * Clear the VSP control panel. Used to "erase" an SRC that was | 651 | * Clear the VSP control panel. Used to "erase" an SRC that was |
650 | * previously displayed. | 652 | * previously displayed. |
651 | */ | 653 | */ |
652 | void mf_clear_src(void) | 654 | static void mf_clear_src(void) |
653 | { | 655 | { |
654 | signal_ce_msg_simple(0x4b, NULL); | 656 | signal_ce_msg_simple(0x4b, NULL); |
655 | } | 657 | } |
656 | 658 | ||
659 | void __init mf_display_progress(u16 value) | ||
660 | { | ||
661 | if (piranha_simulator || !mf_initialized) | ||
662 | return; | ||
663 | |||
664 | if (0xFFFF == value) | ||
665 | mf_clear_src(); | ||
666 | else | ||
667 | mf_display_progress_src(value); | ||
668 | } | ||
669 | |||
657 | /* | 670 | /* |
658 | * Initialization code here. | 671 | * Initialization code here. |
659 | */ | 672 | */ |
660 | void mf_init(void) | 673 | void __init mf_init(void) |
661 | { | 674 | { |
662 | int i; | 675 | int i; |
663 | 676 | ||
664 | /* initialize */ | ||
665 | spin_lock_init(&pending_event_spinlock); | 677 | spin_lock_init(&pending_event_spinlock); |
666 | for (i = 0; | 678 | |
667 | i < sizeof(pending_event_prealloc) / sizeof(*pending_event_prealloc); | 679 | for (i = 0; i < PENDING_EVENT_PREALLOC_LEN; i++) |
668 | ++i) | ||
669 | free_pending_event(&pending_event_prealloc[i]); | 680 | free_pending_event(&pending_event_prealloc[i]); |
681 | |||
670 | HvLpEvent_registerHandler(HvLpEvent_Type_MachineFac, &hv_handler); | 682 | HvLpEvent_registerHandler(HvLpEvent_Type_MachineFac, &hv_handler); |
671 | 683 | ||
672 | /* virtual continue ack */ | 684 | /* virtual continue ack */ |
673 | signal_ce_msg_simple(0x57, NULL); | 685 | signal_ce_msg_simple(0x57, NULL); |
674 | 686 | ||
675 | /* initialization complete */ | 687 | mf_initialized = 1; |
688 | mb(); | ||
689 | |||
676 | printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities " | 690 | printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities " |
677 | "initialized\n"); | 691 | "initialized\n"); |
678 | } | 692 | } |
@@ -692,6 +706,43 @@ static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg) | |||
692 | complete(&rtc->com); | 706 | complete(&rtc->com); |
693 | } | 707 | } |
694 | 708 | ||
709 | static int mf_set_rtc(struct rtc_time *tm) | ||
710 | { | ||
711 | char ce_time[12]; | ||
712 | u8 day, mon, hour, min, sec, y1, y2; | ||
713 | unsigned year; | ||
714 | |||
715 | year = 1900 + tm->tm_year; | ||
716 | y1 = year / 100; | ||
717 | y2 = year % 100; | ||
718 | |||
719 | sec = tm->tm_sec; | ||
720 | min = tm->tm_min; | ||
721 | hour = tm->tm_hour; | ||
722 | day = tm->tm_mday; | ||
723 | mon = tm->tm_mon + 1; | ||
724 | |||
725 | BIN_TO_BCD(sec); | ||
726 | BIN_TO_BCD(min); | ||
727 | BIN_TO_BCD(hour); | ||
728 | BIN_TO_BCD(mon); | ||
729 | BIN_TO_BCD(day); | ||
730 | BIN_TO_BCD(y1); | ||
731 | BIN_TO_BCD(y2); | ||
732 | |||
733 | memset(ce_time, 0, sizeof(ce_time)); | ||
734 | ce_time[3] = 0x41; | ||
735 | ce_time[4] = y1; | ||
736 | ce_time[5] = y2; | ||
737 | ce_time[6] = sec; | ||
738 | ce_time[7] = min; | ||
739 | ce_time[8] = hour; | ||
740 | ce_time[10] = day; | ||
741 | ce_time[11] = mon; | ||
742 | |||
743 | return signal_ce_msg(ce_time, NULL); | ||
744 | } | ||
745 | |||
695 | static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm) | 746 | static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm) |
696 | { | 747 | { |
697 | tm->tm_wday = 0; | 748 | tm->tm_wday = 0; |
@@ -747,7 +798,7 @@ static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm) | |||
747 | return 0; | 798 | return 0; |
748 | } | 799 | } |
749 | 800 | ||
750 | int mf_get_rtc(struct rtc_time *tm) | 801 | static int mf_get_rtc(struct rtc_time *tm) |
751 | { | 802 | { |
752 | struct ce_msg_comp_data ce_complete; | 803 | struct ce_msg_comp_data ce_complete; |
753 | struct rtc_time_data rtc_data; | 804 | struct rtc_time_data rtc_data; |
@@ -780,7 +831,7 @@ static void get_boot_rtc_time_complete(void *token, struct ce_msg_data *ce_msg) | |||
780 | rtc->busy = 0; | 831 | rtc->busy = 0; |
781 | } | 832 | } |
782 | 833 | ||
783 | int mf_get_boot_rtc(struct rtc_time *tm) | 834 | static int mf_get_boot_rtc(struct rtc_time *tm) |
784 | { | 835 | { |
785 | struct ce_msg_comp_data ce_complete; | 836 | struct ce_msg_comp_data ce_complete; |
786 | struct boot_rtc_time_data rtc_data; | 837 | struct boot_rtc_time_data rtc_data; |
@@ -802,43 +853,6 @@ int mf_get_boot_rtc(struct rtc_time *tm) | |||
802 | return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm); | 853 | return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm); |
803 | } | 854 | } |
804 | 855 | ||
805 | int mf_set_rtc(struct rtc_time *tm) | ||
806 | { | ||
807 | char ce_time[12]; | ||
808 | u8 day, mon, hour, min, sec, y1, y2; | ||
809 | unsigned year; | ||
810 | |||
811 | year = 1900 + tm->tm_year; | ||
812 | y1 = year / 100; | ||
813 | y2 = year % 100; | ||
814 | |||
815 | sec = tm->tm_sec; | ||
816 | min = tm->tm_min; | ||
817 | hour = tm->tm_hour; | ||
818 | day = tm->tm_mday; | ||
819 | mon = tm->tm_mon + 1; | ||
820 | |||
821 | BIN_TO_BCD(sec); | ||
822 | BIN_TO_BCD(min); | ||
823 | BIN_TO_BCD(hour); | ||
824 | BIN_TO_BCD(mon); | ||
825 | BIN_TO_BCD(day); | ||
826 | BIN_TO_BCD(y1); | ||
827 | BIN_TO_BCD(y2); | ||
828 | |||
829 | memset(ce_time, 0, sizeof(ce_time)); | ||
830 | ce_time[3] = 0x41; | ||
831 | ce_time[4] = y1; | ||
832 | ce_time[5] = y2; | ||
833 | ce_time[6] = sec; | ||
834 | ce_time[7] = min; | ||
835 | ce_time[8] = hour; | ||
836 | ce_time[10] = day; | ||
837 | ce_time[11] = mon; | ||
838 | |||
839 | return signal_ce_msg(ce_time, NULL); | ||
840 | } | ||
841 | |||
842 | #ifdef CONFIG_PROC_FS | 856 | #ifdef CONFIG_PROC_FS |
843 | 857 | ||
844 | static int proc_mf_dump_cmdline(char *page, char **start, off_t off, | 858 | static int proc_mf_dump_cmdline(char *page, char **start, off_t off, |
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 3ecc4a652d82..6ce8a404ba6b 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <asm/iseries/hv_call_xm.h> | 50 | #include <asm/iseries/hv_call_xm.h> |
51 | #include <asm/iseries/it_lp_queue.h> | 51 | #include <asm/iseries/it_lp_queue.h> |
52 | #include <asm/iseries/mf.h> | 52 | #include <asm/iseries/mf.h> |
53 | #include <asm/iseries/it_exp_vpd_panel.h> | ||
53 | #include <asm/iseries/hv_lp_event.h> | 54 | #include <asm/iseries/hv_lp_event.h> |
54 | #include <asm/iseries/lpar_map.h> | 55 | #include <asm/iseries/lpar_map.h> |
55 | #include <asm/udbg.h> | 56 | #include <asm/udbg.h> |
@@ -89,8 +90,6 @@ extern unsigned long embedded_sysmap_end; | |||
89 | extern unsigned long iSeries_recal_tb; | 90 | extern unsigned long iSeries_recal_tb; |
90 | extern unsigned long iSeries_recal_titan; | 91 | extern unsigned long iSeries_recal_titan; |
91 | 92 | ||
92 | static int mf_initialized; | ||
93 | |||
94 | static unsigned long cmd_mem_limit; | 93 | static unsigned long cmd_mem_limit; |
95 | 94 | ||
96 | struct MemoryBlock { | 95 | struct MemoryBlock { |
@@ -303,8 +302,6 @@ static void __init iSeries_init_early(void) | |||
303 | { | 302 | { |
304 | DBG(" -> iSeries_init_early()\n"); | 303 | DBG(" -> iSeries_init_early()\n"); |
305 | 304 | ||
306 | ppc64_firmware_features = FW_FEATURE_ISERIES; | ||
307 | |||
308 | ppc64_interrupt_controller = IC_ISERIES; | 305 | ppc64_interrupt_controller = IC_ISERIES; |
309 | 306 | ||
310 | #if defined(CONFIG_BLK_DEV_INITRD) | 307 | #if defined(CONFIG_BLK_DEV_INITRD) |
@@ -349,8 +346,6 @@ static void __init iSeries_init_early(void) | |||
349 | HvCallEvent_setLpEventQueueInterruptProc(0, 0); | 346 | HvCallEvent_setLpEventQueueInterruptProc(0, 0); |
350 | 347 | ||
351 | mf_init(); | 348 | mf_init(); |
352 | mf_initialized = 1; | ||
353 | mb(); | ||
354 | 349 | ||
355 | /* If we were passed an initrd, set the ROOT_DEV properly if the values | 350 | /* If we were passed an initrd, set the ROOT_DEV properly if the values |
356 | * look sensible. If not, clear initrd reference. | 351 | * look sensible. If not, clear initrd reference. |
@@ -560,39 +555,10 @@ static void iSeries_show_cpuinfo(struct seq_file *m) | |||
560 | seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n"); | 555 | seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n"); |
561 | } | 556 | } |
562 | 557 | ||
563 | /* | ||
564 | * Document me. | ||
565 | */ | ||
566 | static void iSeries_restart(char *cmd) | ||
567 | { | ||
568 | mf_reboot(); | ||
569 | } | ||
570 | |||
571 | /* | ||
572 | * Document me. | ||
573 | */ | ||
574 | static void iSeries_power_off(void) | ||
575 | { | ||
576 | mf_power_off(); | ||
577 | } | ||
578 | |||
579 | /* | ||
580 | * Document me. | ||
581 | */ | ||
582 | static void iSeries_halt(void) | ||
583 | { | ||
584 | mf_power_off(); | ||
585 | } | ||
586 | |||
587 | static void __init iSeries_progress(char * st, unsigned short code) | 558 | static void __init iSeries_progress(char * st, unsigned short code) |
588 | { | 559 | { |
589 | printk("Progress: [%04x] - %s\n", (unsigned)code, st); | 560 | printk("Progress: [%04x] - %s\n", (unsigned)code, st); |
590 | if (!piranha_simulator && mf_initialized) { | 561 | mf_display_progress(code); |
591 | if (code != 0xffff) | ||
592 | mf_display_progress(code); | ||
593 | else | ||
594 | mf_clear_src(); | ||
595 | } | ||
596 | } | 562 | } |
597 | 563 | ||
598 | static void __init iSeries_fixup_klimit(void) | 564 | static void __init iSeries_fixup_klimit(void) |
@@ -709,21 +675,29 @@ static void iseries_dedicated_idle(void) | |||
709 | void __init iSeries_init_IRQ(void) { } | 675 | void __init iSeries_init_IRQ(void) { } |
710 | #endif | 676 | #endif |
711 | 677 | ||
712 | static int __init iseries_probe(int platform) | 678 | static int __init iseries_probe(void) |
713 | { | 679 | { |
714 | return PLATFORM_ISERIES_LPAR == platform; | 680 | unsigned long root = of_get_flat_dt_root(); |
681 | if (!of_flat_dt_is_compatible(root, "IBM,iSeries")) | ||
682 | return 0; | ||
683 | |||
684 | powerpc_firmware_features |= FW_FEATURE_ISERIES; | ||
685 | powerpc_firmware_features |= FW_FEATURE_LPAR; | ||
686 | |||
687 | return 1; | ||
715 | } | 688 | } |
716 | 689 | ||
717 | struct machdep_calls __initdata iseries_md = { | 690 | define_machine(iseries) { |
691 | .name = "iSeries", | ||
718 | .setup_arch = iSeries_setup_arch, | 692 | .setup_arch = iSeries_setup_arch, |
719 | .show_cpuinfo = iSeries_show_cpuinfo, | 693 | .show_cpuinfo = iSeries_show_cpuinfo, |
720 | .init_IRQ = iSeries_init_IRQ, | 694 | .init_IRQ = iSeries_init_IRQ, |
721 | .get_irq = iSeries_get_irq, | 695 | .get_irq = iSeries_get_irq, |
722 | .init_early = iSeries_init_early, | 696 | .init_early = iSeries_init_early, |
723 | .pcibios_fixup = iSeries_pci_final_fixup, | 697 | .pcibios_fixup = iSeries_pci_final_fixup, |
724 | .restart = iSeries_restart, | 698 | .restart = mf_reboot, |
725 | .power_off = iSeries_power_off, | 699 | .power_off = mf_power_off, |
726 | .halt = iSeries_halt, | 700 | .halt = mf_power_off, |
727 | .get_boot_time = iSeries_get_boot_time, | 701 | .get_boot_time = iSeries_get_boot_time, |
728 | .set_rtc_time = iSeries_set_rtc_time, | 702 | .set_rtc_time = iSeries_set_rtc_time, |
729 | .get_rtc_time = iSeries_get_rtc_time, | 703 | .get_rtc_time = iSeries_get_rtc_time, |
@@ -917,6 +891,24 @@ void dt_cpus(struct iseries_flat_dt *dt) | |||
917 | dt_end_node(dt); | 891 | dt_end_node(dt); |
918 | } | 892 | } |
919 | 893 | ||
894 | void dt_model(struct iseries_flat_dt *dt) | ||
895 | { | ||
896 | char buf[16] = "IBM,"; | ||
897 | |||
898 | /* "IBM," + mfgId[2:3] + systemSerial[1:5] */ | ||
899 | strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2); | ||
900 | strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5); | ||
901 | buf[11] = '\0'; | ||
902 | dt_prop_str(dt, "system-id", buf); | ||
903 | |||
904 | /* "IBM," + machineType[0:4] */ | ||
905 | strne2a(buf + 4, xItExtVpdPanel.machineType, 4); | ||
906 | buf[8] = '\0'; | ||
907 | dt_prop_str(dt, "model", buf); | ||
908 | |||
909 | dt_prop_str(dt, "compatible", "IBM,iSeries"); | ||
910 | } | ||
911 | |||
920 | void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) | 912 | void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) |
921 | { | 913 | { |
922 | u64 tmp[2]; | 914 | u64 tmp[2]; |
@@ -927,6 +919,7 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) | |||
927 | 919 | ||
928 | dt_prop_u32(dt, "#address-cells", 2); | 920 | dt_prop_u32(dt, "#address-cells", 2); |
929 | dt_prop_u32(dt, "#size-cells", 2); | 921 | dt_prop_u32(dt, "#size-cells", 2); |
922 | dt_model(dt); | ||
930 | 923 | ||
931 | /* /memory */ | 924 | /* /memory */ |
932 | dt_start_node(dt, "memory@0"); | 925 | dt_start_node(dt, "memory@0"); |
@@ -939,7 +932,7 @@ void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) | |||
939 | 932 | ||
940 | /* /chosen */ | 933 | /* /chosen */ |
941 | dt_start_node(dt, "chosen"); | 934 | dt_start_node(dt, "chosen"); |
942 | dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR); | 935 | dt_prop_str(dt, "bootargs", cmd_line); |
943 | if (cmd_mem_limit) | 936 | if (cmd_mem_limit) |
944 | dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit); | 937 | dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit); |
945 | dt_end_node(dt); | 938 | dt_end_node(dt); |
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index ec5c1e10c407..24c0aef4ea39 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c | |||
@@ -259,9 +259,10 @@ static void __init maple_progress(char *s, unsigned short hex) | |||
259 | /* | 259 | /* |
260 | * Called very early, MMU is off, device-tree isn't unflattened | 260 | * Called very early, MMU is off, device-tree isn't unflattened |
261 | */ | 261 | */ |
262 | static int __init maple_probe(int platform) | 262 | static int __init maple_probe(void) |
263 | { | 263 | { |
264 | if (platform != PLATFORM_MAPLE) | 264 | unsigned long root = of_get_flat_dt_root(); |
265 | if (!of_flat_dt_is_compatible(root, "Momentum,Maple")) | ||
265 | return 0; | 266 | return 0; |
266 | /* | 267 | /* |
267 | * On U3, the DART (iommu) must be allocated now since it | 268 | * On U3, the DART (iommu) must be allocated now since it |
@@ -274,7 +275,8 @@ static int __init maple_probe(int platform) | |||
274 | return 1; | 275 | return 1; |
275 | } | 276 | } |
276 | 277 | ||
277 | struct machdep_calls __initdata maple_md = { | 278 | define_machine(maple_md) { |
279 | .name = "Maple", | ||
278 | .probe = maple_probe, | 280 | .probe = maple_probe, |
279 | .setup_arch = maple_setup_arch, | 281 | .setup_arch = maple_setup_arch, |
280 | .init_early = maple_init_early, | 282 | .init_early = maple_init_early, |
@@ -290,7 +292,7 @@ struct machdep_calls __initdata maple_md = { | |||
290 | .get_rtc_time = maple_get_rtc_time, | 292 | .get_rtc_time = maple_get_rtc_time, |
291 | .calibrate_decr = generic_calibrate_decr, | 293 | .calibrate_decr = generic_calibrate_decr, |
292 | .progress = maple_progress, | 294 | .progress = maple_progress, |
293 | .idle_loop = native_idle, | 295 | .power_save = power4_idle, |
294 | #ifdef CONFIG_KEXEC | 296 | #ifdef CONFIG_KEXEC |
295 | .machine_kexec = default_machine_kexec, | 297 | .machine_kexec = default_machine_kexec, |
296 | .machine_kexec_prepare = default_machine_kexec_prepare, | 298 | .machine_kexec_prepare = default_machine_kexec_prepare, |
diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c index 50bc4eb85353..b9a2b3d4bf33 100644 --- a/arch/powerpc/platforms/maple/time.c +++ b/arch/powerpc/platforms/maple/time.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/kernel/maple_time.c | ||
3 | * | ||
4 | * (c) Copyright 2004 Benjamin Herrenschmidt (benh@kernel.crashing.org), | 2 | * (c) Copyright 2004 Benjamin Herrenschmidt (benh@kernel.crashing.org), |
5 | * IBM Corp. | 3 | * IBM Corp. |
6 | * | 4 | * |
@@ -62,34 +60,14 @@ static void maple_clock_write(unsigned long val, int addr) | |||
62 | 60 | ||
63 | void maple_get_rtc_time(struct rtc_time *tm) | 61 | void maple_get_rtc_time(struct rtc_time *tm) |
64 | { | 62 | { |
65 | int uip, i; | 63 | do { |
66 | |||
67 | /* The Linux interpretation of the CMOS clock register contents: | ||
68 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the | ||
69 | * RTC registers show the second which has precisely just started. | ||
70 | * Let's hope other operating systems interpret the RTC the same way. | ||
71 | */ | ||
72 | |||
73 | /* Since the UIP flag is set for about 2.2 ms and the clock | ||
74 | * is typically written with a precision of 1 jiffy, trying | ||
75 | * to obtain a precision better than a few milliseconds is | ||
76 | * an illusion. Only consistency is interesting, this also | ||
77 | * allows to use the routine for /dev/rtc without a potential | ||
78 | * 1 second kernel busy loop triggered by any reader of /dev/rtc. | ||
79 | */ | ||
80 | |||
81 | for (i = 0; i<1000000; i++) { | ||
82 | uip = maple_clock_read(RTC_FREQ_SELECT); | ||
83 | tm->tm_sec = maple_clock_read(RTC_SECONDS); | 64 | tm->tm_sec = maple_clock_read(RTC_SECONDS); |
84 | tm->tm_min = maple_clock_read(RTC_MINUTES); | 65 | tm->tm_min = maple_clock_read(RTC_MINUTES); |
85 | tm->tm_hour = maple_clock_read(RTC_HOURS); | 66 | tm->tm_hour = maple_clock_read(RTC_HOURS); |
86 | tm->tm_mday = maple_clock_read(RTC_DAY_OF_MONTH); | 67 | tm->tm_mday = maple_clock_read(RTC_DAY_OF_MONTH); |
87 | tm->tm_mon = maple_clock_read(RTC_MONTH); | 68 | tm->tm_mon = maple_clock_read(RTC_MONTH); |
88 | tm->tm_year = maple_clock_read(RTC_YEAR); | 69 | tm->tm_year = maple_clock_read(RTC_YEAR); |
89 | uip |= maple_clock_read(RTC_FREQ_SELECT); | 70 | } while (tm->tm_sec != maple_clock_read(RTC_SECONDS)); |
90 | if ((uip & RTC_UIP)==0) | ||
91 | break; | ||
92 | } | ||
93 | 71 | ||
94 | if (!(maple_clock_read(RTC_CONTROL) & RTC_DM_BINARY) | 72 | if (!(maple_clock_read(RTC_CONTROL) & RTC_DM_BINARY) |
95 | || RTC_ALWAYS_BCD) { | 73 | || RTC_ALWAYS_BCD) { |
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c index fa8b4d7b5ded..eacbfd9beabc 100644 --- a/arch/powerpc/platforms/powermac/bootx_init.c +++ b/arch/powerpc/platforms/powermac/bootx_init.c | |||
@@ -161,9 +161,7 @@ static void __init bootx_dt_add_prop(char *name, void *data, int size, | |||
161 | static void __init bootx_add_chosen_props(unsigned long base, | 161 | static void __init bootx_add_chosen_props(unsigned long base, |
162 | unsigned long *mem_end) | 162 | unsigned long *mem_end) |
163 | { | 163 | { |
164 | u32 val = _MACH_Pmac; | 164 | u32 val; |
165 | |||
166 | bootx_dt_add_prop("linux,platform", &val, 4, mem_end); | ||
167 | 165 | ||
168 | if (bootx_info->kernelParamsOffset) { | 166 | if (bootx_info->kernelParamsOffset) { |
169 | char *args = (char *)((unsigned long)bootx_info) + | 167 | char *args = (char *)((unsigned long)bootx_info) + |
@@ -493,7 +491,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4) | |||
493 | && (strcmp(model, "iMac,1") == 0 | 491 | && (strcmp(model, "iMac,1") == 0 |
494 | || strcmp(model, "PowerMac1,1") == 0)) { | 492 | || strcmp(model, "PowerMac1,1") == 0)) { |
495 | bootx_printf("iMac,1 detected, shutting down USB \n"); | 493 | bootx_printf("iMac,1 detected, shutting down USB \n"); |
496 | out_le32((unsigned *)0x80880008, 1); /* XXX */ | 494 | out_le32((unsigned __iomem *)0x80880008, 1); /* XXX */ |
497 | } | 495 | } |
498 | } | 496 | } |
499 | 497 | ||
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c index 56fd4e05fede..cfd6527a0d7e 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_32.c +++ b/arch/powerpc/platforms/powermac/cpufreq_32.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/platforms/pmac_cpufreq.c | ||
3 | * | ||
4 | * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2 | * Copyright (C) 2002 - 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org> |
5 | * Copyright (C) 2004 John Steele Scott <toojays@toojays.net> | 3 | * Copyright (C) 2004 John Steele Scott <toojays@toojays.net> |
6 | * | 4 | * |
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c index a415e8d2f7af..b57e465a1b71 100644 --- a/arch/powerpc/platforms/powermac/cpufreq_64.c +++ b/arch/powerpc/platforms/powermac/cpufreq_64.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/cpufreq.h> | 21 | #include <linux/cpufreq.h> |
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
23 | #include <linux/completion.h> | 23 | #include <linux/completion.h> |
24 | #include <linux/mutex.h> | ||
24 | #include <asm/prom.h> | 25 | #include <asm/prom.h> |
25 | #include <asm/machdep.h> | 26 | #include <asm/machdep.h> |
26 | #include <asm/irq.h> | 27 | #include <asm/irq.h> |
@@ -90,7 +91,7 @@ static void (*g5_switch_volt)(int speed_mode); | |||
90 | static int (*g5_switch_freq)(int speed_mode); | 91 | static int (*g5_switch_freq)(int speed_mode); |
91 | static int (*g5_query_freq)(void); | 92 | static int (*g5_query_freq)(void); |
92 | 93 | ||
93 | static DECLARE_MUTEX(g5_switch_mutex); | 94 | static DEFINE_MUTEX(g5_switch_mutex); |
94 | 95 | ||
95 | 96 | ||
96 | static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */ | 97 | static struct smu_sdbp_fvt *g5_fvt_table; /* table of op. points */ |
@@ -327,7 +328,7 @@ static int g5_cpufreq_target(struct cpufreq_policy *policy, | |||
327 | if (g5_pmode_cur == newstate) | 328 | if (g5_pmode_cur == newstate) |
328 | return 0; | 329 | return 0; |
329 | 330 | ||
330 | down(&g5_switch_mutex); | 331 | mutex_lock(&g5_switch_mutex); |
331 | 332 | ||
332 | freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency; | 333 | freqs.old = g5_cpu_freqs[g5_pmode_cur].frequency; |
333 | freqs.new = g5_cpu_freqs[newstate].frequency; | 334 | freqs.new = g5_cpu_freqs[newstate].frequency; |
@@ -337,7 +338,7 @@ static int g5_cpufreq_target(struct cpufreq_policy *policy, | |||
337 | rc = g5_switch_freq(newstate); | 338 | rc = g5_switch_freq(newstate); |
338 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 339 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); |
339 | 340 | ||
340 | up(&g5_switch_mutex); | 341 | mutex_unlock(&g5_switch_mutex); |
341 | 342 | ||
342 | return rc; | 343 | return rc; |
343 | } | 344 | } |
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 34714d3ea69a..a5063cd675c5 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/platforms/pmac_feature.c | ||
3 | * | ||
4 | * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au) | 2 | * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au) |
5 | * Ben. Herrenschmidt (benh@kernel.crashing.org) | 3 | * Ben. Herrenschmidt (benh@kernel.crashing.org) |
6 | * | 4 | * |
@@ -2491,9 +2489,7 @@ found: | |||
2491 | pmac_mb.model_id = PMAC_TYPE_COMET; | 2489 | pmac_mb.model_id = PMAC_TYPE_COMET; |
2492 | iounmap(mach_id_ptr); | 2490 | iounmap(mach_id_ptr); |
2493 | } | 2491 | } |
2494 | #endif /* CONFIG_POWER4 */ | ||
2495 | 2492 | ||
2496 | #ifdef CONFIG_6xx | ||
2497 | /* Set default value of powersave_nap on machines that support it. | 2493 | /* Set default value of powersave_nap on machines that support it. |
2498 | * It appears that uninorth rev 3 has a problem with it, we don't | 2494 | * It appears that uninorth rev 3 has a problem with it, we don't |
2499 | * enable it on those. In theory, the flush-on-lock property is | 2495 | * enable it on those. In theory, the flush-on-lock property is |
@@ -2522,10 +2518,11 @@ found: | |||
2522 | * NAP mode | 2518 | * NAP mode |
2523 | */ | 2519 | */ |
2524 | powersave_lowspeed = 1; | 2520 | powersave_lowspeed = 1; |
2525 | #endif /* CONFIG_6xx */ | 2521 | |
2526 | #ifdef CONFIG_POWER4 | 2522 | #else /* CONFIG_POWER4 */ |
2527 | powersave_nap = 1; | 2523 | powersave_nap = 1; |
2528 | #endif | 2524 | #endif /* CONFIG_POWER4 */ |
2525 | |||
2529 | /* Check for "mobile" machine */ | 2526 | /* Check for "mobile" machine */ |
2530 | if (model && (strncmp(model, "PowerBook", 9) == 0 | 2527 | if (model && (strncmp(model, "PowerBook", 9) == 0 |
2531 | || strncmp(model, "iBook", 5) == 0)) | 2528 | || strncmp(model, "iBook", 5) == 0)) |
@@ -2954,7 +2951,7 @@ static void *pmac_early_vresume_data; | |||
2954 | 2951 | ||
2955 | void pmac_set_early_video_resume(void (*proc)(void *data), void *data) | 2952 | void pmac_set_early_video_resume(void (*proc)(void *data), void *data) |
2956 | { | 2953 | { |
2957 | if (_machine != _MACH_Pmac) | 2954 | if (!machine_is(powermac)) |
2958 | return; | 2955 | return; |
2959 | preempt_disable(); | 2956 | preempt_disable(); |
2960 | pmac_early_vresume_proc = proc; | 2957 | pmac_early_vresume_proc = proc; |
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index 87eb6bb7f0e7..e14f9ac55cf4 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c | |||
@@ -1457,6 +1457,9 @@ int __init pmac_i2c_init(void) | |||
1457 | return 0; | 1457 | return 0; |
1458 | i2c_inited = 1; | 1458 | i2c_inited = 1; |
1459 | 1459 | ||
1460 | if (!machine_is(powermac)) | ||
1461 | return 0; | ||
1462 | |||
1460 | /* Probe keywest-i2c busses */ | 1463 | /* Probe keywest-i2c busses */ |
1461 | kw_i2c_probe(); | 1464 | kw_i2c_probe(); |
1462 | 1465 | ||
diff --git a/arch/powerpc/platforms/powermac/nvram.c b/arch/powerpc/platforms/powermac/nvram.c index 3ebd045a3350..262f967b880a 100644 --- a/arch/powerpc/platforms/powermac/nvram.c +++ b/arch/powerpc/platforms/powermac/nvram.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/platforms/pmac_nvram.c | ||
3 | * | ||
4 | * Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org) | 2 | * Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org) |
5 | * | 3 | * |
6 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
@@ -76,7 +74,7 @@ struct core99_header { | |||
76 | * Read and write the non-volatile RAM on PowerMacs and CHRP machines. | 74 | * Read and write the non-volatile RAM on PowerMacs and CHRP machines. |
77 | */ | 75 | */ |
78 | static int nvram_naddrs; | 76 | static int nvram_naddrs; |
79 | static volatile unsigned char *nvram_data; | 77 | static volatile unsigned char __iomem *nvram_data; |
80 | static int is_core_99; | 78 | static int is_core_99; |
81 | static int core99_bank = 0; | 79 | static int core99_bank = 0; |
82 | static int nvram_partitions[3]; | 80 | static int nvram_partitions[3]; |
@@ -150,7 +148,7 @@ static ssize_t core99_nvram_size(void) | |||
150 | } | 148 | } |
151 | 149 | ||
152 | #ifdef CONFIG_PPC32 | 150 | #ifdef CONFIG_PPC32 |
153 | static volatile unsigned char *nvram_addr; | 151 | static volatile unsigned char __iomem *nvram_addr; |
154 | static int nvram_mult; | 152 | static int nvram_mult; |
155 | 153 | ||
156 | static unsigned char direct_nvram_read_byte(int addr) | 154 | static unsigned char direct_nvram_read_byte(int addr) |
@@ -287,7 +285,7 @@ static int sm_erase_bank(int bank) | |||
287 | int stat, i; | 285 | int stat, i; |
288 | unsigned long timeout; | 286 | unsigned long timeout; |
289 | 287 | ||
290 | u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; | 288 | u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE; |
291 | 289 | ||
292 | DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank); | 290 | DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank); |
293 | 291 | ||
@@ -319,7 +317,7 @@ static int sm_write_bank(int bank, u8* datas) | |||
319 | int i, stat = 0; | 317 | int i, stat = 0; |
320 | unsigned long timeout; | 318 | unsigned long timeout; |
321 | 319 | ||
322 | u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; | 320 | u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE; |
323 | 321 | ||
324 | DBG("nvram: Sharp/Micron Writing bank %d...\n", bank); | 322 | DBG("nvram: Sharp/Micron Writing bank %d...\n", bank); |
325 | 323 | ||
@@ -354,7 +352,7 @@ static int amd_erase_bank(int bank) | |||
354 | int i, stat = 0; | 352 | int i, stat = 0; |
355 | unsigned long timeout; | 353 | unsigned long timeout; |
356 | 354 | ||
357 | u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; | 355 | u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE; |
358 | 356 | ||
359 | DBG("nvram: AMD Erasing bank %d...\n", bank); | 357 | DBG("nvram: AMD Erasing bank %d...\n", bank); |
360 | 358 | ||
@@ -401,7 +399,7 @@ static int amd_write_bank(int bank, u8* datas) | |||
401 | int i, stat = 0; | 399 | int i, stat = 0; |
402 | unsigned long timeout; | 400 | unsigned long timeout; |
403 | 401 | ||
404 | u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; | 402 | u8 __iomem *base = (u8 __iomem *)nvram_data + core99_bank*NVRAM_SIZE; |
405 | 403 | ||
406 | DBG("nvram: AMD Writing bank %d...\n", bank); | 404 | DBG("nvram: AMD Writing bank %d...\n", bank); |
407 | 405 | ||
@@ -599,7 +597,7 @@ int __init pmac_nvram_init(void) | |||
599 | } | 597 | } |
600 | 598 | ||
601 | #ifdef CONFIG_PPC32 | 599 | #ifdef CONFIG_PPC32 |
602 | if (_machine == _MACH_chrp && nvram_naddrs == 1) { | 600 | if (machine_is(chrp) && nvram_naddrs == 1) { |
603 | nvram_data = ioremap(r1.start, s1); | 601 | nvram_data = ioremap(r1.start, s1); |
604 | nvram_mult = 1; | 602 | nvram_mult = 1; |
605 | ppc_md.nvram_read_val = direct_nvram_read_byte; | 603 | ppc_md.nvram_read_val = direct_nvram_read_byte; |
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index de3f30e6b333..f5d8d15d74fa 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c | |||
@@ -1201,7 +1201,7 @@ void __init pmac_pcibios_after_init(void) | |||
1201 | #ifdef CONFIG_PPC32 | 1201 | #ifdef CONFIG_PPC32 |
1202 | void pmac_pci_fixup_cardbus(struct pci_dev* dev) | 1202 | void pmac_pci_fixup_cardbus(struct pci_dev* dev) |
1203 | { | 1203 | { |
1204 | if (_machine != _MACH_Pmac) | 1204 | if (!machine_is(powermac)) |
1205 | return; | 1205 | return; |
1206 | /* | 1206 | /* |
1207 | * Fix the interrupt routing on the various cardbus bridges | 1207 | * Fix the interrupt routing on the various cardbus bridges |
@@ -1244,8 +1244,9 @@ void pmac_pci_fixup_pciata(struct pci_dev* dev) | |||
1244 | * On PowerMacs, we try to switch any PCI ATA controller to | 1244 | * On PowerMacs, we try to switch any PCI ATA controller to |
1245 | * fully native mode | 1245 | * fully native mode |
1246 | */ | 1246 | */ |
1247 | if (_machine != _MACH_Pmac) | 1247 | if (!machine_is(powermac)) |
1248 | return; | 1248 | return; |
1249 | |||
1249 | /* Some controllers don't have the class IDE */ | 1250 | /* Some controllers don't have the class IDE */ |
1250 | if (dev->vendor == PCI_VENDOR_ID_PROMISE) | 1251 | if (dev->vendor == PCI_VENDOR_ID_PROMISE) |
1251 | switch(dev->device) { | 1252 | switch(dev->device) { |
diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c index 9b7150f10414..a3bd3e728fa3 100644 --- a/arch/powerpc/platforms/powermac/pfunc_base.c +++ b/arch/powerpc/platforms/powermac/pfunc_base.c | |||
@@ -336,6 +336,8 @@ int __init pmac_pfunc_base_install(void) | |||
336 | return 0; | 336 | return 0; |
337 | pfbase_inited = 1; | 337 | pfbase_inited = 1; |
338 | 338 | ||
339 | if (!machine_is(powermac)) | ||
340 | return 0; | ||
339 | 341 | ||
340 | DBG("Installing base platform functions...\n"); | 342 | DBG("Installing base platform functions...\n"); |
341 | 343 | ||
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 1955462f4082..4d15e396655c 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c | |||
@@ -86,11 +86,10 @@ int ppc_override_l2cr = 0; | |||
86 | int ppc_override_l2cr_value; | 86 | int ppc_override_l2cr_value; |
87 | int has_l2cache = 0; | 87 | int has_l2cache = 0; |
88 | 88 | ||
89 | int pmac_newworld = 1; | 89 | int pmac_newworld; |
90 | 90 | ||
91 | static int current_root_goodness = -1; | 91 | static int current_root_goodness = -1; |
92 | 92 | ||
93 | extern int pmac_newworld; | ||
94 | extern struct machdep_calls pmac_md; | 93 | extern struct machdep_calls pmac_md; |
95 | 94 | ||
96 | #define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ | 95 | #define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ |
@@ -308,9 +307,10 @@ static void __init pmac_setup_arch(void) | |||
308 | for (ic = NULL; (ic = of_find_all_nodes(ic)) != NULL; ) | 307 | for (ic = NULL; (ic = of_find_all_nodes(ic)) != NULL; ) |
309 | if (get_property(ic, "interrupt-controller", NULL)) | 308 | if (get_property(ic, "interrupt-controller", NULL)) |
310 | break; | 309 | break; |
311 | pmac_newworld = (ic != NULL); | 310 | if (ic) { |
312 | if (ic) | 311 | pmac_newworld = 1; |
313 | of_node_put(ic); | 312 | of_node_put(ic); |
313 | } | ||
314 | 314 | ||
315 | /* Lookup PCI hosts */ | 315 | /* Lookup PCI hosts */ |
316 | pmac_pci_init(); | 316 | pmac_pci_init(); |
@@ -350,6 +350,13 @@ static void __init pmac_setup_arch(void) | |||
350 | smp_ops = &psurge_smp_ops; | 350 | smp_ops = &psurge_smp_ops; |
351 | #endif | 351 | #endif |
352 | #endif /* CONFIG_SMP */ | 352 | #endif /* CONFIG_SMP */ |
353 | |||
354 | #ifdef CONFIG_ADB | ||
355 | if (strstr(cmd_line, "adb_sync")) { | ||
356 | extern int __adb_probe_sync; | ||
357 | __adb_probe_sync = 1; | ||
358 | } | ||
359 | #endif /* CONFIG_ADB */ | ||
353 | } | 360 | } |
354 | 361 | ||
355 | char *bootpath; | 362 | char *bootpath; |
@@ -576,30 +583,6 @@ pmac_halt(void) | |||
576 | pmac_power_off(); | 583 | pmac_power_off(); |
577 | } | 584 | } |
578 | 585 | ||
579 | #ifdef CONFIG_PPC32 | ||
580 | void __init pmac_init(void) | ||
581 | { | ||
582 | /* isa_io_base gets set in pmac_pci_init */ | ||
583 | isa_mem_base = PMAC_ISA_MEM_BASE; | ||
584 | pci_dram_offset = PMAC_PCI_DRAM_OFFSET; | ||
585 | ISA_DMA_THRESHOLD = ~0L; | ||
586 | DMA_MODE_READ = 1; | ||
587 | DMA_MODE_WRITE = 2; | ||
588 | |||
589 | ppc_md = pmac_md; | ||
590 | |||
591 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
592 | #ifdef CONFIG_BLK_DEV_IDE_PMAC | ||
593 | ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; | ||
594 | ppc_ide_md.default_io_base = pmac_ide_get_base; | ||
595 | #endif /* CONFIG_BLK_DEV_IDE_PMAC */ | ||
596 | #endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */ | ||
597 | |||
598 | if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0); | ||
599 | |||
600 | } | ||
601 | #endif | ||
602 | |||
603 | /* | 586 | /* |
604 | * Early initialization. | 587 | * Early initialization. |
605 | */ | 588 | */ |
@@ -621,10 +604,6 @@ static void __init pmac_init_early(void) | |||
621 | /* Probe motherboard chipset */ | 604 | /* Probe motherboard chipset */ |
622 | pmac_feature_init(); | 605 | pmac_feature_init(); |
623 | 606 | ||
624 | /* We can NAP */ | ||
625 | powersave_nap = 1; | ||
626 | printk(KERN_INFO "Using native/NAP idle loop\n"); | ||
627 | |||
628 | /* Initialize debug stuff */ | 607 | /* Initialize debug stuff */ |
629 | udbg_scc_init(!!strstr(cmd_line, "sccdbg")); | 608 | udbg_scc_init(!!strstr(cmd_line, "sccdbg")); |
630 | udbg_adb_init(!!strstr(cmd_line, "btextdbg")); | 609 | udbg_adb_init(!!strstr(cmd_line, "btextdbg")); |
@@ -650,6 +629,12 @@ static int __init pmac_declare_of_platform_devices(void) | |||
650 | { | 629 | { |
651 | struct device_node *np; | 630 | struct device_node *np; |
652 | 631 | ||
632 | if (machine_is(chrp)) | ||
633 | return -1; | ||
634 | |||
635 | if (!machine_is(powermac)) | ||
636 | return 0; | ||
637 | |||
653 | np = of_find_node_by_name(NULL, "valkyrie"); | 638 | np = of_find_node_by_name(NULL, "valkyrie"); |
654 | if (np) | 639 | if (np) |
655 | of_platform_device_create(np, "valkyrie", NULL); | 640 | of_platform_device_create(np, "valkyrie", NULL); |
@@ -670,12 +655,15 @@ device_initcall(pmac_declare_of_platform_devices); | |||
670 | /* | 655 | /* |
671 | * Called very early, MMU is off, device-tree isn't unflattened | 656 | * Called very early, MMU is off, device-tree isn't unflattened |
672 | */ | 657 | */ |
673 | static int __init pmac_probe(int platform) | 658 | static int __init pmac_probe(void) |
674 | { | 659 | { |
675 | #ifdef CONFIG_PPC64 | 660 | unsigned long root = of_get_flat_dt_root(); |
676 | if (platform != PLATFORM_POWERMAC) | 661 | |
662 | if (!of_flat_dt_is_compatible(root, "Power Macintosh") && | ||
663 | !of_flat_dt_is_compatible(root, "MacRISC")) | ||
677 | return 0; | 664 | return 0; |
678 | 665 | ||
666 | #ifdef CONFIG_PPC64 | ||
679 | /* | 667 | /* |
680 | * On U3, the DART (iommu) must be allocated now since it | 668 | * On U3, the DART (iommu) must be allocated now since it |
681 | * has an impact on htab_initialize (due to the large page it | 669 | * has an impact on htab_initialize (due to the large page it |
@@ -685,6 +673,23 @@ static int __init pmac_probe(int platform) | |||
685 | alloc_dart_table(); | 673 | alloc_dart_table(); |
686 | #endif | 674 | #endif |
687 | 675 | ||
676 | #ifdef CONFIG_PPC32 | ||
677 | /* isa_io_base gets set in pmac_pci_init */ | ||
678 | isa_mem_base = PMAC_ISA_MEM_BASE; | ||
679 | pci_dram_offset = PMAC_PCI_DRAM_OFFSET; | ||
680 | ISA_DMA_THRESHOLD = ~0L; | ||
681 | DMA_MODE_READ = 1; | ||
682 | DMA_MODE_WRITE = 2; | ||
683 | |||
684 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
685 | #ifdef CONFIG_BLK_DEV_IDE_PMAC | ||
686 | ppc_ide_md.ide_init_hwif = pmac_ide_init_hwif_ports; | ||
687 | ppc_ide_md.default_io_base = pmac_ide_get_base; | ||
688 | #endif /* CONFIG_BLK_DEV_IDE_PMAC */ | ||
689 | #endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */ | ||
690 | |||
691 | #endif /* CONFIG_PPC32 */ | ||
692 | |||
688 | #ifdef CONFIG_PMAC_SMU | 693 | #ifdef CONFIG_PMAC_SMU |
689 | /* | 694 | /* |
690 | * SMU based G5s need some memory below 2Gb, at least the current | 695 | * SMU based G5s need some memory below 2Gb, at least the current |
@@ -713,10 +718,8 @@ static int pmac_pci_probe_mode(struct pci_bus *bus) | |||
713 | } | 718 | } |
714 | #endif | 719 | #endif |
715 | 720 | ||
716 | struct machdep_calls __initdata pmac_md = { | 721 | define_machine(powermac) { |
717 | #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64) | 722 | .name = "PowerMac", |
718 | .cpu_die = generic_mach_cpu_die, | ||
719 | #endif | ||
720 | .probe = pmac_probe, | 723 | .probe = pmac_probe, |
721 | .setup_arch = pmac_setup_arch, | 724 | .setup_arch = pmac_setup_arch, |
722 | .init_early = pmac_init_early, | 725 | .init_early = pmac_init_early, |
@@ -737,7 +740,7 @@ struct machdep_calls __initdata pmac_md = { | |||
737 | .progress = udbg_progress, | 740 | .progress = udbg_progress, |
738 | #ifdef CONFIG_PPC64 | 741 | #ifdef CONFIG_PPC64 |
739 | .pci_probe_mode = pmac_pci_probe_mode, | 742 | .pci_probe_mode = pmac_pci_probe_mode, |
740 | .idle_loop = native_idle, | 743 | .power_save = power4_idle, |
741 | .enable_pmcs = power4_enable_pmcs, | 744 | .enable_pmcs = power4_enable_pmcs, |
742 | #ifdef CONFIG_KEXEC | 745 | #ifdef CONFIG_KEXEC |
743 | .machine_kexec = default_machine_kexec, | 746 | .machine_kexec = default_machine_kexec, |
@@ -750,4 +753,7 @@ struct machdep_calls __initdata pmac_md = { | |||
750 | .pcibios_after_init = pmac_pcibios_after_init, | 753 | .pcibios_after_init = pmac_pcibios_after_init, |
751 | .phys_mem_access_prot = pci_phys_mem_access_prot, | 754 | .phys_mem_access_prot = pci_phys_mem_access_prot, |
752 | #endif | 755 | #endif |
756 | #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC64) | ||
757 | .cpu_die = generic_mach_cpu_die, | ||
758 | #endif | ||
753 | }; | 759 | }; |
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 6d64a9bf3474..1065d87fc279 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c | |||
@@ -191,9 +191,7 @@ static void smp_psurge_message_pass(int target, int msg) | |||
191 | if (num_online_cpus() < 2) | 191 | if (num_online_cpus() < 2) |
192 | return; | 192 | return; |
193 | 193 | ||
194 | for (i = 0; i < NR_CPUS; i++) { | 194 | for_each_online_cpu(i) { |
195 | if (!cpu_online(i)) | ||
196 | continue; | ||
197 | if (target == MSG_ALL | 195 | if (target == MSG_ALL |
198 | || (target == MSG_ALL_BUT_SELF && i != smp_processor_id()) | 196 | || (target == MSG_ALL_BUT_SELF && i != smp_processor_id()) |
199 | || target == i) { | 197 | || target == i) { |
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c index 5d9afa1fa02d..890758aa9667 100644 --- a/arch/powerpc/platforms/powermac/time.c +++ b/arch/powerpc/platforms/powermac/time.c | |||
@@ -336,10 +336,10 @@ static struct pmu_sleep_notifier time_sleep_notifier = { | |||
336 | */ | 336 | */ |
337 | void __init pmac_calibrate_decr(void) | 337 | void __init pmac_calibrate_decr(void) |
338 | { | 338 | { |
339 | #ifdef CONFIG_PM | 339 | #if defined(CONFIG_PM) && defined(CONFIG_ADB_PMU) |
340 | /* XXX why here? */ | 340 | /* XXX why here? */ |
341 | pmu_register_sleep_notifier(&time_sleep_notifier); | 341 | pmu_register_sleep_notifier(&time_sleep_notifier); |
342 | #endif /* CONFIG_PM */ | 342 | #endif |
343 | 343 | ||
344 | generic_calibrate_decr(); | 344 | generic_calibrate_decr(); |
345 | 345 | ||
diff --git a/arch/powerpc/platforms/powermac/udbg_scc.c b/arch/powerpc/platforms/powermac/udbg_scc.c index c4352a8db644..b4fa9f03b461 100644 --- a/arch/powerpc/platforms/powermac/udbg_scc.c +++ b/arch/powerpc/platforms/powermac/udbg_scc.c | |||
@@ -116,7 +116,7 @@ void udbg_scc_init(int force_scc) | |||
116 | /* Setup for 57600 8N1 */ | 116 | /* Setup for 57600 8N1 */ |
117 | if (ch == ch_a) | 117 | if (ch == ch_a) |
118 | addr += 0x20; | 118 | addr += 0x20; |
119 | sccc = (volatile u8 * __iomem) ioremap(addr & PAGE_MASK, PAGE_SIZE) ; | 119 | sccc = ioremap(addr & PAGE_MASK, PAGE_SIZE) ; |
120 | sccc += addr & ~PAGE_MASK; | 120 | sccc += addr & ~PAGE_MASK; |
121 | sccd = sccc + 0x10; | 121 | sccd = sccc + 0x10; |
122 | 122 | ||
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index 4e5c8f8d869d..a57032cf6f1b 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig | |||
@@ -19,7 +19,7 @@ config SCANLOG | |||
19 | depends on RTAS_PROC && PPC_PSERIES | 19 | depends on RTAS_PROC && PPC_PSERIES |
20 | 20 | ||
21 | config LPARCFG | 21 | config LPARCFG |
22 | tristate "LPAR Configuration Data" | 22 | bool "LPAR Configuration Data" |
23 | depends on PPC_PSERIES || PPC_ISERIES | 23 | depends on PPC_PSERIES || PPC_ISERIES |
24 | help | 24 | help |
25 | Provide system capacity information via human readable | 25 | Provide system capacity information via human readable |
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 61616d144072..930898635c9f 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -1,5 +1,6 @@ | |||
1 | obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ | 1 | obj-y := pci.o lpar.o hvCall.o nvram.o reconfig.o \ |
2 | setup.o iommu.o ras.o rtasd.o pci_dlpar.o | 2 | setup.o iommu.o ras.o rtasd.o pci_dlpar.o \ |
3 | firmware.o | ||
3 | obj-$(CONFIG_SMP) += smp.o | 4 | obj-$(CONFIG_SMP) += smp.o |
4 | obj-$(CONFIG_IBMVIO) += vio.o | 5 | obj-$(CONFIG_IBMVIO) += vio.o |
5 | obj-$(CONFIG_XICS) += xics.o | 6 | obj-$(CONFIG_XICS) += xics.o |
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 2ab9dcdfb415..9b2b1cb117b3 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -1018,7 +1018,7 @@ static int __init eeh_init_proc(void) | |||
1018 | { | 1018 | { |
1019 | struct proc_dir_entry *e; | 1019 | struct proc_dir_entry *e; |
1020 | 1020 | ||
1021 | if (platform_is_pseries()) { | 1021 | if (machine_is(pseries)) { |
1022 | e = create_proc_entry("ppc64/eeh", 0, NULL); | 1022 | e = create_proc_entry("ppc64/eeh", 0, NULL); |
1023 | if (e) | 1023 | if (e) |
1024 | e->proc_fops = &proc_eeh_operations; | 1024 | e->proc_fops = &proc_eeh_operations; |
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index b811d5ff92fe..cc2495a0cdd5 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c | |||
@@ -257,6 +257,7 @@ void handle_eeh_events (struct eeh_event *event) | |||
257 | struct pci_bus *frozen_bus; | 257 | struct pci_bus *frozen_bus; |
258 | int rc = 0; | 258 | int rc = 0; |
259 | enum pci_ers_result result = PCI_ERS_RESULT_NONE; | 259 | enum pci_ers_result result = PCI_ERS_RESULT_NONE; |
260 | const char *pci_str, *drv_str; | ||
260 | 261 | ||
261 | frozen_dn = find_device_pe(event->dn); | 262 | frozen_dn = find_device_pe(event->dn); |
262 | frozen_bus = pcibios_find_pci_bus(frozen_dn); | 263 | frozen_bus = pcibios_find_pci_bus(frozen_dn); |
@@ -291,6 +292,13 @@ void handle_eeh_events (struct eeh_event *event) | |||
291 | 292 | ||
292 | frozen_pdn = PCI_DN(frozen_dn); | 293 | frozen_pdn = PCI_DN(frozen_dn); |
293 | frozen_pdn->eeh_freeze_count++; | 294 | frozen_pdn->eeh_freeze_count++; |
295 | |||
296 | pci_str = pci_name (frozen_pdn->pcidev); | ||
297 | drv_str = pcid_name (frozen_pdn->pcidev); | ||
298 | if (!pci_str) { | ||
299 | pci_str = pci_name (event->dev); | ||
300 | drv_str = pcid_name (event->dev); | ||
301 | } | ||
294 | 302 | ||
295 | if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES) | 303 | if (frozen_pdn->eeh_freeze_count > EEH_MAX_ALLOWED_FREEZES) |
296 | goto hard_fail; | 304 | goto hard_fail; |
@@ -306,9 +314,7 @@ void handle_eeh_events (struct eeh_event *event) | |||
306 | eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */); | 314 | eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */); |
307 | printk(KERN_WARNING | 315 | printk(KERN_WARNING |
308 | "EEH: This PCI device has failed %d times since last reboot: %s - %s\n", | 316 | "EEH: This PCI device has failed %d times since last reboot: %s - %s\n", |
309 | frozen_pdn->eeh_freeze_count, | 317 | frozen_pdn->eeh_freeze_count, drv_str, pci_str); |
310 | pci_name (frozen_pdn->pcidev), | ||
311 | pcid_name(frozen_pdn->pcidev)); | ||
312 | 318 | ||
313 | /* Walk the various device drivers attached to this slot through | 319 | /* Walk the various device drivers attached to this slot through |
314 | * a reset sequence, giving each an opportunity to do what it needs | 320 | * a reset sequence, giving each an opportunity to do what it needs |
@@ -360,9 +366,7 @@ hard_fail: | |||
360 | "EEH: PCI device %s - %s has failed %d times \n" | 366 | "EEH: PCI device %s - %s has failed %d times \n" |
361 | "and has been permanently disabled. Please try reseating\n" | 367 | "and has been permanently disabled. Please try reseating\n" |
362 | "this device or replacing it.\n", | 368 | "this device or replacing it.\n", |
363 | pci_name (frozen_pdn->pcidev), | 369 | drv_str, pci_str, frozen_pdn->eeh_freeze_count); |
364 | pcid_name(frozen_pdn->pcidev), | ||
365 | frozen_pdn->eeh_freeze_count); | ||
366 | 370 | ||
367 | eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */); | 371 | eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */); |
368 | 372 | ||
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c new file mode 100644 index 000000000000..c01d8f0cbe6d --- /dev/null +++ b/arch/powerpc/platforms/pseries/firmware.c | |||
@@ -0,0 +1,103 @@ | |||
1 | /* | ||
2 | * pSeries firmware setup code. | ||
3 | * | ||
4 | * Portions from arch/powerpc/platforms/pseries/setup.c: | ||
5 | * Copyright (C) 1995 Linus Torvalds | ||
6 | * Adapted from 'alpha' version by Gary Thomas | ||
7 | * Modified by Cort Dougan (cort@cs.nmt.edu) | ||
8 | * Modified by PPC64 Team, IBM Corp | ||
9 | * | ||
10 | * Portions from arch/powerpc/kernel/firmware.c | ||
11 | * Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org) | ||
12 | * Modifications for ppc64: | ||
13 | * Copyright (C) 2003 Dave Engebretsen <engebret@us.ibm.com> | ||
14 | * Copyright (C) 2005 Stephen Rothwell, IBM Corporation | ||
15 | * | ||
16 | * Copyright 2006 IBM Corporation. | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or | ||
19 | * modify it under the terms of the GNU General Public License | ||
20 | * as published by the Free Software Foundation; either version | ||
21 | * 2 of the License, or (at your option) any later version. | ||
22 | */ | ||
23 | |||
24 | #undef DEBUG | ||
25 | |||
26 | #include <asm/firmware.h> | ||
27 | #include <asm/prom.h> | ||
28 | |||
29 | #ifdef DEBUG | ||
30 | #define DBG(fmt...) udbg_printf(fmt) | ||
31 | #else | ||
32 | #define DBG(fmt...) | ||
33 | #endif | ||
34 | |||
35 | typedef struct { | ||
36 | unsigned long val; | ||
37 | char * name; | ||
38 | } firmware_feature_t; | ||
39 | |||
40 | static __initdata firmware_feature_t | ||
41 | firmware_features_table[FIRMWARE_MAX_FEATURES] = { | ||
42 | {FW_FEATURE_PFT, "hcall-pft"}, | ||
43 | {FW_FEATURE_TCE, "hcall-tce"}, | ||
44 | {FW_FEATURE_SPRG0, "hcall-sprg0"}, | ||
45 | {FW_FEATURE_DABR, "hcall-dabr"}, | ||
46 | {FW_FEATURE_COPY, "hcall-copy"}, | ||
47 | {FW_FEATURE_ASR, "hcall-asr"}, | ||
48 | {FW_FEATURE_DEBUG, "hcall-debug"}, | ||
49 | {FW_FEATURE_PERF, "hcall-perf"}, | ||
50 | {FW_FEATURE_DUMP, "hcall-dump"}, | ||
51 | {FW_FEATURE_INTERRUPT, "hcall-interrupt"}, | ||
52 | {FW_FEATURE_MIGRATE, "hcall-migrate"}, | ||
53 | {FW_FEATURE_PERFMON, "hcall-perfmon"}, | ||
54 | {FW_FEATURE_CRQ, "hcall-crq"}, | ||
55 | {FW_FEATURE_VIO, "hcall-vio"}, | ||
56 | {FW_FEATURE_RDMA, "hcall-rdma"}, | ||
57 | {FW_FEATURE_LLAN, "hcall-lLAN"}, | ||
58 | {FW_FEATURE_BULK, "hcall-bulk"}, | ||
59 | {FW_FEATURE_XDABR, "hcall-xdabr"}, | ||
60 | {FW_FEATURE_MULTITCE, "hcall-multi-tce"}, | ||
61 | {FW_FEATURE_SPLPAR, "hcall-splpar"}, | ||
62 | }; | ||
63 | |||
64 | /* Build up the firmware features bitmask using the contents of | ||
65 | * device-tree/ibm,hypertas-functions. Ultimately this functionality may | ||
66 | * be moved into prom.c prom_init(). | ||
67 | */ | ||
68 | void __init fw_feature_init(void) | ||
69 | { | ||
70 | struct device_node *dn; | ||
71 | char *hypertas, *s; | ||
72 | int len, i; | ||
73 | |||
74 | DBG(" -> fw_feature_init()\n"); | ||
75 | |||
76 | dn = of_find_node_by_path("/rtas"); | ||
77 | if (dn == NULL) { | ||
78 | printk(KERN_ERR "WARNING! Cannot find RTAS in device-tree!\n"); | ||
79 | goto out; | ||
80 | } | ||
81 | |||
82 | hypertas = get_property(dn, "ibm,hypertas-functions", &len); | ||
83 | if (hypertas == NULL) | ||
84 | goto out; | ||
85 | |||
86 | for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) { | ||
87 | for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) { | ||
88 | /* check value against table of strings */ | ||
89 | if (!firmware_features_table[i].name || | ||
90 | strcmp(firmware_features_table[i].name, s)) | ||
91 | continue; | ||
92 | |||
93 | /* we have a match */ | ||
94 | powerpc_firmware_features |= | ||
95 | firmware_features_table[i].val; | ||
96 | break; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | out: | ||
101 | of_node_put(dn); | ||
102 | DBG(" <- fw_feature_init()\n"); | ||
103 | } | ||
diff --git a/arch/powerpc/platforms/pseries/firmware.h b/arch/powerpc/platforms/pseries/firmware.h new file mode 100644 index 000000000000..714f56f55362 --- /dev/null +++ b/arch/powerpc/platforms/pseries/firmware.h | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * Copyright 2006 IBM Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #ifndef _PSERIES_FIRMWARE_H | ||
11 | #define _PSERIES_FIRMWARE_H | ||
12 | |||
13 | #include <asm/firmware.h> | ||
14 | |||
15 | extern void __init fw_feature_init(void); | ||
16 | |||
17 | #endif /* _PSERIES_FIRMWARE_H */ | ||
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S index 176e8da76466..db7c19fe9297 100644 --- a/arch/powerpc/platforms/pseries/hvCall.S +++ b/arch/powerpc/platforms/pseries/hvCall.S | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/kernel/pSeries_hvCall.S | ||
3 | * | ||
4 | * This file contains the generic code to perform a call to the | 2 | * This file contains the generic code to perform a call to the |
5 | * pSeries LPAR hypervisor. | 3 | * pSeries LPAR hypervisor. |
6 | * NOTE: this file will go away when we move to inline this work. | 4 | * NOTE: this file will go away when we move to inline this work. |
diff --git a/arch/powerpc/platforms/pseries/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c index 138e128a3886..ba6befd96636 100644 --- a/arch/powerpc/platforms/pseries/hvconsole.c +++ b/arch/powerpc/platforms/pseries/hvconsole.c | |||
@@ -62,6 +62,11 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count) | |||
62 | unsigned long *lbuf = (unsigned long *) buf; | 62 | unsigned long *lbuf = (unsigned long *) buf; |
63 | long ret; | 63 | long ret; |
64 | 64 | ||
65 | |||
66 | /* hcall will ret H_PARAMETER if 'count' exceeds firmware max.*/ | ||
67 | if (count > MAX_VIO_PUT_CHARS) | ||
68 | count = MAX_VIO_PUT_CHARS; | ||
69 | |||
65 | ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count, lbuf[0], | 70 | ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count, lbuf[0], |
66 | lbuf[1]); | 71 | lbuf[1]); |
67 | if (ret == H_Success) | 72 | if (ret == H_Success) |
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 48cfbfc43f99..2643078433f0 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/kernel/pSeries_iommu.c | ||
3 | * | ||
4 | * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation | 2 | * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation |
5 | * | 3 | * |
6 | * Rewrite, cleanup: | 4 | * Rewrite, cleanup: |
@@ -582,7 +580,7 @@ void iommu_init_early_pSeries(void) | |||
582 | return; | 580 | return; |
583 | } | 581 | } |
584 | 582 | ||
585 | if (platform_is_lpar()) { | 583 | if (firmware_has_feature(FW_FEATURE_LPAR)) { |
586 | if (firmware_has_feature(FW_FEATURE_MULTITCE)) { | 584 | if (firmware_has_feature(FW_FEATURE_MULTITCE)) { |
587 | ppc_md.tce_build = tce_buildmulti_pSeriesLP; | 585 | ppc_md.tce_build = tce_buildmulti_pSeriesLP; |
588 | ppc_md.tce_free = tce_freemulti_pSeriesLP; | 586 | ppc_md.tce_free = tce_freemulti_pSeriesLP; |
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c index 999a9620b5ce..e97e67f5e079 100644 --- a/arch/powerpc/platforms/pseries/pci.c +++ b/arch/powerpc/platforms/pseries/pci.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc64/kernel/pSeries_pci.c | ||
3 | * | ||
4 | * Copyright (C) 2001 Dave Engebretsen, IBM Corporation | 2 | * Copyright (C) 2001 Dave Engebretsen, IBM Corporation |
5 | * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM | 3 | * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM |
6 | * | 4 | * |
@@ -122,7 +120,7 @@ static void fixup_winbond_82c105(struct pci_dev* dev) | |||
122 | int i; | 120 | int i; |
123 | unsigned int reg; | 121 | unsigned int reg; |
124 | 122 | ||
125 | if (!platform_is_pseries()) | 123 | if (!machine_is(pseries)) |
126 | return; | 124 | return; |
127 | 125 | ||
128 | printk("Using INTC for W82c105 IDE controller.\n"); | 126 | printk("Using INTC for W82c105 IDE controller.\n"); |
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index f3bad900bbcf..6bfacc217085 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c | |||
@@ -27,6 +27,8 @@ | |||
27 | 27 | ||
28 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
29 | #include <asm/pci-bridge.h> | 29 | #include <asm/pci-bridge.h> |
30 | #include <asm/ppc-pci.h> | ||
31 | #include <asm/firmware.h> | ||
30 | 32 | ||
31 | static struct pci_bus * | 33 | static struct pci_bus * |
32 | find_bus_among_children(struct pci_bus *bus, | 34 | find_bus_among_children(struct pci_bus *bus, |
@@ -151,20 +153,24 @@ pcibios_pci_config_bridge(struct pci_dev *dev) | |||
151 | void | 153 | void |
152 | pcibios_add_pci_devices(struct pci_bus * bus) | 154 | pcibios_add_pci_devices(struct pci_bus * bus) |
153 | { | 155 | { |
154 | int slotno, num; | 156 | int slotno, num, mode; |
155 | struct pci_dev *dev; | 157 | struct pci_dev *dev; |
156 | struct device_node *dn = pci_bus_to_OF_node(bus); | 158 | struct device_node *dn = pci_bus_to_OF_node(bus); |
157 | 159 | ||
158 | eeh_add_device_tree_early(dn); | 160 | eeh_add_device_tree_early(dn); |
159 | 161 | ||
160 | if (_machine == PLATFORM_PSERIES_LPAR) { | 162 | mode = PCI_PROBE_NORMAL; |
163 | if (ppc_md.pci_probe_mode) | ||
164 | mode = ppc_md.pci_probe_mode(bus); | ||
165 | |||
166 | if (mode == PCI_PROBE_DEVTREE) { | ||
161 | /* use ofdt-based probe */ | 167 | /* use ofdt-based probe */ |
162 | of_scan_bus(dn, bus); | 168 | of_scan_bus(dn, bus); |
163 | if (!list_empty(&bus->devices)) { | 169 | if (!list_empty(&bus->devices)) { |
164 | pcibios_fixup_new_pci_devices(bus, 0); | 170 | pcibios_fixup_new_pci_devices(bus, 0); |
165 | pci_bus_add_devices(bus); | 171 | pci_bus_add_devices(bus); |
166 | } | 172 | } |
167 | } else { | 173 | } else if (mode == PCI_PROBE_NORMAL) { |
168 | /* use legacy probe */ | 174 | /* use legacy probe */ |
169 | slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); | 175 | slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); |
170 | num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); | 176 | num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); |
@@ -179,3 +185,30 @@ pcibios_add_pci_devices(struct pci_bus * bus) | |||
179 | } | 185 | } |
180 | } | 186 | } |
181 | EXPORT_SYMBOL_GPL(pcibios_add_pci_devices); | 187 | EXPORT_SYMBOL_GPL(pcibios_add_pci_devices); |
188 | |||
189 | struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) | ||
190 | { | ||
191 | struct pci_controller *phb; | ||
192 | int primary; | ||
193 | |||
194 | primary = list_empty(&hose_list); | ||
195 | phb = pcibios_alloc_controller(dn); | ||
196 | if (!phb) | ||
197 | return NULL; | ||
198 | setup_phb(dn, phb); | ||
199 | pci_process_bridge_OF_ranges(phb, dn, 0); | ||
200 | |||
201 | pci_setup_phb_io_dynamic(phb, primary); | ||
202 | |||
203 | pci_devs_phb_init_dynamic(phb); | ||
204 | |||
205 | if (dn->child) | ||
206 | eeh_add_device_tree_early(dn); | ||
207 | |||
208 | scan_phb(phb); | ||
209 | pcibios_fixup_new_pci_devices(phb->bus, 0); | ||
210 | pci_bus_add_devices(phb->bus); | ||
211 | |||
212 | return phb; | ||
213 | } | ||
214 | EXPORT_SYMBOL_GPL(init_phb_dynamic); | ||
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index b046bcf7443d..9639c66b453d 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c | |||
@@ -132,7 +132,7 @@ static int __init init_ras_IRQ(void) | |||
132 | of_node_put(np); | 132 | of_node_put(np); |
133 | } | 133 | } |
134 | 134 | ||
135 | return 1; | 135 | return 0; |
136 | } | 136 | } |
137 | __initcall(init_ras_IRQ); | 137 | __initcall(init_ras_IRQ); |
138 | 138 | ||
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 86cfa6ecdcf3..1773103354be 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
@@ -17,8 +17,9 @@ | |||
17 | #include <linux/proc_fs.h> | 17 | #include <linux/proc_fs.h> |
18 | 18 | ||
19 | #include <asm/prom.h> | 19 | #include <asm/prom.h> |
20 | #include <asm/pSeries_reconfig.h> | 20 | #include <asm/machdep.h> |
21 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
22 | #include <asm/pSeries_reconfig.h> | ||
22 | 23 | ||
23 | 24 | ||
24 | 25 | ||
@@ -94,16 +95,16 @@ static struct device_node *derive_parent(const char *path) | |||
94 | return parent; | 95 | return parent; |
95 | } | 96 | } |
96 | 97 | ||
97 | static struct notifier_block *pSeries_reconfig_chain; | 98 | static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain); |
98 | 99 | ||
99 | int pSeries_reconfig_notifier_register(struct notifier_block *nb) | 100 | int pSeries_reconfig_notifier_register(struct notifier_block *nb) |
100 | { | 101 | { |
101 | return notifier_chain_register(&pSeries_reconfig_chain, nb); | 102 | return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb); |
102 | } | 103 | } |
103 | 104 | ||
104 | void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) | 105 | void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) |
105 | { | 106 | { |
106 | notifier_chain_unregister(&pSeries_reconfig_chain, nb); | 107 | blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb); |
107 | } | 108 | } |
108 | 109 | ||
109 | static int pSeries_reconfig_add_node(const char *path, struct property *proplist) | 110 | static int pSeries_reconfig_add_node(const char *path, struct property *proplist) |
@@ -131,7 +132,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist | |||
131 | goto out_err; | 132 | goto out_err; |
132 | } | 133 | } |
133 | 134 | ||
134 | err = notifier_call_chain(&pSeries_reconfig_chain, | 135 | err = blocking_notifier_call_chain(&pSeries_reconfig_chain, |
135 | PSERIES_RECONFIG_ADD, np); | 136 | PSERIES_RECONFIG_ADD, np); |
136 | if (err == NOTIFY_BAD) { | 137 | if (err == NOTIFY_BAD) { |
137 | printk(KERN_ERR "Failed to add device node %s\n", path); | 138 | printk(KERN_ERR "Failed to add device node %s\n", path); |
@@ -171,7 +172,7 @@ static int pSeries_reconfig_remove_node(struct device_node *np) | |||
171 | 172 | ||
172 | remove_node_proc_entries(np); | 173 | remove_node_proc_entries(np); |
173 | 174 | ||
174 | notifier_call_chain(&pSeries_reconfig_chain, | 175 | blocking_notifier_call_chain(&pSeries_reconfig_chain, |
175 | PSERIES_RECONFIG_REMOVE, np); | 176 | PSERIES_RECONFIG_REMOVE, np); |
176 | of_detach_node(np); | 177 | of_detach_node(np); |
177 | 178 | ||
@@ -508,7 +509,7 @@ static int proc_ppc64_create_ofdt(void) | |||
508 | { | 509 | { |
509 | struct proc_dir_entry *ent; | 510 | struct proc_dir_entry *ent; |
510 | 511 | ||
511 | if (!platform_is_pseries()) | 512 | if (!machine_is(pseries)) |
512 | return 0; | 513 | return 0; |
513 | 514 | ||
514 | ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL); | 515 | ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL); |
diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index a6f628d4c9dc..fcc4d561a236 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <asm/prom.h> | 27 | #include <asm/prom.h> |
28 | #include <asm/nvram.h> | 28 | #include <asm/nvram.h> |
29 | #include <asm/atomic.h> | 29 | #include <asm/atomic.h> |
30 | #include <asm/machdep.h> | ||
30 | 31 | ||
31 | #if 0 | 32 | #if 0 |
32 | #define DEBUG(A...) printk(KERN_ERR A) | 33 | #define DEBUG(A...) printk(KERN_ERR A) |
@@ -481,7 +482,7 @@ static int __init rtas_init(void) | |||
481 | { | 482 | { |
482 | struct proc_dir_entry *entry; | 483 | struct proc_dir_entry *entry; |
483 | 484 | ||
484 | if (!platform_is_pseries()) | 485 | if (!machine_is(pseries)) |
485 | return 0; | 486 | return 0; |
486 | 487 | ||
487 | /* No RTAS */ | 488 | /* No RTAS */ |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 9edeca83f434..b2fbf8ba8fbb 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -60,7 +60,6 @@ | |||
60 | #include <asm/time.h> | 60 | #include <asm/time.h> |
61 | #include <asm/nvram.h> | 61 | #include <asm/nvram.h> |
62 | #include "xics.h" | 62 | #include "xics.h" |
63 | #include <asm/firmware.h> | ||
64 | #include <asm/pmc.h> | 63 | #include <asm/pmc.h> |
65 | #include <asm/mpic.h> | 64 | #include <asm/mpic.h> |
66 | #include <asm/ppc-pci.h> | 65 | #include <asm/ppc-pci.h> |
@@ -70,6 +69,7 @@ | |||
70 | 69 | ||
71 | #include "plpar_wrappers.h" | 70 | #include "plpar_wrappers.h" |
72 | #include "ras.h" | 71 | #include "ras.h" |
72 | #include "firmware.h" | ||
73 | 73 | ||
74 | #ifdef DEBUG | 74 | #ifdef DEBUG |
75 | #define DBG(fmt...) udbg_printf(fmt) | 75 | #define DBG(fmt...) udbg_printf(fmt) |
@@ -81,8 +81,8 @@ extern void find_udbg_vterm(void); | |||
81 | 81 | ||
82 | int fwnmi_active; /* TRUE if an FWNMI handler is present */ | 82 | int fwnmi_active; /* TRUE if an FWNMI handler is present */ |
83 | 83 | ||
84 | static void pseries_shared_idle(void); | 84 | static void pseries_shared_idle_sleep(void); |
85 | static void pseries_dedicated_idle(void); | 85 | static void pseries_dedicated_idle_sleep(void); |
86 | 86 | ||
87 | struct mpic *pSeries_mpic; | 87 | struct mpic *pSeries_mpic; |
88 | 88 | ||
@@ -236,17 +236,16 @@ static void __init pSeries_setup_arch(void) | |||
236 | vpa_init(boot_cpuid); | 236 | vpa_init(boot_cpuid); |
237 | if (get_lppaca()->shared_proc) { | 237 | if (get_lppaca()->shared_proc) { |
238 | printk(KERN_INFO "Using shared processor idle loop\n"); | 238 | printk(KERN_INFO "Using shared processor idle loop\n"); |
239 | ppc_md.idle_loop = pseries_shared_idle; | 239 | ppc_md.power_save = pseries_shared_idle_sleep; |
240 | } else { | 240 | } else { |
241 | printk(KERN_INFO "Using dedicated idle loop\n"); | 241 | printk(KERN_INFO "Using dedicated idle loop\n"); |
242 | ppc_md.idle_loop = pseries_dedicated_idle; | 242 | ppc_md.power_save = pseries_dedicated_idle_sleep; |
243 | } | 243 | } |
244 | } else { | 244 | } else { |
245 | printk(KERN_INFO "Using default idle loop\n"); | 245 | printk(KERN_INFO "Using default idle loop\n"); |
246 | ppc_md.idle_loop = default_idle; | ||
247 | } | 246 | } |
248 | 247 | ||
249 | if (platform_is_lpar()) | 248 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
250 | ppc_md.enable_pmcs = pseries_lpar_enable_pmcs; | 249 | ppc_md.enable_pmcs = pseries_lpar_enable_pmcs; |
251 | else | 250 | else |
252 | ppc_md.enable_pmcs = power4_enable_pmcs; | 251 | ppc_md.enable_pmcs = power4_enable_pmcs; |
@@ -262,53 +261,6 @@ static int __init pSeries_init_panel(void) | |||
262 | } | 261 | } |
263 | arch_initcall(pSeries_init_panel); | 262 | arch_initcall(pSeries_init_panel); |
264 | 263 | ||
265 | |||
266 | /* Build up the ppc64_firmware_features bitmask field | ||
267 | * using contents of device-tree/ibm,hypertas-functions. | ||
268 | * Ultimately this functionality may be moved into prom.c prom_init(). | ||
269 | */ | ||
270 | static void __init fw_feature_init(void) | ||
271 | { | ||
272 | struct device_node * dn; | ||
273 | char * hypertas; | ||
274 | unsigned int len; | ||
275 | |||
276 | DBG(" -> fw_feature_init()\n"); | ||
277 | |||
278 | ppc64_firmware_features = 0; | ||
279 | dn = of_find_node_by_path("/rtas"); | ||
280 | if (dn == NULL) { | ||
281 | printk(KERN_ERR "WARNING ! Cannot find RTAS in device-tree !\n"); | ||
282 | goto no_rtas; | ||
283 | } | ||
284 | |||
285 | hypertas = get_property(dn, "ibm,hypertas-functions", &len); | ||
286 | if (hypertas) { | ||
287 | while (len > 0){ | ||
288 | int i, hypertas_len; | ||
289 | /* check value against table of strings */ | ||
290 | for(i=0; i < FIRMWARE_MAX_FEATURES ;i++) { | ||
291 | if ((firmware_features_table[i].name) && | ||
292 | (strcmp(firmware_features_table[i].name,hypertas))==0) { | ||
293 | /* we have a match */ | ||
294 | ppc64_firmware_features |= | ||
295 | (firmware_features_table[i].val); | ||
296 | break; | ||
297 | } | ||
298 | } | ||
299 | hypertas_len = strlen(hypertas); | ||
300 | len -= hypertas_len +1; | ||
301 | hypertas+= hypertas_len +1; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | of_node_put(dn); | ||
306 | no_rtas: | ||
307 | |||
308 | DBG(" <- fw_feature_init()\n"); | ||
309 | } | ||
310 | |||
311 | |||
312 | static void __init pSeries_discover_pic(void) | 264 | static void __init pSeries_discover_pic(void) |
313 | { | 265 | { |
314 | struct device_node *np; | 266 | struct device_node *np; |
@@ -367,21 +319,16 @@ static int pseries_set_xdabr(unsigned long dabr) | |||
367 | */ | 319 | */ |
368 | static void __init pSeries_init_early(void) | 320 | static void __init pSeries_init_early(void) |
369 | { | 321 | { |
370 | int iommu_off = 0; | ||
371 | |||
372 | DBG(" -> pSeries_init_early()\n"); | 322 | DBG(" -> pSeries_init_early()\n"); |
373 | 323 | ||
374 | fw_feature_init(); | 324 | fw_feature_init(); |
375 | 325 | ||
376 | if (platform_is_lpar()) | 326 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
377 | hpte_init_lpar(); | 327 | hpte_init_lpar(); |
378 | else { | 328 | else |
379 | hpte_init_native(); | 329 | hpte_init_native(); |
380 | iommu_off = (of_chosen && | ||
381 | get_property(of_chosen, "linux,iommu-off", NULL)); | ||
382 | } | ||
383 | 330 | ||
384 | if (platform_is_lpar()) | 331 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
385 | find_udbg_vterm(); | 332 | find_udbg_vterm(); |
386 | 333 | ||
387 | if (firmware_has_feature(FW_FEATURE_DABR)) | 334 | if (firmware_has_feature(FW_FEATURE_DABR)) |
@@ -425,158 +372,128 @@ static int pSeries_check_legacy_ioport(unsigned int baseport) | |||
425 | /* | 372 | /* |
426 | * Called very early, MMU is off, device-tree isn't unflattened | 373 | * Called very early, MMU is off, device-tree isn't unflattened |
427 | */ | 374 | */ |
428 | extern struct machdep_calls pSeries_md; | ||
429 | 375 | ||
430 | static int __init pSeries_probe(int platform) | 376 | static int __init pSeries_probe_hypertas(unsigned long node, |
377 | const char *uname, int depth, | ||
378 | void *data) | ||
431 | { | 379 | { |
432 | if (platform != PLATFORM_PSERIES && | 380 | if (depth != 1 || |
433 | platform != PLATFORM_PSERIES_LPAR) | 381 | (strcmp(uname, "rtas") != 0 && strcmp(uname, "rtas@0") != 0)) |
434 | return 0; | 382 | return 0; |
435 | 383 | ||
436 | /* if we have some ppc_md fixups for LPAR to do, do | 384 | if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL) |
437 | * it here ... | 385 | powerpc_firmware_features |= FW_FEATURE_LPAR; |
438 | */ | ||
439 | 386 | ||
440 | return 1; | 387 | return 1; |
441 | } | 388 | } |
442 | 389 | ||
443 | DECLARE_PER_CPU(unsigned long, smt_snooze_delay); | 390 | static int __init pSeries_probe(void) |
444 | |||
445 | static inline void dedicated_idle_sleep(unsigned int cpu) | ||
446 | { | 391 | { |
447 | struct lppaca *plppaca = &lppaca[cpu ^ 1]; | 392 | char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(), |
393 | "device_type", NULL); | ||
394 | if (dtype == NULL) | ||
395 | return 0; | ||
396 | if (strcmp(dtype, "chrp")) | ||
397 | return 0; | ||
448 | 398 | ||
449 | /* Only sleep if the other thread is not idle */ | 399 | DBG("pSeries detected, looking for LPAR capability...\n"); |
450 | if (!(plppaca->idle)) { | ||
451 | local_irq_disable(); | ||
452 | 400 | ||
453 | /* | 401 | /* Now try to figure out if we are running on LPAR */ |
454 | * We are about to sleep the thread and so wont be polling any | 402 | of_scan_flat_dt(pSeries_probe_hypertas, NULL); |
455 | * more. | 403 | |
456 | */ | 404 | DBG("Machine is%s LPAR !\n", |
457 | clear_thread_flag(TIF_POLLING_NRFLAG); | 405 | (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not"); |
458 | smp_mb__after_clear_bit(); | 406 | |
459 | 407 | return 1; | |
460 | /* | ||
461 | * SMT dynamic mode. Cede will result in this thread going | ||
462 | * dormant, if the partner thread is still doing work. Thread | ||
463 | * wakes up if partner goes idle, an interrupt is presented, or | ||
464 | * a prod occurs. Returning from the cede enables external | ||
465 | * interrupts. | ||
466 | */ | ||
467 | if (!need_resched()) | ||
468 | cede_processor(); | ||
469 | else | ||
470 | local_irq_enable(); | ||
471 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
472 | } else { | ||
473 | /* | ||
474 | * Give the HV an opportunity at the processor, since we are | ||
475 | * not doing any work. | ||
476 | */ | ||
477 | poll_pending(); | ||
478 | } | ||
479 | } | 408 | } |
480 | 409 | ||
481 | static void pseries_dedicated_idle(void) | 410 | |
411 | DECLARE_PER_CPU(unsigned long, smt_snooze_delay); | ||
412 | |||
413 | static void pseries_dedicated_idle_sleep(void) | ||
482 | { | 414 | { |
483 | unsigned int cpu = smp_processor_id(); | 415 | unsigned int cpu = smp_processor_id(); |
484 | unsigned long start_snooze; | 416 | unsigned long start_snooze; |
485 | unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay); | 417 | unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay); |
486 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
487 | |||
488 | while (1) { | ||
489 | /* | ||
490 | * Indicate to the HV that we are idle. Now would be | ||
491 | * a good time to find other work to dispatch. | ||
492 | */ | ||
493 | get_lppaca()->idle = 1; | ||
494 | |||
495 | if (!need_resched()) { | ||
496 | start_snooze = get_tb() + | ||
497 | *smt_snooze_delay * tb_ticks_per_usec; | ||
498 | |||
499 | while (!need_resched() && !cpu_is_offline(cpu)) { | ||
500 | ppc64_runlatch_off(); | ||
501 | |||
502 | /* | ||
503 | * Go into low thread priority and possibly | ||
504 | * low power mode. | ||
505 | */ | ||
506 | HMT_low(); | ||
507 | HMT_very_low(); | ||
508 | |||
509 | if (*smt_snooze_delay != 0 && | ||
510 | get_tb() > start_snooze) { | ||
511 | HMT_medium(); | ||
512 | dedicated_idle_sleep(cpu); | ||
513 | } | ||
514 | |||
515 | } | ||
516 | |||
517 | HMT_medium(); | ||
518 | } | ||
519 | 418 | ||
520 | get_lppaca()->idle = 0; | 419 | /* |
521 | ppc64_runlatch_on(); | 420 | * Indicate to the HV that we are idle. Now would be |
522 | 421 | * a good time to find other work to dispatch. | |
523 | preempt_enable_no_resched(); | 422 | */ |
524 | schedule(); | 423 | get_lppaca()->idle = 1; |
525 | preempt_disable(); | ||
526 | 424 | ||
527 | if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) | 425 | /* |
528 | cpu_die(); | 426 | * We come in with interrupts disabled, and need_resched() |
529 | } | 427 | * has been checked recently. If we should poll for a little |
530 | } | 428 | * while, do so. |
429 | */ | ||
430 | if (*smt_snooze_delay) { | ||
431 | start_snooze = get_tb() + | ||
432 | *smt_snooze_delay * tb_ticks_per_usec; | ||
433 | local_irq_enable(); | ||
434 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
531 | 435 | ||
532 | static void pseries_shared_idle(void) | 436 | while (get_tb() < start_snooze) { |
533 | { | 437 | if (need_resched() || cpu_is_offline(cpu)) |
534 | unsigned int cpu = smp_processor_id(); | 438 | goto out; |
439 | ppc64_runlatch_off(); | ||
440 | HMT_low(); | ||
441 | HMT_very_low(); | ||
442 | } | ||
535 | 443 | ||
536 | while (1) { | 444 | HMT_medium(); |
537 | /* | 445 | clear_thread_flag(TIF_POLLING_NRFLAG); |
538 | * Indicate to the HV that we are idle. Now would be | 446 | smp_mb(); |
539 | * a good time to find other work to dispatch. | 447 | local_irq_disable(); |
540 | */ | 448 | if (need_resched() || cpu_is_offline(cpu)) |
541 | get_lppaca()->idle = 1; | 449 | goto out; |
450 | } | ||
542 | 451 | ||
543 | while (!need_resched() && !cpu_is_offline(cpu)) { | 452 | /* |
544 | local_irq_disable(); | 453 | * Cede if the other thread is not idle, so that it can |
545 | ppc64_runlatch_off(); | 454 | * go single-threaded. If the other thread is idle, |
455 | * we ask the hypervisor if it has pending work it | ||
456 | * wants to do and cede if it does. Otherwise we keep | ||
457 | * polling in order to reduce interrupt latency. | ||
458 | * | ||
459 | * Doing the cede when the other thread is active will | ||
460 | * result in this thread going dormant, meaning the other | ||
461 | * thread gets to run in single-threaded (ST) mode, which | ||
462 | * is slightly faster than SMT mode with this thread at | ||
463 | * very low priority. The cede enables interrupts, which | ||
464 | * doesn't matter here. | ||
465 | */ | ||
466 | if (!lppaca[cpu ^ 1].idle || poll_pending() == H_Pending) | ||
467 | cede_processor(); | ||
546 | 468 | ||
547 | /* | 469 | out: |
548 | * Yield the processor to the hypervisor. We return if | 470 | HMT_medium(); |
549 | * an external interrupt occurs (which are driven prior | 471 | get_lppaca()->idle = 0; |
550 | * to returning here) or if a prod occurs from another | 472 | } |
551 | * processor. When returning here, external interrupts | ||
552 | * are enabled. | ||
553 | * | ||
554 | * Check need_resched() again with interrupts disabled | ||
555 | * to avoid a race. | ||
556 | */ | ||
557 | if (!need_resched()) | ||
558 | cede_processor(); | ||
559 | else | ||
560 | local_irq_enable(); | ||
561 | |||
562 | HMT_medium(); | ||
563 | } | ||
564 | 473 | ||
565 | get_lppaca()->idle = 0; | 474 | static void pseries_shared_idle_sleep(void) |
566 | ppc64_runlatch_on(); | 475 | { |
476 | /* | ||
477 | * Indicate to the HV that we are idle. Now would be | ||
478 | * a good time to find other work to dispatch. | ||
479 | */ | ||
480 | get_lppaca()->idle = 1; | ||
567 | 481 | ||
568 | preempt_enable_no_resched(); | 482 | /* |
569 | schedule(); | 483 | * Yield the processor to the hypervisor. We return if |
570 | preempt_disable(); | 484 | * an external interrupt occurs (which are driven prior |
485 | * to returning here) or if a prod occurs from another | ||
486 | * processor. When returning here, external interrupts | ||
487 | * are enabled. | ||
488 | */ | ||
489 | cede_processor(); | ||
571 | 490 | ||
572 | if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) | 491 | get_lppaca()->idle = 0; |
573 | cpu_die(); | ||
574 | } | ||
575 | } | 492 | } |
576 | 493 | ||
577 | static int pSeries_pci_probe_mode(struct pci_bus *bus) | 494 | static int pSeries_pci_probe_mode(struct pci_bus *bus) |
578 | { | 495 | { |
579 | if (platform_is_lpar()) | 496 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
580 | return PCI_PROBE_DEVTREE; | 497 | return PCI_PROBE_DEVTREE; |
581 | return PCI_PROBE_NORMAL; | 498 | return PCI_PROBE_NORMAL; |
582 | } | 499 | } |
@@ -602,7 +519,8 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) | |||
602 | } | 519 | } |
603 | #endif | 520 | #endif |
604 | 521 | ||
605 | struct machdep_calls __initdata pSeries_md = { | 522 | define_machine(pseries) { |
523 | .name = "pSeries", | ||
606 | .probe = pSeries_probe, | 524 | .probe = pSeries_probe, |
607 | .setup_arch = pSeries_setup_arch, | 525 | .setup_arch = pSeries_setup_arch, |
608 | .init_early = pSeries_init_early, | 526 | .init_early = pSeries_init_early, |
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 8d710af50756..3cf78a6cd27c 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c | |||
@@ -443,7 +443,7 @@ void __init smp_init_pSeries(void) | |||
443 | smp_ops->cpu_die = pSeries_cpu_die; | 443 | smp_ops->cpu_die = pSeries_cpu_die; |
444 | 444 | ||
445 | /* Processors can be added/removed only on LPAR */ | 445 | /* Processors can be added/removed only on LPAR */ |
446 | if (platform_is_lpar()) | 446 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
447 | pSeries_reconfig_notifier_register(&pSeries_smp_nb); | 447 | pSeries_reconfig_notifier_register(&pSeries_smp_nb); |
448 | #endif | 448 | #endif |
449 | 449 | ||
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index fd823c7c9ac8..4864cb32be25 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/gfp.h> | 20 | #include <linux/gfp.h> |
21 | #include <linux/radix-tree.h> | 21 | #include <linux/radix-tree.h> |
22 | #include <linux/cpu.h> | 22 | #include <linux/cpu.h> |
23 | #include <asm/firmware.h> | ||
23 | #include <asm/prom.h> | 24 | #include <asm/prom.h> |
24 | #include <asm/io.h> | 25 | #include <asm/io.h> |
25 | #include <asm/pgtable.h> | 26 | #include <asm/pgtable.h> |
@@ -499,7 +500,7 @@ nextnode: | |||
499 | np; | 500 | np; |
500 | np = of_find_node_by_type(np, "cpu")) { | 501 | np = of_find_node_by_type(np, "cpu")) { |
501 | ireg = (uint *)get_property(np, "reg", &ilen); | 502 | ireg = (uint *)get_property(np, "reg", &ilen); |
502 | if (ireg && ireg[0] == boot_cpuid_phys) { | 503 | if (ireg && ireg[0] == get_hard_smp_processor_id(boot_cpuid)) { |
503 | ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", | 504 | ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", |
504 | &ilen); | 505 | &ilen); |
505 | i = ilen / sizeof(int); | 506 | i = ilen / sizeof(int); |
@@ -536,11 +537,11 @@ nextnode: | |||
536 | of_node_put(np); | 537 | of_node_put(np); |
537 | } | 538 | } |
538 | 539 | ||
539 | if (platform_is_lpar()) | 540 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
540 | ops = &pSeriesLP_ops; | 541 | ops = &pSeriesLP_ops; |
541 | else { | 542 | else { |
542 | #ifdef CONFIG_SMP | 543 | #ifdef CONFIG_SMP |
543 | for_each_cpu(i) { | 544 | for_each_possible_cpu(i) { |
544 | int hard_id; | 545 | int hard_id; |
545 | 546 | ||
546 | /* FIXME: Do this dynamically! --RR */ | 547 | /* FIXME: Do this dynamically! --RR */ |
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 6298264efe36..61d317428610 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c | |||
@@ -194,8 +194,6 @@ static int dart_init(struct device_node *dart_node) | |||
194 | * prefetching into invalid pages and corrupting data | 194 | * prefetching into invalid pages and corrupting data |
195 | */ | 195 | */ |
196 | tmp = lmb_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE); | 196 | tmp = lmb_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE); |
197 | if (!tmp) | ||
198 | panic("DART: Cannot allocate spare page!"); | ||
199 | dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) & | 197 | dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) & |
200 | DARTMAP_RPNMASK); | 198 | DARTMAP_RPNMASK); |
201 | 199 | ||
diff --git a/arch/powerpc/sysdev/dcr.S b/arch/powerpc/sysdev/dcr.S index 895f10243a43..2078f39e2f17 100644 --- a/arch/powerpc/sysdev/dcr.S +++ b/arch/powerpc/sysdev/dcr.S | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/syslib/dcr.S | ||
3 | * | ||
4 | * "Indirect" DCR access | 2 | * "Indirect" DCR access |
5 | * | 3 | * |
6 | * Copyright (c) 2004 Eugene Surovegin <ebs@ebshome.net> | 4 | * Copyright (c) 2004 Eugene Surovegin <ebs@ebshome.net> |
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 064c9de47732..ceb584682fa3 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
@@ -40,7 +40,7 @@ phys_addr_t get_immrbase(void) | |||
40 | return immrbase; | 40 | return immrbase; |
41 | 41 | ||
42 | soc = of_find_node_by_type(NULL, "soc"); | 42 | soc = of_find_node_by_type(NULL, "soc"); |
43 | if (soc != 0) { | 43 | if (soc) { |
44 | unsigned int size; | 44 | unsigned int size; |
45 | void *prop = get_property(soc, "reg", &size); | 45 | void *prop = get_property(soc, "reg", &size); |
46 | immrbase = of_translate_address(soc, prop); | 46 | immrbase = of_translate_address(soc, prop); |
@@ -49,21 +49,20 @@ phys_addr_t get_immrbase(void) | |||
49 | 49 | ||
50 | return immrbase; | 50 | return immrbase; |
51 | } | 51 | } |
52 | EXPORT_SYMBOL(get_immrbase); | ||
53 | 52 | ||
54 | static const char * gfar_tx_intr = "tx"; | 53 | EXPORT_SYMBOL(get_immrbase); |
55 | static const char * gfar_rx_intr = "rx"; | ||
56 | static const char * gfar_err_intr = "error"; | ||
57 | 54 | ||
58 | static int __init gfar_of_init(void) | 55 | static int __init gfar_mdio_of_init(void) |
59 | { | 56 | { |
60 | struct device_node *np; | 57 | struct device_node *np; |
61 | unsigned int i; | 58 | unsigned int i; |
62 | struct platform_device *mdio_dev, *gfar_dev; | 59 | struct platform_device *mdio_dev; |
63 | struct resource res; | 60 | struct resource res; |
64 | int ret; | 61 | int ret; |
65 | 62 | ||
66 | for (np = NULL, i = 0; (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL; i++) { | 63 | for (np = NULL, i = 0; |
64 | (np = of_find_compatible_node(np, "mdio", "gianfar")) != NULL; | ||
65 | i++) { | ||
67 | int k; | 66 | int k; |
68 | struct device_node *child = NULL; | 67 | struct device_node *child = NULL; |
69 | struct gianfar_mdio_data mdio_data; | 68 | struct gianfar_mdio_data mdio_data; |
@@ -73,12 +72,14 @@ static int __init gfar_of_init(void) | |||
73 | 72 | ||
74 | ret = of_address_to_resource(np, 0, &res); | 73 | ret = of_address_to_resource(np, 0, &res); |
75 | if (ret) | 74 | if (ret) |
76 | goto mdio_err; | 75 | goto err; |
77 | 76 | ||
78 | mdio_dev = platform_device_register_simple("fsl-gianfar_mdio", res.start, &res, 1); | 77 | mdio_dev = |
78 | platform_device_register_simple("fsl-gianfar_mdio", | ||
79 | res.start, &res, 1); | ||
79 | if (IS_ERR(mdio_dev)) { | 80 | if (IS_ERR(mdio_dev)) { |
80 | ret = PTR_ERR(mdio_dev); | 81 | ret = PTR_ERR(mdio_dev); |
81 | goto mdio_err; | 82 | goto err; |
82 | } | 83 | } |
83 | 84 | ||
84 | for (k = 0; k < 32; k++) | 85 | for (k = 0; k < 32; k++) |
@@ -86,17 +87,44 @@ static int __init gfar_of_init(void) | |||
86 | 87 | ||
87 | while ((child = of_get_next_child(np, child)) != NULL) { | 88 | while ((child = of_get_next_child(np, child)) != NULL) { |
88 | if (child->n_intrs) { | 89 | if (child->n_intrs) { |
89 | u32 *id = (u32 *) get_property(child, "reg", NULL); | 90 | u32 *id = |
91 | (u32 *) get_property(child, "reg", NULL); | ||
90 | mdio_data.irq[*id] = child->intrs[0].line; | 92 | mdio_data.irq[*id] = child->intrs[0].line; |
91 | } | 93 | } |
92 | } | 94 | } |
93 | 95 | ||
94 | ret = platform_device_add_data(mdio_dev, &mdio_data, sizeof(struct gianfar_mdio_data)); | 96 | ret = |
97 | platform_device_add_data(mdio_dev, &mdio_data, | ||
98 | sizeof(struct gianfar_mdio_data)); | ||
95 | if (ret) | 99 | if (ret) |
96 | goto mdio_unreg; | 100 | goto unreg; |
97 | } | 101 | } |
98 | 102 | ||
99 | for (np = NULL, i = 0; (np = of_find_compatible_node(np, "network", "gianfar")) != NULL; i++) { | 103 | return 0; |
104 | |||
105 | unreg: | ||
106 | platform_device_unregister(mdio_dev); | ||
107 | err: | ||
108 | return ret; | ||
109 | } | ||
110 | |||
111 | arch_initcall(gfar_mdio_of_init); | ||
112 | |||
113 | static const char *gfar_tx_intr = "tx"; | ||
114 | static const char *gfar_rx_intr = "rx"; | ||
115 | static const char *gfar_err_intr = "error"; | ||
116 | |||
117 | static int __init gfar_of_init(void) | ||
118 | { | ||
119 | struct device_node *np; | ||
120 | unsigned int i; | ||
121 | struct platform_device *gfar_dev; | ||
122 | struct resource res; | ||
123 | int ret; | ||
124 | |||
125 | for (np = NULL, i = 0; | ||
126 | (np = of_find_compatible_node(np, "network", "gianfar")) != NULL; | ||
127 | i++) { | ||
100 | struct resource r[4]; | 128 | struct resource r[4]; |
101 | struct device_node *phy, *mdio; | 129 | struct device_node *phy, *mdio; |
102 | struct gianfar_platform_data gfar_data; | 130 | struct gianfar_platform_data gfar_data; |
@@ -110,7 +138,7 @@ static int __init gfar_of_init(void) | |||
110 | 138 | ||
111 | ret = of_address_to_resource(np, 0, &r[0]); | 139 | ret = of_address_to_resource(np, 0, &r[0]); |
112 | if (ret) | 140 | if (ret) |
113 | goto gfar_err; | 141 | goto err; |
114 | 142 | ||
115 | r[1].start = np->intrs[0].line; | 143 | r[1].start = np->intrs[0].line; |
116 | r[1].end = np->intrs[0].line; | 144 | r[1].end = np->intrs[0].line; |
@@ -133,11 +161,13 @@ static int __init gfar_of_init(void) | |||
133 | r[3].flags = IORESOURCE_IRQ; | 161 | r[3].flags = IORESOURCE_IRQ; |
134 | } | 162 | } |
135 | 163 | ||
136 | gfar_dev = platform_device_register_simple("fsl-gianfar", i, &r[0], np->n_intrs + 1); | 164 | gfar_dev = |
165 | platform_device_register_simple("fsl-gianfar", i, &r[0], | ||
166 | np->n_intrs + 1); | ||
137 | 167 | ||
138 | if (IS_ERR(gfar_dev)) { | 168 | if (IS_ERR(gfar_dev)) { |
139 | ret = PTR_ERR(gfar_dev); | 169 | ret = PTR_ERR(gfar_dev); |
140 | goto gfar_err; | 170 | goto err; |
141 | } | 171 | } |
142 | 172 | ||
143 | mac_addr = get_property(np, "address", NULL); | 173 | mac_addr = get_property(np, "address", NULL); |
@@ -145,26 +175,26 @@ static int __init gfar_of_init(void) | |||
145 | 175 | ||
146 | if (model && !strcasecmp(model, "TSEC")) | 176 | if (model && !strcasecmp(model, "TSEC")) |
147 | gfar_data.device_flags = | 177 | gfar_data.device_flags = |
148 | FSL_GIANFAR_DEV_HAS_GIGABIT | | 178 | FSL_GIANFAR_DEV_HAS_GIGABIT | |
149 | FSL_GIANFAR_DEV_HAS_COALESCE | | 179 | FSL_GIANFAR_DEV_HAS_COALESCE | |
150 | FSL_GIANFAR_DEV_HAS_RMON | | 180 | FSL_GIANFAR_DEV_HAS_RMON | |
151 | FSL_GIANFAR_DEV_HAS_MULTI_INTR; | 181 | FSL_GIANFAR_DEV_HAS_MULTI_INTR; |
152 | if (model && !strcasecmp(model, "eTSEC")) | 182 | if (model && !strcasecmp(model, "eTSEC")) |
153 | gfar_data.device_flags = | 183 | gfar_data.device_flags = |
154 | FSL_GIANFAR_DEV_HAS_GIGABIT | | 184 | FSL_GIANFAR_DEV_HAS_GIGABIT | |
155 | FSL_GIANFAR_DEV_HAS_COALESCE | | 185 | FSL_GIANFAR_DEV_HAS_COALESCE | |
156 | FSL_GIANFAR_DEV_HAS_RMON | | 186 | FSL_GIANFAR_DEV_HAS_RMON | |
157 | FSL_GIANFAR_DEV_HAS_MULTI_INTR | | 187 | FSL_GIANFAR_DEV_HAS_MULTI_INTR | |
158 | FSL_GIANFAR_DEV_HAS_CSUM | | 188 | FSL_GIANFAR_DEV_HAS_CSUM | |
159 | FSL_GIANFAR_DEV_HAS_VLAN | | 189 | FSL_GIANFAR_DEV_HAS_VLAN | |
160 | FSL_GIANFAR_DEV_HAS_EXTENDED_HASH; | 190 | FSL_GIANFAR_DEV_HAS_EXTENDED_HASH; |
161 | 191 | ||
162 | ph = (phandle *) get_property(np, "phy-handle", NULL); | 192 | ph = (phandle *) get_property(np, "phy-handle", NULL); |
163 | phy = of_find_node_by_phandle(*ph); | 193 | phy = of_find_node_by_phandle(*ph); |
164 | 194 | ||
165 | if (phy == NULL) { | 195 | if (phy == NULL) { |
166 | ret = -ENODEV; | 196 | ret = -ENODEV; |
167 | goto gfar_unreg; | 197 | goto unreg; |
168 | } | 198 | } |
169 | 199 | ||
170 | mdio = of_get_parent(phy); | 200 | mdio = of_get_parent(phy); |
@@ -174,7 +204,7 @@ static int __init gfar_of_init(void) | |||
174 | if (ret) { | 204 | if (ret) { |
175 | of_node_put(phy); | 205 | of_node_put(phy); |
176 | of_node_put(mdio); | 206 | of_node_put(mdio); |
177 | goto gfar_unreg; | 207 | goto unreg; |
178 | } | 208 | } |
179 | 209 | ||
180 | gfar_data.phy_id = *id; | 210 | gfar_data.phy_id = *id; |
@@ -183,23 +213,22 @@ static int __init gfar_of_init(void) | |||
183 | of_node_put(phy); | 213 | of_node_put(phy); |
184 | of_node_put(mdio); | 214 | of_node_put(mdio); |
185 | 215 | ||
186 | ret = platform_device_add_data(gfar_dev, &gfar_data, sizeof(struct gianfar_platform_data)); | 216 | ret = |
217 | platform_device_add_data(gfar_dev, &gfar_data, | ||
218 | sizeof(struct | ||
219 | gianfar_platform_data)); | ||
187 | if (ret) | 220 | if (ret) |
188 | goto gfar_unreg; | 221 | goto unreg; |
189 | } | 222 | } |
190 | 223 | ||
191 | return 0; | 224 | return 0; |
192 | 225 | ||
193 | mdio_unreg: | 226 | unreg: |
194 | platform_device_unregister(mdio_dev); | ||
195 | mdio_err: | ||
196 | return ret; | ||
197 | |||
198 | gfar_unreg: | ||
199 | platform_device_unregister(gfar_dev); | 227 | platform_device_unregister(gfar_dev); |
200 | gfar_err: | 228 | err: |
201 | return ret; | 229 | return ret; |
202 | } | 230 | } |
231 | |||
203 | arch_initcall(gfar_of_init); | 232 | arch_initcall(gfar_of_init); |
204 | 233 | ||
205 | static int __init fsl_i2c_of_init(void) | 234 | static int __init fsl_i2c_of_init(void) |
@@ -209,17 +238,19 @@ static int __init fsl_i2c_of_init(void) | |||
209 | struct platform_device *i2c_dev; | 238 | struct platform_device *i2c_dev; |
210 | int ret; | 239 | int ret; |
211 | 240 | ||
212 | for (np = NULL, i = 0; (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL; i++) { | 241 | for (np = NULL, i = 0; |
242 | (np = of_find_compatible_node(np, "i2c", "fsl-i2c")) != NULL; | ||
243 | i++) { | ||
213 | struct resource r[2]; | 244 | struct resource r[2]; |
214 | struct fsl_i2c_platform_data i2c_data; | 245 | struct fsl_i2c_platform_data i2c_data; |
215 | unsigned char * flags = NULL; | 246 | unsigned char *flags = NULL; |
216 | 247 | ||
217 | memset(&r, 0, sizeof(r)); | 248 | memset(&r, 0, sizeof(r)); |
218 | memset(&i2c_data, 0, sizeof(i2c_data)); | 249 | memset(&i2c_data, 0, sizeof(i2c_data)); |
219 | 250 | ||
220 | ret = of_address_to_resource(np, 0, &r[0]); | 251 | ret = of_address_to_resource(np, 0, &r[0]); |
221 | if (ret) | 252 | if (ret) |
222 | goto i2c_err; | 253 | goto err; |
223 | 254 | ||
224 | r[1].start = np->intrs[0].line; | 255 | r[1].start = np->intrs[0].line; |
225 | r[1].end = np->intrs[0].line; | 256 | r[1].end = np->intrs[0].line; |
@@ -228,7 +259,7 @@ static int __init fsl_i2c_of_init(void) | |||
228 | i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2); | 259 | i2c_dev = platform_device_register_simple("fsl-i2c", i, r, 2); |
229 | if (IS_ERR(i2c_dev)) { | 260 | if (IS_ERR(i2c_dev)) { |
230 | ret = PTR_ERR(i2c_dev); | 261 | ret = PTR_ERR(i2c_dev); |
231 | goto i2c_err; | 262 | goto err; |
232 | } | 263 | } |
233 | 264 | ||
234 | i2c_data.device_flags = 0; | 265 | i2c_data.device_flags = 0; |
@@ -240,18 +271,22 @@ static int __init fsl_i2c_of_init(void) | |||
240 | if (flags) | 271 | if (flags) |
241 | i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200; | 272 | i2c_data.device_flags |= FSL_I2C_DEV_CLOCK_5200; |
242 | 273 | ||
243 | ret = platform_device_add_data(i2c_dev, &i2c_data, sizeof(struct fsl_i2c_platform_data)); | 274 | ret = |
275 | platform_device_add_data(i2c_dev, &i2c_data, | ||
276 | sizeof(struct | ||
277 | fsl_i2c_platform_data)); | ||
244 | if (ret) | 278 | if (ret) |
245 | goto i2c_unreg; | 279 | goto unreg; |
246 | } | 280 | } |
247 | 281 | ||
248 | return 0; | 282 | return 0; |
249 | 283 | ||
250 | i2c_unreg: | 284 | unreg: |
251 | platform_device_unregister(i2c_dev); | 285 | platform_device_unregister(i2c_dev); |
252 | i2c_err: | 286 | err: |
253 | return ret; | 287 | return ret; |
254 | } | 288 | } |
289 | |||
255 | arch_initcall(fsl_i2c_of_init); | 290 | arch_initcall(fsl_i2c_of_init); |
256 | 291 | ||
257 | #ifdef CONFIG_PPC_83xx | 292 | #ifdef CONFIG_PPC_83xx |
@@ -267,51 +302,192 @@ static int __init mpc83xx_wdt_init(void) | |||
267 | 302 | ||
268 | if (!np) { | 303 | if (!np) { |
269 | ret = -ENODEV; | 304 | ret = -ENODEV; |
270 | goto mpc83xx_wdt_nodev; | 305 | goto nodev; |
271 | } | 306 | } |
272 | 307 | ||
273 | soc = of_find_node_by_type(NULL, "soc"); | 308 | soc = of_find_node_by_type(NULL, "soc"); |
274 | 309 | ||
275 | if (!soc) { | 310 | if (!soc) { |
276 | ret = -ENODEV; | 311 | ret = -ENODEV; |
277 | goto mpc83xx_wdt_nosoc; | 312 | goto nosoc; |
278 | } | 313 | } |
279 | 314 | ||
280 | freq = (unsigned int *)get_property(soc, "bus-frequency", NULL); | 315 | freq = (unsigned int *)get_property(soc, "bus-frequency", NULL); |
281 | if (!freq) { | 316 | if (!freq) { |
282 | ret = -ENODEV; | 317 | ret = -ENODEV; |
283 | goto mpc83xx_wdt_err; | 318 | goto err; |
284 | } | 319 | } |
285 | 320 | ||
286 | memset(&r, 0, sizeof(r)); | 321 | memset(&r, 0, sizeof(r)); |
287 | 322 | ||
288 | ret = of_address_to_resource(np, 0, &r); | 323 | ret = of_address_to_resource(np, 0, &r); |
289 | if (ret) | 324 | if (ret) |
290 | goto mpc83xx_wdt_err; | 325 | goto err; |
291 | 326 | ||
292 | dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1); | 327 | dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1); |
293 | if (IS_ERR(dev)) { | 328 | if (IS_ERR(dev)) { |
294 | ret = PTR_ERR(dev); | 329 | ret = PTR_ERR(dev); |
295 | goto mpc83xx_wdt_err; | 330 | goto err; |
296 | } | 331 | } |
297 | 332 | ||
298 | ret = platform_device_add_data(dev, freq, sizeof(int)); | 333 | ret = platform_device_add_data(dev, freq, sizeof(int)); |
299 | if (ret) | 334 | if (ret) |
300 | goto mpc83xx_wdt_unreg; | 335 | goto unreg; |
301 | 336 | ||
302 | of_node_put(soc); | 337 | of_node_put(soc); |
303 | of_node_put(np); | 338 | of_node_put(np); |
304 | 339 | ||
305 | return 0; | 340 | return 0; |
306 | 341 | ||
307 | mpc83xx_wdt_unreg: | 342 | unreg: |
308 | platform_device_unregister(dev); | 343 | platform_device_unregister(dev); |
309 | mpc83xx_wdt_err: | 344 | err: |
310 | of_node_put(soc); | 345 | of_node_put(soc); |
311 | mpc83xx_wdt_nosoc: | 346 | nosoc: |
312 | of_node_put(np); | 347 | of_node_put(np); |
313 | mpc83xx_wdt_nodev: | 348 | nodev: |
314 | return ret; | 349 | return ret; |
315 | } | 350 | } |
351 | |||
316 | arch_initcall(mpc83xx_wdt_init); | 352 | arch_initcall(mpc83xx_wdt_init); |
317 | #endif | 353 | #endif |
354 | |||
355 | static enum fsl_usb2_phy_modes determine_usb_phy(char * phy_type) | ||
356 | { | ||
357 | if (!phy_type) | ||
358 | return FSL_USB2_PHY_NONE; | ||
359 | if (!strcasecmp(phy_type, "ulpi")) | ||
360 | return FSL_USB2_PHY_ULPI; | ||
361 | if (!strcasecmp(phy_type, "utmi")) | ||
362 | return FSL_USB2_PHY_UTMI; | ||
363 | if (!strcasecmp(phy_type, "utmi_wide")) | ||
364 | return FSL_USB2_PHY_UTMI_WIDE; | ||
365 | if (!strcasecmp(phy_type, "serial")) | ||
366 | return FSL_USB2_PHY_SERIAL; | ||
367 | |||
368 | return FSL_USB2_PHY_NONE; | ||
369 | } | ||
370 | |||
371 | static int __init fsl_usb_of_init(void) | ||
372 | { | ||
373 | struct device_node *np; | ||
374 | unsigned int i; | ||
375 | struct platform_device *usb_dev; | ||
376 | int ret; | ||
377 | |||
378 | for (np = NULL, i = 0; | ||
379 | (np = of_find_compatible_node(np, "usb", "fsl-usb2-mph")) != NULL; | ||
380 | i++) { | ||
381 | struct resource r[2]; | ||
382 | struct fsl_usb2_platform_data usb_data; | ||
383 | unsigned char *prop = NULL; | ||
384 | |||
385 | memset(&r, 0, sizeof(r)); | ||
386 | memset(&usb_data, 0, sizeof(usb_data)); | ||
387 | |||
388 | ret = of_address_to_resource(np, 0, &r[0]); | ||
389 | if (ret) | ||
390 | goto err; | ||
391 | |||
392 | r[1].start = np->intrs[0].line; | ||
393 | r[1].end = np->intrs[0].line; | ||
394 | r[1].flags = IORESOURCE_IRQ; | ||
395 | |||
396 | usb_dev = | ||
397 | platform_device_register_simple("fsl-usb2-mph", i, r, 2); | ||
398 | if (IS_ERR(usb_dev)) { | ||
399 | ret = PTR_ERR(usb_dev); | ||
400 | goto err; | ||
401 | } | ||
402 | |||
403 | usb_dev->dev.coherent_dma_mask = 0xffffffffUL; | ||
404 | usb_dev->dev.dma_mask = &usb_dev->dev.coherent_dma_mask; | ||
405 | |||
406 | usb_data.operating_mode = FSL_USB2_MPH_HOST; | ||
407 | |||
408 | prop = get_property(np, "port0", NULL); | ||
409 | if (prop) | ||
410 | usb_data.port_enables |= FSL_USB2_PORT0_ENABLED; | ||
411 | |||
412 | prop = get_property(np, "port1", NULL); | ||
413 | if (prop) | ||
414 | usb_data.port_enables |= FSL_USB2_PORT1_ENABLED; | ||
415 | |||
416 | prop = get_property(np, "phy_type", NULL); | ||
417 | usb_data.phy_mode = determine_usb_phy(prop); | ||
418 | |||
419 | ret = | ||
420 | platform_device_add_data(usb_dev, &usb_data, | ||
421 | sizeof(struct | ||
422 | fsl_usb2_platform_data)); | ||
423 | if (ret) | ||
424 | goto unreg; | ||
425 | } | ||
426 | |||
427 | return 0; | ||
428 | |||
429 | unreg: | ||
430 | platform_device_unregister(usb_dev); | ||
431 | err: | ||
432 | return ret; | ||
433 | } | ||
434 | |||
435 | arch_initcall(fsl_usb_of_init); | ||
436 | |||
437 | static int __init fsl_usb_dr_of_init(void) | ||
438 | { | ||
439 | struct device_node *np; | ||
440 | unsigned int i; | ||
441 | struct platform_device *usb_dev; | ||
442 | int ret; | ||
443 | |||
444 | for (np = NULL, i = 0; | ||
445 | (np = of_find_compatible_node(np, "usb", "fsl-usb2-dr")) != NULL; | ||
446 | i++) { | ||
447 | struct resource r[2]; | ||
448 | struct fsl_usb2_platform_data usb_data; | ||
449 | unsigned char *prop = NULL; | ||
450 | |||
451 | memset(&r, 0, sizeof(r)); | ||
452 | memset(&usb_data, 0, sizeof(usb_data)); | ||
453 | |||
454 | ret = of_address_to_resource(np, 0, &r[0]); | ||
455 | if (ret) | ||
456 | goto err; | ||
457 | |||
458 | r[1].start = np->intrs[0].line; | ||
459 | r[1].end = np->intrs[0].line; | ||
460 | r[1].flags = IORESOURCE_IRQ; | ||
461 | |||
462 | usb_dev = | ||
463 | platform_device_register_simple("fsl-usb2-dr", i, r, 2); | ||
464 | if (IS_ERR(usb_dev)) { | ||
465 | ret = PTR_ERR(usb_dev); | ||
466 | goto err; | ||
467 | } | ||
468 | |||
469 | usb_dev->dev.coherent_dma_mask = 0xffffffffUL; | ||
470 | usb_dev->dev.dma_mask = &usb_dev->dev.coherent_dma_mask; | ||
471 | |||
472 | usb_data.operating_mode = FSL_USB2_DR_HOST; | ||
473 | |||
474 | prop = get_property(np, "phy_type", NULL); | ||
475 | usb_data.phy_mode = determine_usb_phy(prop); | ||
476 | |||
477 | ret = | ||
478 | platform_device_add_data(usb_dev, &usb_data, | ||
479 | sizeof(struct | ||
480 | fsl_usb2_platform_data)); | ||
481 | if (ret) | ||
482 | goto unreg; | ||
483 | } | ||
484 | |||
485 | return 0; | ||
486 | |||
487 | unreg: | ||
488 | platform_device_unregister(usb_dev); | ||
489 | err: | ||
490 | return ret; | ||
491 | } | ||
492 | |||
493 | arch_initcall(fsl_usb_dr_of_init); | ||
diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h index a7ce7da8785c..a60c9d18bb7f 100644 --- a/arch/powerpc/sysdev/ipic.h +++ b/arch/powerpc/sysdev/ipic.h | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * arch/ppc/kernel/ipic.h | ||
3 | * | ||
4 | * IPIC private definitions and structure. | 2 | * IPIC private definitions and structure. |
5 | * | 3 | * |
6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> | 4 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 7d02fa2a8990..4735b41c113c 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -191,6 +191,7 @@ Commands:\n\ | |||
191 | di dump instructions\n\ | 191 | di dump instructions\n\ |
192 | df dump float values\n\ | 192 | df dump float values\n\ |
193 | dd dump double values\n\ | 193 | dd dump double values\n\ |
194 | dr dump stream of raw bytes\n\ | ||
194 | e print exception information\n\ | 195 | e print exception information\n\ |
195 | f flush cache\n\ | 196 | f flush cache\n\ |
196 | la lookup symbol+offset of specified address\n\ | 197 | la lookup symbol+offset of specified address\n\ |
@@ -1938,6 +1939,28 @@ bsesc(void) | |||
1938 | return c; | 1939 | return c; |
1939 | } | 1940 | } |
1940 | 1941 | ||
1942 | static void xmon_rawdump (unsigned long adrs, long ndump) | ||
1943 | { | ||
1944 | long n, m, r, nr; | ||
1945 | unsigned char temp[16]; | ||
1946 | |||
1947 | for (n = ndump; n > 0;) { | ||
1948 | r = n < 16? n: 16; | ||
1949 | nr = mread(adrs, temp, r); | ||
1950 | adrs += nr; | ||
1951 | for (m = 0; m < r; ++m) { | ||
1952 | if (m < nr) | ||
1953 | printf("%.2x", temp[m]); | ||
1954 | else | ||
1955 | printf("%s", fault_chars[fault_type]); | ||
1956 | } | ||
1957 | n -= r; | ||
1958 | if (nr < r) | ||
1959 | break; | ||
1960 | } | ||
1961 | printf("\n"); | ||
1962 | } | ||
1963 | |||
1941 | #define isxdigit(c) (('0' <= (c) && (c) <= '9') \ | 1964 | #define isxdigit(c) (('0' <= (c) && (c) <= '9') \ |
1942 | || ('a' <= (c) && (c) <= 'f') \ | 1965 | || ('a' <= (c) && (c) <= 'f') \ |
1943 | || ('A' <= (c) && (c) <= 'F')) | 1966 | || ('A' <= (c) && (c) <= 'F')) |
@@ -1960,6 +1983,13 @@ dump(void) | |||
1960 | nidump = MAX_DUMP; | 1983 | nidump = MAX_DUMP; |
1961 | adrs += ppc_inst_dump(adrs, nidump, 1); | 1984 | adrs += ppc_inst_dump(adrs, nidump, 1); |
1962 | last_cmd = "di\n"; | 1985 | last_cmd = "di\n"; |
1986 | } else if (c == 'r') { | ||
1987 | scanhex(&ndump); | ||
1988 | if (ndump == 0) | ||
1989 | ndump = 64; | ||
1990 | xmon_rawdump(adrs, ndump); | ||
1991 | adrs += ndump; | ||
1992 | last_cmd = "dr\n"; | ||
1963 | } else { | 1993 | } else { |
1964 | scanhex(&ndump); | 1994 | scanhex(&ndump); |
1965 | if (ndump == 0) | 1995 | if (ndump == 0) |