diff options
-rw-r--r-- | arch/powerpc/Kconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/Makefile | 18 | ||||
-rw-r--r-- | arch/powerpc/kernel/dma_64.c (renamed from arch/ppc64/kernel/dma.c) | 0 | ||||
-rw-r--r-- | arch/powerpc/kernel/iomap.c (renamed from arch/ppc64/kernel/iomap.c) | 0 | ||||
-rw-r--r-- | arch/powerpc/kernel/iommu.c (renamed from arch/ppc64/kernel/iommu.c) | 0 | ||||
-rw-r--r-- | arch/powerpc/kernel/kprobes.c (renamed from arch/ppc64/kernel/kprobes.c) | 0 | ||||
-rw-r--r-- | arch/powerpc/kernel/machine_kexec_64.c (renamed from arch/ppc64/kernel/machine_kexec.c) | 0 | ||||
-rw-r--r-- | arch/powerpc/kernel/module_64.c (renamed from arch/ppc64/kernel/module.c) | 0 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_64.c (renamed from arch/ppc64/kernel/pci.c) | 0 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_direct_iommu.c (renamed from arch/ppc64/kernel/pci_direct_iommu.c) | 0 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_dn.c (renamed from arch/ppc64/kernel/pci_dn.c) | 0 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_iommu.c (renamed from arch/ppc64/kernel/pci_iommu.c) | 0 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/Makefile | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/hvconsole.c (renamed from arch/ppc64/kernel/hvconsole.c) | 0 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/hvcserver.c (renamed from arch/ppc64/kernel/hvcserver.c) | 0 | ||||
-rw-r--r-- | arch/ppc64/Kconfig | 520 | ||||
-rw-r--r-- | arch/ppc64/kernel/Makefile | 40 | ||||
-rw-r--r-- | arch/ppc64/kernel/asm-offsets.c | 195 | ||||
-rw-r--r-- | arch/ppc64/kernel/btext.c | 792 | ||||
-rw-r--r-- | arch/ppc64/kernel/head.S | 2007 | ||||
-rw-r--r-- | arch/ppc64/kernel/misc.S | 940 | ||||
-rw-r--r-- | arch/ppc64/kernel/ppc_ksyms.c | 76 | ||||
-rw-r--r-- | arch/ppc64/kernel/prom.c | 1956 | ||||
-rw-r--r-- | arch/ppc64/kernel/prom_init.c | 2051 | ||||
-rw-r--r-- | arch/ppc64/kernel/semaphore.c | 136 | ||||
-rw-r--r-- | arch/ppc64/kernel/vdso.c | 625 | ||||
-rw-r--r-- | arch/ppc64/kernel/vmlinux.lds.S | 151 | ||||
-rw-r--r-- | arch/ppc64/xmon/privinst.h | 64 | ||||
-rw-r--r-- | include/asm-ppc64/page.h | 328 |
29 files changed, 19 insertions, 9886 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index c523029674e6..c5c3f4213cd9 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -932,6 +932,7 @@ source "arch/powerpc/oprofile/Kconfig" | |||
932 | 932 | ||
933 | config KPROBES | 933 | config KPROBES |
934 | bool "Kprobes (EXPERIMENTAL)" | 934 | bool "Kprobes (EXPERIMENTAL)" |
935 | depends on PPC64 | ||
935 | help | 936 | help |
936 | Kprobes allows you to trap at almost any kernel address and | 937 | Kprobes allows you to trap at almost any kernel address and |
937 | execute a callback function. register_kprobe() establishes | 938 | execute a callback function. register_kprobe() establishes |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 046b4bf1f21e..4970e3721a84 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -49,12 +49,23 @@ extra-y += vmlinux.lds | |||
49 | obj-y += process.o init_task.o time.o \ | 49 | obj-y += process.o init_task.o time.o \ |
50 | prom.o traps.o setup-common.o | 50 | prom.o traps.o setup-common.o |
51 | obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o | 51 | obj-$(CONFIG_PPC32) += entry_32.o setup_32.o misc_32.o systbl.o |
52 | obj-$(CONFIG_PPC64) += misc_64.o | 52 | obj-$(CONFIG_PPC64) += misc_64.o dma_64.o iommu.o |
53 | obj-$(CONFIG_PPC_OF) += prom_init.o | 53 | obj-$(CONFIG_PPC_OF) += prom_init.o |
54 | obj-$(CONFIG_MODULES) += ppc_ksyms.o | 54 | obj-$(CONFIG_MODULES) += ppc_ksyms.o |
55 | obj-$(CONFIG_BOOTX_TEXT) += btext.o | 55 | obj-$(CONFIG_BOOTX_TEXT) += btext.o |
56 | obj-$(CONFIG_6xx) += idle_6xx.o | 56 | obj-$(CONFIG_6xx) += idle_6xx.o |
57 | obj-$(CONFIG_SMP) += smp.o | 57 | obj-$(CONFIG_SMP) += smp.o |
58 | obj-$(CONFIG_KPROBES) += kprobes.o | ||
59 | |||
60 | module-$(CONFIG_PPC64) += module_64.o | ||
61 | obj-$(CONFIG_MODULES) += $(module-y) | ||
62 | |||
63 | pci64-$(CONFIG_PPC64) += pci_64.o pci_dn.o pci_iommu.o \ | ||
64 | pci_direct_iommu.o iomap.o | ||
65 | obj-$(CONFIG_PCI) += $(pci64-y) | ||
66 | |||
67 | kexec64-$(CONFIG_PPC64) += machine_kexec_64.o | ||
68 | obj-$(CONFIG_KEXEC) += $(kexec64-y) | ||
58 | 69 | ||
59 | ifeq ($(CONFIG_PPC_ISERIES),y) | 70 | ifeq ($(CONFIG_PPC_ISERIES),y) |
60 | $(obj)/head_64.o: $(obj)/lparmap.s | 71 | $(obj)/head_64.o: $(obj)/lparmap.s |
@@ -62,11 +73,8 @@ AFLAGS_head_64.o += -I$(obj) | |||
62 | endif | 73 | endif |
63 | 74 | ||
64 | else | 75 | else |
65 | # stuff used from here for ARCH=ppc or ARCH=ppc64 | 76 | # stuff used from here for ARCH=ppc |
66 | smpobj-$(CONFIG_SMP) += smp.o | 77 | smpobj-$(CONFIG_SMP) += smp.o |
67 | obj-$(CONFIG_PPC64) += traps.o process.o init_task.o time.o \ | ||
68 | setup-common.o $(smpobj-y) | ||
69 | |||
70 | 78 | ||
71 | endif | 79 | endif |
72 | 80 | ||
diff --git a/arch/ppc64/kernel/dma.c b/arch/powerpc/kernel/dma_64.c index 7c3419656ccc..7c3419656ccc 100644 --- a/arch/ppc64/kernel/dma.c +++ b/arch/powerpc/kernel/dma_64.c | |||
diff --git a/arch/ppc64/kernel/iomap.c b/arch/powerpc/kernel/iomap.c index 6160c8dbb7c5..6160c8dbb7c5 100644 --- a/arch/ppc64/kernel/iomap.c +++ b/arch/powerpc/kernel/iomap.c | |||
diff --git a/arch/ppc64/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 4d9b4388918b..4d9b4388918b 100644 --- a/arch/ppc64/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 511af54e6230..511af54e6230 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
diff --git a/arch/ppc64/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec_64.c index 97c51e452be7..97c51e452be7 100644 --- a/arch/ppc64/kernel/machine_kexec.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
diff --git a/arch/ppc64/kernel/module.c b/arch/powerpc/kernel/module_64.c index 928b8581fcb0..928b8581fcb0 100644 --- a/arch/ppc64/kernel/module.c +++ b/arch/powerpc/kernel/module_64.c | |||
diff --git a/arch/ppc64/kernel/pci.c b/arch/powerpc/kernel/pci_64.c index 3cef1b8f57f0..3cef1b8f57f0 100644 --- a/arch/ppc64/kernel/pci.c +++ b/arch/powerpc/kernel/pci_64.c | |||
diff --git a/arch/ppc64/kernel/pci_direct_iommu.c b/arch/powerpc/kernel/pci_direct_iommu.c index e1a32f802c0b..e1a32f802c0b 100644 --- a/arch/ppc64/kernel/pci_direct_iommu.c +++ b/arch/powerpc/kernel/pci_direct_iommu.c | |||
diff --git a/arch/ppc64/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 12c4c9e9bbc7..12c4c9e9bbc7 100644 --- a/arch/ppc64/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c | |||
diff --git a/arch/ppc64/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c index bdf15dbbf4f0..bdf15dbbf4f0 100644 --- a/arch/ppc64/kernel/pci_iommu.c +++ b/arch/powerpc/kernel/pci_iommu.c | |||
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index e7ca5b1f591e..06d5ef501218 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -4,4 +4,7 @@ obj-$(CONFIG_SMP) += smp.o | |||
4 | obj-$(CONFIG_IBMVIO) += vio.o | 4 | obj-$(CONFIG_IBMVIO) += vio.o |
5 | obj-$(CONFIG_XICS) += xics.o | 5 | obj-$(CONFIG_XICS) += xics.o |
6 | obj-$(CONFIG_SCANLOG) += scanlog.o | 6 | obj-$(CONFIG_SCANLOG) += scanlog.o |
7 | obj-$(CONFIG_EEH) += eeh.o eeh_event.o | 7 | obj-$(CONFIG_EEH) += eeh.o eeh_event.o |
8 | |||
9 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | ||
10 | obj-$(CONFIG_HVCS) += hvcserver.o | ||
diff --git a/arch/ppc64/kernel/hvconsole.c b/arch/powerpc/platforms/pseries/hvconsole.c index 138e128a3886..138e128a3886 100644 --- a/arch/ppc64/kernel/hvconsole.c +++ b/arch/powerpc/platforms/pseries/hvconsole.c | |||
diff --git a/arch/ppc64/kernel/hvcserver.c b/arch/powerpc/platforms/pseries/hvcserver.c index 4d584172055a..4d584172055a 100644 --- a/arch/ppc64/kernel/hvcserver.c +++ b/arch/powerpc/platforms/pseries/hvcserver.c | |||
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig deleted file mode 100644 index 9d10c12e87fe..000000000000 --- a/arch/ppc64/Kconfig +++ /dev/null | |||
@@ -1,520 +0,0 @@ | |||
1 | # | ||
2 | # For a description of the syntax of this configuration file, | ||
3 | # see Documentation/kbuild/kconfig-language.txt. | ||
4 | # | ||
5 | |||
6 | config 64BIT | ||
7 | def_bool y | ||
8 | |||
9 | config MMU | ||
10 | bool | ||
11 | default y | ||
12 | |||
13 | config PPC_STD_MMU | ||
14 | def_bool y | ||
15 | |||
16 | config UID16 | ||
17 | bool | ||
18 | |||
19 | config RWSEM_GENERIC_SPINLOCK | ||
20 | bool | ||
21 | |||
22 | config RWSEM_XCHGADD_ALGORITHM | ||
23 | bool | ||
24 | default y | ||
25 | |||
26 | config GENERIC_CALIBRATE_DELAY | ||
27 | bool | ||
28 | default y | ||
29 | |||
30 | config GENERIC_ISA_DMA | ||
31 | bool | ||
32 | default y | ||
33 | |||
34 | config EARLY_PRINTK | ||
35 | bool | ||
36 | default y | ||
37 | |||
38 | config COMPAT | ||
39 | bool | ||
40 | default y | ||
41 | |||
42 | config SCHED_NO_NO_OMIT_FRAME_POINTER | ||
43 | bool | ||
44 | default y | ||
45 | |||
46 | config ARCH_MAY_HAVE_PC_FDC | ||
47 | bool | ||
48 | default y | ||
49 | |||
50 | config PPC_STD_MMU | ||
51 | bool | ||
52 | default y | ||
53 | |||
54 | # We optimistically allocate largepages from the VM, so make the limit | ||
55 | # large enough (16MB). This badly named config option is actually | ||
56 | # max order + 1 | ||
57 | config FORCE_MAX_ZONEORDER | ||
58 | int | ||
59 | default "9" if PPC_64K_PAGES | ||
60 | default "13" | ||
61 | |||
62 | source "init/Kconfig" | ||
63 | |||
64 | config SYSVIPC_COMPAT | ||
65 | bool | ||
66 | depends on COMPAT && SYSVIPC | ||
67 | default y | ||
68 | |||
69 | menu "Platform support" | ||
70 | |||
71 | choice | ||
72 | prompt "Platform Type" | ||
73 | default PPC_MULTIPLATFORM | ||
74 | |||
75 | config PPC_ISERIES | ||
76 | bool "IBM Legacy iSeries" | ||
77 | |||
78 | config PPC_MULTIPLATFORM | ||
79 | bool "Generic" | ||
80 | |||
81 | endchoice | ||
82 | |||
83 | config PPC_PSERIES | ||
84 | depends on PPC_MULTIPLATFORM | ||
85 | bool " IBM pSeries & new iSeries" | ||
86 | default y | ||
87 | |||
88 | config PPC_BPA | ||
89 | bool " Broadband Processor Architecture" | ||
90 | depends on PPC_MULTIPLATFORM | ||
91 | |||
92 | config PPC_PMAC | ||
93 | depends on PPC_MULTIPLATFORM | ||
94 | bool " Apple G5 based machines" | ||
95 | default y | ||
96 | select U3_DART | ||
97 | select GENERIC_TBSYNC | ||
98 | |||
99 | config PPC_MAPLE | ||
100 | depends on PPC_MULTIPLATFORM | ||
101 | bool " Maple 970FX Evaluation Board" | ||
102 | select U3_DART | ||
103 | select MPIC_BROKEN_U3 | ||
104 | select GENERIC_TBSYNC | ||
105 | default n | ||
106 | help | ||
107 | This option enables support for the Maple 970FX Evaluation Board. | ||
108 | For more informations, refer to <http://www.970eval.com> | ||
109 | |||
110 | config PPC | ||
111 | bool | ||
112 | default y | ||
113 | |||
114 | config PPC64 | ||
115 | bool | ||
116 | default y | ||
117 | |||
118 | config PPC_OF | ||
119 | depends on PPC_MULTIPLATFORM | ||
120 | bool | ||
121 | default y | ||
122 | |||
123 | config XICS | ||
124 | depends on PPC_PSERIES | ||
125 | bool | ||
126 | default y | ||
127 | |||
128 | config MPIC | ||
129 | depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE | ||
130 | bool | ||
131 | default y | ||
132 | |||
133 | config PPC_I8259 | ||
134 | depends on PPC_PSERIES | ||
135 | bool | ||
136 | default y | ||
137 | |||
138 | config BPA_IIC | ||
139 | depends on PPC_BPA | ||
140 | bool | ||
141 | default y | ||
142 | |||
143 | # VMX is pSeries only for now until somebody writes the iSeries | ||
144 | # exception vectors for it | ||
145 | config ALTIVEC | ||
146 | bool "Support for VMX (Altivec) vector unit" | ||
147 | depends on PPC_MULTIPLATFORM | ||
148 | default y | ||
149 | |||
150 | config PPC_SPLPAR | ||
151 | depends on PPC_PSERIES | ||
152 | bool "Support for shared-processor logical partitions" | ||
153 | default n | ||
154 | help | ||
155 | Enabling this option will make the kernel run more efficiently | ||
156 | on logically-partitioned pSeries systems which use shared | ||
157 | processors, that is, which share physical processors between | ||
158 | two or more partitions. | ||
159 | |||
160 | config KEXEC | ||
161 | bool "kexec system call (EXPERIMENTAL)" | ||
162 | depends on PPC_MULTIPLATFORM && EXPERIMENTAL | ||
163 | help | ||
164 | kexec is a system call that implements the ability to shutdown your | ||
165 | current kernel, and to start another kernel. It is like a reboot | ||
166 | but it is indepedent of the system firmware. And like a reboot | ||
167 | you can start any kernel with it, not just Linux. | ||
168 | |||
169 | The name comes from the similiarity to the exec system call. | ||
170 | |||
171 | It is an ongoing process to be certain the hardware in a machine | ||
172 | is properly shutdown, so do not be surprised if this code does not | ||
173 | initially work for you. It may help to enable device hotplugging | ||
174 | support. As of this writing the exact hardware interface is | ||
175 | strongly in flux, so no good recommendation can be made. | ||
176 | |||
177 | source "drivers/cpufreq/Kconfig" | ||
178 | |||
179 | config CPU_FREQ_PMAC64 | ||
180 | bool "Support for some Apple G5s" | ||
181 | depends on CPU_FREQ && PMAC_SMU && PPC64 | ||
182 | select CPU_FREQ_TABLE | ||
183 | help | ||
184 | This adds support for frequency switching on Apple iMac G5, | ||
185 | and some of the more recent desktop G5 machines as well. | ||
186 | |||
187 | config IBMVIO | ||
188 | depends on PPC_PSERIES || PPC_ISERIES | ||
189 | bool | ||
190 | default y | ||
191 | |||
192 | config U3_DART | ||
193 | bool | ||
194 | depends on PPC_MULTIPLATFORM | ||
195 | default n | ||
196 | |||
197 | config MPIC_BROKEN_U3 | ||
198 | bool | ||
199 | depends on PPC_MAPLE | ||
200 | default y | ||
201 | |||
202 | config GENERIC_TBSYNC | ||
203 | def_bool n | ||
204 | |||
205 | config PPC_PMAC64 | ||
206 | bool | ||
207 | depends on PPC_PMAC | ||
208 | default y | ||
209 | |||
210 | config BOOTX_TEXT | ||
211 | bool "Support for early boot text console" | ||
212 | depends PPC_OF | ||
213 | help | ||
214 | Say Y here to see progress messages from the boot firmware in text | ||
215 | mode. Requires an Open Firmware compatible video card. | ||
216 | |||
217 | config POWER4 | ||
218 | def_bool y | ||
219 | |||
220 | config PPC_FPU | ||
221 | def_bool y | ||
222 | |||
223 | config POWER4_ONLY | ||
224 | bool "Optimize for POWER4" | ||
225 | default n | ||
226 | ---help--- | ||
227 | Cause the compiler to optimize for POWER4 processors. The resulting | ||
228 | binary will not work on POWER3 or RS64 processors when compiled with | ||
229 | binutils 2.15 or later. | ||
230 | |||
231 | config IOMMU_VMERGE | ||
232 | bool "Enable IOMMU virtual merging (EXPERIMENTAL)" | ||
233 | depends on EXPERIMENTAL | ||
234 | default n | ||
235 | help | ||
236 | Cause IO segments sent to a device for DMA to be merged virtually | ||
237 | by the IOMMU when they happen to have been allocated contiguously. | ||
238 | This doesn't add pressure to the IOMMU allocator. However, some | ||
239 | drivers don't support getting large merged segments coming back | ||
240 | from *_map_sg(). Say Y if you know the drivers you are using are | ||
241 | properly handling this case. | ||
242 | |||
243 | config SMP | ||
244 | bool "Symmetric multi-processing support" | ||
245 | ---help--- | ||
246 | This enables support for systems with more than one CPU. If you have | ||
247 | a system with only one CPU, say N. If you have a system with more | ||
248 | than one CPU, say Y. | ||
249 | |||
250 | If you say N here, the kernel will run on single and multiprocessor | ||
251 | machines, but will use only one CPU of a multiprocessor machine. If | ||
252 | you say Y here, the kernel will run on single-processor machines. | ||
253 | On a single-processor machine, the kernel will run faster if you say | ||
254 | N here. | ||
255 | |||
256 | If you don't know what to do here, say Y. | ||
257 | |||
258 | config NR_CPUS | ||
259 | int "Maximum number of CPUs (2-128)" | ||
260 | range 2 128 | ||
261 | depends on SMP | ||
262 | default "32" | ||
263 | |||
264 | config HMT | ||
265 | bool "Hardware multithreading" | ||
266 | depends on SMP && PPC_PSERIES && BROKEN | ||
267 | help | ||
268 | This option enables hardware multithreading on RS64 cpus. | ||
269 | pSeries systems p620 and p660 have such a cpu type. | ||
270 | |||
271 | config NUMA | ||
272 | bool "NUMA support" | ||
273 | default y if SMP && PPC_PSERIES | ||
274 | |||
275 | config ARCH_SELECT_MEMORY_MODEL | ||
276 | def_bool y | ||
277 | |||
278 | config ARCH_FLATMEM_ENABLE | ||
279 | def_bool y | ||
280 | depends on !NUMA | ||
281 | |||
282 | config ARCH_SPARSEMEM_ENABLE | ||
283 | def_bool y | ||
284 | |||
285 | config ARCH_SPARSEMEM_DEFAULT | ||
286 | def_bool y | ||
287 | depends on NUMA | ||
288 | |||
289 | source "mm/Kconfig" | ||
290 | |||
291 | config HAVE_ARCH_EARLY_PFN_TO_NID | ||
292 | def_bool y | ||
293 | depends on NEED_MULTIPLE_NODES | ||
294 | |||
295 | config ARCH_MEMORY_PROBE | ||
296 | def_bool y | ||
297 | depends on MEMORY_HOTPLUG | ||
298 | |||
299 | # Some NUMA nodes have memory ranges that span | ||
300 | # other nodes. Even though a pfn is valid and | ||
301 | # between a node's start and end pfns, it may not | ||
302 | # reside on that node. | ||
303 | # | ||
304 | # This is a relatively temporary hack that should | ||
305 | # be able to go away when sparsemem is fully in | ||
306 | # place | ||
307 | config NODES_SPAN_OTHER_NODES | ||
308 | def_bool y | ||
309 | depends on NEED_MULTIPLE_NODES | ||
310 | |||
311 | config PPC_64K_PAGES | ||
312 | bool "64k page size" | ||
313 | help | ||
314 | This option changes the kernel logical page size to 64k. On machines | ||
315 | without processor support for 64k pages, the kernel will simulate | ||
316 | them by loading each individual 4k page on demand transparently, | ||
317 | while on hardware with such support, it will be used to map | ||
318 | normal application pages. | ||
319 | |||
320 | config SCHED_SMT | ||
321 | bool "SMT (Hyperthreading) scheduler support" | ||
322 | depends on SMP | ||
323 | default off | ||
324 | help | ||
325 | SMT scheduler support improves the CPU scheduler's decision making | ||
326 | when dealing with POWER5 cpus at a cost of slightly increased | ||
327 | overhead in some places. If unsure say N here. | ||
328 | |||
329 | source "kernel/Kconfig.preempt" | ||
330 | source kernel/Kconfig.hz | ||
331 | |||
332 | config EEH | ||
333 | bool "PCI Extended Error Handling (EEH)" if EMBEDDED | ||
334 | depends on PPC_PSERIES | ||
335 | default y if !EMBEDDED | ||
336 | |||
337 | # | ||
338 | # Use the generic interrupt handling code in kernel/irq/: | ||
339 | # | ||
340 | config GENERIC_HARDIRQS | ||
341 | bool | ||
342 | default y | ||
343 | |||
344 | config PPC_RTAS | ||
345 | bool | ||
346 | depends on PPC_PSERIES || PPC_BPA | ||
347 | default y | ||
348 | |||
349 | config RTAS_ERROR_LOGGING | ||
350 | bool | ||
351 | depends on PPC_RTAS | ||
352 | default y | ||
353 | |||
354 | config RTAS_PROC | ||
355 | bool "Proc interface to RTAS" | ||
356 | depends on PPC_RTAS | ||
357 | default y | ||
358 | |||
359 | config RTAS_FLASH | ||
360 | tristate "Firmware flash interface" | ||
361 | depends on RTAS_PROC | ||
362 | |||
363 | config SCANLOG | ||
364 | tristate "Scanlog dump interface" | ||
365 | depends on RTAS_PROC && PPC_PSERIES | ||
366 | |||
367 | config LPARCFG | ||
368 | tristate "LPAR Configuration Data" | ||
369 | depends on PPC_PSERIES || PPC_ISERIES | ||
370 | help | ||
371 | Provide system capacity information via human readable | ||
372 | <key word>=<value> pairs through a /proc/ppc64/lparcfg interface. | ||
373 | |||
374 | config SECCOMP | ||
375 | bool "Enable seccomp to safely compute untrusted bytecode" | ||
376 | depends on PROC_FS | ||
377 | default y | ||
378 | help | ||
379 | This kernel feature is useful for number crunching applications | ||
380 | that may need to compute untrusted bytecode during their | ||
381 | execution. By using pipes or other transports made available to | ||
382 | the process as file descriptors supporting the read/write | ||
383 | syscalls, it's possible to isolate those applications in | ||
384 | their own address space using seccomp. Once seccomp is | ||
385 | enabled via /proc/<pid>/seccomp, it cannot be disabled | ||
386 | and the task is only allowed to execute a few safe syscalls | ||
387 | defined by each seccomp mode. | ||
388 | |||
389 | If unsure, say Y. Only embedded should say N here. | ||
390 | |||
391 | source "fs/Kconfig.binfmt" | ||
392 | |||
393 | config HOTPLUG_CPU | ||
394 | bool "Support for hot-pluggable CPUs" | ||
395 | depends on SMP && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC) | ||
396 | select HOTPLUG | ||
397 | ---help--- | ||
398 | Say Y here to be able to turn CPUs off and on. | ||
399 | |||
400 | Say N if you are unsure. | ||
401 | |||
402 | config PROC_DEVICETREE | ||
403 | bool "Support for Open Firmware device tree in /proc" | ||
404 | help | ||
405 | This option adds a device-tree directory under /proc which contains | ||
406 | an image of the device tree that the kernel copies from Open | ||
407 | Firmware. If unsure, say Y here. | ||
408 | |||
409 | config CMDLINE_BOOL | ||
410 | bool "Default bootloader kernel arguments" | ||
411 | depends on !PPC_ISERIES | ||
412 | |||
413 | config CMDLINE | ||
414 | string "Initial kernel command string" | ||
415 | depends on CMDLINE_BOOL | ||
416 | default "console=ttyS0,9600 console=tty0 root=/dev/sda2" | ||
417 | help | ||
418 | On some platforms, there is currently no way for the boot loader to | ||
419 | pass arguments to the kernel. For these platforms, you can supply | ||
420 | some command-line options at build time by entering them here. In | ||
421 | most cases you will need to specify the root device here. | ||
422 | |||
423 | endmenu | ||
424 | |||
425 | config ISA_DMA_API | ||
426 | bool | ||
427 | default y | ||
428 | |||
429 | menu "Bus Options" | ||
430 | |||
431 | config ISA | ||
432 | bool | ||
433 | help | ||
434 | Find out whether you have ISA slots on your motherboard. ISA is the | ||
435 | name of a bus system, i.e. the way the CPU talks to the other stuff | ||
436 | inside your box. If you have an Apple machine, say N here; if you | ||
437 | have an IBM RS/6000 or pSeries machine or a PReP machine, say Y. If | ||
438 | you have an embedded board, consult your board documentation. | ||
439 | |||
440 | config SBUS | ||
441 | bool | ||
442 | |||
443 | config MCA | ||
444 | bool | ||
445 | |||
446 | config EISA | ||
447 | bool | ||
448 | |||
449 | config PCI | ||
450 | bool "support for PCI devices" if (EMBEDDED && PPC_ISERIES) | ||
451 | default y | ||
452 | help | ||
453 | Find out whether your system includes a PCI bus. PCI is the name of | ||
454 | a bus system, i.e. the way the CPU talks to the other stuff inside | ||
455 | your box. If you say Y here, the kernel will include drivers and | ||
456 | infrastructure code to support PCI bus devices. | ||
457 | |||
458 | config PCI_DOMAINS | ||
459 | bool | ||
460 | default PCI | ||
461 | |||
462 | source "drivers/pci/Kconfig" | ||
463 | |||
464 | source "drivers/pcmcia/Kconfig" | ||
465 | |||
466 | source "drivers/pci/hotplug/Kconfig" | ||
467 | |||
468 | endmenu | ||
469 | |||
470 | source "net/Kconfig" | ||
471 | |||
472 | source "drivers/Kconfig" | ||
473 | |||
474 | source "fs/Kconfig" | ||
475 | |||
476 | menu "iSeries device drivers" | ||
477 | depends on PPC_ISERIES | ||
478 | |||
479 | config VIOCONS | ||
480 | tristate "iSeries Virtual Console Support" | ||
481 | |||
482 | config VIODASD | ||
483 | tristate "iSeries Virtual I/O disk support" | ||
484 | help | ||
485 | If you are running on an iSeries system and you want to use | ||
486 | virtual disks created and managed by OS/400, say Y. | ||
487 | |||
488 | config VIOCD | ||
489 | tristate "iSeries Virtual I/O CD support" | ||
490 | help | ||
491 | If you are running Linux on an IBM iSeries system and you want to | ||
492 | read a CD drive owned by OS/400, say Y here. | ||
493 | |||
494 | config VIOTAPE | ||
495 | tristate "iSeries Virtual Tape Support" | ||
496 | help | ||
497 | If you are running Linux on an iSeries system and you want Linux | ||
498 | to read and/or write a tape drive owned by OS/400, say Y here. | ||
499 | |||
500 | endmenu | ||
501 | |||
502 | config VIOPATH | ||
503 | bool | ||
504 | depends on VIOCONS || VIODASD || VIOCD || VIOTAPE || VETH | ||
505 | default y | ||
506 | |||
507 | source "arch/powerpc/oprofile/Kconfig" | ||
508 | |||
509 | source "arch/ppc64/Kconfig.debug" | ||
510 | |||
511 | source "security/Kconfig" | ||
512 | |||
513 | config KEYS_COMPAT | ||
514 | bool | ||
515 | depends on COMPAT && KEYS | ||
516 | default y | ||
517 | |||
518 | source "crypto/Kconfig" | ||
519 | |||
520 | source "lib/Kconfig" | ||
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile index d0edea503c49..e876c213f5ce 100644 --- a/arch/ppc64/kernel/Makefile +++ b/arch/ppc64/kernel/Makefile | |||
@@ -2,44 +2,6 @@ | |||
2 | # Makefile for the linux ppc64 kernel. | 2 | # Makefile for the linux ppc64 kernel. |
3 | # | 3 | # |
4 | 4 | ||
5 | ifneq ($(CONFIG_PPC_MERGE),y) | 5 | obj-y += idle.o align.o |
6 | |||
7 | EXTRA_CFLAGS += -mno-minimal-toc | ||
8 | extra-y := head.o vmlinux.lds | ||
9 | |||
10 | obj-y := misc.o prom.o | ||
11 | |||
12 | endif | ||
13 | |||
14 | obj-y += idle.o dma.o \ | ||
15 | align.o \ | ||
16 | iommu.o | ||
17 | |||
18 | pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o | ||
19 | |||
20 | obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y) | ||
21 | 6 | ||
22 | obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o | 7 | obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o |
23 | ifneq ($(CONFIG_PPC_MERGE),y) | ||
24 | obj-$(CONFIG_PPC_MULTIPLATFORM) += prom_init.o | ||
25 | endif | ||
26 | |||
27 | obj-$(CONFIG_KEXEC) += machine_kexec.o | ||
28 | obj-$(CONFIG_MODULES) += module.o | ||
29 | ifneq ($(CONFIG_PPC_MERGE),y) | ||
30 | obj-$(CONFIG_MODULES) += ppc_ksyms.o | ||
31 | endif | ||
32 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | ||
33 | ifneq ($(CONFIG_PPC_MERGE),y) | ||
34 | obj-$(CONFIG_BOOTX_TEXT) += btext.o | ||
35 | endif | ||
36 | obj-$(CONFIG_HVCS) += hvcserver.o | ||
37 | |||
38 | obj-$(CONFIG_KPROBES) += kprobes.o | ||
39 | |||
40 | ifneq ($(CONFIG_PPC_MERGE),y) | ||
41 | ifeq ($(CONFIG_PPC_ISERIES),y) | ||
42 | arch/ppc64/kernel/head.o: arch/powerpc/kernel/lparmap.s | ||
43 | AFLAGS_head.o += -Iarch/powerpc/kernel | ||
44 | endif | ||
45 | endif | ||
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c deleted file mode 100644 index 84ab5c18ef52..000000000000 --- a/arch/ppc64/kernel/asm-offsets.c +++ /dev/null | |||
@@ -1,195 +0,0 @@ | |||
1 | /* | ||
2 | * This program is used to generate definitions needed by | ||
3 | * assembly language modules. | ||
4 | * | ||
5 | * We use the technique used in the OSF Mach kernel code: | ||
6 | * generate asm statements containing #defines, | ||
7 | * compile this file to assembler, and then extract the | ||
8 | * #defines from the assembly-language output. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * as published by the Free Software Foundation; either version | ||
13 | * 2 of the License, or (at your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/config.h> | ||
17 | #include <linux/signal.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/string.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/mman.h> | ||
24 | #include <linux/mm.h> | ||
25 | #include <linux/time.h> | ||
26 | #include <linux/hardirq.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/page.h> | ||
29 | #include <asm/pgtable.h> | ||
30 | #include <asm/processor.h> | ||
31 | |||
32 | #include <asm/paca.h> | ||
33 | #include <asm/lppaca.h> | ||
34 | #include <asm/iseries/hv_lp_event.h> | ||
35 | #include <asm/rtas.h> | ||
36 | #include <asm/cputable.h> | ||
37 | #include <asm/cache.h> | ||
38 | #include <asm/systemcfg.h> | ||
39 | #include <asm/compat.h> | ||
40 | |||
41 | #define DEFINE(sym, val) \ | ||
42 | asm volatile("\n->" #sym " %0 " #val : : "i" (val)) | ||
43 | |||
44 | #define BLANK() asm volatile("\n->" : : ) | ||
45 | |||
46 | int main(void) | ||
47 | { | ||
48 | /* thread struct on stack */ | ||
49 | DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); | ||
50 | DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); | ||
51 | DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror)); | ||
52 | |||
53 | /* task_struct->thread */ | ||
54 | DEFINE(THREAD, offsetof(struct task_struct, thread)); | ||
55 | DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); | ||
56 | DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); | ||
57 | DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); | ||
58 | DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr)); | ||
59 | DEFINE(KSP, offsetof(struct thread_struct, ksp)); | ||
60 | DEFINE(KSP_VSID, offsetof(struct thread_struct, ksp_vsid)); | ||
61 | |||
62 | #ifdef CONFIG_ALTIVEC | ||
63 | DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0])); | ||
64 | DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave)); | ||
65 | DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr)); | ||
66 | DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr)); | ||
67 | #endif /* CONFIG_ALTIVEC */ | ||
68 | DEFINE(MM, offsetof(struct task_struct, mm)); | ||
69 | DEFINE(AUDITCONTEXT, offsetof(struct task_struct, audit_context)); | ||
70 | |||
71 | DEFINE(DCACHEL1LINESIZE, offsetof(struct ppc64_caches, dline_size)); | ||
72 | DEFINE(DCACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_dline_size)); | ||
73 | DEFINE(DCACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, dlines_per_page)); | ||
74 | DEFINE(ICACHEL1LINESIZE, offsetof(struct ppc64_caches, iline_size)); | ||
75 | DEFINE(ICACHEL1LOGLINESIZE, offsetof(struct ppc64_caches, log_iline_size)); | ||
76 | DEFINE(ICACHEL1LINESPERPAGE, offsetof(struct ppc64_caches, ilines_per_page)); | ||
77 | DEFINE(PLATFORM_LPAR, PLATFORM_LPAR); | ||
78 | |||
79 | /* paca */ | ||
80 | DEFINE(PACA_SIZE, sizeof(struct paca_struct)); | ||
81 | DEFINE(PACAPACAINDEX, offsetof(struct paca_struct, paca_index)); | ||
82 | DEFINE(PACAPROCSTART, offsetof(struct paca_struct, cpu_start)); | ||
83 | DEFINE(PACAKSAVE, offsetof(struct paca_struct, kstack)); | ||
84 | DEFINE(PACACURRENT, offsetof(struct paca_struct, __current)); | ||
85 | DEFINE(PACASAVEDMSR, offsetof(struct paca_struct, saved_msr)); | ||
86 | DEFINE(PACASTABREAL, offsetof(struct paca_struct, stab_real)); | ||
87 | DEFINE(PACASTABVIRT, offsetof(struct paca_struct, stab_addr)); | ||
88 | DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr)); | ||
89 | DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1)); | ||
90 | DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc)); | ||
91 | DEFINE(PACAPROCENABLED, offsetof(struct paca_struct, proc_enabled)); | ||
92 | DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); | ||
93 | DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); | ||
94 | DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); | ||
95 | #ifdef CONFIG_PPC_64K_PAGES | ||
96 | DEFINE(PACAPGDIR, offsetof(struct paca_struct, pgdir)); | ||
97 | #endif | ||
98 | #ifdef CONFIG_HUGETLB_PAGE | ||
99 | DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); | ||
100 | DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); | ||
101 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
102 | DEFINE(PACADEFAULTDECR, offsetof(struct paca_struct, default_decr)); | ||
103 | DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen)); | ||
104 | DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); | ||
105 | DEFINE(PACA_EXSLB, offsetof(struct paca_struct, exslb)); | ||
106 | DEFINE(PACA_EXDSI, offsetof(struct paca_struct, exdsi)); | ||
107 | DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); | ||
108 | DEFINE(PACALPPACA, offsetof(struct paca_struct, lppaca)); | ||
109 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); | ||
110 | DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); | ||
111 | DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1)); | ||
112 | DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int)); | ||
113 | DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int)); | ||
114 | |||
115 | /* RTAS */ | ||
116 | DEFINE(RTASBASE, offsetof(struct rtas_t, base)); | ||
117 | DEFINE(RTASENTRY, offsetof(struct rtas_t, entry)); | ||
118 | |||
119 | /* Interrupt register frame */ | ||
120 | DEFINE(STACK_FRAME_OVERHEAD, STACK_FRAME_OVERHEAD); | ||
121 | |||
122 | DEFINE(SWITCH_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs)); | ||
123 | |||
124 | /* 288 = # of volatile regs, int & fp, for leaf routines */ | ||
125 | /* which do not stack a frame. See the PPC64 ABI. */ | ||
126 | DEFINE(INT_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 288); | ||
127 | /* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */ | ||
128 | DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); | ||
129 | DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16); | ||
130 | DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0])); | ||
131 | DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1])); | ||
132 | DEFINE(GPR2, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[2])); | ||
133 | DEFINE(GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[3])); | ||
134 | DEFINE(GPR4, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[4])); | ||
135 | DEFINE(GPR5, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[5])); | ||
136 | DEFINE(GPR6, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[6])); | ||
137 | DEFINE(GPR7, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[7])); | ||
138 | DEFINE(GPR8, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[8])); | ||
139 | DEFINE(GPR9, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[9])); | ||
140 | DEFINE(GPR10, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[10])); | ||
141 | DEFINE(GPR11, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[11])); | ||
142 | DEFINE(GPR12, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[12])); | ||
143 | DEFINE(GPR13, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[13])); | ||
144 | /* | ||
145 | * Note: these symbols include _ because they overlap with special | ||
146 | * register names | ||
147 | */ | ||
148 | DEFINE(_NIP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, nip)); | ||
149 | DEFINE(_MSR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, msr)); | ||
150 | DEFINE(_CTR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ctr)); | ||
151 | DEFINE(_LINK, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, link)); | ||
152 | DEFINE(_CCR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, ccr)); | ||
153 | DEFINE(_XER, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, xer)); | ||
154 | DEFINE(_DAR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dar)); | ||
155 | DEFINE(_DSISR, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, dsisr)); | ||
156 | DEFINE(ORIG_GPR3, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, orig_gpr3)); | ||
157 | DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result)); | ||
158 | DEFINE(_TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap)); | ||
159 | DEFINE(SOFTE, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, softe)); | ||
160 | |||
161 | /* These _only_ to be used with {PROM,RTAS}_FRAME_SIZE!!! */ | ||
162 | DEFINE(_SRR0, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)); | ||
163 | DEFINE(_SRR1, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)+8); | ||
164 | |||
165 | DEFINE(CLONE_VM, CLONE_VM); | ||
166 | DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); | ||
167 | |||
168 | /* About the CPU features table */ | ||
169 | DEFINE(CPU_SPEC_ENTRY_SIZE, sizeof(struct cpu_spec)); | ||
170 | DEFINE(CPU_SPEC_PVR_MASK, offsetof(struct cpu_spec, pvr_mask)); | ||
171 | DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value)); | ||
172 | DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); | ||
173 | DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); | ||
174 | |||
175 | /* systemcfg offsets for use by vdso */ | ||
176 | DEFINE(CFG_TB_ORIG_STAMP, offsetof(struct systemcfg, tb_orig_stamp)); | ||
177 | DEFINE(CFG_TB_TICKS_PER_SEC, offsetof(struct systemcfg, tb_ticks_per_sec)); | ||
178 | DEFINE(CFG_TB_TO_XS, offsetof(struct systemcfg, tb_to_xs)); | ||
179 | DEFINE(CFG_STAMP_XSEC, offsetof(struct systemcfg, stamp_xsec)); | ||
180 | DEFINE(CFG_TB_UPDATE_COUNT, offsetof(struct systemcfg, tb_update_count)); | ||
181 | DEFINE(CFG_TZ_MINUTEWEST, offsetof(struct systemcfg, tz_minuteswest)); | ||
182 | DEFINE(CFG_TZ_DSTTIME, offsetof(struct systemcfg, tz_dsttime)); | ||
183 | DEFINE(CFG_SYSCALL_MAP32, offsetof(struct systemcfg, syscall_map_32)); | ||
184 | DEFINE(CFG_SYSCALL_MAP64, offsetof(struct systemcfg, syscall_map_64)); | ||
185 | |||
186 | /* timeval/timezone offsets for use by vdso */ | ||
187 | DEFINE(TVAL64_TV_SEC, offsetof(struct timeval, tv_sec)); | ||
188 | DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec)); | ||
189 | DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec)); | ||
190 | DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec)); | ||
191 | DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); | ||
192 | DEFINE(TZONE_TZ_DSTTIME, offsetof(struct timezone, tz_dsttime)); | ||
193 | |||
194 | return 0; | ||
195 | } | ||
diff --git a/arch/ppc64/kernel/btext.c b/arch/ppc64/kernel/btext.c deleted file mode 100644 index 506a37885c5c..000000000000 --- a/arch/ppc64/kernel/btext.c +++ /dev/null | |||
@@ -1,792 +0,0 @@ | |||
1 | /* | ||
2 | * Procedures for drawing on the screen early on in the boot process. | ||
3 | * | ||
4 | * Benjamin Herrenschmidt <benh@kernel.crashing.org> | ||
5 | */ | ||
6 | #include <linux/config.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/string.h> | ||
9 | #include <linux/init.h> | ||
10 | |||
11 | #include <asm/sections.h> | ||
12 | #include <asm/prom.h> | ||
13 | #include <asm/btext.h> | ||
14 | #include <asm/prom.h> | ||
15 | #include <asm/page.h> | ||
16 | #include <asm/mmu.h> | ||
17 | #include <asm/pgtable.h> | ||
18 | #include <asm/io.h> | ||
19 | #include <asm/lmb.h> | ||
20 | #include <asm/processor.h> | ||
21 | #include <asm/udbg.h> | ||
22 | |||
23 | #undef NO_SCROLL | ||
24 | |||
25 | #ifndef NO_SCROLL | ||
26 | static void scrollscreen(void); | ||
27 | #endif | ||
28 | |||
29 | static void draw_byte(unsigned char c, long locX, long locY); | ||
30 | static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb); | ||
31 | static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb); | ||
32 | static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb); | ||
33 | |||
34 | static int g_loc_X; | ||
35 | static int g_loc_Y; | ||
36 | static int g_max_loc_X; | ||
37 | static int g_max_loc_Y; | ||
38 | |||
39 | static int dispDeviceRowBytes; | ||
40 | static int dispDeviceDepth; | ||
41 | static int dispDeviceRect[4]; | ||
42 | static unsigned char *dispDeviceBase, *logicalDisplayBase; | ||
43 | |||
44 | unsigned long disp_BAT[2] __initdata = {0, 0}; | ||
45 | |||
46 | #define cmapsz (16*256) | ||
47 | |||
48 | static unsigned char vga_font[cmapsz]; | ||
49 | |||
50 | int boot_text_mapped; | ||
51 | int force_printk_to_btext = 0; | ||
52 | |||
53 | |||
54 | /* Here's a small text engine to use during early boot | ||
55 | * or for debugging purposes | ||
56 | * | ||
57 | * todo: | ||
58 | * | ||
59 | * - build some kind of vgacon with it to enable early printk | ||
60 | * - move to a separate file | ||
61 | * - add a few video driver hooks to keep in sync with display | ||
62 | * changes. | ||
63 | */ | ||
64 | |||
65 | void map_boot_text(void) | ||
66 | { | ||
67 | unsigned long base, offset, size; | ||
68 | unsigned char *vbase; | ||
69 | |||
70 | /* By default, we are no longer mapped */ | ||
71 | boot_text_mapped = 0; | ||
72 | if (dispDeviceBase == 0) | ||
73 | return; | ||
74 | base = ((unsigned long) dispDeviceBase) & 0xFFFFF000UL; | ||
75 | offset = ((unsigned long) dispDeviceBase) - base; | ||
76 | size = dispDeviceRowBytes * dispDeviceRect[3] + offset | ||
77 | + dispDeviceRect[0]; | ||
78 | vbase = __ioremap(base, size, _PAGE_NO_CACHE); | ||
79 | if (vbase == 0) | ||
80 | return; | ||
81 | logicalDisplayBase = vbase + offset; | ||
82 | boot_text_mapped = 1; | ||
83 | } | ||
84 | |||
85 | int btext_initialize(struct device_node *np) | ||
86 | { | ||
87 | unsigned int width, height, depth, pitch; | ||
88 | unsigned long address = 0; | ||
89 | u32 *prop; | ||
90 | |||
91 | prop = (u32 *)get_property(np, "width", NULL); | ||
92 | if (prop == NULL) | ||
93 | return -EINVAL; | ||
94 | width = *prop; | ||
95 | prop = (u32 *)get_property(np, "height", NULL); | ||
96 | if (prop == NULL) | ||
97 | return -EINVAL; | ||
98 | height = *prop; | ||
99 | prop = (u32 *)get_property(np, "depth", NULL); | ||
100 | if (prop == NULL) | ||
101 | return -EINVAL; | ||
102 | depth = *prop; | ||
103 | pitch = width * ((depth + 7) / 8); | ||
104 | prop = (u32 *)get_property(np, "linebytes", NULL); | ||
105 | if (prop) | ||
106 | pitch = *prop; | ||
107 | if (pitch == 1) | ||
108 | pitch = 0x1000; | ||
109 | prop = (u32 *)get_property(np, "address", NULL); | ||
110 | if (prop) | ||
111 | address = *prop; | ||
112 | |||
113 | /* FIXME: Add support for PCI reg properties */ | ||
114 | |||
115 | if (address == 0) | ||
116 | return -EINVAL; | ||
117 | |||
118 | g_loc_X = 0; | ||
119 | g_loc_Y = 0; | ||
120 | g_max_loc_X = width / 8; | ||
121 | g_max_loc_Y = height / 16; | ||
122 | logicalDisplayBase = (unsigned char *)address; | ||
123 | dispDeviceBase = (unsigned char *)address; | ||
124 | dispDeviceRowBytes = pitch; | ||
125 | dispDeviceDepth = depth; | ||
126 | dispDeviceRect[0] = dispDeviceRect[1] = 0; | ||
127 | dispDeviceRect[2] = width; | ||
128 | dispDeviceRect[3] = height; | ||
129 | |||
130 | map_boot_text(); | ||
131 | |||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static void btext_putc(unsigned char c) | ||
136 | { | ||
137 | btext_drawchar(c); | ||
138 | } | ||
139 | |||
140 | void __init init_boot_display(void) | ||
141 | { | ||
142 | char *name; | ||
143 | struct device_node *np = NULL; | ||
144 | int rc = -ENODEV; | ||
145 | |||
146 | printk("trying to initialize btext ...\n"); | ||
147 | |||
148 | name = (char *)get_property(of_chosen, "linux,stdout-path", NULL); | ||
149 | if (name != NULL) { | ||
150 | np = of_find_node_by_path(name); | ||
151 | if (np != NULL) { | ||
152 | if (strcmp(np->type, "display") != 0) { | ||
153 | printk("boot stdout isn't a display !\n"); | ||
154 | of_node_put(np); | ||
155 | np = NULL; | ||
156 | } | ||
157 | } | ||
158 | } | ||
159 | if (np) | ||
160 | rc = btext_initialize(np); | ||
161 | if (rc) { | ||
162 | for (np = NULL; (np = of_find_node_by_type(np, "display"));) { | ||
163 | if (get_property(np, "linux,opened", NULL)) { | ||
164 | printk("trying %s ...\n", np->full_name); | ||
165 | rc = btext_initialize(np); | ||
166 | printk("result: %d\n", rc); | ||
167 | } | ||
168 | if (rc == 0) | ||
169 | break; | ||
170 | } | ||
171 | } | ||
172 | if (rc == 0 && udbg_putc == NULL) | ||
173 | udbg_putc = btext_putc; | ||
174 | } | ||
175 | |||
176 | |||
177 | /* Calc the base address of a given point (x,y) */ | ||
178 | static unsigned char * calc_base(int x, int y) | ||
179 | { | ||
180 | unsigned char *base; | ||
181 | |||
182 | base = logicalDisplayBase; | ||
183 | if (base == 0) | ||
184 | base = dispDeviceBase; | ||
185 | base += (x + dispDeviceRect[0]) * (dispDeviceDepth >> 3); | ||
186 | base += (y + dispDeviceRect[1]) * dispDeviceRowBytes; | ||
187 | return base; | ||
188 | } | ||
189 | |||
190 | /* Adjust the display to a new resolution */ | ||
191 | void btext_update_display(unsigned long phys, int width, int height, | ||
192 | int depth, int pitch) | ||
193 | { | ||
194 | if (dispDeviceBase == 0) | ||
195 | return; | ||
196 | |||
197 | /* check it's the same frame buffer (within 256MB) */ | ||
198 | if ((phys ^ (unsigned long)dispDeviceBase) & 0xf0000000) | ||
199 | return; | ||
200 | |||
201 | dispDeviceBase = (__u8 *) phys; | ||
202 | dispDeviceRect[0] = 0; | ||
203 | dispDeviceRect[1] = 0; | ||
204 | dispDeviceRect[2] = width; | ||
205 | dispDeviceRect[3] = height; | ||
206 | dispDeviceDepth = depth; | ||
207 | dispDeviceRowBytes = pitch; | ||
208 | if (boot_text_mapped) { | ||
209 | iounmap(logicalDisplayBase); | ||
210 | boot_text_mapped = 0; | ||
211 | } | ||
212 | map_boot_text(); | ||
213 | g_loc_X = 0; | ||
214 | g_loc_Y = 0; | ||
215 | g_max_loc_X = width / 8; | ||
216 | g_max_loc_Y = height / 16; | ||
217 | } | ||
218 | |||
219 | void btext_clearscreen(void) | ||
220 | { | ||
221 | unsigned long *base = (unsigned long *)calc_base(0, 0); | ||
222 | unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * | ||
223 | (dispDeviceDepth >> 3)) >> 3; | ||
224 | int i,j; | ||
225 | |||
226 | for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1]); i++) | ||
227 | { | ||
228 | unsigned long *ptr = base; | ||
229 | for(j=width; j; --j) | ||
230 | *(ptr++) = 0; | ||
231 | base += (dispDeviceRowBytes >> 3); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | #ifndef NO_SCROLL | ||
236 | static void scrollscreen(void) | ||
237 | { | ||
238 | unsigned long *src = (unsigned long *)calc_base(0,16); | ||
239 | unsigned long *dst = (unsigned long *)calc_base(0,0); | ||
240 | unsigned long width = ((dispDeviceRect[2] - dispDeviceRect[0]) * | ||
241 | (dispDeviceDepth >> 3)) >> 3; | ||
242 | int i,j; | ||
243 | |||
244 | for (i=0; i<(dispDeviceRect[3] - dispDeviceRect[1] - 16); i++) | ||
245 | { | ||
246 | unsigned long *src_ptr = src; | ||
247 | unsigned long *dst_ptr = dst; | ||
248 | for(j=width; j; --j) | ||
249 | *(dst_ptr++) = *(src_ptr++); | ||
250 | src += (dispDeviceRowBytes >> 3); | ||
251 | dst += (dispDeviceRowBytes >> 3); | ||
252 | } | ||
253 | for (i=0; i<16; i++) | ||
254 | { | ||
255 | unsigned long *dst_ptr = dst; | ||
256 | for(j=width; j; --j) | ||
257 | *(dst_ptr++) = 0; | ||
258 | dst += (dispDeviceRowBytes >> 3); | ||
259 | } | ||
260 | } | ||
261 | #endif /* ndef NO_SCROLL */ | ||
262 | |||
263 | void btext_drawchar(char c) | ||
264 | { | ||
265 | int cline = 0; | ||
266 | #ifdef NO_SCROLL | ||
267 | int x; | ||
268 | #endif | ||
269 | if (!boot_text_mapped) | ||
270 | return; | ||
271 | |||
272 | switch (c) { | ||
273 | case '\b': | ||
274 | if (g_loc_X > 0) | ||
275 | --g_loc_X; | ||
276 | break; | ||
277 | case '\t': | ||
278 | g_loc_X = (g_loc_X & -8) + 8; | ||
279 | break; | ||
280 | case '\r': | ||
281 | g_loc_X = 0; | ||
282 | break; | ||
283 | case '\n': | ||
284 | g_loc_X = 0; | ||
285 | g_loc_Y++; | ||
286 | cline = 1; | ||
287 | break; | ||
288 | default: | ||
289 | draw_byte(c, g_loc_X++, g_loc_Y); | ||
290 | } | ||
291 | if (g_loc_X >= g_max_loc_X) { | ||
292 | g_loc_X = 0; | ||
293 | g_loc_Y++; | ||
294 | cline = 1; | ||
295 | } | ||
296 | #ifndef NO_SCROLL | ||
297 | while (g_loc_Y >= g_max_loc_Y) { | ||
298 | scrollscreen(); | ||
299 | g_loc_Y--; | ||
300 | } | ||
301 | #else | ||
302 | /* wrap around from bottom to top of screen so we don't | ||
303 | waste time scrolling each line. -- paulus. */ | ||
304 | if (g_loc_Y >= g_max_loc_Y) | ||
305 | g_loc_Y = 0; | ||
306 | if (cline) { | ||
307 | for (x = 0; x < g_max_loc_X; ++x) | ||
308 | draw_byte(' ', x, g_loc_Y); | ||
309 | } | ||
310 | #endif | ||
311 | } | ||
312 | |||
313 | void btext_drawstring(const char *c) | ||
314 | { | ||
315 | if (!boot_text_mapped) | ||
316 | return; | ||
317 | while (*c) | ||
318 | btext_drawchar(*c++); | ||
319 | } | ||
320 | |||
321 | void btext_drawhex(unsigned long v) | ||
322 | { | ||
323 | char *hex_table = "0123456789abcdef"; | ||
324 | |||
325 | if (!boot_text_mapped) | ||
326 | return; | ||
327 | btext_drawchar(hex_table[(v >> 60) & 0x0000000FUL]); | ||
328 | btext_drawchar(hex_table[(v >> 56) & 0x0000000FUL]); | ||
329 | btext_drawchar(hex_table[(v >> 52) & 0x0000000FUL]); | ||
330 | btext_drawchar(hex_table[(v >> 48) & 0x0000000FUL]); | ||
331 | btext_drawchar(hex_table[(v >> 44) & 0x0000000FUL]); | ||
332 | btext_drawchar(hex_table[(v >> 40) & 0x0000000FUL]); | ||
333 | btext_drawchar(hex_table[(v >> 36) & 0x0000000FUL]); | ||
334 | btext_drawchar(hex_table[(v >> 32) & 0x0000000FUL]); | ||
335 | btext_drawchar(hex_table[(v >> 28) & 0x0000000FUL]); | ||
336 | btext_drawchar(hex_table[(v >> 24) & 0x0000000FUL]); | ||
337 | btext_drawchar(hex_table[(v >> 20) & 0x0000000FUL]); | ||
338 | btext_drawchar(hex_table[(v >> 16) & 0x0000000FUL]); | ||
339 | btext_drawchar(hex_table[(v >> 12) & 0x0000000FUL]); | ||
340 | btext_drawchar(hex_table[(v >> 8) & 0x0000000FUL]); | ||
341 | btext_drawchar(hex_table[(v >> 4) & 0x0000000FUL]); | ||
342 | btext_drawchar(hex_table[(v >> 0) & 0x0000000FUL]); | ||
343 | btext_drawchar(' '); | ||
344 | } | ||
345 | |||
346 | static void draw_byte(unsigned char c, long locX, long locY) | ||
347 | { | ||
348 | unsigned char *base = calc_base(locX << 3, locY << 4); | ||
349 | unsigned char *font = &vga_font[((unsigned int)c) * 16]; | ||
350 | int rb = dispDeviceRowBytes; | ||
351 | |||
352 | switch(dispDeviceDepth) { | ||
353 | case 24: | ||
354 | case 32: | ||
355 | draw_byte_32(font, (unsigned int *)base, rb); | ||
356 | break; | ||
357 | case 15: | ||
358 | case 16: | ||
359 | draw_byte_16(font, (unsigned int *)base, rb); | ||
360 | break; | ||
361 | case 8: | ||
362 | draw_byte_8(font, (unsigned int *)base, rb); | ||
363 | break; | ||
364 | } | ||
365 | } | ||
366 | |||
367 | static unsigned int expand_bits_8[16] = { | ||
368 | 0x00000000, | ||
369 | 0x000000ff, | ||
370 | 0x0000ff00, | ||
371 | 0x0000ffff, | ||
372 | 0x00ff0000, | ||
373 | 0x00ff00ff, | ||
374 | 0x00ffff00, | ||
375 | 0x00ffffff, | ||
376 | 0xff000000, | ||
377 | 0xff0000ff, | ||
378 | 0xff00ff00, | ||
379 | 0xff00ffff, | ||
380 | 0xffff0000, | ||
381 | 0xffff00ff, | ||
382 | 0xffffff00, | ||
383 | 0xffffffff | ||
384 | }; | ||
385 | |||
386 | static unsigned int expand_bits_16[4] = { | ||
387 | 0x00000000, | ||
388 | 0x0000ffff, | ||
389 | 0xffff0000, | ||
390 | 0xffffffff | ||
391 | }; | ||
392 | |||
393 | |||
394 | static void draw_byte_32(unsigned char *font, unsigned int *base, int rb) | ||
395 | { | ||
396 | int l, bits; | ||
397 | int fg = 0xFFFFFFFFUL; | ||
398 | int bg = 0x00000000UL; | ||
399 | |||
400 | for (l = 0; l < 16; ++l) | ||
401 | { | ||
402 | bits = *font++; | ||
403 | base[0] = (-(bits >> 7) & fg) ^ bg; | ||
404 | base[1] = (-((bits >> 6) & 1) & fg) ^ bg; | ||
405 | base[2] = (-((bits >> 5) & 1) & fg) ^ bg; | ||
406 | base[3] = (-((bits >> 4) & 1) & fg) ^ bg; | ||
407 | base[4] = (-((bits >> 3) & 1) & fg) ^ bg; | ||
408 | base[5] = (-((bits >> 2) & 1) & fg) ^ bg; | ||
409 | base[6] = (-((bits >> 1) & 1) & fg) ^ bg; | ||
410 | base[7] = (-(bits & 1) & fg) ^ bg; | ||
411 | base = (unsigned int *) ((char *)base + rb); | ||
412 | } | ||
413 | } | ||
414 | |||
415 | static void draw_byte_16(unsigned char *font, unsigned int *base, int rb) | ||
416 | { | ||
417 | int l, bits; | ||
418 | int fg = 0xFFFFFFFFUL; | ||
419 | int bg = 0x00000000UL; | ||
420 | unsigned int *eb = (int *)expand_bits_16; | ||
421 | |||
422 | for (l = 0; l < 16; ++l) | ||
423 | { | ||
424 | bits = *font++; | ||
425 | base[0] = (eb[bits >> 6] & fg) ^ bg; | ||
426 | base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg; | ||
427 | base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg; | ||
428 | base[3] = (eb[bits & 3] & fg) ^ bg; | ||
429 | base = (unsigned int *) ((char *)base + rb); | ||
430 | } | ||
431 | } | ||
432 | |||
433 | static void draw_byte_8(unsigned char *font, unsigned int *base, int rb) | ||
434 | { | ||
435 | int l, bits; | ||
436 | int fg = 0x0F0F0F0FUL; | ||
437 | int bg = 0x00000000UL; | ||
438 | unsigned int *eb = (int *)expand_bits_8; | ||
439 | |||
440 | for (l = 0; l < 16; ++l) | ||
441 | { | ||
442 | bits = *font++; | ||
443 | base[0] = (eb[bits >> 4] & fg) ^ bg; | ||
444 | base[1] = (eb[bits & 0xf] & fg) ^ bg; | ||
445 | base = (unsigned int *) ((char *)base + rb); | ||
446 | } | ||
447 | } | ||
448 | |||
449 | static unsigned char vga_font[cmapsz] = { | ||
450 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
451 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, | ||
452 | 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, | ||
453 | 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, | ||
454 | 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, | ||
455 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, | ||
456 | 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, | ||
457 | 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, | ||
458 | 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, | ||
459 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, | ||
460 | 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, | ||
461 | 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
462 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, | ||
463 | 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, | ||
464 | 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, | ||
465 | 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, | ||
466 | 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, | ||
467 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, | ||
468 | 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, | ||
469 | 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, | ||
470 | 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, | ||
471 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, | ||
472 | 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, | ||
473 | 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, | ||
474 | 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, | ||
475 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, | ||
476 | 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, | ||
477 | 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, | ||
478 | 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, | ||
479 | 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
480 | 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, | ||
481 | 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, | ||
482 | 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
483 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
484 | 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
485 | 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
486 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, | ||
487 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, | ||
488 | 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
489 | 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
490 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, | ||
491 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, | ||
492 | 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
493 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
494 | 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, | ||
495 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, | ||
496 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, | ||
497 | 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, | ||
498 | 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, | ||
499 | 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, | ||
500 | 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, | ||
501 | 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, | ||
502 | 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
503 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, | ||
504 | 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, | ||
505 | 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, | ||
506 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, | ||
507 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, | ||
508 | 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
509 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, | ||
510 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, | ||
511 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
512 | 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
513 | 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, | ||
514 | 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, | ||
515 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, | ||
516 | 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, | ||
517 | 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, | ||
518 | 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, | ||
519 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, | ||
520 | 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, | ||
521 | 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
522 | 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, | ||
523 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, | ||
524 | 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, | ||
525 | 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
526 | 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, | ||
527 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, | ||
528 | 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
529 | 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, | ||
530 | 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, | ||
531 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, | ||
532 | 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, | ||
533 | 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, | ||
534 | 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, | ||
535 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, | ||
536 | 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, | ||
537 | 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, | ||
538 | 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, | ||
539 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, | ||
540 | 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, | ||
541 | 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, | ||
542 | 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, | ||
543 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, | ||
544 | 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, | ||
545 | 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, | ||
546 | 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, | ||
547 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
548 | 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, | ||
549 | 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, | ||
550 | 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, | ||
551 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, | ||
552 | 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, | ||
553 | 0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, | ||
554 | 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, | ||
555 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, | ||
556 | 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, | ||
557 | 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, | ||
558 | 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, | ||
559 | 0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, | ||
560 | 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, | ||
561 | 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
562 | 0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, | ||
563 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, | ||
564 | 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, | ||
565 | 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, | ||
566 | 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, | ||
567 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, | ||
568 | 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, | ||
569 | 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, | ||
570 | 0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, | ||
571 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, | ||
572 | 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, | ||
573 | 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, | ||
574 | 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, | ||
575 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, | ||
576 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
577 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, | ||
578 | 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
579 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, | ||
580 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, | ||
581 | 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
582 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, | ||
583 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, | ||
584 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
585 | 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
586 | 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, | ||
587 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, | ||
588 | 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, | ||
589 | 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, | ||
590 | 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, | ||
591 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, | ||
592 | 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, | ||
593 | 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, | ||
594 | 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, | ||
595 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, | ||
596 | 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
597 | 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, | ||
598 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, | ||
599 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, | ||
600 | 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
601 | 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, | ||
602 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, | ||
603 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, | ||
604 | 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, | ||
605 | 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, | ||
606 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, | ||
607 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, | ||
608 | 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
609 | 0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, | ||
610 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, | ||
611 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, | ||
612 | 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
613 | 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, | ||
614 | 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, | ||
615 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, | ||
616 | 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, | ||
617 | 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, | ||
618 | 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
619 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, | ||
620 | 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, | ||
621 | 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, | ||
622 | 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, | ||
623 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, | ||
624 | 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, | ||
625 | 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, | ||
626 | 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, | ||
627 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, | ||
628 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, | ||
629 | 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, | ||
630 | 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, | ||
631 | 0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, | ||
632 | 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, | ||
633 | 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
634 | 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, | ||
635 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, | ||
636 | 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, | ||
637 | 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, | ||
638 | 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, | ||
639 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, | ||
640 | 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, | ||
641 | 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, | ||
642 | 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, | ||
643 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, | ||
644 | 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, | ||
645 | 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, | ||
646 | 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, | ||
647 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, | ||
648 | 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, | ||
649 | 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, | ||
650 | 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, | ||
651 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, | ||
652 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, | ||
653 | 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, | ||
654 | 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, | ||
655 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, | ||
656 | 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, | ||
657 | 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, | ||
658 | 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, | ||
659 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, | ||
660 | 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, | ||
661 | 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, | ||
662 | 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
663 | 0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, | ||
664 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, | ||
665 | 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, | ||
666 | 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, | ||
667 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, | ||
668 | 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, | ||
669 | 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, | ||
670 | 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, | ||
671 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, | ||
672 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, | ||
673 | 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
674 | 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, | ||
675 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, | ||
676 | 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
677 | 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
678 | 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, | ||
679 | 0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, | ||
680 | 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, | ||
681 | 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, | ||
682 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, | ||
683 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, | ||
684 | 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, | ||
685 | 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, | ||
686 | 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, | ||
687 | 0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, | ||
688 | 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, | ||
689 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
690 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, | ||
691 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, | ||
692 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, | ||
693 | 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
694 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, | ||
695 | 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, | ||
696 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, | ||
697 | 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
698 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
699 | 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, | ||
700 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
701 | 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
702 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, | ||
703 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, | ||
704 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
705 | 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
706 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, | ||
707 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, | ||
708 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
709 | 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
710 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, | ||
711 | 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, | ||
712 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, | ||
713 | 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
714 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, | ||
715 | 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, | ||
716 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
717 | 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
718 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, | ||
719 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, | ||
720 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
721 | 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
722 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, | ||
723 | 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, | ||
724 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, | ||
725 | 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
726 | 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, | ||
727 | 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, | ||
728 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
729 | 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
730 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, | ||
731 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, | ||
732 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, | ||
733 | 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
734 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, | ||
735 | 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, | ||
736 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
737 | 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | ||
738 | 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, | ||
739 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, | ||
740 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
741 | 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
742 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
743 | 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, | ||
744 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, | ||
745 | 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, | ||
746 | 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, | ||
747 | 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, | ||
748 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
749 | 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, | ||
750 | 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, | ||
751 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, | ||
752 | 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
753 | 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, | ||
754 | 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, | ||
755 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, | ||
756 | 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
757 | 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, | ||
758 | 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
759 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, | ||
760 | 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, | ||
761 | 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, | ||
762 | 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, | ||
763 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, | ||
764 | 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
765 | 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
766 | 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, | ||
767 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, | ||
768 | 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, | ||
769 | 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, | ||
770 | 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, | ||
771 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, | ||
772 | 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, | ||
773 | 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, | ||
774 | 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, | ||
775 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, | ||
776 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, | ||
777 | 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, | ||
778 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, | ||
779 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, | ||
780 | 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, | ||
781 | 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
782 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, | ||
783 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
784 | 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, | ||
785 | 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, | ||
786 | 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
787 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, | ||
788 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
789 | 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
790 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
791 | 0x00, 0x00, 0x00, 0x00, | ||
792 | }; | ||
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S deleted file mode 100644 index 1c869ea72d28..000000000000 --- a/arch/ppc64/kernel/head.S +++ /dev/null | |||
@@ -1,2007 +0,0 @@ | |||
1 | /* | ||
2 | * arch/ppc64/kernel/head.S | ||
3 | * | ||
4 | * PowerPC version | ||
5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | ||
6 | * | ||
7 | * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP | ||
8 | * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu> | ||
9 | * Adapted for Power Macintosh by Paul Mackerras. | ||
10 | * Low-level exception handlers and MMU support | ||
11 | * rewritten by Paul Mackerras. | ||
12 | * Copyright (C) 1996 Paul Mackerras. | ||
13 | * | ||
14 | * Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and | ||
15 | * Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com | ||
16 | * | ||
17 | * This file contains the low-level support and setup for the | ||
18 | * PowerPC-64 platform, including trap and interrupt dispatch. | ||
19 | * | ||
20 | * This program is free software; you can redistribute it and/or | ||
21 | * modify it under the terms of the GNU General Public License | ||
22 | * as published by the Free Software Foundation; either version | ||
23 | * 2 of the License, or (at your option) any later version. | ||
24 | */ | ||
25 | |||
26 | #include <linux/config.h> | ||
27 | #include <linux/threads.h> | ||
28 | #include <asm/processor.h> | ||
29 | #include <asm/page.h> | ||
30 | #include <asm/mmu.h> | ||
31 | #include <asm/ppc_asm.h> | ||
32 | #include <asm/asm-offsets.h> | ||
33 | #include <asm/bug.h> | ||
34 | #include <asm/cputable.h> | ||
35 | #include <asm/setup.h> | ||
36 | #include <asm/hvcall.h> | ||
37 | #include <asm/iseries/lpar_map.h> | ||
38 | #include <asm/thread_info.h> | ||
39 | |||
40 | #ifdef CONFIG_PPC_ISERIES | ||
41 | #define DO_SOFT_DISABLE | ||
42 | #endif | ||
43 | |||
44 | /* | ||
45 | * We layout physical memory as follows: | ||
46 | * 0x0000 - 0x00ff : Secondary processor spin code | ||
47 | * 0x0100 - 0x2fff : pSeries Interrupt prologs | ||
48 | * 0x3000 - 0x5fff : interrupt support, iSeries and common interrupt prologs | ||
49 | * 0x6000 - 0x6fff : Initial (CPU0) segment table | ||
50 | * 0x7000 - 0x7fff : FWNMI data area | ||
51 | * 0x8000 - : Early init and support code | ||
52 | */ | ||
53 | |||
54 | /* | ||
55 | * SPRG Usage | ||
56 | * | ||
57 | * Register Definition | ||
58 | * | ||
59 | * SPRG0 reserved for hypervisor | ||
60 | * SPRG1 temp - used to save gpr | ||
61 | * SPRG2 temp - used to save gpr | ||
62 | * SPRG3 virt addr of paca | ||
63 | */ | ||
64 | |||
65 | /* | ||
66 | * Entering into this code we make the following assumptions: | ||
67 | * For pSeries: | ||
68 | * 1. The MMU is off & open firmware is running in real mode. | ||
69 | * 2. The kernel is entered at __start | ||
70 | * | ||
71 | * For iSeries: | ||
72 | * 1. The MMU is on (as it always is for iSeries) | ||
73 | * 2. The kernel is entered at system_reset_iSeries | ||
74 | */ | ||
75 | |||
76 | .text | ||
77 | .globl _stext | ||
78 | _stext: | ||
79 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
80 | _GLOBAL(__start) | ||
81 | /* NOP this out unconditionally */ | ||
82 | BEGIN_FTR_SECTION | ||
83 | b .__start_initialization_multiplatform | ||
84 | END_FTR_SECTION(0, 1) | ||
85 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
86 | |||
87 | /* Catch branch to 0 in real mode */ | ||
88 | trap | ||
89 | |||
90 | #ifdef CONFIG_PPC_ISERIES | ||
91 | /* | ||
92 | * At offset 0x20, there is a pointer to iSeries LPAR data. | ||
93 | * This is required by the hypervisor | ||
94 | */ | ||
95 | . = 0x20 | ||
96 | .llong hvReleaseData-KERNELBASE | ||
97 | |||
98 | /* | ||
99 | * At offset 0x28 and 0x30 are offsets to the mschunks_map | ||
100 | * array (used by the iSeries LPAR debugger to do translation | ||
101 | * between physical addresses and absolute addresses) and | ||
102 | * to the pidhash table (also used by the debugger) | ||
103 | */ | ||
104 | .llong mschunks_map-KERNELBASE | ||
105 | .llong 0 /* pidhash-KERNELBASE SFRXXX */ | ||
106 | |||
107 | /* Offset 0x38 - Pointer to start of embedded System.map */ | ||
108 | .globl embedded_sysmap_start | ||
109 | embedded_sysmap_start: | ||
110 | .llong 0 | ||
111 | /* Offset 0x40 - Pointer to end of embedded System.map */ | ||
112 | .globl embedded_sysmap_end | ||
113 | embedded_sysmap_end: | ||
114 | .llong 0 | ||
115 | |||
116 | #endif /* CONFIG_PPC_ISERIES */ | ||
117 | |||
118 | /* Secondary processors spin on this value until it goes to 1. */ | ||
119 | .globl __secondary_hold_spinloop | ||
120 | __secondary_hold_spinloop: | ||
121 | .llong 0x0 | ||
122 | |||
123 | /* Secondary processors write this value with their cpu # */ | ||
124 | /* after they enter the spin loop immediately below. */ | ||
125 | .globl __secondary_hold_acknowledge | ||
126 | __secondary_hold_acknowledge: | ||
127 | .llong 0x0 | ||
128 | |||
129 | . = 0x60 | ||
130 | /* | ||
131 | * The following code is used on pSeries to hold secondary processors | ||
132 | * in a spin loop after they have been freed from OpenFirmware, but | ||
133 | * before the bulk of the kernel has been relocated. This code | ||
134 | * is relocated to physical address 0x60 before prom_init is run. | ||
135 | * All of it must fit below the first exception vector at 0x100. | ||
136 | */ | ||
137 | _GLOBAL(__secondary_hold) | ||
138 | mfmsr r24 | ||
139 | ori r24,r24,MSR_RI | ||
140 | mtmsrd r24 /* RI on */ | ||
141 | |||
142 | /* Grab our linux cpu number */ | ||
143 | mr r24,r3 | ||
144 | |||
145 | /* Tell the master cpu we're here */ | ||
146 | /* Relocation is off & we are located at an address less */ | ||
147 | /* than 0x100, so only need to grab low order offset. */ | ||
148 | std r24,__secondary_hold_acknowledge@l(0) | ||
149 | sync | ||
150 | |||
151 | /* All secondary cpus wait here until told to start. */ | ||
152 | 100: ld r4,__secondary_hold_spinloop@l(0) | ||
153 | cmpdi 0,r4,1 | ||
154 | bne 100b | ||
155 | |||
156 | #ifdef CONFIG_HMT | ||
157 | b .hmt_init | ||
158 | #else | ||
159 | #ifdef CONFIG_SMP | ||
160 | mr r3,r24 | ||
161 | b .pSeries_secondary_smp_init | ||
162 | #else | ||
163 | BUG_OPCODE | ||
164 | #endif | ||
165 | #endif | ||
166 | |||
167 | /* This value is used to mark exception frames on the stack. */ | ||
168 | .section ".toc","aw" | ||
169 | exception_marker: | ||
170 | .tc ID_72656773_68657265[TC],0x7265677368657265 | ||
171 | .text | ||
172 | |||
173 | /* | ||
174 | * The following macros define the code that appears as | ||
175 | * the prologue to each of the exception handlers. They | ||
176 | * are split into two parts to allow a single kernel binary | ||
177 | * to be used for pSeries and iSeries. | ||
178 | * LOL. One day... - paulus | ||
179 | */ | ||
180 | |||
181 | /* | ||
182 | * We make as much of the exception code common between native | ||
183 | * exception handlers (including pSeries LPAR) and iSeries LPAR | ||
184 | * implementations as possible. | ||
185 | */ | ||
186 | |||
187 | /* | ||
188 | * This is the start of the interrupt handlers for pSeries | ||
189 | * This code runs with relocation off. | ||
190 | */ | ||
191 | #define EX_R9 0 | ||
192 | #define EX_R10 8 | ||
193 | #define EX_R11 16 | ||
194 | #define EX_R12 24 | ||
195 | #define EX_R13 32 | ||
196 | #define EX_SRR0 40 | ||
197 | #define EX_DAR 48 | ||
198 | #define EX_DSISR 56 | ||
199 | #define EX_CCR 60 | ||
200 | #define EX_R3 64 | ||
201 | #define EX_LR 72 | ||
202 | |||
203 | #define EXCEPTION_PROLOG_PSERIES(area, label) \ | ||
204 | mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ | ||
205 | std r9,area+EX_R9(r13); /* save r9 - r12 */ \ | ||
206 | std r10,area+EX_R10(r13); \ | ||
207 | std r11,area+EX_R11(r13); \ | ||
208 | std r12,area+EX_R12(r13); \ | ||
209 | mfspr r9,SPRN_SPRG1; \ | ||
210 | std r9,area+EX_R13(r13); \ | ||
211 | mfcr r9; \ | ||
212 | clrrdi r12,r13,32; /* get high part of &label */ \ | ||
213 | mfmsr r10; \ | ||
214 | mfspr r11,SPRN_SRR0; /* save SRR0 */ \ | ||
215 | ori r12,r12,(label)@l; /* virt addr of handler */ \ | ||
216 | ori r10,r10,MSR_IR|MSR_DR|MSR_RI; \ | ||
217 | mtspr SPRN_SRR0,r12; \ | ||
218 | mfspr r12,SPRN_SRR1; /* and SRR1 */ \ | ||
219 | mtspr SPRN_SRR1,r10; \ | ||
220 | rfid; \ | ||
221 | b . /* prevent speculative execution */ | ||
222 | |||
223 | /* | ||
224 | * This is the start of the interrupt handlers for iSeries | ||
225 | * This code runs with relocation on. | ||
226 | */ | ||
227 | #define EXCEPTION_PROLOG_ISERIES_1(area) \ | ||
228 | mfspr r13,SPRN_SPRG3; /* get paca address into r13 */ \ | ||
229 | std r9,area+EX_R9(r13); /* save r9 - r12 */ \ | ||
230 | std r10,area+EX_R10(r13); \ | ||
231 | std r11,area+EX_R11(r13); \ | ||
232 | std r12,area+EX_R12(r13); \ | ||
233 | mfspr r9,SPRN_SPRG1; \ | ||
234 | std r9,area+EX_R13(r13); \ | ||
235 | mfcr r9 | ||
236 | |||
237 | #define EXCEPTION_PROLOG_ISERIES_2 \ | ||
238 | mfmsr r10; \ | ||
239 | ld r11,PACALPPACA+LPPACASRR0(r13); \ | ||
240 | ld r12,PACALPPACA+LPPACASRR1(r13); \ | ||
241 | ori r10,r10,MSR_RI; \ | ||
242 | mtmsrd r10,1 | ||
243 | |||
244 | /* | ||
245 | * The common exception prolog is used for all except a few exceptions | ||
246 | * such as a segment miss on a kernel address. We have to be prepared | ||
247 | * to take another exception from the point where we first touch the | ||
248 | * kernel stack onwards. | ||
249 | * | ||
250 | * On entry r13 points to the paca, r9-r13 are saved in the paca, | ||
251 | * r9 contains the saved CR, r11 and r12 contain the saved SRR0 and | ||
252 | * SRR1, and relocation is on. | ||
253 | */ | ||
254 | #define EXCEPTION_PROLOG_COMMON(n, area) \ | ||
255 | andi. r10,r12,MSR_PR; /* See if coming from user */ \ | ||
256 | mr r10,r1; /* Save r1 */ \ | ||
257 | subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */ \ | ||
258 | beq- 1f; \ | ||
259 | ld r1,PACAKSAVE(r13); /* kernel stack to use */ \ | ||
260 | 1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \ | ||
261 | bge- cr1,bad_stack; /* abort if it is */ \ | ||
262 | std r9,_CCR(r1); /* save CR in stackframe */ \ | ||
263 | std r11,_NIP(r1); /* save SRR0 in stackframe */ \ | ||
264 | std r12,_MSR(r1); /* save SRR1 in stackframe */ \ | ||
265 | std r10,0(r1); /* make stack chain pointer */ \ | ||
266 | std r0,GPR0(r1); /* save r0 in stackframe */ \ | ||
267 | std r10,GPR1(r1); /* save r1 in stackframe */ \ | ||
268 | std r2,GPR2(r1); /* save r2 in stackframe */ \ | ||
269 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ | ||
270 | SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ | ||
271 | ld r9,area+EX_R9(r13); /* move r9, r10 to stackframe */ \ | ||
272 | ld r10,area+EX_R10(r13); \ | ||
273 | std r9,GPR9(r1); \ | ||
274 | std r10,GPR10(r1); \ | ||
275 | ld r9,area+EX_R11(r13); /* move r11 - r13 to stackframe */ \ | ||
276 | ld r10,area+EX_R12(r13); \ | ||
277 | ld r11,area+EX_R13(r13); \ | ||
278 | std r9,GPR11(r1); \ | ||
279 | std r10,GPR12(r1); \ | ||
280 | std r11,GPR13(r1); \ | ||
281 | ld r2,PACATOC(r13); /* get kernel TOC into r2 */ \ | ||
282 | mflr r9; /* save LR in stackframe */ \ | ||
283 | std r9,_LINK(r1); \ | ||
284 | mfctr r10; /* save CTR in stackframe */ \ | ||
285 | std r10,_CTR(r1); \ | ||
286 | mfspr r11,SPRN_XER; /* save XER in stackframe */ \ | ||
287 | std r11,_XER(r1); \ | ||
288 | li r9,(n)+1; \ | ||
289 | std r9,_TRAP(r1); /* set trap number */ \ | ||
290 | li r10,0; \ | ||
291 | ld r11,exception_marker@toc(r2); \ | ||
292 | std r10,RESULT(r1); /* clear regs->result */ \ | ||
293 | std r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */ | ||
294 | |||
295 | /* | ||
296 | * Exception vectors. | ||
297 | */ | ||
298 | #define STD_EXCEPTION_PSERIES(n, label) \ | ||
299 | . = n; \ | ||
300 | .globl label##_pSeries; \ | ||
301 | label##_pSeries: \ | ||
302 | HMT_MEDIUM; \ | ||
303 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
304 | RUNLATCH_ON(r13); \ | ||
305 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) | ||
306 | |||
307 | #define STD_EXCEPTION_ISERIES(n, label, area) \ | ||
308 | .globl label##_iSeries; \ | ||
309 | label##_iSeries: \ | ||
310 | HMT_MEDIUM; \ | ||
311 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
312 | RUNLATCH_ON(r13); \ | ||
313 | EXCEPTION_PROLOG_ISERIES_1(area); \ | ||
314 | EXCEPTION_PROLOG_ISERIES_2; \ | ||
315 | b label##_common | ||
316 | |||
317 | #define MASKABLE_EXCEPTION_ISERIES(n, label) \ | ||
318 | .globl label##_iSeries; \ | ||
319 | label##_iSeries: \ | ||
320 | HMT_MEDIUM; \ | ||
321 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
322 | RUNLATCH_ON(r13); \ | ||
323 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ | ||
324 | lbz r10,PACAPROCENABLED(r13); \ | ||
325 | cmpwi 0,r10,0; \ | ||
326 | beq- label##_iSeries_masked; \ | ||
327 | EXCEPTION_PROLOG_ISERIES_2; \ | ||
328 | b label##_common; \ | ||
329 | |||
330 | #ifdef DO_SOFT_DISABLE | ||
331 | #define DISABLE_INTS \ | ||
332 | lbz r10,PACAPROCENABLED(r13); \ | ||
333 | li r11,0; \ | ||
334 | std r10,SOFTE(r1); \ | ||
335 | mfmsr r10; \ | ||
336 | stb r11,PACAPROCENABLED(r13); \ | ||
337 | ori r10,r10,MSR_EE; \ | ||
338 | mtmsrd r10,1 | ||
339 | |||
340 | #define ENABLE_INTS \ | ||
341 | lbz r10,PACAPROCENABLED(r13); \ | ||
342 | mfmsr r11; \ | ||
343 | std r10,SOFTE(r1); \ | ||
344 | ori r11,r11,MSR_EE; \ | ||
345 | mtmsrd r11,1 | ||
346 | |||
347 | #else /* hard enable/disable interrupts */ | ||
348 | #define DISABLE_INTS | ||
349 | |||
350 | #define ENABLE_INTS \ | ||
351 | ld r12,_MSR(r1); \ | ||
352 | mfmsr r11; \ | ||
353 | rlwimi r11,r12,0,MSR_EE; \ | ||
354 | mtmsrd r11,1 | ||
355 | |||
356 | #endif | ||
357 | |||
358 | #define STD_EXCEPTION_COMMON(trap, label, hdlr) \ | ||
359 | .align 7; \ | ||
360 | .globl label##_common; \ | ||
361 | label##_common: \ | ||
362 | EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ | ||
363 | DISABLE_INTS; \ | ||
364 | bl .save_nvgprs; \ | ||
365 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
366 | bl hdlr; \ | ||
367 | b .ret_from_except | ||
368 | |||
369 | #define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr) \ | ||
370 | .align 7; \ | ||
371 | .globl label##_common; \ | ||
372 | label##_common: \ | ||
373 | EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ | ||
374 | DISABLE_INTS; \ | ||
375 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
376 | bl hdlr; \ | ||
377 | b .ret_from_except_lite | ||
378 | |||
379 | /* | ||
380 | * Start of pSeries system interrupt routines | ||
381 | */ | ||
382 | . = 0x100 | ||
383 | .globl __start_interrupts | ||
384 | __start_interrupts: | ||
385 | |||
386 | STD_EXCEPTION_PSERIES(0x100, system_reset) | ||
387 | |||
388 | . = 0x200 | ||
389 | _machine_check_pSeries: | ||
390 | HMT_MEDIUM | ||
391 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
392 | RUNLATCH_ON(r13) | ||
393 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) | ||
394 | |||
395 | . = 0x300 | ||
396 | .globl data_access_pSeries | ||
397 | data_access_pSeries: | ||
398 | HMT_MEDIUM | ||
399 | mtspr SPRN_SPRG1,r13 | ||
400 | BEGIN_FTR_SECTION | ||
401 | mtspr SPRN_SPRG2,r12 | ||
402 | mfspr r13,SPRN_DAR | ||
403 | mfspr r12,SPRN_DSISR | ||
404 | srdi r13,r13,60 | ||
405 | rlwimi r13,r12,16,0x20 | ||
406 | mfcr r12 | ||
407 | cmpwi r13,0x2c | ||
408 | beq .do_stab_bolted_pSeries | ||
409 | mtcrf 0x80,r12 | ||
410 | mfspr r12,SPRN_SPRG2 | ||
411 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
412 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common) | ||
413 | |||
414 | . = 0x380 | ||
415 | .globl data_access_slb_pSeries | ||
416 | data_access_slb_pSeries: | ||
417 | HMT_MEDIUM | ||
418 | mtspr SPRN_SPRG1,r13 | ||
419 | RUNLATCH_ON(r13) | ||
420 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
421 | std r3,PACA_EXSLB+EX_R3(r13) | ||
422 | mfspr r3,SPRN_DAR | ||
423 | std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ | ||
424 | mfcr r9 | ||
425 | #ifdef __DISABLED__ | ||
426 | /* Keep that around for when we re-implement dynamic VSIDs */ | ||
427 | cmpdi r3,0 | ||
428 | bge slb_miss_user_pseries | ||
429 | #endif /* __DISABLED__ */ | ||
430 | std r10,PACA_EXSLB+EX_R10(r13) | ||
431 | std r11,PACA_EXSLB+EX_R11(r13) | ||
432 | std r12,PACA_EXSLB+EX_R12(r13) | ||
433 | mfspr r10,SPRN_SPRG1 | ||
434 | std r10,PACA_EXSLB+EX_R13(r13) | ||
435 | mfspr r12,SPRN_SRR1 /* and SRR1 */ | ||
436 | b .slb_miss_realmode /* Rel. branch works in real mode */ | ||
437 | |||
438 | STD_EXCEPTION_PSERIES(0x400, instruction_access) | ||
439 | |||
440 | . = 0x480 | ||
441 | .globl instruction_access_slb_pSeries | ||
442 | instruction_access_slb_pSeries: | ||
443 | HMT_MEDIUM | ||
444 | mtspr SPRN_SPRG1,r13 | ||
445 | RUNLATCH_ON(r13) | ||
446 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
447 | std r3,PACA_EXSLB+EX_R3(r13) | ||
448 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ | ||
449 | std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ | ||
450 | mfcr r9 | ||
451 | #ifdef __DISABLED__ | ||
452 | /* Keep that around for when we re-implement dynamic VSIDs */ | ||
453 | cmpdi r3,0 | ||
454 | bge slb_miss_user_pseries | ||
455 | #endif /* __DISABLED__ */ | ||
456 | std r10,PACA_EXSLB+EX_R10(r13) | ||
457 | std r11,PACA_EXSLB+EX_R11(r13) | ||
458 | std r12,PACA_EXSLB+EX_R12(r13) | ||
459 | mfspr r10,SPRN_SPRG1 | ||
460 | std r10,PACA_EXSLB+EX_R13(r13) | ||
461 | mfspr r12,SPRN_SRR1 /* and SRR1 */ | ||
462 | b .slb_miss_realmode /* Rel. branch works in real mode */ | ||
463 | |||
464 | STD_EXCEPTION_PSERIES(0x500, hardware_interrupt) | ||
465 | STD_EXCEPTION_PSERIES(0x600, alignment) | ||
466 | STD_EXCEPTION_PSERIES(0x700, program_check) | ||
467 | STD_EXCEPTION_PSERIES(0x800, fp_unavailable) | ||
468 | STD_EXCEPTION_PSERIES(0x900, decrementer) | ||
469 | STD_EXCEPTION_PSERIES(0xa00, trap_0a) | ||
470 | STD_EXCEPTION_PSERIES(0xb00, trap_0b) | ||
471 | |||
472 | . = 0xc00 | ||
473 | .globl system_call_pSeries | ||
474 | system_call_pSeries: | ||
475 | HMT_MEDIUM | ||
476 | RUNLATCH_ON(r9) | ||
477 | mr r9,r13 | ||
478 | mfmsr r10 | ||
479 | mfspr r13,SPRN_SPRG3 | ||
480 | mfspr r11,SPRN_SRR0 | ||
481 | clrrdi r12,r13,32 | ||
482 | oris r12,r12,system_call_common@h | ||
483 | ori r12,r12,system_call_common@l | ||
484 | mtspr SPRN_SRR0,r12 | ||
485 | ori r10,r10,MSR_IR|MSR_DR|MSR_RI | ||
486 | mfspr r12,SPRN_SRR1 | ||
487 | mtspr SPRN_SRR1,r10 | ||
488 | rfid | ||
489 | b . /* prevent speculative execution */ | ||
490 | |||
491 | STD_EXCEPTION_PSERIES(0xd00, single_step) | ||
492 | STD_EXCEPTION_PSERIES(0xe00, trap_0e) | ||
493 | |||
494 | /* We need to deal with the Altivec unavailable exception | ||
495 | * here which is at 0xf20, thus in the middle of the | ||
496 | * prolog code of the PerformanceMonitor one. A little | ||
497 | * trickery is thus necessary | ||
498 | */ | ||
499 | . = 0xf00 | ||
500 | b performance_monitor_pSeries | ||
501 | |||
502 | STD_EXCEPTION_PSERIES(0xf20, altivec_unavailable) | ||
503 | |||
504 | STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint) | ||
505 | STD_EXCEPTION_PSERIES(0x1700, altivec_assist) | ||
506 | |||
507 | . = 0x3000 | ||
508 | |||
509 | /*** pSeries interrupt support ***/ | ||
510 | |||
511 | /* moved from 0xf00 */ | ||
512 | STD_EXCEPTION_PSERIES(., performance_monitor) | ||
513 | |||
514 | .align 7 | ||
515 | _GLOBAL(do_stab_bolted_pSeries) | ||
516 | mtcrf 0x80,r12 | ||
517 | mfspr r12,SPRN_SPRG2 | ||
518 | EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) | ||
519 | |||
520 | /* | ||
521 | * We have some room here we use that to put | ||
522 | * the peries slb miss user trampoline code so it's reasonably | ||
523 | * away from slb_miss_user_common to avoid problems with rfid | ||
524 | * | ||
525 | * This is used for when the SLB miss handler has to go virtual, | ||
526 | * which doesn't happen for now anymore but will once we re-implement | ||
527 | * dynamic VSIDs for shared page tables | ||
528 | */ | ||
529 | #ifdef __DISABLED__ | ||
530 | slb_miss_user_pseries: | ||
531 | std r10,PACA_EXGEN+EX_R10(r13) | ||
532 | std r11,PACA_EXGEN+EX_R11(r13) | ||
533 | std r12,PACA_EXGEN+EX_R12(r13) | ||
534 | mfspr r10,SPRG1 | ||
535 | ld r11,PACA_EXSLB+EX_R9(r13) | ||
536 | ld r12,PACA_EXSLB+EX_R3(r13) | ||
537 | std r10,PACA_EXGEN+EX_R13(r13) | ||
538 | std r11,PACA_EXGEN+EX_R9(r13) | ||
539 | std r12,PACA_EXGEN+EX_R3(r13) | ||
540 | clrrdi r12,r13,32 | ||
541 | mfmsr r10 | ||
542 | mfspr r11,SRR0 /* save SRR0 */ | ||
543 | ori r12,r12,slb_miss_user_common@l /* virt addr of handler */ | ||
544 | ori r10,r10,MSR_IR|MSR_DR|MSR_RI | ||
545 | mtspr SRR0,r12 | ||
546 | mfspr r12,SRR1 /* and SRR1 */ | ||
547 | mtspr SRR1,r10 | ||
548 | rfid | ||
549 | b . /* prevent spec. execution */ | ||
550 | #endif /* __DISABLED__ */ | ||
551 | |||
552 | /* | ||
553 | * Vectors for the FWNMI option. Share common code. | ||
554 | */ | ||
555 | .globl system_reset_fwnmi | ||
556 | system_reset_fwnmi: | ||
557 | HMT_MEDIUM | ||
558 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
559 | RUNLATCH_ON(r13) | ||
560 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common) | ||
561 | |||
562 | .globl machine_check_fwnmi | ||
563 | machine_check_fwnmi: | ||
564 | HMT_MEDIUM | ||
565 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
566 | RUNLATCH_ON(r13) | ||
567 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) | ||
568 | |||
569 | #ifdef CONFIG_PPC_ISERIES | ||
570 | /*** ISeries-LPAR interrupt handlers ***/ | ||
571 | |||
572 | STD_EXCEPTION_ISERIES(0x200, machine_check, PACA_EXMC) | ||
573 | |||
574 | .globl data_access_iSeries | ||
575 | data_access_iSeries: | ||
576 | mtspr SPRN_SPRG1,r13 | ||
577 | BEGIN_FTR_SECTION | ||
578 | mtspr SPRN_SPRG2,r12 | ||
579 | mfspr r13,SPRN_DAR | ||
580 | mfspr r12,SPRN_DSISR | ||
581 | srdi r13,r13,60 | ||
582 | rlwimi r13,r12,16,0x20 | ||
583 | mfcr r12 | ||
584 | cmpwi r13,0x2c | ||
585 | beq .do_stab_bolted_iSeries | ||
586 | mtcrf 0x80,r12 | ||
587 | mfspr r12,SPRN_SPRG2 | ||
588 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
589 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN) | ||
590 | EXCEPTION_PROLOG_ISERIES_2 | ||
591 | b data_access_common | ||
592 | |||
593 | .do_stab_bolted_iSeries: | ||
594 | mtcrf 0x80,r12 | ||
595 | mfspr r12,SPRN_SPRG2 | ||
596 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXSLB) | ||
597 | EXCEPTION_PROLOG_ISERIES_2 | ||
598 | b .do_stab_bolted | ||
599 | |||
600 | .globl data_access_slb_iSeries | ||
601 | data_access_slb_iSeries: | ||
602 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
603 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
604 | std r3,PACA_EXSLB+EX_R3(r13) | ||
605 | mfspr r3,SPRN_DAR | ||
606 | std r9,PACA_EXSLB+EX_R9(r13) | ||
607 | mfcr r9 | ||
608 | #ifdef __DISABLED__ | ||
609 | cmpdi r3,0 | ||
610 | bge slb_miss_user_iseries | ||
611 | #endif | ||
612 | std r10,PACA_EXSLB+EX_R10(r13) | ||
613 | std r11,PACA_EXSLB+EX_R11(r13) | ||
614 | std r12,PACA_EXSLB+EX_R12(r13) | ||
615 | mfspr r10,SPRN_SPRG1 | ||
616 | std r10,PACA_EXSLB+EX_R13(r13) | ||
617 | ld r12,PACALPPACA+LPPACASRR1(r13); | ||
618 | b .slb_miss_realmode | ||
619 | |||
620 | STD_EXCEPTION_ISERIES(0x400, instruction_access, PACA_EXGEN) | ||
621 | |||
622 | .globl instruction_access_slb_iSeries | ||
623 | instruction_access_slb_iSeries: | ||
624 | mtspr SPRN_SPRG1,r13 /* save r13 */ | ||
625 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | ||
626 | std r3,PACA_EXSLB+EX_R3(r13) | ||
627 | ld r3,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ | ||
628 | std r9,PACA_EXSLB+EX_R9(r13) | ||
629 | mfcr r9 | ||
630 | #ifdef __DISABLED__ | ||
631 | cmpdi r3,0 | ||
632 | bge .slb_miss_user_iseries | ||
633 | #endif | ||
634 | std r10,PACA_EXSLB+EX_R10(r13) | ||
635 | std r11,PACA_EXSLB+EX_R11(r13) | ||
636 | std r12,PACA_EXSLB+EX_R12(r13) | ||
637 | mfspr r10,SPRN_SPRG1 | ||
638 | std r10,PACA_EXSLB+EX_R13(r13) | ||
639 | ld r12,PACALPPACA+LPPACASRR1(r13); | ||
640 | b .slb_miss_realmode | ||
641 | |||
642 | #ifdef __DISABLED__ | ||
643 | slb_miss_user_iseries: | ||
644 | std r10,PACA_EXGEN+EX_R10(r13) | ||
645 | std r11,PACA_EXGEN+EX_R11(r13) | ||
646 | std r12,PACA_EXGEN+EX_R12(r13) | ||
647 | mfspr r10,SPRG1 | ||
648 | ld r11,PACA_EXSLB+EX_R9(r13) | ||
649 | ld r12,PACA_EXSLB+EX_R3(r13) | ||
650 | std r10,PACA_EXGEN+EX_R13(r13) | ||
651 | std r11,PACA_EXGEN+EX_R9(r13) | ||
652 | std r12,PACA_EXGEN+EX_R3(r13) | ||
653 | EXCEPTION_PROLOG_ISERIES_2 | ||
654 | b slb_miss_user_common | ||
655 | #endif | ||
656 | |||
657 | MASKABLE_EXCEPTION_ISERIES(0x500, hardware_interrupt) | ||
658 | STD_EXCEPTION_ISERIES(0x600, alignment, PACA_EXGEN) | ||
659 | STD_EXCEPTION_ISERIES(0x700, program_check, PACA_EXGEN) | ||
660 | STD_EXCEPTION_ISERIES(0x800, fp_unavailable, PACA_EXGEN) | ||
661 | MASKABLE_EXCEPTION_ISERIES(0x900, decrementer) | ||
662 | STD_EXCEPTION_ISERIES(0xa00, trap_0a, PACA_EXGEN) | ||
663 | STD_EXCEPTION_ISERIES(0xb00, trap_0b, PACA_EXGEN) | ||
664 | |||
665 | .globl system_call_iSeries | ||
666 | system_call_iSeries: | ||
667 | mr r9,r13 | ||
668 | mfspr r13,SPRN_SPRG3 | ||
669 | EXCEPTION_PROLOG_ISERIES_2 | ||
670 | b system_call_common | ||
671 | |||
672 | STD_EXCEPTION_ISERIES( 0xd00, single_step, PACA_EXGEN) | ||
673 | STD_EXCEPTION_ISERIES( 0xe00, trap_0e, PACA_EXGEN) | ||
674 | STD_EXCEPTION_ISERIES( 0xf00, performance_monitor, PACA_EXGEN) | ||
675 | |||
676 | .globl system_reset_iSeries | ||
677 | system_reset_iSeries: | ||
678 | mfspr r13,SPRN_SPRG3 /* Get paca address */ | ||
679 | mfmsr r24 | ||
680 | ori r24,r24,MSR_RI | ||
681 | mtmsrd r24 /* RI on */ | ||
682 | lhz r24,PACAPACAINDEX(r13) /* Get processor # */ | ||
683 | cmpwi 0,r24,0 /* Are we processor 0? */ | ||
684 | beq .__start_initialization_iSeries /* Start up the first processor */ | ||
685 | mfspr r4,SPRN_CTRLF | ||
686 | li r5,CTRL_RUNLATCH /* Turn off the run light */ | ||
687 | andc r4,r4,r5 | ||
688 | mtspr SPRN_CTRLT,r4 | ||
689 | |||
690 | 1: | ||
691 | HMT_LOW | ||
692 | #ifdef CONFIG_SMP | ||
693 | lbz r23,PACAPROCSTART(r13) /* Test if this processor | ||
694 | * should start */ | ||
695 | sync | ||
696 | LOADADDR(r3,current_set) | ||
697 | sldi r28,r24,3 /* get current_set[cpu#] */ | ||
698 | ldx r3,r3,r28 | ||
699 | addi r1,r3,THREAD_SIZE | ||
700 | subi r1,r1,STACK_FRAME_OVERHEAD | ||
701 | |||
702 | cmpwi 0,r23,0 | ||
703 | beq iSeries_secondary_smp_loop /* Loop until told to go */ | ||
704 | bne .__secondary_start /* Loop until told to go */ | ||
705 | iSeries_secondary_smp_loop: | ||
706 | /* Let the Hypervisor know we are alive */ | ||
707 | /* 8002 is a call to HvCallCfg::getLps, a harmless Hypervisor function */ | ||
708 | lis r3,0x8002 | ||
709 | rldicr r3,r3,32,15 /* r0 = (r3 << 32) & 0xffff000000000000 */ | ||
710 | #else /* CONFIG_SMP */ | ||
711 | /* Yield the processor. This is required for non-SMP kernels | ||
712 | which are running on multi-threaded machines. */ | ||
713 | lis r3,0x8000 | ||
714 | rldicr r3,r3,32,15 /* r3 = (r3 << 32) & 0xffff000000000000 */ | ||
715 | addi r3,r3,18 /* r3 = 0x8000000000000012 which is "yield" */ | ||
716 | li r4,0 /* "yield timed" */ | ||
717 | li r5,-1 /* "yield forever" */ | ||
718 | #endif /* CONFIG_SMP */ | ||
719 | li r0,-1 /* r0=-1 indicates a Hypervisor call */ | ||
720 | sc /* Invoke the hypervisor via a system call */ | ||
721 | mfspr r13,SPRN_SPRG3 /* Put r13 back ???? */ | ||
722 | b 1b /* If SMP not configured, secondaries | ||
723 | * loop forever */ | ||
724 | |||
725 | .globl decrementer_iSeries_masked | ||
726 | decrementer_iSeries_masked: | ||
727 | li r11,1 | ||
728 | stb r11,PACALPPACA+LPPACADECRINT(r13) | ||
729 | lwz r12,PACADEFAULTDECR(r13) | ||
730 | mtspr SPRN_DEC,r12 | ||
731 | /* fall through */ | ||
732 | |||
733 | .globl hardware_interrupt_iSeries_masked | ||
734 | hardware_interrupt_iSeries_masked: | ||
735 | mtcrf 0x80,r9 /* Restore regs */ | ||
736 | ld r11,PACALPPACA+LPPACASRR0(r13) | ||
737 | ld r12,PACALPPACA+LPPACASRR1(r13) | ||
738 | mtspr SPRN_SRR0,r11 | ||
739 | mtspr SPRN_SRR1,r12 | ||
740 | ld r9,PACA_EXGEN+EX_R9(r13) | ||
741 | ld r10,PACA_EXGEN+EX_R10(r13) | ||
742 | ld r11,PACA_EXGEN+EX_R11(r13) | ||
743 | ld r12,PACA_EXGEN+EX_R12(r13) | ||
744 | ld r13,PACA_EXGEN+EX_R13(r13) | ||
745 | rfid | ||
746 | b . /* prevent speculative execution */ | ||
747 | #endif /* CONFIG_PPC_ISERIES */ | ||
748 | |||
749 | /*** Common interrupt handlers ***/ | ||
750 | |||
751 | STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception) | ||
752 | |||
753 | /* | ||
754 | * Machine check is different because we use a different | ||
755 | * save area: PACA_EXMC instead of PACA_EXGEN. | ||
756 | */ | ||
757 | .align 7 | ||
758 | .globl machine_check_common | ||
759 | machine_check_common: | ||
760 | EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC) | ||
761 | DISABLE_INTS | ||
762 | bl .save_nvgprs | ||
763 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
764 | bl .machine_check_exception | ||
765 | b .ret_from_except | ||
766 | |||
767 | STD_EXCEPTION_COMMON_LITE(0x900, decrementer, .timer_interrupt) | ||
768 | STD_EXCEPTION_COMMON(0xa00, trap_0a, .unknown_exception) | ||
769 | STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception) | ||
770 | STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception) | ||
771 | STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception) | ||
772 | STD_EXCEPTION_COMMON(0xf00, performance_monitor, .performance_monitor_exception) | ||
773 | STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception) | ||
774 | #ifdef CONFIG_ALTIVEC | ||
775 | STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception) | ||
776 | #else | ||
777 | STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception) | ||
778 | #endif | ||
779 | |||
780 | /* | ||
781 | * Here we have detected that the kernel stack pointer is bad. | ||
782 | * R9 contains the saved CR, r13 points to the paca, | ||
783 | * r10 contains the (bad) kernel stack pointer, | ||
784 | * r11 and r12 contain the saved SRR0 and SRR1. | ||
785 | * We switch to using an emergency stack, save the registers there, | ||
786 | * and call kernel_bad_stack(), which panics. | ||
787 | */ | ||
788 | bad_stack: | ||
789 | ld r1,PACAEMERGSP(r13) | ||
790 | subi r1,r1,64+INT_FRAME_SIZE | ||
791 | std r9,_CCR(r1) | ||
792 | std r10,GPR1(r1) | ||
793 | std r11,_NIP(r1) | ||
794 | std r12,_MSR(r1) | ||
795 | mfspr r11,SPRN_DAR | ||
796 | mfspr r12,SPRN_DSISR | ||
797 | std r11,_DAR(r1) | ||
798 | std r12,_DSISR(r1) | ||
799 | mflr r10 | ||
800 | mfctr r11 | ||
801 | mfxer r12 | ||
802 | std r10,_LINK(r1) | ||
803 | std r11,_CTR(r1) | ||
804 | std r12,_XER(r1) | ||
805 | SAVE_GPR(0,r1) | ||
806 | SAVE_GPR(2,r1) | ||
807 | SAVE_4GPRS(3,r1) | ||
808 | SAVE_2GPRS(7,r1) | ||
809 | SAVE_10GPRS(12,r1) | ||
810 | SAVE_10GPRS(22,r1) | ||
811 | addi r11,r1,INT_FRAME_SIZE | ||
812 | std r11,0(r1) | ||
813 | li r12,0 | ||
814 | std r12,0(r11) | ||
815 | ld r2,PACATOC(r13) | ||
816 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
817 | bl .kernel_bad_stack | ||
818 | b 1b | ||
819 | |||
820 | /* | ||
821 | * Return from an exception with minimal checks. | ||
822 | * The caller is assumed to have done EXCEPTION_PROLOG_COMMON. | ||
823 | * If interrupts have been enabled, or anything has been | ||
824 | * done that might have changed the scheduling status of | ||
825 | * any task or sent any task a signal, you should use | ||
826 | * ret_from_except or ret_from_except_lite instead of this. | ||
827 | */ | ||
828 | .globl fast_exception_return | ||
829 | fast_exception_return: | ||
830 | ld r12,_MSR(r1) | ||
831 | ld r11,_NIP(r1) | ||
832 | andi. r3,r12,MSR_RI /* check if RI is set */ | ||
833 | beq- unrecov_fer | ||
834 | ld r3,_CCR(r1) | ||
835 | ld r4,_LINK(r1) | ||
836 | ld r5,_CTR(r1) | ||
837 | ld r6,_XER(r1) | ||
838 | mtcr r3 | ||
839 | mtlr r4 | ||
840 | mtctr r5 | ||
841 | mtxer r6 | ||
842 | REST_GPR(0, r1) | ||
843 | REST_8GPRS(2, r1) | ||
844 | |||
845 | mfmsr r10 | ||
846 | clrrdi r10,r10,2 /* clear RI (LE is 0 already) */ | ||
847 | mtmsrd r10,1 | ||
848 | |||
849 | mtspr SPRN_SRR1,r12 | ||
850 | mtspr SPRN_SRR0,r11 | ||
851 | REST_4GPRS(10, r1) | ||
852 | ld r1,GPR1(r1) | ||
853 | rfid | ||
854 | b . /* prevent speculative execution */ | ||
855 | |||
856 | unrecov_fer: | ||
857 | bl .save_nvgprs | ||
858 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
859 | bl .unrecoverable_exception | ||
860 | b 1b | ||
861 | |||
862 | /* | ||
863 | * Here r13 points to the paca, r9 contains the saved CR, | ||
864 | * SRR0 and SRR1 are saved in r11 and r12, | ||
865 | * r9 - r13 are saved in paca->exgen. | ||
866 | */ | ||
867 | .align 7 | ||
868 | .globl data_access_common | ||
869 | data_access_common: | ||
870 | RUNLATCH_ON(r10) /* It wont fit in the 0x300 handler */ | ||
871 | mfspr r10,SPRN_DAR | ||
872 | std r10,PACA_EXGEN+EX_DAR(r13) | ||
873 | mfspr r10,SPRN_DSISR | ||
874 | stw r10,PACA_EXGEN+EX_DSISR(r13) | ||
875 | EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN) | ||
876 | ld r3,PACA_EXGEN+EX_DAR(r13) | ||
877 | lwz r4,PACA_EXGEN+EX_DSISR(r13) | ||
878 | li r5,0x300 | ||
879 | b .do_hash_page /* Try to handle as hpte fault */ | ||
880 | |||
881 | .align 7 | ||
882 | .globl instruction_access_common | ||
883 | instruction_access_common: | ||
884 | EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN) | ||
885 | ld r3,_NIP(r1) | ||
886 | andis. r4,r12,0x5820 | ||
887 | li r5,0x400 | ||
888 | b .do_hash_page /* Try to handle as hpte fault */ | ||
889 | |||
890 | /* | ||
891 | * Here is the common SLB miss user that is used when going to virtual | ||
892 | * mode for SLB misses, that is currently not used | ||
893 | */ | ||
894 | #ifdef __DISABLED__ | ||
895 | .align 7 | ||
896 | .globl slb_miss_user_common | ||
897 | slb_miss_user_common: | ||
898 | mflr r10 | ||
899 | std r3,PACA_EXGEN+EX_DAR(r13) | ||
900 | stw r9,PACA_EXGEN+EX_CCR(r13) | ||
901 | std r10,PACA_EXGEN+EX_LR(r13) | ||
902 | std r11,PACA_EXGEN+EX_SRR0(r13) | ||
903 | bl .slb_allocate_user | ||
904 | |||
905 | ld r10,PACA_EXGEN+EX_LR(r13) | ||
906 | ld r3,PACA_EXGEN+EX_R3(r13) | ||
907 | lwz r9,PACA_EXGEN+EX_CCR(r13) | ||
908 | ld r11,PACA_EXGEN+EX_SRR0(r13) | ||
909 | mtlr r10 | ||
910 | beq- slb_miss_fault | ||
911 | |||
912 | andi. r10,r12,MSR_RI /* check for unrecoverable exception */ | ||
913 | beq- unrecov_user_slb | ||
914 | mfmsr r10 | ||
915 | |||
916 | .machine push | ||
917 | .machine "power4" | ||
918 | mtcrf 0x80,r9 | ||
919 | .machine pop | ||
920 | |||
921 | clrrdi r10,r10,2 /* clear RI before setting SRR0/1 */ | ||
922 | mtmsrd r10,1 | ||
923 | |||
924 | mtspr SRR0,r11 | ||
925 | mtspr SRR1,r12 | ||
926 | |||
927 | ld r9,PACA_EXGEN+EX_R9(r13) | ||
928 | ld r10,PACA_EXGEN+EX_R10(r13) | ||
929 | ld r11,PACA_EXGEN+EX_R11(r13) | ||
930 | ld r12,PACA_EXGEN+EX_R12(r13) | ||
931 | ld r13,PACA_EXGEN+EX_R13(r13) | ||
932 | rfid | ||
933 | b . | ||
934 | |||
935 | slb_miss_fault: | ||
936 | EXCEPTION_PROLOG_COMMON(0x380, PACA_EXGEN) | ||
937 | ld r4,PACA_EXGEN+EX_DAR(r13) | ||
938 | li r5,0 | ||
939 | std r4,_DAR(r1) | ||
940 | std r5,_DSISR(r1) | ||
941 | b .handle_page_fault | ||
942 | |||
943 | unrecov_user_slb: | ||
944 | EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) | ||
945 | DISABLE_INTS | ||
946 | bl .save_nvgprs | ||
947 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
948 | bl .unrecoverable_exception | ||
949 | b 1b | ||
950 | |||
951 | #endif /* __DISABLED__ */ | ||
952 | |||
953 | |||
954 | /* | ||
955 | * r13 points to the PACA, r9 contains the saved CR, | ||
956 | * r12 contain the saved SRR1, SRR0 is still ready for return | ||
957 | * r3 has the faulting address | ||
958 | * r9 - r13 are saved in paca->exslb. | ||
959 | * r3 is saved in paca->slb_r3 | ||
960 | * We assume we aren't going to take any exceptions during this procedure. | ||
961 | */ | ||
962 | _GLOBAL(slb_miss_realmode) | ||
963 | mflr r10 | ||
964 | |||
965 | stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ | ||
966 | std r10,PACA_EXSLB+EX_LR(r13) /* save LR */ | ||
967 | |||
968 | bl .slb_allocate_realmode | ||
969 | |||
970 | /* All done -- return from exception. */ | ||
971 | |||
972 | ld r10,PACA_EXSLB+EX_LR(r13) | ||
973 | ld r3,PACA_EXSLB+EX_R3(r13) | ||
974 | lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ | ||
975 | #ifdef CONFIG_PPC_ISERIES | ||
976 | ld r11,PACALPPACA+LPPACASRR0(r13) /* get SRR0 value */ | ||
977 | #endif /* CONFIG_PPC_ISERIES */ | ||
978 | |||
979 | mtlr r10 | ||
980 | |||
981 | andi. r10,r12,MSR_RI /* check for unrecoverable exception */ | ||
982 | beq- unrecov_slb | ||
983 | |||
984 | .machine push | ||
985 | .machine "power4" | ||
986 | mtcrf 0x80,r9 | ||
987 | mtcrf 0x01,r9 /* slb_allocate uses cr0 and cr7 */ | ||
988 | .machine pop | ||
989 | |||
990 | #ifdef CONFIG_PPC_ISERIES | ||
991 | mtspr SPRN_SRR0,r11 | ||
992 | mtspr SPRN_SRR1,r12 | ||
993 | #endif /* CONFIG_PPC_ISERIES */ | ||
994 | ld r9,PACA_EXSLB+EX_R9(r13) | ||
995 | ld r10,PACA_EXSLB+EX_R10(r13) | ||
996 | ld r11,PACA_EXSLB+EX_R11(r13) | ||
997 | ld r12,PACA_EXSLB+EX_R12(r13) | ||
998 | ld r13,PACA_EXSLB+EX_R13(r13) | ||
999 | rfid | ||
1000 | b . /* prevent speculative execution */ | ||
1001 | |||
1002 | unrecov_slb: | ||
1003 | EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) | ||
1004 | DISABLE_INTS | ||
1005 | bl .save_nvgprs | ||
1006 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
1007 | bl .unrecoverable_exception | ||
1008 | b 1b | ||
1009 | |||
1010 | .align 7 | ||
1011 | .globl hardware_interrupt_common | ||
1012 | .globl hardware_interrupt_entry | ||
1013 | hardware_interrupt_common: | ||
1014 | EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN) | ||
1015 | hardware_interrupt_entry: | ||
1016 | DISABLE_INTS | ||
1017 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1018 | bl .do_IRQ | ||
1019 | b .ret_from_except_lite | ||
1020 | |||
1021 | .align 7 | ||
1022 | .globl alignment_common | ||
1023 | alignment_common: | ||
1024 | mfspr r10,SPRN_DAR | ||
1025 | std r10,PACA_EXGEN+EX_DAR(r13) | ||
1026 | mfspr r10,SPRN_DSISR | ||
1027 | stw r10,PACA_EXGEN+EX_DSISR(r13) | ||
1028 | EXCEPTION_PROLOG_COMMON(0x600, PACA_EXGEN) | ||
1029 | ld r3,PACA_EXGEN+EX_DAR(r13) | ||
1030 | lwz r4,PACA_EXGEN+EX_DSISR(r13) | ||
1031 | std r3,_DAR(r1) | ||
1032 | std r4,_DSISR(r1) | ||
1033 | bl .save_nvgprs | ||
1034 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1035 | ENABLE_INTS | ||
1036 | bl .alignment_exception | ||
1037 | b .ret_from_except | ||
1038 | |||
1039 | .align 7 | ||
1040 | .globl program_check_common | ||
1041 | program_check_common: | ||
1042 | EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN) | ||
1043 | bl .save_nvgprs | ||
1044 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1045 | ENABLE_INTS | ||
1046 | bl .program_check_exception | ||
1047 | b .ret_from_except | ||
1048 | |||
1049 | .align 7 | ||
1050 | .globl fp_unavailable_common | ||
1051 | fp_unavailable_common: | ||
1052 | EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN) | ||
1053 | bne .load_up_fpu /* if from user, just load it up */ | ||
1054 | bl .save_nvgprs | ||
1055 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1056 | ENABLE_INTS | ||
1057 | bl .kernel_fp_unavailable_exception | ||
1058 | BUG_OPCODE | ||
1059 | |||
1060 | .align 7 | ||
1061 | .globl altivec_unavailable_common | ||
1062 | altivec_unavailable_common: | ||
1063 | EXCEPTION_PROLOG_COMMON(0xf20, PACA_EXGEN) | ||
1064 | #ifdef CONFIG_ALTIVEC | ||
1065 | BEGIN_FTR_SECTION | ||
1066 | bne .load_up_altivec /* if from user, just load it up */ | ||
1067 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | ||
1068 | #endif | ||
1069 | bl .save_nvgprs | ||
1070 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1071 | ENABLE_INTS | ||
1072 | bl .altivec_unavailable_exception | ||
1073 | b .ret_from_except | ||
1074 | |||
1075 | #ifdef CONFIG_ALTIVEC | ||
1076 | /* | ||
1077 | * load_up_altivec(unused, unused, tsk) | ||
1078 | * Disable VMX for the task which had it previously, | ||
1079 | * and save its vector registers in its thread_struct. | ||
1080 | * Enables the VMX for use in the kernel on return. | ||
1081 | * On SMP we know the VMX is free, since we give it up every | ||
1082 | * switch (ie, no lazy save of the vector registers). | ||
1083 | * On entry: r13 == 'current' && last_task_used_altivec != 'current' | ||
1084 | */ | ||
1085 | _STATIC(load_up_altivec) | ||
1086 | mfmsr r5 /* grab the current MSR */ | ||
1087 | oris r5,r5,MSR_VEC@h | ||
1088 | mtmsrd r5 /* enable use of VMX now */ | ||
1089 | isync | ||
1090 | |||
1091 | /* | ||
1092 | * For SMP, we don't do lazy VMX switching because it just gets too | ||
1093 | * horrendously complex, especially when a task switches from one CPU | ||
1094 | * to another. Instead we call giveup_altvec in switch_to. | ||
1095 | * VRSAVE isn't dealt with here, that is done in the normal context | ||
1096 | * switch code. Note that we could rely on vrsave value to eventually | ||
1097 | * avoid saving all of the VREGs here... | ||
1098 | */ | ||
1099 | #ifndef CONFIG_SMP | ||
1100 | ld r3,last_task_used_altivec@got(r2) | ||
1101 | ld r4,0(r3) | ||
1102 | cmpdi 0,r4,0 | ||
1103 | beq 1f | ||
1104 | /* Save VMX state to last_task_used_altivec's THREAD struct */ | ||
1105 | addi r4,r4,THREAD | ||
1106 | SAVE_32VRS(0,r5,r4) | ||
1107 | mfvscr vr0 | ||
1108 | li r10,THREAD_VSCR | ||
1109 | stvx vr0,r10,r4 | ||
1110 | /* Disable VMX for last_task_used_altivec */ | ||
1111 | ld r5,PT_REGS(r4) | ||
1112 | ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
1113 | lis r6,MSR_VEC@h | ||
1114 | andc r4,r4,r6 | ||
1115 | std r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
1116 | 1: | ||
1117 | #endif /* CONFIG_SMP */ | ||
1118 | /* Hack: if we get an altivec unavailable trap with VRSAVE | ||
1119 | * set to all zeros, we assume this is a broken application | ||
1120 | * that fails to set it properly, and thus we switch it to | ||
1121 | * all 1's | ||
1122 | */ | ||
1123 | mfspr r4,SPRN_VRSAVE | ||
1124 | cmpdi 0,r4,0 | ||
1125 | bne+ 1f | ||
1126 | li r4,-1 | ||
1127 | mtspr SPRN_VRSAVE,r4 | ||
1128 | 1: | ||
1129 | /* enable use of VMX after return */ | ||
1130 | ld r4,PACACURRENT(r13) | ||
1131 | addi r5,r4,THREAD /* Get THREAD */ | ||
1132 | oris r12,r12,MSR_VEC@h | ||
1133 | std r12,_MSR(r1) | ||
1134 | li r4,1 | ||
1135 | li r10,THREAD_VSCR | ||
1136 | stw r4,THREAD_USED_VR(r5) | ||
1137 | lvx vr0,r10,r5 | ||
1138 | mtvscr vr0 | ||
1139 | REST_32VRS(0,r4,r5) | ||
1140 | #ifndef CONFIG_SMP | ||
1141 | /* Update last_task_used_math to 'current' */ | ||
1142 | subi r4,r5,THREAD /* Back to 'current' */ | ||
1143 | std r4,0(r3) | ||
1144 | #endif /* CONFIG_SMP */ | ||
1145 | /* restore registers and return */ | ||
1146 | b fast_exception_return | ||
1147 | #endif /* CONFIG_ALTIVEC */ | ||
1148 | |||
1149 | /* | ||
1150 | * Hash table stuff | ||
1151 | */ | ||
1152 | .align 7 | ||
1153 | _GLOBAL(do_hash_page) | ||
1154 | std r3,_DAR(r1) | ||
1155 | std r4,_DSISR(r1) | ||
1156 | |||
1157 | andis. r0,r4,0xa450 /* weird error? */ | ||
1158 | bne- .handle_page_fault /* if not, try to insert a HPTE */ | ||
1159 | BEGIN_FTR_SECTION | ||
1160 | andis. r0,r4,0x0020 /* Is it a segment table fault? */ | ||
1161 | bne- .do_ste_alloc /* If so handle it */ | ||
1162 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | ||
1163 | |||
1164 | /* | ||
1165 | * We need to set the _PAGE_USER bit if MSR_PR is set or if we are | ||
1166 | * accessing a userspace segment (even from the kernel). We assume | ||
1167 | * kernel addresses always have the high bit set. | ||
1168 | */ | ||
1169 | rlwinm r4,r4,32-25+9,31-9,31-9 /* DSISR_STORE -> _PAGE_RW */ | ||
1170 | rotldi r0,r3,15 /* Move high bit into MSR_PR posn */ | ||
1171 | orc r0,r12,r0 /* MSR_PR | ~high_bit */ | ||
1172 | rlwimi r4,r0,32-13,30,30 /* becomes _PAGE_USER access bit */ | ||
1173 | ori r4,r4,1 /* add _PAGE_PRESENT */ | ||
1174 | rlwimi r4,r5,22+2,31-2,31-2 /* Set _PAGE_EXEC if trap is 0x400 */ | ||
1175 | |||
1176 | /* | ||
1177 | * On iSeries, we soft-disable interrupts here, then | ||
1178 | * hard-enable interrupts so that the hash_page code can spin on | ||
1179 | * the hash_table_lock without problems on a shared processor. | ||
1180 | */ | ||
1181 | DISABLE_INTS | ||
1182 | |||
1183 | /* | ||
1184 | * r3 contains the faulting address | ||
1185 | * r4 contains the required access permissions | ||
1186 | * r5 contains the trap number | ||
1187 | * | ||
1188 | * at return r3 = 0 for success | ||
1189 | */ | ||
1190 | bl .hash_page /* build HPTE if possible */ | ||
1191 | cmpdi r3,0 /* see if hash_page succeeded */ | ||
1192 | |||
1193 | #ifdef DO_SOFT_DISABLE | ||
1194 | /* | ||
1195 | * If we had interrupts soft-enabled at the point where the | ||
1196 | * DSI/ISI occurred, and an interrupt came in during hash_page, | ||
1197 | * handle it now. | ||
1198 | * We jump to ret_from_except_lite rather than fast_exception_return | ||
1199 | * because ret_from_except_lite will check for and handle pending | ||
1200 | * interrupts if necessary. | ||
1201 | */ | ||
1202 | beq .ret_from_except_lite | ||
1203 | /* For a hash failure, we don't bother re-enabling interrupts */ | ||
1204 | ble- 12f | ||
1205 | |||
1206 | /* | ||
1207 | * hash_page couldn't handle it, set soft interrupt enable back | ||
1208 | * to what it was before the trap. Note that .local_irq_restore | ||
1209 | * handles any interrupts pending at this point. | ||
1210 | */ | ||
1211 | ld r3,SOFTE(r1) | ||
1212 | bl .local_irq_restore | ||
1213 | b 11f | ||
1214 | #else | ||
1215 | beq fast_exception_return /* Return from exception on success */ | ||
1216 | ble- 12f /* Failure return from hash_page */ | ||
1217 | |||
1218 | /* fall through */ | ||
1219 | #endif | ||
1220 | |||
1221 | /* Here we have a page fault that hash_page can't handle. */ | ||
1222 | _GLOBAL(handle_page_fault) | ||
1223 | ENABLE_INTS | ||
1224 | 11: ld r4,_DAR(r1) | ||
1225 | ld r5,_DSISR(r1) | ||
1226 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1227 | bl .do_page_fault | ||
1228 | cmpdi r3,0 | ||
1229 | beq+ .ret_from_except_lite | ||
1230 | bl .save_nvgprs | ||
1231 | mr r5,r3 | ||
1232 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1233 | lwz r4,_DAR(r1) | ||
1234 | bl .bad_page_fault | ||
1235 | b .ret_from_except | ||
1236 | |||
1237 | /* We have a page fault that hash_page could handle but HV refused | ||
1238 | * the PTE insertion | ||
1239 | */ | ||
1240 | 12: bl .save_nvgprs | ||
1241 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1242 | lwz r4,_DAR(r1) | ||
1243 | bl .low_hash_fault | ||
1244 | b .ret_from_except | ||
1245 | |||
1246 | /* here we have a segment miss */ | ||
1247 | _GLOBAL(do_ste_alloc) | ||
1248 | bl .ste_allocate /* try to insert stab entry */ | ||
1249 | cmpdi r3,0 | ||
1250 | beq+ fast_exception_return | ||
1251 | b .handle_page_fault | ||
1252 | |||
1253 | /* | ||
1254 | * r13 points to the PACA, r9 contains the saved CR, | ||
1255 | * r11 and r12 contain the saved SRR0 and SRR1. | ||
1256 | * r9 - r13 are saved in paca->exslb. | ||
1257 | * We assume we aren't going to take any exceptions during this procedure. | ||
1258 | * We assume (DAR >> 60) == 0xc. | ||
1259 | */ | ||
1260 | .align 7 | ||
1261 | _GLOBAL(do_stab_bolted) | ||
1262 | stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ | ||
1263 | std r11,PACA_EXSLB+EX_SRR0(r13) /* save SRR0 in exc. frame */ | ||
1264 | |||
1265 | /* Hash to the primary group */ | ||
1266 | ld r10,PACASTABVIRT(r13) | ||
1267 | mfspr r11,SPRN_DAR | ||
1268 | srdi r11,r11,28 | ||
1269 | rldimi r10,r11,7,52 /* r10 = first ste of the group */ | ||
1270 | |||
1271 | /* Calculate VSID */ | ||
1272 | /* This is a kernel address, so protovsid = ESID */ | ||
1273 | ASM_VSID_SCRAMBLE(r11, r9) | ||
1274 | rldic r9,r11,12,16 /* r9 = vsid << 12 */ | ||
1275 | |||
1276 | /* Search the primary group for a free entry */ | ||
1277 | 1: ld r11,0(r10) /* Test valid bit of the current ste */ | ||
1278 | andi. r11,r11,0x80 | ||
1279 | beq 2f | ||
1280 | addi r10,r10,16 | ||
1281 | andi. r11,r10,0x70 | ||
1282 | bne 1b | ||
1283 | |||
1284 | /* Stick for only searching the primary group for now. */ | ||
1285 | /* At least for now, we use a very simple random castout scheme */ | ||
1286 | /* Use the TB as a random number ; OR in 1 to avoid entry 0 */ | ||
1287 | mftb r11 | ||
1288 | rldic r11,r11,4,57 /* r11 = (r11 << 4) & 0x70 */ | ||
1289 | ori r11,r11,0x10 | ||
1290 | |||
1291 | /* r10 currently points to an ste one past the group of interest */ | ||
1292 | /* make it point to the randomly selected entry */ | ||
1293 | subi r10,r10,128 | ||
1294 | or r10,r10,r11 /* r10 is the entry to invalidate */ | ||
1295 | |||
1296 | isync /* mark the entry invalid */ | ||
1297 | ld r11,0(r10) | ||
1298 | rldicl r11,r11,56,1 /* clear the valid bit */ | ||
1299 | rotldi r11,r11,8 | ||
1300 | std r11,0(r10) | ||
1301 | sync | ||
1302 | |||
1303 | clrrdi r11,r11,28 /* Get the esid part of the ste */ | ||
1304 | slbie r11 | ||
1305 | |||
1306 | 2: std r9,8(r10) /* Store the vsid part of the ste */ | ||
1307 | eieio | ||
1308 | |||
1309 | mfspr r11,SPRN_DAR /* Get the new esid */ | ||
1310 | clrrdi r11,r11,28 /* Permits a full 32b of ESID */ | ||
1311 | ori r11,r11,0x90 /* Turn on valid and kp */ | ||
1312 | std r11,0(r10) /* Put new entry back into the stab */ | ||
1313 | |||
1314 | sync | ||
1315 | |||
1316 | /* All done -- return from exception. */ | ||
1317 | lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ | ||
1318 | ld r11,PACA_EXSLB+EX_SRR0(r13) /* get saved SRR0 */ | ||
1319 | |||
1320 | andi. r10,r12,MSR_RI | ||
1321 | beq- unrecov_slb | ||
1322 | |||
1323 | mtcrf 0x80,r9 /* restore CR */ | ||
1324 | |||
1325 | mfmsr r10 | ||
1326 | clrrdi r10,r10,2 | ||
1327 | mtmsrd r10,1 | ||
1328 | |||
1329 | mtspr SPRN_SRR0,r11 | ||
1330 | mtspr SPRN_SRR1,r12 | ||
1331 | ld r9,PACA_EXSLB+EX_R9(r13) | ||
1332 | ld r10,PACA_EXSLB+EX_R10(r13) | ||
1333 | ld r11,PACA_EXSLB+EX_R11(r13) | ||
1334 | ld r12,PACA_EXSLB+EX_R12(r13) | ||
1335 | ld r13,PACA_EXSLB+EX_R13(r13) | ||
1336 | rfid | ||
1337 | b . /* prevent speculative execution */ | ||
1338 | |||
1339 | /* | ||
1340 | * Space for CPU0's segment table. | ||
1341 | * | ||
1342 | * On iSeries, the hypervisor must fill in at least one entry before | ||
1343 | * we get control (with relocate on). The address is give to the hv | ||
1344 | * as a page number (see xLparMap in lpardata.c), so this must be at a | ||
1345 | * fixed address (the linker can't compute (u64)&initial_stab >> | ||
1346 | * PAGE_SHIFT). | ||
1347 | */ | ||
1348 | . = STAB0_PHYS_ADDR /* 0x6000 */ | ||
1349 | .globl initial_stab | ||
1350 | initial_stab: | ||
1351 | .space 4096 | ||
1352 | |||
1353 | /* | ||
1354 | * Data area reserved for FWNMI option. | ||
1355 | * This address (0x7000) is fixed by the RPA. | ||
1356 | */ | ||
1357 | .= 0x7000 | ||
1358 | .globl fwnmi_data_area | ||
1359 | fwnmi_data_area: | ||
1360 | |||
1361 | /* iSeries does not use the FWNMI stuff, so it is safe to put | ||
1362 | * this here, even if we later allow kernels that will boot on | ||
1363 | * both pSeries and iSeries */ | ||
1364 | #ifdef CONFIG_PPC_ISERIES | ||
1365 | . = LPARMAP_PHYS | ||
1366 | #include "lparmap.s" | ||
1367 | /* | ||
1368 | * This ".text" is here for old compilers that generate a trailing | ||
1369 | * .note section when compiling .c files to .s | ||
1370 | */ | ||
1371 | .text | ||
1372 | #endif /* CONFIG_PPC_ISERIES */ | ||
1373 | |||
1374 | . = 0x8000 | ||
1375 | |||
1376 | /* | ||
1377 | * On pSeries, secondary processors spin in the following code. | ||
1378 | * At entry, r3 = this processor's number (physical cpu id) | ||
1379 | */ | ||
1380 | _GLOBAL(pSeries_secondary_smp_init) | ||
1381 | mr r24,r3 | ||
1382 | |||
1383 | /* turn on 64-bit mode */ | ||
1384 | bl .enable_64b_mode | ||
1385 | isync | ||
1386 | |||
1387 | /* Copy some CPU settings from CPU 0 */ | ||
1388 | bl .__restore_cpu_setup | ||
1389 | |||
1390 | /* Set up a paca value for this processor. Since we have the | ||
1391 | * physical cpu id in r24, we need to search the pacas to find | ||
1392 | * which logical id maps to our physical one. | ||
1393 | */ | ||
1394 | LOADADDR(r13, paca) /* Get base vaddr of paca array */ | ||
1395 | li r5,0 /* logical cpu id */ | ||
1396 | 1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ | ||
1397 | cmpw r6,r24 /* Compare to our id */ | ||
1398 | beq 2f | ||
1399 | addi r13,r13,PACA_SIZE /* Loop to next PACA on miss */ | ||
1400 | addi r5,r5,1 | ||
1401 | cmpwi r5,NR_CPUS | ||
1402 | blt 1b | ||
1403 | |||
1404 | mr r3,r24 /* not found, copy phys to r3 */ | ||
1405 | b .kexec_wait /* next kernel might do better */ | ||
1406 | |||
1407 | 2: mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ | ||
1408 | /* From now on, r24 is expected to be logical cpuid */ | ||
1409 | mr r24,r5 | ||
1410 | 3: HMT_LOW | ||
1411 | lbz r23,PACAPROCSTART(r13) /* Test if this processor should */ | ||
1412 | /* start. */ | ||
1413 | sync | ||
1414 | |||
1415 | /* Create a temp kernel stack for use before relocation is on. */ | ||
1416 | ld r1,PACAEMERGSP(r13) | ||
1417 | subi r1,r1,STACK_FRAME_OVERHEAD | ||
1418 | |||
1419 | cmpwi 0,r23,0 | ||
1420 | #ifdef CONFIG_SMP | ||
1421 | bne .__secondary_start | ||
1422 | #endif | ||
1423 | b 3b /* Loop until told to go */ | ||
1424 | |||
1425 | #ifdef CONFIG_PPC_ISERIES | ||
1426 | _STATIC(__start_initialization_iSeries) | ||
1427 | /* Clear out the BSS */ | ||
1428 | LOADADDR(r11,__bss_stop) | ||
1429 | LOADADDR(r8,__bss_start) | ||
1430 | sub r11,r11,r8 /* bss size */ | ||
1431 | addi r11,r11,7 /* round up to an even double word */ | ||
1432 | rldicl. r11,r11,61,3 /* shift right by 3 */ | ||
1433 | beq 4f | ||
1434 | addi r8,r8,-8 | ||
1435 | li r0,0 | ||
1436 | mtctr r11 /* zero this many doublewords */ | ||
1437 | 3: stdu r0,8(r8) | ||
1438 | bdnz 3b | ||
1439 | 4: | ||
1440 | LOADADDR(r1,init_thread_union) | ||
1441 | addi r1,r1,THREAD_SIZE | ||
1442 | li r0,0 | ||
1443 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | ||
1444 | |||
1445 | LOADADDR(r3,cpu_specs) | ||
1446 | LOADADDR(r4,cur_cpu_spec) | ||
1447 | li r5,0 | ||
1448 | bl .identify_cpu | ||
1449 | |||
1450 | LOADADDR(r2,__toc_start) | ||
1451 | addi r2,r2,0x4000 | ||
1452 | addi r2,r2,0x4000 | ||
1453 | |||
1454 | bl .iSeries_early_setup | ||
1455 | bl .early_setup | ||
1456 | |||
1457 | /* relocation is on at this point */ | ||
1458 | |||
1459 | b .start_here_common | ||
1460 | #endif /* CONFIG_PPC_ISERIES */ | ||
1461 | |||
1462 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
1463 | |||
1464 | _STATIC(__mmu_off) | ||
1465 | mfmsr r3 | ||
1466 | andi. r0,r3,MSR_IR|MSR_DR | ||
1467 | beqlr | ||
1468 | andc r3,r3,r0 | ||
1469 | mtspr SPRN_SRR0,r4 | ||
1470 | mtspr SPRN_SRR1,r3 | ||
1471 | sync | ||
1472 | rfid | ||
1473 | b . /* prevent speculative execution */ | ||
1474 | |||
1475 | |||
1476 | /* | ||
1477 | * Here is our main kernel entry point. We support currently 2 kind of entries | ||
1478 | * depending on the value of r5. | ||
1479 | * | ||
1480 | * r5 != NULL -> OF entry, we go to prom_init, "legacy" parameter content | ||
1481 | * in r3...r7 | ||
1482 | * | ||
1483 | * r5 == NULL -> kexec style entry. r3 is a physical pointer to the | ||
1484 | * DT block, r4 is a physical pointer to the kernel itself | ||
1485 | * | ||
1486 | */ | ||
1487 | _GLOBAL(__start_initialization_multiplatform) | ||
1488 | /* | ||
1489 | * Are we booted from a PROM Of-type client-interface ? | ||
1490 | */ | ||
1491 | cmpldi cr0,r5,0 | ||
1492 | bne .__boot_from_prom /* yes -> prom */ | ||
1493 | |||
1494 | /* Save parameters */ | ||
1495 | mr r31,r3 | ||
1496 | mr r30,r4 | ||
1497 | |||
1498 | /* Make sure we are running in 64 bits mode */ | ||
1499 | bl .enable_64b_mode | ||
1500 | |||
1501 | /* Setup some critical 970 SPRs before switching MMU off */ | ||
1502 | bl .__970_cpu_preinit | ||
1503 | |||
1504 | /* cpu # */ | ||
1505 | li r24,0 | ||
1506 | |||
1507 | /* Switch off MMU if not already */ | ||
1508 | LOADADDR(r4, .__after_prom_start - KERNELBASE) | ||
1509 | add r4,r4,r30 | ||
1510 | bl .__mmu_off | ||
1511 | b .__after_prom_start | ||
1512 | |||
1513 | _STATIC(__boot_from_prom) | ||
1514 | /* Save parameters */ | ||
1515 | mr r31,r3 | ||
1516 | mr r30,r4 | ||
1517 | mr r29,r5 | ||
1518 | mr r28,r6 | ||
1519 | mr r27,r7 | ||
1520 | |||
1521 | /* Make sure we are running in 64 bits mode */ | ||
1522 | bl .enable_64b_mode | ||
1523 | |||
1524 | /* put a relocation offset into r3 */ | ||
1525 | bl .reloc_offset | ||
1526 | |||
1527 | LOADADDR(r2,__toc_start) | ||
1528 | addi r2,r2,0x4000 | ||
1529 | addi r2,r2,0x4000 | ||
1530 | |||
1531 | /* Relocate the TOC from a virt addr to a real addr */ | ||
1532 | sub r2,r2,r3 | ||
1533 | |||
1534 | /* Restore parameters */ | ||
1535 | mr r3,r31 | ||
1536 | mr r4,r30 | ||
1537 | mr r5,r29 | ||
1538 | mr r6,r28 | ||
1539 | mr r7,r27 | ||
1540 | |||
1541 | /* Do all of the interaction with OF client interface */ | ||
1542 | bl .prom_init | ||
1543 | /* We never return */ | ||
1544 | trap | ||
1545 | |||
1546 | /* | ||
1547 | * At this point, r3 contains the physical address we are running at, | ||
1548 | * returned by prom_init() | ||
1549 | */ | ||
1550 | _STATIC(__after_prom_start) | ||
1551 | |||
1552 | /* | ||
1553 | * We need to run with __start at physical address 0. | ||
1554 | * This will leave some code in the first 256B of | ||
1555 | * real memory, which are reserved for software use. | ||
1556 | * The remainder of the first page is loaded with the fixed | ||
1557 | * interrupt vectors. The next two pages are filled with | ||
1558 | * unknown exception placeholders. | ||
1559 | * | ||
1560 | * Note: This process overwrites the OF exception vectors. | ||
1561 | * r26 == relocation offset | ||
1562 | * r27 == KERNELBASE | ||
1563 | */ | ||
1564 | bl .reloc_offset | ||
1565 | mr r26,r3 | ||
1566 | SET_REG_TO_CONST(r27,KERNELBASE) | ||
1567 | |||
1568 | li r3,0 /* target addr */ | ||
1569 | |||
1570 | // XXX FIXME: Use phys returned by OF (r30) | ||
1571 | sub r4,r27,r26 /* source addr */ | ||
1572 | /* current address of _start */ | ||
1573 | /* i.e. where we are running */ | ||
1574 | /* the source addr */ | ||
1575 | |||
1576 | LOADADDR(r5,copy_to_here) /* # bytes of memory to copy */ | ||
1577 | sub r5,r5,r27 | ||
1578 | |||
1579 | li r6,0x100 /* Start offset, the first 0x100 */ | ||
1580 | /* bytes were copied earlier. */ | ||
1581 | |||
1582 | bl .copy_and_flush /* copy the first n bytes */ | ||
1583 | /* this includes the code being */ | ||
1584 | /* executed here. */ | ||
1585 | |||
1586 | LOADADDR(r0, 4f) /* Jump to the copy of this code */ | ||
1587 | mtctr r0 /* that we just made/relocated */ | ||
1588 | bctr | ||
1589 | |||
1590 | 4: LOADADDR(r5,klimit) | ||
1591 | sub r5,r5,r26 | ||
1592 | ld r5,0(r5) /* get the value of klimit */ | ||
1593 | sub r5,r5,r27 | ||
1594 | bl .copy_and_flush /* copy the rest */ | ||
1595 | b .start_here_multiplatform | ||
1596 | |||
1597 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
1598 | |||
1599 | /* | ||
1600 | * Copy routine used to copy the kernel to start at physical address 0 | ||
1601 | * and flush and invalidate the caches as needed. | ||
1602 | * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset | ||
1603 | * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5. | ||
1604 | * | ||
1605 | * Note: this routine *only* clobbers r0, r6 and lr | ||
1606 | */ | ||
1607 | _GLOBAL(copy_and_flush) | ||
1608 | addi r5,r5,-8 | ||
1609 | addi r6,r6,-8 | ||
1610 | 4: li r0,16 /* Use the least common */ | ||
1611 | /* denominator cache line */ | ||
1612 | /* size. This results in */ | ||
1613 | /* extra cache line flushes */ | ||
1614 | /* but operation is correct. */ | ||
1615 | /* Can't get cache line size */ | ||
1616 | /* from NACA as it is being */ | ||
1617 | /* moved too. */ | ||
1618 | |||
1619 | mtctr r0 /* put # words/line in ctr */ | ||
1620 | 3: addi r6,r6,8 /* copy a cache line */ | ||
1621 | ldx r0,r6,r4 | ||
1622 | stdx r0,r6,r3 | ||
1623 | bdnz 3b | ||
1624 | dcbst r6,r3 /* write it to memory */ | ||
1625 | sync | ||
1626 | icbi r6,r3 /* flush the icache line */ | ||
1627 | cmpld 0,r6,r5 | ||
1628 | blt 4b | ||
1629 | sync | ||
1630 | addi r5,r5,8 | ||
1631 | addi r6,r6,8 | ||
1632 | blr | ||
1633 | |||
1634 | .align 8 | ||
1635 | copy_to_here: | ||
1636 | |||
1637 | #ifdef CONFIG_SMP | ||
1638 | #ifdef CONFIG_PPC_PMAC | ||
1639 | /* | ||
1640 | * On PowerMac, secondary processors starts from the reset vector, which | ||
1641 | * is temporarily turned into a call to one of the functions below. | ||
1642 | */ | ||
1643 | .section ".text"; | ||
1644 | .align 2 ; | ||
1645 | |||
1646 | .globl __secondary_start_pmac_0 | ||
1647 | __secondary_start_pmac_0: | ||
1648 | /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */ | ||
1649 | li r24,0 | ||
1650 | b 1f | ||
1651 | li r24,1 | ||
1652 | b 1f | ||
1653 | li r24,2 | ||
1654 | b 1f | ||
1655 | li r24,3 | ||
1656 | 1: | ||
1657 | |||
1658 | _GLOBAL(pmac_secondary_start) | ||
1659 | /* turn on 64-bit mode */ | ||
1660 | bl .enable_64b_mode | ||
1661 | isync | ||
1662 | |||
1663 | /* Copy some CPU settings from CPU 0 */ | ||
1664 | bl .__restore_cpu_setup | ||
1665 | |||
1666 | /* pSeries do that early though I don't think we really need it */ | ||
1667 | mfmsr r3 | ||
1668 | ori r3,r3,MSR_RI | ||
1669 | mtmsrd r3 /* RI on */ | ||
1670 | |||
1671 | /* Set up a paca value for this processor. */ | ||
1672 | LOADADDR(r4, paca) /* Get base vaddr of paca array */ | ||
1673 | mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ | ||
1674 | add r13,r13,r4 /* for this processor. */ | ||
1675 | mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ | ||
1676 | |||
1677 | /* Create a temp kernel stack for use before relocation is on. */ | ||
1678 | ld r1,PACAEMERGSP(r13) | ||
1679 | subi r1,r1,STACK_FRAME_OVERHEAD | ||
1680 | |||
1681 | b .__secondary_start | ||
1682 | |||
1683 | #endif /* CONFIG_PPC_PMAC */ | ||
1684 | |||
1685 | /* | ||
1686 | * This function is called after the master CPU has released the | ||
1687 | * secondary processors. The execution environment is relocation off. | ||
1688 | * The paca for this processor has the following fields initialized at | ||
1689 | * this point: | ||
1690 | * 1. Processor number | ||
1691 | * 2. Segment table pointer (virtual address) | ||
1692 | * On entry the following are set: | ||
1693 | * r1 = stack pointer. vaddr for iSeries, raddr (temp stack) for pSeries | ||
1694 | * r24 = cpu# (in Linux terms) | ||
1695 | * r13 = paca virtual address | ||
1696 | * SPRG3 = paca virtual address | ||
1697 | */ | ||
1698 | _GLOBAL(__secondary_start) | ||
1699 | |||
1700 | HMT_MEDIUM /* Set thread priority to MEDIUM */ | ||
1701 | |||
1702 | ld r2,PACATOC(r13) | ||
1703 | |||
1704 | /* Do early setup for that CPU */ | ||
1705 | bl .early_setup_secondary | ||
1706 | |||
1707 | /* Initialize the kernel stack. Just a repeat for iSeries. */ | ||
1708 | LOADADDR(r3,current_set) | ||
1709 | sldi r28,r24,3 /* get current_set[cpu#] */ | ||
1710 | ldx r1,r3,r28 | ||
1711 | addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD | ||
1712 | std r1,PACAKSAVE(r13) | ||
1713 | |||
1714 | li r7,0 | ||
1715 | mtlr r7 | ||
1716 | |||
1717 | /* enable MMU and jump to start_secondary */ | ||
1718 | LOADADDR(r3,.start_secondary_prolog) | ||
1719 | SET_REG_TO_CONST(r4, MSR_KERNEL) | ||
1720 | #ifdef DO_SOFT_DISABLE | ||
1721 | ori r4,r4,MSR_EE | ||
1722 | #endif | ||
1723 | mtspr SPRN_SRR0,r3 | ||
1724 | mtspr SPRN_SRR1,r4 | ||
1725 | rfid | ||
1726 | b . /* prevent speculative execution */ | ||
1727 | |||
1728 | /* | ||
1729 | * Running with relocation on at this point. All we want to do is | ||
1730 | * zero the stack back-chain pointer before going into C code. | ||
1731 | */ | ||
1732 | _GLOBAL(start_secondary_prolog) | ||
1733 | li r3,0 | ||
1734 | std r3,0(r1) /* Zero the stack frame pointer */ | ||
1735 | bl .start_secondary | ||
1736 | #endif | ||
1737 | |||
1738 | /* | ||
1739 | * This subroutine clobbers r11 and r12 | ||
1740 | */ | ||
1741 | _GLOBAL(enable_64b_mode) | ||
1742 | mfmsr r11 /* grab the current MSR */ | ||
1743 | li r12,1 | ||
1744 | rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG) | ||
1745 | or r11,r11,r12 | ||
1746 | li r12,1 | ||
1747 | rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG) | ||
1748 | or r11,r11,r12 | ||
1749 | mtmsrd r11 | ||
1750 | isync | ||
1751 | blr | ||
1752 | |||
1753 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
1754 | /* | ||
1755 | * This is where the main kernel code starts. | ||
1756 | */ | ||
1757 | _STATIC(start_here_multiplatform) | ||
1758 | /* get a new offset, now that the kernel has moved. */ | ||
1759 | bl .reloc_offset | ||
1760 | mr r26,r3 | ||
1761 | |||
1762 | /* Clear out the BSS. It may have been done in prom_init, | ||
1763 | * already but that's irrelevant since prom_init will soon | ||
1764 | * be detached from the kernel completely. Besides, we need | ||
1765 | * to clear it now for kexec-style entry. | ||
1766 | */ | ||
1767 | LOADADDR(r11,__bss_stop) | ||
1768 | LOADADDR(r8,__bss_start) | ||
1769 | sub r11,r11,r8 /* bss size */ | ||
1770 | addi r11,r11,7 /* round up to an even double word */ | ||
1771 | rldicl. r11,r11,61,3 /* shift right by 3 */ | ||
1772 | beq 4f | ||
1773 | addi r8,r8,-8 | ||
1774 | li r0,0 | ||
1775 | mtctr r11 /* zero this many doublewords */ | ||
1776 | 3: stdu r0,8(r8) | ||
1777 | bdnz 3b | ||
1778 | 4: | ||
1779 | |||
1780 | mfmsr r6 | ||
1781 | ori r6,r6,MSR_RI | ||
1782 | mtmsrd r6 /* RI on */ | ||
1783 | |||
1784 | #ifdef CONFIG_HMT | ||
1785 | /* Start up the second thread on cpu 0 */ | ||
1786 | mfspr r3,SPRN_PVR | ||
1787 | srwi r3,r3,16 | ||
1788 | cmpwi r3,0x34 /* Pulsar */ | ||
1789 | beq 90f | ||
1790 | cmpwi r3,0x36 /* Icestar */ | ||
1791 | beq 90f | ||
1792 | cmpwi r3,0x37 /* SStar */ | ||
1793 | beq 90f | ||
1794 | b 91f /* HMT not supported */ | ||
1795 | 90: li r3,0 | ||
1796 | bl .hmt_start_secondary | ||
1797 | 91: | ||
1798 | #endif | ||
1799 | |||
1800 | /* The following gets the stack and TOC set up with the regs */ | ||
1801 | /* pointing to the real addr of the kernel stack. This is */ | ||
1802 | /* all done to support the C function call below which sets */ | ||
1803 | /* up the htab. This is done because we have relocated the */ | ||
1804 | /* kernel but are still running in real mode. */ | ||
1805 | |||
1806 | LOADADDR(r3,init_thread_union) | ||
1807 | sub r3,r3,r26 | ||
1808 | |||
1809 | /* set up a stack pointer (physical address) */ | ||
1810 | addi r1,r3,THREAD_SIZE | ||
1811 | li r0,0 | ||
1812 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | ||
1813 | |||
1814 | /* set up the TOC (physical address) */ | ||
1815 | LOADADDR(r2,__toc_start) | ||
1816 | addi r2,r2,0x4000 | ||
1817 | addi r2,r2,0x4000 | ||
1818 | sub r2,r2,r26 | ||
1819 | |||
1820 | LOADADDR(r3,cpu_specs) | ||
1821 | sub r3,r3,r26 | ||
1822 | LOADADDR(r4,cur_cpu_spec) | ||
1823 | sub r4,r4,r26 | ||
1824 | mr r5,r26 | ||
1825 | bl .identify_cpu | ||
1826 | |||
1827 | /* Save some low level config HIDs of CPU0 to be copied to | ||
1828 | * other CPUs later on, or used for suspend/resume | ||
1829 | */ | ||
1830 | bl .__save_cpu_setup | ||
1831 | sync | ||
1832 | |||
1833 | /* Setup a valid physical PACA pointer in SPRG3 for early_setup | ||
1834 | * note that boot_cpuid can always be 0 nowadays since there is | ||
1835 | * nowhere it can be initialized differently before we reach this | ||
1836 | * code | ||
1837 | */ | ||
1838 | LOADADDR(r27, boot_cpuid) | ||
1839 | sub r27,r27,r26 | ||
1840 | lwz r27,0(r27) | ||
1841 | |||
1842 | LOADADDR(r24, paca) /* Get base vaddr of paca array */ | ||
1843 | mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */ | ||
1844 | add r13,r13,r24 /* for this processor. */ | ||
1845 | sub r13,r13,r26 /* convert to physical addr */ | ||
1846 | mtspr SPRN_SPRG3,r13 /* PPPBBB: Temp... -Peter */ | ||
1847 | |||
1848 | /* Do very early kernel initializations, including initial hash table, | ||
1849 | * stab and slb setup before we turn on relocation. */ | ||
1850 | |||
1851 | /* Restore parameters passed from prom_init/kexec */ | ||
1852 | mr r3,r31 | ||
1853 | bl .early_setup | ||
1854 | |||
1855 | LOADADDR(r3,.start_here_common) | ||
1856 | SET_REG_TO_CONST(r4, MSR_KERNEL) | ||
1857 | mtspr SPRN_SRR0,r3 | ||
1858 | mtspr SPRN_SRR1,r4 | ||
1859 | rfid | ||
1860 | b . /* prevent speculative execution */ | ||
1861 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
1862 | |||
1863 | /* This is where all platforms converge execution */ | ||
1864 | _STATIC(start_here_common) | ||
1865 | /* relocation is on at this point */ | ||
1866 | |||
1867 | /* The following code sets up the SP and TOC now that we are */ | ||
1868 | /* running with translation enabled. */ | ||
1869 | |||
1870 | LOADADDR(r3,init_thread_union) | ||
1871 | |||
1872 | /* set up the stack */ | ||
1873 | addi r1,r3,THREAD_SIZE | ||
1874 | li r0,0 | ||
1875 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | ||
1876 | |||
1877 | /* Apply the CPUs-specific fixups (nop out sections not relevant | ||
1878 | * to this CPU | ||
1879 | */ | ||
1880 | li r3,0 | ||
1881 | bl .do_cpu_ftr_fixups | ||
1882 | |||
1883 | LOADADDR(r26, boot_cpuid) | ||
1884 | lwz r26,0(r26) | ||
1885 | |||
1886 | LOADADDR(r24, paca) /* Get base vaddr of paca array */ | ||
1887 | mulli r13,r26,PACA_SIZE /* Calculate vaddr of right paca */ | ||
1888 | add r13,r13,r24 /* for this processor. */ | ||
1889 | mtspr SPRN_SPRG3,r13 | ||
1890 | |||
1891 | /* ptr to current */ | ||
1892 | LOADADDR(r4,init_task) | ||
1893 | std r4,PACACURRENT(r13) | ||
1894 | |||
1895 | /* Load the TOC */ | ||
1896 | ld r2,PACATOC(r13) | ||
1897 | std r1,PACAKSAVE(r13) | ||
1898 | |||
1899 | bl .setup_system | ||
1900 | |||
1901 | /* Load up the kernel context */ | ||
1902 | 5: | ||
1903 | #ifdef DO_SOFT_DISABLE | ||
1904 | li r5,0 | ||
1905 | stb r5,PACAPROCENABLED(r13) /* Soft Disabled */ | ||
1906 | mfmsr r5 | ||
1907 | ori r5,r5,MSR_EE /* Hard Enabled */ | ||
1908 | mtmsrd r5 | ||
1909 | #endif | ||
1910 | |||
1911 | bl .start_kernel | ||
1912 | |||
1913 | _GLOBAL(hmt_init) | ||
1914 | #ifdef CONFIG_HMT | ||
1915 | LOADADDR(r5, hmt_thread_data) | ||
1916 | mfspr r7,SPRN_PVR | ||
1917 | srwi r7,r7,16 | ||
1918 | cmpwi r7,0x34 /* Pulsar */ | ||
1919 | beq 90f | ||
1920 | cmpwi r7,0x36 /* Icestar */ | ||
1921 | beq 91f | ||
1922 | cmpwi r7,0x37 /* SStar */ | ||
1923 | beq 91f | ||
1924 | b 101f | ||
1925 | 90: mfspr r6,SPRN_PIR | ||
1926 | andi. r6,r6,0x1f | ||
1927 | b 92f | ||
1928 | 91: mfspr r6,SPRN_PIR | ||
1929 | andi. r6,r6,0x3ff | ||
1930 | 92: sldi r4,r24,3 | ||
1931 | stwx r6,r5,r4 | ||
1932 | bl .hmt_start_secondary | ||
1933 | b 101f | ||
1934 | |||
1935 | __hmt_secondary_hold: | ||
1936 | LOADADDR(r5, hmt_thread_data) | ||
1937 | clrldi r5,r5,4 | ||
1938 | li r7,0 | ||
1939 | mfspr r6,SPRN_PIR | ||
1940 | mfspr r8,SPRN_PVR | ||
1941 | srwi r8,r8,16 | ||
1942 | cmpwi r8,0x34 | ||
1943 | bne 93f | ||
1944 | andi. r6,r6,0x1f | ||
1945 | b 103f | ||
1946 | 93: andi. r6,r6,0x3f | ||
1947 | |||
1948 | 103: lwzx r8,r5,r7 | ||
1949 | cmpw r8,r6 | ||
1950 | beq 104f | ||
1951 | addi r7,r7,8 | ||
1952 | b 103b | ||
1953 | |||
1954 | 104: addi r7,r7,4 | ||
1955 | lwzx r9,r5,r7 | ||
1956 | mr r24,r9 | ||
1957 | 101: | ||
1958 | #endif | ||
1959 | mr r3,r24 | ||
1960 | b .pSeries_secondary_smp_init | ||
1961 | |||
1962 | #ifdef CONFIG_HMT | ||
1963 | _GLOBAL(hmt_start_secondary) | ||
1964 | LOADADDR(r4,__hmt_secondary_hold) | ||
1965 | clrldi r4,r4,4 | ||
1966 | mtspr SPRN_NIADORM, r4 | ||
1967 | mfspr r4, SPRN_MSRDORM | ||
1968 | li r5, -65 | ||
1969 | and r4, r4, r5 | ||
1970 | mtspr SPRN_MSRDORM, r4 | ||
1971 | lis r4,0xffef | ||
1972 | ori r4,r4,0x7403 | ||
1973 | mtspr SPRN_TSC, r4 | ||
1974 | li r4,0x1f4 | ||
1975 | mtspr SPRN_TST, r4 | ||
1976 | mfspr r4, SPRN_HID0 | ||
1977 | ori r4, r4, 0x1 | ||
1978 | mtspr SPRN_HID0, r4 | ||
1979 | mfspr r4, SPRN_CTRLF | ||
1980 | oris r4, r4, 0x40 | ||
1981 | mtspr SPRN_CTRLT, r4 | ||
1982 | blr | ||
1983 | #endif | ||
1984 | |||
1985 | /* | ||
1986 | * We put a few things here that have to be page-aligned. | ||
1987 | * This stuff goes at the beginning of the bss, which is page-aligned. | ||
1988 | */ | ||
1989 | .section ".bss" | ||
1990 | |||
1991 | .align PAGE_SHIFT | ||
1992 | |||
1993 | .globl empty_zero_page | ||
1994 | empty_zero_page: | ||
1995 | .space PAGE_SIZE | ||
1996 | |||
1997 | .globl swapper_pg_dir | ||
1998 | swapper_pg_dir: | ||
1999 | .space PAGE_SIZE | ||
2000 | |||
2001 | /* | ||
2002 | * This space gets a copy of optional info passed to us by the bootstrap | ||
2003 | * Used to pass parameters into the kernel like root=/dev/sda1, etc. | ||
2004 | */ | ||
2005 | .globl cmd_line | ||
2006 | cmd_line: | ||
2007 | .space COMMAND_LINE_SIZE | ||
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S deleted file mode 100644 index 5e089deb0a2b..000000000000 --- a/arch/ppc64/kernel/misc.S +++ /dev/null | |||
@@ -1,940 +0,0 @@ | |||
1 | /* | ||
2 | * arch/ppc/kernel/misc.S | ||
3 | * | ||
4 | * | ||
5 | * | ||
6 | * This file contains miscellaneous low-level functions. | ||
7 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | ||
8 | * | ||
9 | * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) | ||
10 | * and Paul Mackerras. | ||
11 | * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com) | ||
12 | * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com) | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or | ||
15 | * modify it under the terms of the GNU General Public License | ||
16 | * as published by the Free Software Foundation; either version | ||
17 | * 2 of the License, or (at your option) any later version. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/config.h> | ||
22 | #include <linux/sys.h> | ||
23 | #include <asm/unistd.h> | ||
24 | #include <asm/errno.h> | ||
25 | #include <asm/processor.h> | ||
26 | #include <asm/page.h> | ||
27 | #include <asm/cache.h> | ||
28 | #include <asm/ppc_asm.h> | ||
29 | #include <asm/asm-offsets.h> | ||
30 | #include <asm/cputable.h> | ||
31 | #include <asm/thread_info.h> | ||
32 | |||
33 | .text | ||
34 | |||
35 | /* | ||
36 | * Returns (address we were linked at) - (address we are running at) | ||
37 | * for use before the text and data are mapped to KERNELBASE. | ||
38 | */ | ||
39 | |||
40 | _GLOBAL(reloc_offset) | ||
41 | mflr r0 | ||
42 | bl 1f | ||
43 | 1: mflr r3 | ||
44 | LOADADDR(r4,1b) | ||
45 | sub r3,r4,r3 | ||
46 | mtlr r0 | ||
47 | blr | ||
48 | |||
49 | _GLOBAL(get_msr) | ||
50 | mfmsr r3 | ||
51 | blr | ||
52 | |||
53 | _GLOBAL(get_dar) | ||
54 | mfdar r3 | ||
55 | blr | ||
56 | |||
57 | _GLOBAL(get_srr0) | ||
58 | mfsrr0 r3 | ||
59 | blr | ||
60 | |||
61 | _GLOBAL(get_srr1) | ||
62 | mfsrr1 r3 | ||
63 | blr | ||
64 | |||
65 | _GLOBAL(get_sp) | ||
66 | mr r3,r1 | ||
67 | blr | ||
68 | |||
69 | #ifdef CONFIG_IRQSTACKS | ||
70 | _GLOBAL(call_do_softirq) | ||
71 | mflr r0 | ||
72 | std r0,16(r1) | ||
73 | stdu r1,THREAD_SIZE-112(r3) | ||
74 | mr r1,r3 | ||
75 | bl .__do_softirq | ||
76 | ld r1,0(r1) | ||
77 | ld r0,16(r1) | ||
78 | mtlr r0 | ||
79 | blr | ||
80 | |||
81 | _GLOBAL(call___do_IRQ) | ||
82 | mflr r0 | ||
83 | std r0,16(r1) | ||
84 | stdu r1,THREAD_SIZE-112(r5) | ||
85 | mr r1,r5 | ||
86 | bl .__do_IRQ | ||
87 | ld r1,0(r1) | ||
88 | ld r0,16(r1) | ||
89 | mtlr r0 | ||
90 | blr | ||
91 | #endif /* CONFIG_IRQSTACKS */ | ||
92 | |||
93 | /* | ||
94 | * To be called by C code which needs to do some operations with MMU | ||
95 | * disabled. Note that interrupts have to be disabled by the caller | ||
96 | * prior to calling us. The code called _MUST_ be in the RMO of course | ||
97 | * and part of the linear mapping as we don't attempt to translate the | ||
98 | * stack pointer at all. The function is called with the stack switched | ||
99 | * to this CPU emergency stack | ||
100 | * | ||
101 | * prototype is void *call_with_mmu_off(void *func, void *data); | ||
102 | * | ||
103 | * the called function is expected to be of the form | ||
104 | * | ||
105 | * void *called(void *data); | ||
106 | */ | ||
107 | _GLOBAL(call_with_mmu_off) | ||
108 | mflr r0 /* get link, save it on stackframe */ | ||
109 | std r0,16(r1) | ||
110 | mr r1,r5 /* save old stack ptr */ | ||
111 | ld r1,PACAEMERGSP(r13) /* get emerg. stack */ | ||
112 | subi r1,r1,STACK_FRAME_OVERHEAD | ||
113 | std r0,16(r1) /* save link on emerg. stack */ | ||
114 | std r5,0(r1) /* save old stack ptr in backchain */ | ||
115 | ld r3,0(r3) /* get to real function ptr (assume same TOC) */ | ||
116 | bl 2f /* we need LR to return, continue at label 2 */ | ||
117 | |||
118 | ld r0,16(r1) /* we return here from the call, get LR and */ | ||
119 | ld r1,0(r1) /* .. old stack ptr */ | ||
120 | mtspr SPRN_SRR0,r0 /* and get back to virtual mode with these */ | ||
121 | mfmsr r4 | ||
122 | ori r4,r4,MSR_IR|MSR_DR | ||
123 | mtspr SPRN_SRR1,r4 | ||
124 | rfid | ||
125 | |||
126 | 2: mtspr SPRN_SRR0,r3 /* coming from above, enter real mode */ | ||
127 | mr r3,r4 /* get parameter */ | ||
128 | mfmsr r0 | ||
129 | ori r0,r0,MSR_IR|MSR_DR | ||
130 | xori r0,r0,MSR_IR|MSR_DR | ||
131 | mtspr SPRN_SRR1,r0 | ||
132 | rfid | ||
133 | |||
134 | |||
135 | .section ".toc","aw" | ||
136 | PPC64_CACHES: | ||
137 | .tc ppc64_caches[TC],ppc64_caches | ||
138 | .section ".text" | ||
139 | |||
140 | /* | ||
141 | * Write any modified data cache blocks out to memory | ||
142 | * and invalidate the corresponding instruction cache blocks. | ||
143 | * | ||
144 | * flush_icache_range(unsigned long start, unsigned long stop) | ||
145 | * | ||
146 | * flush all bytes from start through stop-1 inclusive | ||
147 | */ | ||
148 | |||
149 | _KPROBE(__flush_icache_range) | ||
150 | |||
151 | /* | ||
152 | * Flush the data cache to memory | ||
153 | * | ||
154 | * Different systems have different cache line sizes | ||
155 | * and in some cases i-cache and d-cache line sizes differ from | ||
156 | * each other. | ||
157 | */ | ||
158 | ld r10,PPC64_CACHES@toc(r2) | ||
159 | lwz r7,DCACHEL1LINESIZE(r10)/* Get cache line size */ | ||
160 | addi r5,r7,-1 | ||
161 | andc r6,r3,r5 /* round low to line bdy */ | ||
162 | subf r8,r6,r4 /* compute length */ | ||
163 | add r8,r8,r5 /* ensure we get enough */ | ||
164 | lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of cache line size */ | ||
165 | srw. r8,r8,r9 /* compute line count */ | ||
166 | beqlr /* nothing to do? */ | ||
167 | mtctr r8 | ||
168 | 1: dcbst 0,r6 | ||
169 | add r6,r6,r7 | ||
170 | bdnz 1b | ||
171 | sync | ||
172 | |||
173 | /* Now invalidate the instruction cache */ | ||
174 | |||
175 | lwz r7,ICACHEL1LINESIZE(r10) /* Get Icache line size */ | ||
176 | addi r5,r7,-1 | ||
177 | andc r6,r3,r5 /* round low to line bdy */ | ||
178 | subf r8,r6,r4 /* compute length */ | ||
179 | add r8,r8,r5 | ||
180 | lwz r9,ICACHEL1LOGLINESIZE(r10) /* Get log-2 of Icache line size */ | ||
181 | srw. r8,r8,r9 /* compute line count */ | ||
182 | beqlr /* nothing to do? */ | ||
183 | mtctr r8 | ||
184 | 2: icbi 0,r6 | ||
185 | add r6,r6,r7 | ||
186 | bdnz 2b | ||
187 | isync | ||
188 | blr | ||
189 | |||
190 | .text | ||
191 | /* | ||
192 | * Like above, but only do the D-cache. | ||
193 | * | ||
194 | * flush_dcache_range(unsigned long start, unsigned long stop) | ||
195 | * | ||
196 | * flush all bytes from start to stop-1 inclusive | ||
197 | */ | ||
198 | _GLOBAL(flush_dcache_range) | ||
199 | |||
200 | /* | ||
201 | * Flush the data cache to memory | ||
202 | * | ||
203 | * Different systems have different cache line sizes | ||
204 | */ | ||
205 | ld r10,PPC64_CACHES@toc(r2) | ||
206 | lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ | ||
207 | addi r5,r7,-1 | ||
208 | andc r6,r3,r5 /* round low to line bdy */ | ||
209 | subf r8,r6,r4 /* compute length */ | ||
210 | add r8,r8,r5 /* ensure we get enough */ | ||
211 | lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ | ||
212 | srw. r8,r8,r9 /* compute line count */ | ||
213 | beqlr /* nothing to do? */ | ||
214 | mtctr r8 | ||
215 | 0: dcbst 0,r6 | ||
216 | add r6,r6,r7 | ||
217 | bdnz 0b | ||
218 | sync | ||
219 | blr | ||
220 | |||
221 | /* | ||
222 | * Like above, but works on non-mapped physical addresses. | ||
223 | * Use only for non-LPAR setups ! It also assumes real mode | ||
224 | * is cacheable. Used for flushing out the DART before using | ||
225 | * it as uncacheable memory | ||
226 | * | ||
227 | * flush_dcache_phys_range(unsigned long start, unsigned long stop) | ||
228 | * | ||
229 | * flush all bytes from start to stop-1 inclusive | ||
230 | */ | ||
231 | _GLOBAL(flush_dcache_phys_range) | ||
232 | ld r10,PPC64_CACHES@toc(r2) | ||
233 | lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ | ||
234 | addi r5,r7,-1 | ||
235 | andc r6,r3,r5 /* round low to line bdy */ | ||
236 | subf r8,r6,r4 /* compute length */ | ||
237 | add r8,r8,r5 /* ensure we get enough */ | ||
238 | lwz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ | ||
239 | srw. r8,r8,r9 /* compute line count */ | ||
240 | beqlr /* nothing to do? */ | ||
241 | mfmsr r5 /* Disable MMU Data Relocation */ | ||
242 | ori r0,r5,MSR_DR | ||
243 | xori r0,r0,MSR_DR | ||
244 | sync | ||
245 | mtmsr r0 | ||
246 | sync | ||
247 | isync | ||
248 | mtctr r8 | ||
249 | 0: dcbst 0,r6 | ||
250 | add r6,r6,r7 | ||
251 | bdnz 0b | ||
252 | sync | ||
253 | isync | ||
254 | mtmsr r5 /* Re-enable MMU Data Relocation */ | ||
255 | sync | ||
256 | isync | ||
257 | blr | ||
258 | |||
259 | _GLOBAL(flush_inval_dcache_range) | ||
260 | ld r10,PPC64_CACHES@toc(r2) | ||
261 | lwz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ | ||
262 | addi r5,r7,-1 | ||
263 | andc r6,r3,r5 /* round low to line bdy */ | ||
264 | subf r8,r6,r4 /* compute length */ | ||
265 | add r8,r8,r5 /* ensure we get enough */ | ||
266 | lwz r9,DCACHEL1LOGLINESIZE(r10)/* Get log-2 of dcache line size */ | ||
267 | srw. r8,r8,r9 /* compute line count */ | ||
268 | beqlr /* nothing to do? */ | ||
269 | sync | ||
270 | isync | ||
271 | mtctr r8 | ||
272 | 0: dcbf 0,r6 | ||
273 | add r6,r6,r7 | ||
274 | bdnz 0b | ||
275 | sync | ||
276 | isync | ||
277 | blr | ||
278 | |||
279 | |||
280 | /* | ||
281 | * Flush a particular page from the data cache to RAM. | ||
282 | * Note: this is necessary because the instruction cache does *not* | ||
283 | * snoop from the data cache. | ||
284 | * | ||
285 | * void __flush_dcache_icache(void *page) | ||
286 | */ | ||
287 | _GLOBAL(__flush_dcache_icache) | ||
288 | /* | ||
289 | * Flush the data cache to memory | ||
290 | * | ||
291 | * Different systems have different cache line sizes | ||
292 | */ | ||
293 | |||
294 | /* Flush the dcache */ | ||
295 | ld r7,PPC64_CACHES@toc(r2) | ||
296 | clrrdi r3,r3,PAGE_SHIFT /* Page align */ | ||
297 | lwz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */ | ||
298 | lwz r5,DCACHEL1LINESIZE(r7) /* Get dcache line size */ | ||
299 | mr r6,r3 | ||
300 | mtctr r4 | ||
301 | 0: dcbst 0,r6 | ||
302 | add r6,r6,r5 | ||
303 | bdnz 0b | ||
304 | sync | ||
305 | |||
306 | /* Now invalidate the icache */ | ||
307 | |||
308 | lwz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */ | ||
309 | lwz r5,ICACHEL1LINESIZE(r7) /* Get icache line size */ | ||
310 | mtctr r4 | ||
311 | 1: icbi 0,r3 | ||
312 | add r3,r3,r5 | ||
313 | bdnz 1b | ||
314 | isync | ||
315 | blr | ||
316 | |||
317 | /* | ||
318 | * I/O string operations | ||
319 | * | ||
320 | * insb(port, buf, len) | ||
321 | * outsb(port, buf, len) | ||
322 | * insw(port, buf, len) | ||
323 | * outsw(port, buf, len) | ||
324 | * insl(port, buf, len) | ||
325 | * outsl(port, buf, len) | ||
326 | * insw_ns(port, buf, len) | ||
327 | * outsw_ns(port, buf, len) | ||
328 | * insl_ns(port, buf, len) | ||
329 | * outsl_ns(port, buf, len) | ||
330 | * | ||
331 | * The *_ns versions don't do byte-swapping. | ||
332 | */ | ||
333 | _GLOBAL(_insb) | ||
334 | cmpwi 0,r5,0 | ||
335 | mtctr r5 | ||
336 | subi r4,r4,1 | ||
337 | blelr- | ||
338 | 00: lbz r5,0(r3) | ||
339 | eieio | ||
340 | stbu r5,1(r4) | ||
341 | bdnz 00b | ||
342 | twi 0,r5,0 | ||
343 | isync | ||
344 | blr | ||
345 | |||
346 | _GLOBAL(_outsb) | ||
347 | cmpwi 0,r5,0 | ||
348 | mtctr r5 | ||
349 | subi r4,r4,1 | ||
350 | blelr- | ||
351 | 00: lbzu r5,1(r4) | ||
352 | stb r5,0(r3) | ||
353 | bdnz 00b | ||
354 | sync | ||
355 | blr | ||
356 | |||
357 | _GLOBAL(_insw) | ||
358 | cmpwi 0,r5,0 | ||
359 | mtctr r5 | ||
360 | subi r4,r4,2 | ||
361 | blelr- | ||
362 | 00: lhbrx r5,0,r3 | ||
363 | eieio | ||
364 | sthu r5,2(r4) | ||
365 | bdnz 00b | ||
366 | twi 0,r5,0 | ||
367 | isync | ||
368 | blr | ||
369 | |||
370 | _GLOBAL(_outsw) | ||
371 | cmpwi 0,r5,0 | ||
372 | mtctr r5 | ||
373 | subi r4,r4,2 | ||
374 | blelr- | ||
375 | 00: lhzu r5,2(r4) | ||
376 | sthbrx r5,0,r3 | ||
377 | bdnz 00b | ||
378 | sync | ||
379 | blr | ||
380 | |||
381 | _GLOBAL(_insl) | ||
382 | cmpwi 0,r5,0 | ||
383 | mtctr r5 | ||
384 | subi r4,r4,4 | ||
385 | blelr- | ||
386 | 00: lwbrx r5,0,r3 | ||
387 | eieio | ||
388 | stwu r5,4(r4) | ||
389 | bdnz 00b | ||
390 | twi 0,r5,0 | ||
391 | isync | ||
392 | blr | ||
393 | |||
394 | _GLOBAL(_outsl) | ||
395 | cmpwi 0,r5,0 | ||
396 | mtctr r5 | ||
397 | subi r4,r4,4 | ||
398 | blelr- | ||
399 | 00: lwzu r5,4(r4) | ||
400 | stwbrx r5,0,r3 | ||
401 | bdnz 00b | ||
402 | sync | ||
403 | blr | ||
404 | |||
405 | /* _GLOBAL(ide_insw) now in drivers/ide/ide-iops.c */ | ||
406 | _GLOBAL(_insw_ns) | ||
407 | cmpwi 0,r5,0 | ||
408 | mtctr r5 | ||
409 | subi r4,r4,2 | ||
410 | blelr- | ||
411 | 00: lhz r5,0(r3) | ||
412 | eieio | ||
413 | sthu r5,2(r4) | ||
414 | bdnz 00b | ||
415 | twi 0,r5,0 | ||
416 | isync | ||
417 | blr | ||
418 | |||
419 | /* _GLOBAL(ide_outsw) now in drivers/ide/ide-iops.c */ | ||
420 | _GLOBAL(_outsw_ns) | ||
421 | cmpwi 0,r5,0 | ||
422 | mtctr r5 | ||
423 | subi r4,r4,2 | ||
424 | blelr- | ||
425 | 00: lhzu r5,2(r4) | ||
426 | sth r5,0(r3) | ||
427 | bdnz 00b | ||
428 | sync | ||
429 | blr | ||
430 | |||
431 | _GLOBAL(_insl_ns) | ||
432 | cmpwi 0,r5,0 | ||
433 | mtctr r5 | ||
434 | subi r4,r4,4 | ||
435 | blelr- | ||
436 | 00: lwz r5,0(r3) | ||
437 | eieio | ||
438 | stwu r5,4(r4) | ||
439 | bdnz 00b | ||
440 | twi 0,r5,0 | ||
441 | isync | ||
442 | blr | ||
443 | |||
444 | _GLOBAL(_outsl_ns) | ||
445 | cmpwi 0,r5,0 | ||
446 | mtctr r5 | ||
447 | subi r4,r4,4 | ||
448 | blelr- | ||
449 | 00: lwzu r5,4(r4) | ||
450 | stw r5,0(r3) | ||
451 | bdnz 00b | ||
452 | sync | ||
453 | blr | ||
454 | |||
455 | /* | ||
456 | * identify_cpu and calls setup_cpu | ||
457 | * In: r3 = base of the cpu_specs array | ||
458 | * r4 = address of cur_cpu_spec | ||
459 | * r5 = relocation offset | ||
460 | */ | ||
461 | _GLOBAL(identify_cpu) | ||
462 | mfpvr r7 | ||
463 | 1: | ||
464 | lwz r8,CPU_SPEC_PVR_MASK(r3) | ||
465 | and r8,r8,r7 | ||
466 | lwz r9,CPU_SPEC_PVR_VALUE(r3) | ||
467 | cmplw 0,r9,r8 | ||
468 | beq 1f | ||
469 | addi r3,r3,CPU_SPEC_ENTRY_SIZE | ||
470 | b 1b | ||
471 | 1: | ||
472 | add r0,r3,r5 | ||
473 | std r0,0(r4) | ||
474 | ld r4,CPU_SPEC_SETUP(r3) | ||
475 | sub r4,r4,r5 | ||
476 | ld r4,0(r4) | ||
477 | sub r4,r4,r5 | ||
478 | mtctr r4 | ||
479 | /* Calling convention for cpu setup is r3=offset, r4=cur_cpu_spec */ | ||
480 | mr r4,r3 | ||
481 | mr r3,r5 | ||
482 | bctr | ||
483 | |||
484 | /* | ||
485 | * do_cpu_ftr_fixups - goes through the list of CPU feature fixups | ||
486 | * and writes nop's over sections of code that don't apply for this cpu. | ||
487 | * r3 = data offset (not changed) | ||
488 | */ | ||
489 | _GLOBAL(do_cpu_ftr_fixups) | ||
490 | /* Get CPU 0 features */ | ||
491 | LOADADDR(r6,cur_cpu_spec) | ||
492 | sub r6,r6,r3 | ||
493 | ld r4,0(r6) | ||
494 | sub r4,r4,r3 | ||
495 | ld r4,CPU_SPEC_FEATURES(r4) | ||
496 | /* Get the fixup table */ | ||
497 | LOADADDR(r6,__start___ftr_fixup) | ||
498 | sub r6,r6,r3 | ||
499 | LOADADDR(r7,__stop___ftr_fixup) | ||
500 | sub r7,r7,r3 | ||
501 | /* Do the fixup */ | ||
502 | 1: cmpld r6,r7 | ||
503 | bgelr | ||
504 | addi r6,r6,32 | ||
505 | ld r8,-32(r6) /* mask */ | ||
506 | and r8,r8,r4 | ||
507 | ld r9,-24(r6) /* value */ | ||
508 | cmpld r8,r9 | ||
509 | beq 1b | ||
510 | ld r8,-16(r6) /* section begin */ | ||
511 | ld r9,-8(r6) /* section end */ | ||
512 | subf. r9,r8,r9 | ||
513 | beq 1b | ||
514 | /* write nops over the section of code */ | ||
515 | /* todo: if large section, add a branch at the start of it */ | ||
516 | srwi r9,r9,2 | ||
517 | mtctr r9 | ||
518 | sub r8,r8,r3 | ||
519 | lis r0,0x60000000@h /* nop */ | ||
520 | 3: stw r0,0(r8) | ||
521 | andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l | ||
522 | beq 2f | ||
523 | dcbst 0,r8 /* suboptimal, but simpler */ | ||
524 | sync | ||
525 | icbi 0,r8 | ||
526 | 2: addi r8,r8,4 | ||
527 | bdnz 3b | ||
528 | sync /* additional sync needed on g4 */ | ||
529 | isync | ||
530 | b 1b | ||
531 | |||
532 | #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) | ||
533 | /* | ||
534 | * Do an IO access in real mode | ||
535 | */ | ||
536 | _GLOBAL(real_readb) | ||
537 | mfmsr r7 | ||
538 | ori r0,r7,MSR_DR | ||
539 | xori r0,r0,MSR_DR | ||
540 | sync | ||
541 | mtmsrd r0 | ||
542 | sync | ||
543 | isync | ||
544 | mfspr r6,SPRN_HID4 | ||
545 | rldicl r5,r6,32,0 | ||
546 | ori r5,r5,0x100 | ||
547 | rldicl r5,r5,32,0 | ||
548 | sync | ||
549 | mtspr SPRN_HID4,r5 | ||
550 | isync | ||
551 | slbia | ||
552 | isync | ||
553 | lbz r3,0(r3) | ||
554 | sync | ||
555 | mtspr SPRN_HID4,r6 | ||
556 | isync | ||
557 | slbia | ||
558 | isync | ||
559 | mtmsrd r7 | ||
560 | sync | ||
561 | isync | ||
562 | blr | ||
563 | |||
564 | /* | ||
565 | * Do an IO access in real mode | ||
566 | */ | ||
567 | _GLOBAL(real_writeb) | ||
568 | mfmsr r7 | ||
569 | ori r0,r7,MSR_DR | ||
570 | xori r0,r0,MSR_DR | ||
571 | sync | ||
572 | mtmsrd r0 | ||
573 | sync | ||
574 | isync | ||
575 | mfspr r6,SPRN_HID4 | ||
576 | rldicl r5,r6,32,0 | ||
577 | ori r5,r5,0x100 | ||
578 | rldicl r5,r5,32,0 | ||
579 | sync | ||
580 | mtspr SPRN_HID4,r5 | ||
581 | isync | ||
582 | slbia | ||
583 | isync | ||
584 | stb r3,0(r4) | ||
585 | sync | ||
586 | mtspr SPRN_HID4,r6 | ||
587 | isync | ||
588 | slbia | ||
589 | isync | ||
590 | mtmsrd r7 | ||
591 | sync | ||
592 | isync | ||
593 | blr | ||
594 | #endif /* defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) */ | ||
595 | |||
596 | /* | ||
597 | * SCOM access functions for 970 (FX only for now) | ||
598 | * | ||
599 | * unsigned long scom970_read(unsigned int address); | ||
600 | * void scom970_write(unsigned int address, unsigned long value); | ||
601 | * | ||
602 | * The address passed in is the 24 bits register address. This code | ||
603 | * is 970 specific and will not check the status bits, so you should | ||
604 | * know what you are doing. | ||
605 | */ | ||
606 | _GLOBAL(scom970_read) | ||
607 | /* interrupts off */ | ||
608 | mfmsr r4 | ||
609 | ori r0,r4,MSR_EE | ||
610 | xori r0,r0,MSR_EE | ||
611 | mtmsrd r0,1 | ||
612 | |||
613 | /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits | ||
614 | * (including parity). On current CPUs they must be 0'd, | ||
615 | * and finally or in RW bit | ||
616 | */ | ||
617 | rlwinm r3,r3,8,0,15 | ||
618 | ori r3,r3,0x8000 | ||
619 | |||
620 | /* do the actual scom read */ | ||
621 | sync | ||
622 | mtspr SPRN_SCOMC,r3 | ||
623 | isync | ||
624 | mfspr r3,SPRN_SCOMD | ||
625 | isync | ||
626 | mfspr r0,SPRN_SCOMC | ||
627 | isync | ||
628 | |||
629 | /* XXX: fixup result on some buggy 970's (ouch ! we lost a bit, bah | ||
630 | * that's the best we can do). Not implemented yet as we don't use | ||
631 | * the scom on any of the bogus CPUs yet, but may have to be done | ||
632 | * ultimately | ||
633 | */ | ||
634 | |||
635 | /* restore interrupts */ | ||
636 | mtmsrd r4,1 | ||
637 | blr | ||
638 | |||
639 | |||
640 | _GLOBAL(scom970_write) | ||
641 | /* interrupts off */ | ||
642 | mfmsr r5 | ||
643 | ori r0,r5,MSR_EE | ||
644 | xori r0,r0,MSR_EE | ||
645 | mtmsrd r0,1 | ||
646 | |||
647 | /* rotate 24 bits SCOM address 8 bits left and mask out it's low 8 bits | ||
648 | * (including parity). On current CPUs they must be 0'd. | ||
649 | */ | ||
650 | |||
651 | rlwinm r3,r3,8,0,15 | ||
652 | |||
653 | sync | ||
654 | mtspr SPRN_SCOMD,r4 /* write data */ | ||
655 | isync | ||
656 | mtspr SPRN_SCOMC,r3 /* write command */ | ||
657 | isync | ||
658 | mfspr 3,SPRN_SCOMC | ||
659 | isync | ||
660 | |||
661 | /* restore interrupts */ | ||
662 | mtmsrd r5,1 | ||
663 | blr | ||
664 | |||
665 | |||
666 | /* | ||
667 | * Create a kernel thread | ||
668 | * kernel_thread(fn, arg, flags) | ||
669 | */ | ||
670 | _GLOBAL(kernel_thread) | ||
671 | std r29,-24(r1) | ||
672 | std r30,-16(r1) | ||
673 | stdu r1,-STACK_FRAME_OVERHEAD(r1) | ||
674 | mr r29,r3 | ||
675 | mr r30,r4 | ||
676 | ori r3,r5,CLONE_VM /* flags */ | ||
677 | oris r3,r3,(CLONE_UNTRACED>>16) | ||
678 | li r4,0 /* new sp (unused) */ | ||
679 | li r0,__NR_clone | ||
680 | sc | ||
681 | cmpdi 0,r3,0 /* parent or child? */ | ||
682 | bne 1f /* return if parent */ | ||
683 | li r0,0 | ||
684 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | ||
685 | ld r2,8(r29) | ||
686 | ld r29,0(r29) | ||
687 | mtlr r29 /* fn addr in lr */ | ||
688 | mr r3,r30 /* load arg and call fn */ | ||
689 | blrl | ||
690 | li r0,__NR_exit /* exit after child exits */ | ||
691 | li r3,0 | ||
692 | sc | ||
693 | 1: addi r1,r1,STACK_FRAME_OVERHEAD | ||
694 | ld r29,-24(r1) | ||
695 | ld r30,-16(r1) | ||
696 | blr | ||
697 | |||
698 | /* | ||
699 | * disable_kernel_fp() | ||
700 | * Disable the FPU. | ||
701 | */ | ||
702 | _GLOBAL(disable_kernel_fp) | ||
703 | mfmsr r3 | ||
704 | rldicl r0,r3,(63-MSR_FP_LG),1 | ||
705 | rldicl r3,r0,(MSR_FP_LG+1),0 | ||
706 | mtmsrd r3 /* disable use of fpu now */ | ||
707 | isync | ||
708 | blr | ||
709 | |||
710 | #ifdef CONFIG_ALTIVEC | ||
711 | |||
712 | #if 0 /* this has no callers for now */ | ||
713 | /* | ||
714 | * disable_kernel_altivec() | ||
715 | * Disable the VMX. | ||
716 | */ | ||
717 | _GLOBAL(disable_kernel_altivec) | ||
718 | mfmsr r3 | ||
719 | rldicl r0,r3,(63-MSR_VEC_LG),1 | ||
720 | rldicl r3,r0,(MSR_VEC_LG+1),0 | ||
721 | mtmsrd r3 /* disable use of VMX now */ | ||
722 | isync | ||
723 | blr | ||
724 | #endif /* 0 */ | ||
725 | |||
726 | /* | ||
727 | * giveup_altivec(tsk) | ||
728 | * Disable VMX for the task given as the argument, | ||
729 | * and save the vector registers in its thread_struct. | ||
730 | * Enables the VMX for use in the kernel on return. | ||
731 | */ | ||
732 | _GLOBAL(giveup_altivec) | ||
733 | mfmsr r5 | ||
734 | oris r5,r5,MSR_VEC@h | ||
735 | mtmsrd r5 /* enable use of VMX now */ | ||
736 | isync | ||
737 | cmpdi 0,r3,0 | ||
738 | beqlr- /* if no previous owner, done */ | ||
739 | addi r3,r3,THREAD /* want THREAD of task */ | ||
740 | ld r5,PT_REGS(r3) | ||
741 | cmpdi 0,r5,0 | ||
742 | SAVE_32VRS(0,r4,r3) | ||
743 | mfvscr vr0 | ||
744 | li r4,THREAD_VSCR | ||
745 | stvx vr0,r4,r3 | ||
746 | beq 1f | ||
747 | ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
748 | lis r3,MSR_VEC@h | ||
749 | andc r4,r4,r3 /* disable FP for previous task */ | ||
750 | std r4,_MSR-STACK_FRAME_OVERHEAD(r5) | ||
751 | 1: | ||
752 | #ifndef CONFIG_SMP | ||
753 | li r5,0 | ||
754 | ld r4,last_task_used_altivec@got(r2) | ||
755 | std r5,0(r4) | ||
756 | #endif /* CONFIG_SMP */ | ||
757 | blr | ||
758 | |||
759 | #endif /* CONFIG_ALTIVEC */ | ||
760 | |||
761 | _GLOBAL(__setup_cpu_power3) | ||
762 | blr | ||
763 | |||
764 | _GLOBAL(execve) | ||
765 | li r0,__NR_execve | ||
766 | sc | ||
767 | bnslr | ||
768 | neg r3,r3 | ||
769 | blr | ||
770 | |||
771 | /* kexec_wait(phys_cpu) | ||
772 | * | ||
773 | * wait for the flag to change, indicating this kernel is going away but | ||
774 | * the slave code for the next one is at addresses 0 to 100. | ||
775 | * | ||
776 | * This is used by all slaves. | ||
777 | * | ||
778 | * Physical (hardware) cpu id should be in r3. | ||
779 | */ | ||
780 | _GLOBAL(kexec_wait) | ||
781 | bl 1f | ||
782 | 1: mflr r5 | ||
783 | addi r5,r5,kexec_flag-1b | ||
784 | |||
785 | 99: HMT_LOW | ||
786 | #ifdef CONFIG_KEXEC /* use no memory without kexec */ | ||
787 | lwz r4,0(r5) | ||
788 | cmpwi 0,r4,0 | ||
789 | bnea 0x60 | ||
790 | #endif | ||
791 | b 99b | ||
792 | |||
793 | /* this can be in text because we won't change it until we are | ||
794 | * running in real anyways | ||
795 | */ | ||
796 | kexec_flag: | ||
797 | .long 0 | ||
798 | |||
799 | |||
800 | #ifdef CONFIG_KEXEC | ||
801 | |||
802 | /* kexec_smp_wait(void) | ||
803 | * | ||
804 | * call with interrupts off | ||
805 | * note: this is a terminal routine, it does not save lr | ||
806 | * | ||
807 | * get phys id from paca | ||
808 | * set paca id to -1 to say we got here | ||
809 | * switch to real mode | ||
810 | * join other cpus in kexec_wait(phys_id) | ||
811 | */ | ||
812 | _GLOBAL(kexec_smp_wait) | ||
813 | lhz r3,PACAHWCPUID(r13) | ||
814 | li r4,-1 | ||
815 | sth r4,PACAHWCPUID(r13) /* let others know we left */ | ||
816 | bl real_mode | ||
817 | b .kexec_wait | ||
818 | |||
819 | /* | ||
820 | * switch to real mode (turn mmu off) | ||
821 | * we use the early kernel trick that the hardware ignores bits | ||
822 | * 0 and 1 (big endian) of the effective address in real mode | ||
823 | * | ||
824 | * don't overwrite r3 here, it is live for kexec_wait above. | ||
825 | */ | ||
826 | real_mode: /* assume normal blr return */ | ||
827 | 1: li r9,MSR_RI | ||
828 | li r10,MSR_DR|MSR_IR | ||
829 | mflr r11 /* return address to SRR0 */ | ||
830 | mfmsr r12 | ||
831 | andc r9,r12,r9 | ||
832 | andc r10,r12,r10 | ||
833 | |||
834 | mtmsrd r9,1 | ||
835 | mtspr SPRN_SRR1,r10 | ||
836 | mtspr SPRN_SRR0,r11 | ||
837 | rfid | ||
838 | |||
839 | |||
840 | /* | ||
841 | * kexec_sequence(newstack, start, image, control, clear_all()) | ||
842 | * | ||
843 | * does the grungy work with stack switching and real mode switches | ||
844 | * also does simple calls to other code | ||
845 | */ | ||
846 | |||
847 | _GLOBAL(kexec_sequence) | ||
848 | mflr r0 | ||
849 | std r0,16(r1) | ||
850 | |||
851 | /* switch stacks to newstack -- &kexec_stack.stack */ | ||
852 | stdu r1,THREAD_SIZE-112(r3) | ||
853 | mr r1,r3 | ||
854 | |||
855 | li r0,0 | ||
856 | std r0,16(r1) | ||
857 | |||
858 | /* save regs for local vars on new stack. | ||
859 | * yes, we won't go back, but ... | ||
860 | */ | ||
861 | std r31,-8(r1) | ||
862 | std r30,-16(r1) | ||
863 | std r29,-24(r1) | ||
864 | std r28,-32(r1) | ||
865 | std r27,-40(r1) | ||
866 | std r26,-48(r1) | ||
867 | std r25,-56(r1) | ||
868 | |||
869 | stdu r1,-112-64(r1) | ||
870 | |||
871 | /* save args into preserved regs */ | ||
872 | mr r31,r3 /* newstack (both) */ | ||
873 | mr r30,r4 /* start (real) */ | ||
874 | mr r29,r5 /* image (virt) */ | ||
875 | mr r28,r6 /* control, unused */ | ||
876 | mr r27,r7 /* clear_all() fn desc */ | ||
877 | mr r26,r8 /* spare */ | ||
878 | lhz r25,PACAHWCPUID(r13) /* get our phys cpu from paca */ | ||
879 | |||
880 | /* disable interrupts, we are overwriting kernel data next */ | ||
881 | mfmsr r3 | ||
882 | rlwinm r3,r3,0,17,15 | ||
883 | mtmsrd r3,1 | ||
884 | |||
885 | /* copy dest pages, flush whole dest image */ | ||
886 | mr r3,r29 | ||
887 | bl .kexec_copy_flush /* (image) */ | ||
888 | |||
889 | /* turn off mmu */ | ||
890 | bl real_mode | ||
891 | |||
892 | /* clear out hardware hash page table and tlb */ | ||
893 | ld r5,0(r27) /* deref function descriptor */ | ||
894 | mtctr r5 | ||
895 | bctrl /* ppc_md.hash_clear_all(void); */ | ||
896 | |||
897 | /* | ||
898 | * kexec image calling is: | ||
899 | * the first 0x100 bytes of the entry point are copied to 0 | ||
900 | * | ||
901 | * all slaves branch to slave = 0x60 (absolute) | ||
902 | * slave(phys_cpu_id); | ||
903 | * | ||
904 | * master goes to start = entry point | ||
905 | * start(phys_cpu_id, start, 0); | ||
906 | * | ||
907 | * | ||
908 | * a wrapper is needed to call existing kernels, here is an approximate | ||
909 | * description of one method: | ||
910 | * | ||
911 | * v2: (2.6.10) | ||
912 | * start will be near the boot_block (maybe 0x100 bytes before it?) | ||
913 | * it will have a 0x60, which will b to boot_block, where it will wait | ||
914 | * and 0 will store phys into struct boot-block and load r3 from there, | ||
915 | * copy kernel 0-0x100 and tell slaves to back down to 0x60 again | ||
916 | * | ||
917 | * v1: (2.6.9) | ||
918 | * boot block will have all cpus scanning device tree to see if they | ||
919 | * are the boot cpu ????? | ||
920 | * other device tree differences (prop sizes, va vs pa, etc)... | ||
921 | */ | ||
922 | |||
923 | /* copy 0x100 bytes starting at start to 0 */ | ||
924 | li r3,0 | ||
925 | mr r4,r30 | ||
926 | li r5,0x100 | ||
927 | li r6,0 | ||
928 | bl .copy_and_flush /* (dest, src, copy limit, start offset) */ | ||
929 | 1: /* assume normal blr return */ | ||
930 | |||
931 | /* release other cpus to the new kernel secondary start at 0x60 */ | ||
932 | mflr r5 | ||
933 | li r6,1 | ||
934 | stw r6,kexec_flag-1b(5) | ||
935 | mr r3,r25 # my phys cpu | ||
936 | mr r4,r30 # start, aka phys mem offset | ||
937 | mtlr 4 | ||
938 | li r5,0 | ||
939 | blr /* image->start(physid, image->start, 0); */ | ||
940 | #endif /* CONFIG_KEXEC */ | ||
diff --git a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c deleted file mode 100644 index 84006e26342c..000000000000 --- a/arch/ppc64/kernel/ppc_ksyms.c +++ /dev/null | |||
@@ -1,76 +0,0 @@ | |||
1 | /* | ||
2 | * c 2001 PPC 64 Team, IBM Corp | ||
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 | #include <linux/config.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/string.h> | ||
12 | #include <linux/console.h> | ||
13 | #include <net/checksum.h> | ||
14 | |||
15 | #include <asm/processor.h> | ||
16 | #include <asm/uaccess.h> | ||
17 | #include <asm/io.h> | ||
18 | #include <asm/system.h> | ||
19 | #include <asm/hw_irq.h> | ||
20 | #include <asm/abs_addr.h> | ||
21 | #include <asm/cacheflush.h> | ||
22 | |||
23 | EXPORT_SYMBOL(strcpy); | ||
24 | EXPORT_SYMBOL(strncpy); | ||
25 | EXPORT_SYMBOL(strcat); | ||
26 | EXPORT_SYMBOL(strncat); | ||
27 | EXPORT_SYMBOL(strchr); | ||
28 | EXPORT_SYMBOL(strrchr); | ||
29 | EXPORT_SYMBOL(strpbrk); | ||
30 | EXPORT_SYMBOL(strstr); | ||
31 | EXPORT_SYMBOL(strlen); | ||
32 | EXPORT_SYMBOL(strnlen); | ||
33 | EXPORT_SYMBOL(strcmp); | ||
34 | EXPORT_SYMBOL(strncmp); | ||
35 | |||
36 | EXPORT_SYMBOL(csum_partial); | ||
37 | EXPORT_SYMBOL(csum_partial_copy_generic); | ||
38 | EXPORT_SYMBOL(ip_fast_csum); | ||
39 | EXPORT_SYMBOL(csum_tcpudp_magic); | ||
40 | |||
41 | EXPORT_SYMBOL(__copy_tofrom_user); | ||
42 | EXPORT_SYMBOL(__clear_user); | ||
43 | EXPORT_SYMBOL(__strncpy_from_user); | ||
44 | EXPORT_SYMBOL(__strnlen_user); | ||
45 | |||
46 | EXPORT_SYMBOL(reloc_offset); | ||
47 | |||
48 | EXPORT_SYMBOL(_insb); | ||
49 | EXPORT_SYMBOL(_outsb); | ||
50 | EXPORT_SYMBOL(_insw); | ||
51 | EXPORT_SYMBOL(_outsw); | ||
52 | EXPORT_SYMBOL(_insl); | ||
53 | EXPORT_SYMBOL(_outsl); | ||
54 | EXPORT_SYMBOL(_insw_ns); | ||
55 | EXPORT_SYMBOL(_outsw_ns); | ||
56 | EXPORT_SYMBOL(_insl_ns); | ||
57 | EXPORT_SYMBOL(_outsl_ns); | ||
58 | |||
59 | EXPORT_SYMBOL(kernel_thread); | ||
60 | |||
61 | EXPORT_SYMBOL(giveup_fpu); | ||
62 | #ifdef CONFIG_ALTIVEC | ||
63 | EXPORT_SYMBOL(giveup_altivec); | ||
64 | #endif | ||
65 | EXPORT_SYMBOL(__flush_icache_range); | ||
66 | EXPORT_SYMBOL(flush_dcache_range); | ||
67 | |||
68 | EXPORT_SYMBOL(memcpy); | ||
69 | EXPORT_SYMBOL(memset); | ||
70 | EXPORT_SYMBOL(memmove); | ||
71 | EXPORT_SYMBOL(memscan); | ||
72 | EXPORT_SYMBOL(memcmp); | ||
73 | EXPORT_SYMBOL(memchr); | ||
74 | |||
75 | EXPORT_SYMBOL(timer_interrupt); | ||
76 | EXPORT_SYMBOL(console_drivers); | ||
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c deleted file mode 100644 index 47cc26e78957..000000000000 --- a/arch/ppc64/kernel/prom.c +++ /dev/null | |||
@@ -1,1956 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * | ||
4 | * Procedures for interfacing to Open Firmware. | ||
5 | * | ||
6 | * Paul Mackerras August 1996. | ||
7 | * Copyright (C) 1996 Paul Mackerras. | ||
8 | * | ||
9 | * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. | ||
10 | * {engebret|bergner}@us.ibm.com | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version | ||
15 | * 2 of the License, or (at your option) any later version. | ||
16 | */ | ||
17 | |||
18 | #undef DEBUG | ||
19 | |||
20 | #include <stdarg.h> | ||
21 | #include <linux/config.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/string.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/threads.h> | ||
26 | #include <linux/spinlock.h> | ||
27 | #include <linux/types.h> | ||
28 | #include <linux/pci.h> | ||
29 | #include <linux/stringify.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/initrd.h> | ||
32 | #include <linux/bitops.h> | ||
33 | #include <linux/module.h> | ||
34 | #include <linux/module.h> | ||
35 | |||
36 | #include <asm/prom.h> | ||
37 | #include <asm/rtas.h> | ||
38 | #include <asm/lmb.h> | ||
39 | #include <asm/abs_addr.h> | ||
40 | #include <asm/page.h> | ||
41 | #include <asm/processor.h> | ||
42 | #include <asm/irq.h> | ||
43 | #include <asm/io.h> | ||
44 | #include <asm/smp.h> | ||
45 | #include <asm/system.h> | ||
46 | #include <asm/mmu.h> | ||
47 | #include <asm/pgtable.h> | ||
48 | #include <asm/pci.h> | ||
49 | #include <asm/iommu.h> | ||
50 | #include <asm/btext.h> | ||
51 | #include <asm/sections.h> | ||
52 | #include <asm/machdep.h> | ||
53 | #include <asm/pSeries_reconfig.h> | ||
54 | |||
55 | #ifdef DEBUG | ||
56 | #define DBG(fmt...) udbg_printf(fmt) | ||
57 | #else | ||
58 | #define DBG(fmt...) | ||
59 | #endif | ||
60 | |||
61 | struct pci_reg_property { | ||
62 | struct pci_address addr; | ||
63 | u32 size_hi; | ||
64 | u32 size_lo; | ||
65 | }; | ||
66 | |||
67 | struct isa_reg_property { | ||
68 | u32 space; | ||
69 | u32 address; | ||
70 | u32 size; | ||
71 | }; | ||
72 | |||
73 | |||
74 | typedef int interpret_func(struct device_node *, unsigned long *, | ||
75 | int, int, int); | ||
76 | |||
77 | extern struct rtas_t rtas; | ||
78 | extern struct lmb lmb; | ||
79 | extern unsigned long klimit; | ||
80 | extern unsigned long memory_limit; | ||
81 | |||
82 | static int __initdata dt_root_addr_cells; | ||
83 | static int __initdata dt_root_size_cells; | ||
84 | static int __initdata iommu_is_off; | ||
85 | int __initdata iommu_force_on; | ||
86 | unsigned long tce_alloc_start, tce_alloc_end; | ||
87 | |||
88 | typedef u32 cell_t; | ||
89 | |||
90 | #if 0 | ||
91 | static struct boot_param_header *initial_boot_params __initdata; | ||
92 | #else | ||
93 | struct boot_param_header *initial_boot_params; | ||
94 | #endif | ||
95 | |||
96 | static struct device_node *allnodes = NULL; | ||
97 | |||
98 | /* use when traversing tree through the allnext, child, sibling, | ||
99 | * or parent members of struct device_node. | ||
100 | */ | ||
101 | static DEFINE_RWLOCK(devtree_lock); | ||
102 | |||
103 | /* export that to outside world */ | ||
104 | struct device_node *of_chosen; | ||
105 | |||
106 | /* | ||
107 | * Wrapper for allocating memory for various data that needs to be | ||
108 | * attached to device nodes as they are processed at boot or when | ||
109 | * added to the device tree later (e.g. DLPAR). At boot there is | ||
110 | * already a region reserved so we just increment *mem_start by size; | ||
111 | * otherwise we call kmalloc. | ||
112 | */ | ||
113 | static void * prom_alloc(unsigned long size, unsigned long *mem_start) | ||
114 | { | ||
115 | unsigned long tmp; | ||
116 | |||
117 | if (!mem_start) | ||
118 | return kmalloc(size, GFP_KERNEL); | ||
119 | |||
120 | tmp = *mem_start; | ||
121 | *mem_start += size; | ||
122 | return (void *)tmp; | ||
123 | } | ||
124 | |||
125 | /* | ||
126 | * Find the device_node with a given phandle. | ||
127 | */ | ||
128 | static struct device_node * find_phandle(phandle ph) | ||
129 | { | ||
130 | struct device_node *np; | ||
131 | |||
132 | for (np = allnodes; np != 0; np = np->allnext) | ||
133 | if (np->linux_phandle == ph) | ||
134 | return np; | ||
135 | return NULL; | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * Find the interrupt parent of a node. | ||
140 | */ | ||
141 | static struct device_node * __devinit intr_parent(struct device_node *p) | ||
142 | { | ||
143 | phandle *parp; | ||
144 | |||
145 | parp = (phandle *) get_property(p, "interrupt-parent", NULL); | ||
146 | if (parp == NULL) | ||
147 | return p->parent; | ||
148 | return find_phandle(*parp); | ||
149 | } | ||
150 | |||
151 | /* | ||
152 | * Find out the size of each entry of the interrupts property | ||
153 | * for a node. | ||
154 | */ | ||
155 | int __devinit prom_n_intr_cells(struct device_node *np) | ||
156 | { | ||
157 | struct device_node *p; | ||
158 | unsigned int *icp; | ||
159 | |||
160 | for (p = np; (p = intr_parent(p)) != NULL; ) { | ||
161 | icp = (unsigned int *) | ||
162 | get_property(p, "#interrupt-cells", NULL); | ||
163 | if (icp != NULL) | ||
164 | return *icp; | ||
165 | if (get_property(p, "interrupt-controller", NULL) != NULL | ||
166 | || get_property(p, "interrupt-map", NULL) != NULL) { | ||
167 | printk("oops, node %s doesn't have #interrupt-cells\n", | ||
168 | p->full_name); | ||
169 | return 1; | ||
170 | } | ||
171 | } | ||
172 | #ifdef DEBUG_IRQ | ||
173 | printk("prom_n_intr_cells failed for %s\n", np->full_name); | ||
174 | #endif | ||
175 | return 1; | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * Map an interrupt from a device up to the platform interrupt | ||
180 | * descriptor. | ||
181 | */ | ||
182 | static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictrler, | ||
183 | struct device_node *np, unsigned int *ints, | ||
184 | int nintrc) | ||
185 | { | ||
186 | struct device_node *p, *ipar; | ||
187 | unsigned int *imap, *imask, *ip; | ||
188 | int i, imaplen, match; | ||
189 | int newintrc = 0, newaddrc = 0; | ||
190 | unsigned int *reg; | ||
191 | int naddrc; | ||
192 | |||
193 | reg = (unsigned int *) get_property(np, "reg", NULL); | ||
194 | naddrc = prom_n_addr_cells(np); | ||
195 | p = intr_parent(np); | ||
196 | while (p != NULL) { | ||
197 | if (get_property(p, "interrupt-controller", NULL) != NULL) | ||
198 | /* this node is an interrupt controller, stop here */ | ||
199 | break; | ||
200 | imap = (unsigned int *) | ||
201 | get_property(p, "interrupt-map", &imaplen); | ||
202 | if (imap == NULL) { | ||
203 | p = intr_parent(p); | ||
204 | continue; | ||
205 | } | ||
206 | imask = (unsigned int *) | ||
207 | get_property(p, "interrupt-map-mask", NULL); | ||
208 | if (imask == NULL) { | ||
209 | printk("oops, %s has interrupt-map but no mask\n", | ||
210 | p->full_name); | ||
211 | return 0; | ||
212 | } | ||
213 | imaplen /= sizeof(unsigned int); | ||
214 | match = 0; | ||
215 | ipar = NULL; | ||
216 | while (imaplen > 0 && !match) { | ||
217 | /* check the child-interrupt field */ | ||
218 | match = 1; | ||
219 | for (i = 0; i < naddrc && match; ++i) | ||
220 | match = ((reg[i] ^ imap[i]) & imask[i]) == 0; | ||
221 | for (; i < naddrc + nintrc && match; ++i) | ||
222 | match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0; | ||
223 | imap += naddrc + nintrc; | ||
224 | imaplen -= naddrc + nintrc; | ||
225 | /* grab the interrupt parent */ | ||
226 | ipar = find_phandle((phandle) *imap++); | ||
227 | --imaplen; | ||
228 | if (ipar == NULL) { | ||
229 | printk("oops, no int parent %x in map of %s\n", | ||
230 | imap[-1], p->full_name); | ||
231 | return 0; | ||
232 | } | ||
233 | /* find the parent's # addr and intr cells */ | ||
234 | ip = (unsigned int *) | ||
235 | get_property(ipar, "#interrupt-cells", NULL); | ||
236 | if (ip == NULL) { | ||
237 | printk("oops, no #interrupt-cells on %s\n", | ||
238 | ipar->full_name); | ||
239 | return 0; | ||
240 | } | ||
241 | newintrc = *ip; | ||
242 | ip = (unsigned int *) | ||
243 | get_property(ipar, "#address-cells", NULL); | ||
244 | newaddrc = (ip == NULL)? 0: *ip; | ||
245 | imap += newaddrc + newintrc; | ||
246 | imaplen -= newaddrc + newintrc; | ||
247 | } | ||
248 | if (imaplen < 0) { | ||
249 | printk("oops, error decoding int-map on %s, len=%d\n", | ||
250 | p->full_name, imaplen); | ||
251 | return 0; | ||
252 | } | ||
253 | if (!match) { | ||
254 | #ifdef DEBUG_IRQ | ||
255 | printk("oops, no match in %s int-map for %s\n", | ||
256 | p->full_name, np->full_name); | ||
257 | #endif | ||
258 | return 0; | ||
259 | } | ||
260 | p = ipar; | ||
261 | naddrc = newaddrc; | ||
262 | nintrc = newintrc; | ||
263 | ints = imap - nintrc; | ||
264 | reg = ints - naddrc; | ||
265 | } | ||
266 | if (p == NULL) { | ||
267 | #ifdef DEBUG_IRQ | ||
268 | printk("hmmm, int tree for %s doesn't have ctrler\n", | ||
269 | np->full_name); | ||
270 | #endif | ||
271 | return 0; | ||
272 | } | ||
273 | *irq = ints; | ||
274 | *ictrler = p; | ||
275 | return nintrc; | ||
276 | } | ||
277 | |||
278 | static int __devinit finish_node_interrupts(struct device_node *np, | ||
279 | unsigned long *mem_start, | ||
280 | int measure_only) | ||
281 | { | ||
282 | unsigned int *ints; | ||
283 | int intlen, intrcells, intrcount; | ||
284 | int i, j, n; | ||
285 | unsigned int *irq, virq; | ||
286 | struct device_node *ic; | ||
287 | |||
288 | ints = (unsigned int *) get_property(np, "interrupts", &intlen); | ||
289 | if (ints == NULL) | ||
290 | return 0; | ||
291 | intrcells = prom_n_intr_cells(np); | ||
292 | intlen /= intrcells * sizeof(unsigned int); | ||
293 | |||
294 | np->intrs = prom_alloc(intlen * sizeof(*(np->intrs)), mem_start); | ||
295 | if (!np->intrs) | ||
296 | return -ENOMEM; | ||
297 | |||
298 | if (measure_only) | ||
299 | return 0; | ||
300 | |||
301 | intrcount = 0; | ||
302 | for (i = 0; i < intlen; ++i, ints += intrcells) { | ||
303 | n = map_interrupt(&irq, &ic, np, ints, intrcells); | ||
304 | if (n <= 0) | ||
305 | continue; | ||
306 | |||
307 | /* don't map IRQ numbers under a cascaded 8259 controller */ | ||
308 | if (ic && device_is_compatible(ic, "chrp,iic")) { | ||
309 | np->intrs[intrcount].line = irq[0]; | ||
310 | } else { | ||
311 | virq = virt_irq_create_mapping(irq[0]); | ||
312 | if (virq == NO_IRQ) { | ||
313 | printk(KERN_CRIT "Could not allocate interrupt" | ||
314 | " number for %s\n", np->full_name); | ||
315 | continue; | ||
316 | } | ||
317 | np->intrs[intrcount].line = irq_offset_up(virq); | ||
318 | } | ||
319 | |||
320 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ | ||
321 | if (_machine == PLATFORM_POWERMAC && ic && ic->parent) { | ||
322 | char *name = get_property(ic->parent, "name", NULL); | ||
323 | if (name && !strcmp(name, "u3")) | ||
324 | np->intrs[intrcount].line += 128; | ||
325 | else if (!(name && !strcmp(name, "mac-io"))) | ||
326 | /* ignore other cascaded controllers, such as | ||
327 | the k2-sata-root */ | ||
328 | break; | ||
329 | } | ||
330 | np->intrs[intrcount].sense = 1; | ||
331 | if (n > 1) | ||
332 | np->intrs[intrcount].sense = irq[1]; | ||
333 | if (n > 2) { | ||
334 | printk("hmmm, got %d intr cells for %s:", n, | ||
335 | np->full_name); | ||
336 | for (j = 0; j < n; ++j) | ||
337 | printk(" %d", irq[j]); | ||
338 | printk("\n"); | ||
339 | } | ||
340 | ++intrcount; | ||
341 | } | ||
342 | np->n_intrs = intrcount; | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | static int __devinit interpret_pci_props(struct device_node *np, | ||
348 | unsigned long *mem_start, | ||
349 | int naddrc, int nsizec, | ||
350 | int measure_only) | ||
351 | { | ||
352 | struct address_range *adr; | ||
353 | struct pci_reg_property *pci_addrs; | ||
354 | int i, l, n_addrs; | ||
355 | |||
356 | pci_addrs = (struct pci_reg_property *) | ||
357 | get_property(np, "assigned-addresses", &l); | ||
358 | if (!pci_addrs) | ||
359 | return 0; | ||
360 | |||
361 | n_addrs = l / sizeof(*pci_addrs); | ||
362 | |||
363 | adr = prom_alloc(n_addrs * sizeof(*adr), mem_start); | ||
364 | if (!adr) | ||
365 | return -ENOMEM; | ||
366 | |||
367 | if (measure_only) | ||
368 | return 0; | ||
369 | |||
370 | np->addrs = adr; | ||
371 | np->n_addrs = n_addrs; | ||
372 | |||
373 | for (i = 0; i < n_addrs; i++) { | ||
374 | adr[i].space = pci_addrs[i].addr.a_hi; | ||
375 | adr[i].address = pci_addrs[i].addr.a_lo | | ||
376 | ((u64)pci_addrs[i].addr.a_mid << 32); | ||
377 | adr[i].size = pci_addrs[i].size_lo; | ||
378 | } | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static int __init interpret_dbdma_props(struct device_node *np, | ||
384 | unsigned long *mem_start, | ||
385 | int naddrc, int nsizec, | ||
386 | int measure_only) | ||
387 | { | ||
388 | struct reg_property32 *rp; | ||
389 | struct address_range *adr; | ||
390 | unsigned long base_address; | ||
391 | int i, l; | ||
392 | struct device_node *db; | ||
393 | |||
394 | base_address = 0; | ||
395 | if (!measure_only) { | ||
396 | for (db = np->parent; db != NULL; db = db->parent) { | ||
397 | if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) { | ||
398 | base_address = db->addrs[0].address; | ||
399 | break; | ||
400 | } | ||
401 | } | ||
402 | } | ||
403 | |||
404 | rp = (struct reg_property32 *) get_property(np, "reg", &l); | ||
405 | if (rp != 0 && l >= sizeof(struct reg_property32)) { | ||
406 | i = 0; | ||
407 | adr = (struct address_range *) (*mem_start); | ||
408 | while ((l -= sizeof(struct reg_property32)) >= 0) { | ||
409 | if (!measure_only) { | ||
410 | adr[i].space = 2; | ||
411 | adr[i].address = rp[i].address + base_address; | ||
412 | adr[i].size = rp[i].size; | ||
413 | } | ||
414 | ++i; | ||
415 | } | ||
416 | np->addrs = adr; | ||
417 | np->n_addrs = i; | ||
418 | (*mem_start) += i * sizeof(struct address_range); | ||
419 | } | ||
420 | |||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | static int __init interpret_macio_props(struct device_node *np, | ||
425 | unsigned long *mem_start, | ||
426 | int naddrc, int nsizec, | ||
427 | int measure_only) | ||
428 | { | ||
429 | struct reg_property32 *rp; | ||
430 | struct address_range *adr; | ||
431 | unsigned long base_address; | ||
432 | int i, l; | ||
433 | struct device_node *db; | ||
434 | |||
435 | base_address = 0; | ||
436 | if (!measure_only) { | ||
437 | for (db = np->parent; db != NULL; db = db->parent) { | ||
438 | if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) { | ||
439 | base_address = db->addrs[0].address; | ||
440 | break; | ||
441 | } | ||
442 | } | ||
443 | } | ||
444 | |||
445 | rp = (struct reg_property32 *) get_property(np, "reg", &l); | ||
446 | if (rp != 0 && l >= sizeof(struct reg_property32)) { | ||
447 | i = 0; | ||
448 | adr = (struct address_range *) (*mem_start); | ||
449 | while ((l -= sizeof(struct reg_property32)) >= 0) { | ||
450 | if (!measure_only) { | ||
451 | adr[i].space = 2; | ||
452 | adr[i].address = rp[i].address + base_address; | ||
453 | adr[i].size = rp[i].size; | ||
454 | } | ||
455 | ++i; | ||
456 | } | ||
457 | np->addrs = adr; | ||
458 | np->n_addrs = i; | ||
459 | (*mem_start) += i * sizeof(struct address_range); | ||
460 | } | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static int __init interpret_isa_props(struct device_node *np, | ||
466 | unsigned long *mem_start, | ||
467 | int naddrc, int nsizec, | ||
468 | int measure_only) | ||
469 | { | ||
470 | struct isa_reg_property *rp; | ||
471 | struct address_range *adr; | ||
472 | int i, l; | ||
473 | |||
474 | rp = (struct isa_reg_property *) get_property(np, "reg", &l); | ||
475 | if (rp != 0 && l >= sizeof(struct isa_reg_property)) { | ||
476 | i = 0; | ||
477 | adr = (struct address_range *) (*mem_start); | ||
478 | while ((l -= sizeof(struct isa_reg_property)) >= 0) { | ||
479 | if (!measure_only) { | ||
480 | adr[i].space = rp[i].space; | ||
481 | adr[i].address = rp[i].address; | ||
482 | adr[i].size = rp[i].size; | ||
483 | } | ||
484 | ++i; | ||
485 | } | ||
486 | np->addrs = adr; | ||
487 | np->n_addrs = i; | ||
488 | (*mem_start) += i * sizeof(struct address_range); | ||
489 | } | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static int __init interpret_root_props(struct device_node *np, | ||
495 | unsigned long *mem_start, | ||
496 | int naddrc, int nsizec, | ||
497 | int measure_only) | ||
498 | { | ||
499 | struct address_range *adr; | ||
500 | int i, l; | ||
501 | unsigned int *rp; | ||
502 | int rpsize = (naddrc + nsizec) * sizeof(unsigned int); | ||
503 | |||
504 | rp = (unsigned int *) get_property(np, "reg", &l); | ||
505 | if (rp != 0 && l >= rpsize) { | ||
506 | i = 0; | ||
507 | adr = (struct address_range *) (*mem_start); | ||
508 | while ((l -= rpsize) >= 0) { | ||
509 | if (!measure_only) { | ||
510 | adr[i].space = 0; | ||
511 | adr[i].address = rp[naddrc - 1]; | ||
512 | adr[i].size = rp[naddrc + nsizec - 1]; | ||
513 | } | ||
514 | ++i; | ||
515 | rp += naddrc + nsizec; | ||
516 | } | ||
517 | np->addrs = adr; | ||
518 | np->n_addrs = i; | ||
519 | (*mem_start) += i * sizeof(struct address_range); | ||
520 | } | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static int __devinit finish_node(struct device_node *np, | ||
526 | unsigned long *mem_start, | ||
527 | interpret_func *ifunc, | ||
528 | int naddrc, int nsizec, | ||
529 | int measure_only) | ||
530 | { | ||
531 | struct device_node *child; | ||
532 | int *ip, rc = 0; | ||
533 | |||
534 | /* get the device addresses and interrupts */ | ||
535 | if (ifunc != NULL) | ||
536 | rc = ifunc(np, mem_start, naddrc, nsizec, measure_only); | ||
537 | if (rc) | ||
538 | goto out; | ||
539 | |||
540 | rc = finish_node_interrupts(np, mem_start, measure_only); | ||
541 | if (rc) | ||
542 | goto out; | ||
543 | |||
544 | /* Look for #address-cells and #size-cells properties. */ | ||
545 | ip = (int *) get_property(np, "#address-cells", NULL); | ||
546 | if (ip != NULL) | ||
547 | naddrc = *ip; | ||
548 | ip = (int *) get_property(np, "#size-cells", NULL); | ||
549 | if (ip != NULL) | ||
550 | nsizec = *ip; | ||
551 | |||
552 | if (!strcmp(np->name, "device-tree") || np->parent == NULL) | ||
553 | ifunc = interpret_root_props; | ||
554 | else if (np->type == 0) | ||
555 | ifunc = NULL; | ||
556 | else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci")) | ||
557 | ifunc = interpret_pci_props; | ||
558 | else if (!strcmp(np->type, "dbdma")) | ||
559 | ifunc = interpret_dbdma_props; | ||
560 | else if (!strcmp(np->type, "mac-io") || ifunc == interpret_macio_props) | ||
561 | ifunc = interpret_macio_props; | ||
562 | else if (!strcmp(np->type, "isa")) | ||
563 | ifunc = interpret_isa_props; | ||
564 | else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3")) | ||
565 | ifunc = interpret_root_props; | ||
566 | else if (!((ifunc == interpret_dbdma_props | ||
567 | || ifunc == interpret_macio_props) | ||
568 | && (!strcmp(np->type, "escc") | ||
569 | || !strcmp(np->type, "media-bay")))) | ||
570 | ifunc = NULL; | ||
571 | |||
572 | for (child = np->child; child != NULL; child = child->sibling) { | ||
573 | rc = finish_node(child, mem_start, ifunc, | ||
574 | naddrc, nsizec, measure_only); | ||
575 | if (rc) | ||
576 | goto out; | ||
577 | } | ||
578 | out: | ||
579 | return rc; | ||
580 | } | ||
581 | |||
582 | /** | ||
583 | * finish_device_tree is called once things are running normally | ||
584 | * (i.e. with text and data mapped to the address they were linked at). | ||
585 | * It traverses the device tree and fills in some of the additional, | ||
586 | * fields in each node like {n_}addrs and {n_}intrs, the virt interrupt | ||
587 | * mapping is also initialized at this point. | ||
588 | */ | ||
589 | void __init finish_device_tree(void) | ||
590 | { | ||
591 | unsigned long start, end, size = 0; | ||
592 | |||
593 | DBG(" -> finish_device_tree\n"); | ||
594 | |||
595 | if (ppc64_interrupt_controller == IC_INVALID) { | ||
596 | DBG("failed to configure interrupt controller type\n"); | ||
597 | panic("failed to configure interrupt controller type\n"); | ||
598 | } | ||
599 | |||
600 | /* Initialize virtual IRQ map */ | ||
601 | virt_irq_init(); | ||
602 | |||
603 | /* | ||
604 | * Finish device-tree (pre-parsing some properties etc...) | ||
605 | * We do this in 2 passes. One with "measure_only" set, which | ||
606 | * will only measure the amount of memory needed, then we can | ||
607 | * allocate that memory, and call finish_node again. However, | ||
608 | * we must be careful as most routines will fail nowadays when | ||
609 | * prom_alloc() returns 0, so we must make sure our first pass | ||
610 | * doesn't start at 0. We pre-initialize size to 16 for that | ||
611 | * reason and then remove those additional 16 bytes | ||
612 | */ | ||
613 | size = 16; | ||
614 | finish_node(allnodes, &size, NULL, 0, 0, 1); | ||
615 | size -= 16; | ||
616 | end = start = (unsigned long)abs_to_virt(lmb_alloc(size, 128)); | ||
617 | finish_node(allnodes, &end, NULL, 0, 0, 0); | ||
618 | BUG_ON(end != start + size); | ||
619 | |||
620 | DBG(" <- finish_device_tree\n"); | ||
621 | } | ||
622 | |||
623 | #ifdef DEBUG | ||
624 | #define printk udbg_printf | ||
625 | #endif | ||
626 | |||
627 | static inline char *find_flat_dt_string(u32 offset) | ||
628 | { | ||
629 | return ((char *)initial_boot_params) + | ||
630 | initial_boot_params->off_dt_strings + offset; | ||
631 | } | ||
632 | |||
633 | /** | ||
634 | * This function is used to scan the flattened device-tree, it is | ||
635 | * used to extract the memory informations at boot before we can | ||
636 | * unflatten the tree | ||
637 | */ | ||
638 | int __init of_scan_flat_dt(int (*it)(unsigned long node, | ||
639 | const char *uname, int depth, | ||
640 | void *data), | ||
641 | void *data) | ||
642 | { | ||
643 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
644 | initial_boot_params->off_dt_struct; | ||
645 | int rc = 0; | ||
646 | int depth = -1; | ||
647 | |||
648 | do { | ||
649 | u32 tag = *((u32 *)p); | ||
650 | char *pathp; | ||
651 | |||
652 | p += 4; | ||
653 | if (tag == OF_DT_END_NODE) { | ||
654 | depth --; | ||
655 | continue; | ||
656 | } | ||
657 | if (tag == OF_DT_NOP) | ||
658 | continue; | ||
659 | if (tag == OF_DT_END) | ||
660 | break; | ||
661 | if (tag == OF_DT_PROP) { | ||
662 | u32 sz = *((u32 *)p); | ||
663 | p += 8; | ||
664 | if (initial_boot_params->version < 0x10) | ||
665 | p = _ALIGN(p, sz >= 8 ? 8 : 4); | ||
666 | p += sz; | ||
667 | p = _ALIGN(p, 4); | ||
668 | continue; | ||
669 | } | ||
670 | if (tag != OF_DT_BEGIN_NODE) { | ||
671 | printk(KERN_WARNING "Invalid tag %x scanning flattened" | ||
672 | " device tree !\n", tag); | ||
673 | return -EINVAL; | ||
674 | } | ||
675 | depth++; | ||
676 | pathp = (char *)p; | ||
677 | p = _ALIGN(p + strlen(pathp) + 1, 4); | ||
678 | if ((*pathp) == '/') { | ||
679 | char *lp, *np; | ||
680 | for (lp = NULL, np = pathp; *np; np++) | ||
681 | if ((*np) == '/') | ||
682 | lp = np+1; | ||
683 | if (lp != NULL) | ||
684 | pathp = lp; | ||
685 | } | ||
686 | rc = it(p, pathp, depth, data); | ||
687 | if (rc != 0) | ||
688 | break; | ||
689 | } while(1); | ||
690 | |||
691 | return rc; | ||
692 | } | ||
693 | |||
694 | /** | ||
695 | * This function can be used within scan_flattened_dt callback to get | ||
696 | * access to properties | ||
697 | */ | ||
698 | void* __init of_get_flat_dt_prop(unsigned long node, const char *name, | ||
699 | unsigned long *size) | ||
700 | { | ||
701 | unsigned long p = node; | ||
702 | |||
703 | do { | ||
704 | u32 tag = *((u32 *)p); | ||
705 | u32 sz, noff; | ||
706 | const char *nstr; | ||
707 | |||
708 | p += 4; | ||
709 | if (tag == OF_DT_NOP) | ||
710 | continue; | ||
711 | if (tag != OF_DT_PROP) | ||
712 | return NULL; | ||
713 | |||
714 | sz = *((u32 *)p); | ||
715 | noff = *((u32 *)(p + 4)); | ||
716 | p += 8; | ||
717 | if (initial_boot_params->version < 0x10) | ||
718 | p = _ALIGN(p, sz >= 8 ? 8 : 4); | ||
719 | |||
720 | nstr = find_flat_dt_string(noff); | ||
721 | if (nstr == NULL) { | ||
722 | printk(KERN_WARNING "Can't find property index" | ||
723 | " name !\n"); | ||
724 | return NULL; | ||
725 | } | ||
726 | if (strcmp(name, nstr) == 0) { | ||
727 | if (size) | ||
728 | *size = sz; | ||
729 | return (void *)p; | ||
730 | } | ||
731 | p += sz; | ||
732 | p = _ALIGN(p, 4); | ||
733 | } while(1); | ||
734 | } | ||
735 | |||
736 | static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, | ||
737 | unsigned long align) | ||
738 | { | ||
739 | void *res; | ||
740 | |||
741 | *mem = _ALIGN(*mem, align); | ||
742 | res = (void *)*mem; | ||
743 | *mem += size; | ||
744 | |||
745 | return res; | ||
746 | } | ||
747 | |||
748 | static unsigned long __init unflatten_dt_node(unsigned long mem, | ||
749 | unsigned long *p, | ||
750 | struct device_node *dad, | ||
751 | struct device_node ***allnextpp, | ||
752 | unsigned long fpsize) | ||
753 | { | ||
754 | struct device_node *np; | ||
755 | struct property *pp, **prev_pp = NULL; | ||
756 | char *pathp; | ||
757 | u32 tag; | ||
758 | unsigned int l, allocl; | ||
759 | int has_name = 0; | ||
760 | int new_format = 0; | ||
761 | |||
762 | tag = *((u32 *)(*p)); | ||
763 | if (tag != OF_DT_BEGIN_NODE) { | ||
764 | printk("Weird tag at start of node: %x\n", tag); | ||
765 | return mem; | ||
766 | } | ||
767 | *p += 4; | ||
768 | pathp = (char *)*p; | ||
769 | l = allocl = strlen(pathp) + 1; | ||
770 | *p = _ALIGN(*p + l, 4); | ||
771 | |||
772 | /* version 0x10 has a more compact unit name here instead of the full | ||
773 | * path. we accumulate the full path size using "fpsize", we'll rebuild | ||
774 | * it later. We detect this because the first character of the name is | ||
775 | * not '/'. | ||
776 | */ | ||
777 | if ((*pathp) != '/') { | ||
778 | new_format = 1; | ||
779 | if (fpsize == 0) { | ||
780 | /* root node: special case. fpsize accounts for path | ||
781 | * plus terminating zero. root node only has '/', so | ||
782 | * fpsize should be 2, but we want to avoid the first | ||
783 | * level nodes to have two '/' so we use fpsize 1 here | ||
784 | */ | ||
785 | fpsize = 1; | ||
786 | allocl = 2; | ||
787 | } else { | ||
788 | /* account for '/' and path size minus terminal 0 | ||
789 | * already in 'l' | ||
790 | */ | ||
791 | fpsize += l; | ||
792 | allocl = fpsize; | ||
793 | } | ||
794 | } | ||
795 | |||
796 | |||
797 | np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl, | ||
798 | __alignof__(struct device_node)); | ||
799 | if (allnextpp) { | ||
800 | memset(np, 0, sizeof(*np)); | ||
801 | np->full_name = ((char*)np) + sizeof(struct device_node); | ||
802 | if (new_format) { | ||
803 | char *p = np->full_name; | ||
804 | /* rebuild full path for new format */ | ||
805 | if (dad && dad->parent) { | ||
806 | strcpy(p, dad->full_name); | ||
807 | #ifdef DEBUG | ||
808 | if ((strlen(p) + l + 1) != allocl) { | ||
809 | DBG("%s: p: %d, l: %d, a: %d\n", | ||
810 | pathp, strlen(p), l, allocl); | ||
811 | } | ||
812 | #endif | ||
813 | p += strlen(p); | ||
814 | } | ||
815 | *(p++) = '/'; | ||
816 | memcpy(p, pathp, l); | ||
817 | } else | ||
818 | memcpy(np->full_name, pathp, l); | ||
819 | prev_pp = &np->properties; | ||
820 | **allnextpp = np; | ||
821 | *allnextpp = &np->allnext; | ||
822 | if (dad != NULL) { | ||
823 | np->parent = dad; | ||
824 | /* we temporarily use the next field as `last_child'*/ | ||
825 | if (dad->next == 0) | ||
826 | dad->child = np; | ||
827 | else | ||
828 | dad->next->sibling = np; | ||
829 | dad->next = np; | ||
830 | } | ||
831 | kref_init(&np->kref); | ||
832 | } | ||
833 | while(1) { | ||
834 | u32 sz, noff; | ||
835 | char *pname; | ||
836 | |||
837 | tag = *((u32 *)(*p)); | ||
838 | if (tag == OF_DT_NOP) { | ||
839 | *p += 4; | ||
840 | continue; | ||
841 | } | ||
842 | if (tag != OF_DT_PROP) | ||
843 | break; | ||
844 | *p += 4; | ||
845 | sz = *((u32 *)(*p)); | ||
846 | noff = *((u32 *)((*p) + 4)); | ||
847 | *p += 8; | ||
848 | if (initial_boot_params->version < 0x10) | ||
849 | *p = _ALIGN(*p, sz >= 8 ? 8 : 4); | ||
850 | |||
851 | pname = find_flat_dt_string(noff); | ||
852 | if (pname == NULL) { | ||
853 | printk("Can't find property name in list !\n"); | ||
854 | break; | ||
855 | } | ||
856 | if (strcmp(pname, "name") == 0) | ||
857 | has_name = 1; | ||
858 | l = strlen(pname) + 1; | ||
859 | pp = unflatten_dt_alloc(&mem, sizeof(struct property), | ||
860 | __alignof__(struct property)); | ||
861 | if (allnextpp) { | ||
862 | if (strcmp(pname, "linux,phandle") == 0) { | ||
863 | np->node = *((u32 *)*p); | ||
864 | if (np->linux_phandle == 0) | ||
865 | np->linux_phandle = np->node; | ||
866 | } | ||
867 | if (strcmp(pname, "ibm,phandle") == 0) | ||
868 | np->linux_phandle = *((u32 *)*p); | ||
869 | pp->name = pname; | ||
870 | pp->length = sz; | ||
871 | pp->value = (void *)*p; | ||
872 | *prev_pp = pp; | ||
873 | prev_pp = &pp->next; | ||
874 | } | ||
875 | *p = _ALIGN((*p) + sz, 4); | ||
876 | } | ||
877 | /* with version 0x10 we may not have the name property, recreate | ||
878 | * it here from the unit name if absent | ||
879 | */ | ||
880 | if (!has_name) { | ||
881 | char *p = pathp, *ps = pathp, *pa = NULL; | ||
882 | int sz; | ||
883 | |||
884 | while (*p) { | ||
885 | if ((*p) == '@') | ||
886 | pa = p; | ||
887 | if ((*p) == '/') | ||
888 | ps = p + 1; | ||
889 | p++; | ||
890 | } | ||
891 | if (pa < ps) | ||
892 | pa = p; | ||
893 | sz = (pa - ps) + 1; | ||
894 | pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz, | ||
895 | __alignof__(struct property)); | ||
896 | if (allnextpp) { | ||
897 | pp->name = "name"; | ||
898 | pp->length = sz; | ||
899 | pp->value = (unsigned char *)(pp + 1); | ||
900 | *prev_pp = pp; | ||
901 | prev_pp = &pp->next; | ||
902 | memcpy(pp->value, ps, sz - 1); | ||
903 | ((char *)pp->value)[sz - 1] = 0; | ||
904 | DBG("fixed up name for %s -> %s\n", pathp, pp->value); | ||
905 | } | ||
906 | } | ||
907 | if (allnextpp) { | ||
908 | *prev_pp = NULL; | ||
909 | np->name = get_property(np, "name", NULL); | ||
910 | np->type = get_property(np, "device_type", NULL); | ||
911 | |||
912 | if (!np->name) | ||
913 | np->name = "<NULL>"; | ||
914 | if (!np->type) | ||
915 | np->type = "<NULL>"; | ||
916 | } | ||
917 | while (tag == OF_DT_BEGIN_NODE) { | ||
918 | mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); | ||
919 | tag = *((u32 *)(*p)); | ||
920 | } | ||
921 | if (tag != OF_DT_END_NODE) { | ||
922 | printk("Weird tag at end of node: %x\n", tag); | ||
923 | return mem; | ||
924 | } | ||
925 | *p += 4; | ||
926 | return mem; | ||
927 | } | ||
928 | |||
929 | |||
930 | /** | ||
931 | * unflattens the device-tree passed by the firmware, creating the | ||
932 | * tree of struct device_node. It also fills the "name" and "type" | ||
933 | * pointers of the nodes so the normal device-tree walking functions | ||
934 | * can be used (this used to be done by finish_device_tree) | ||
935 | */ | ||
936 | void __init unflatten_device_tree(void) | ||
937 | { | ||
938 | unsigned long start, mem, size; | ||
939 | struct device_node **allnextp = &allnodes; | ||
940 | char *p = NULL; | ||
941 | int l = 0; | ||
942 | |||
943 | DBG(" -> unflatten_device_tree()\n"); | ||
944 | |||
945 | /* First pass, scan for size */ | ||
946 | start = ((unsigned long)initial_boot_params) + | ||
947 | initial_boot_params->off_dt_struct; | ||
948 | size = unflatten_dt_node(0, &start, NULL, NULL, 0); | ||
949 | size = (size | 3) + 1; | ||
950 | |||
951 | DBG(" size is %lx, allocating...\n", size); | ||
952 | |||
953 | /* Allocate memory for the expanded device tree */ | ||
954 | mem = lmb_alloc(size + 4, __alignof__(struct device_node)); | ||
955 | if (!mem) { | ||
956 | DBG("Couldn't allocate memory with lmb_alloc()!\n"); | ||
957 | panic("Couldn't allocate memory with lmb_alloc()!\n"); | ||
958 | } | ||
959 | mem = (unsigned long)abs_to_virt(mem); | ||
960 | |||
961 | ((u32 *)mem)[size / 4] = 0xdeadbeef; | ||
962 | |||
963 | DBG(" unflattening...\n", mem); | ||
964 | |||
965 | /* Second pass, do actual unflattening */ | ||
966 | start = ((unsigned long)initial_boot_params) + | ||
967 | initial_boot_params->off_dt_struct; | ||
968 | unflatten_dt_node(mem, &start, NULL, &allnextp, 0); | ||
969 | if (*((u32 *)start) != OF_DT_END) | ||
970 | printk(KERN_WARNING "Weird tag at end of tree: %08x\n", *((u32 *)start)); | ||
971 | if (((u32 *)mem)[size / 4] != 0xdeadbeef) | ||
972 | printk(KERN_WARNING "End of tree marker overwritten: %08x\n", | ||
973 | ((u32 *)mem)[size / 4] ); | ||
974 | *allnextp = NULL; | ||
975 | |||
976 | /* Get pointer to OF "/chosen" node for use everywhere */ | ||
977 | of_chosen = of_find_node_by_path("/chosen"); | ||
978 | |||
979 | /* Retreive command line */ | ||
980 | if (of_chosen != NULL) { | ||
981 | p = (char *)get_property(of_chosen, "bootargs", &l); | ||
982 | if (p != NULL && l > 0) | ||
983 | strlcpy(cmd_line, p, min(l, COMMAND_LINE_SIZE)); | ||
984 | } | ||
985 | #ifdef CONFIG_CMDLINE | ||
986 | if (l == 0 || (l == 1 && (*p) == 0)) | ||
987 | strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); | ||
988 | #endif /* CONFIG_CMDLINE */ | ||
989 | |||
990 | DBG("Command line is: %s\n", cmd_line); | ||
991 | |||
992 | DBG(" <- unflatten_device_tree()\n"); | ||
993 | } | ||
994 | |||
995 | |||
996 | static int __init early_init_dt_scan_cpus(unsigned long node, | ||
997 | const char *uname, int depth, void *data) | ||
998 | { | ||
999 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | ||
1000 | u32 *prop; | ||
1001 | unsigned long size; | ||
1002 | |||
1003 | /* We are scanning "cpu" nodes only */ | ||
1004 | if (type == NULL || strcmp(type, "cpu") != 0) | ||
1005 | return 0; | ||
1006 | |||
1007 | if (initial_boot_params && initial_boot_params->version >= 2) { | ||
1008 | /* version 2 of the kexec param format adds the phys cpuid | ||
1009 | * of booted proc. | ||
1010 | */ | ||
1011 | boot_cpuid_phys = initial_boot_params->boot_cpuid_phys; | ||
1012 | boot_cpuid = 0; | ||
1013 | } else { | ||
1014 | /* Check if it's the boot-cpu, set it's hw index in paca now */ | ||
1015 | if (of_get_flat_dt_prop(node, "linux,boot-cpu", NULL) | ||
1016 | != NULL) { | ||
1017 | u32 *prop = of_get_flat_dt_prop(node, "reg", NULL); | ||
1018 | set_hard_smp_processor_id(0, prop == NULL ? 0 : *prop); | ||
1019 | boot_cpuid_phys = get_hard_smp_processor_id(0); | ||
1020 | } | ||
1021 | } | ||
1022 | |||
1023 | #ifdef CONFIG_ALTIVEC | ||
1024 | /* Check if we have a VMX and eventually update CPU features */ | ||
1025 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL); | ||
1026 | if (prop && (*prop) > 0) { | ||
1027 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; | ||
1028 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; | ||
1029 | } | ||
1030 | |||
1031 | /* Same goes for Apple's "altivec" property */ | ||
1032 | prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL); | ||
1033 | if (prop) { | ||
1034 | cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; | ||
1035 | cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; | ||
1036 | } | ||
1037 | #endif /* CONFIG_ALTIVEC */ | ||
1038 | |||
1039 | /* | ||
1040 | * Check for an SMT capable CPU and set the CPU feature. We do | ||
1041 | * this by looking at the size of the ibm,ppc-interrupt-server#s | ||
1042 | * property | ||
1043 | */ | ||
1044 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", | ||
1045 | &size); | ||
1046 | cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; | ||
1047 | if (prop && ((size / sizeof(u32)) > 1)) | ||
1048 | cur_cpu_spec->cpu_features |= CPU_FTR_SMT; | ||
1049 | |||
1050 | return 0; | ||
1051 | } | ||
1052 | |||
1053 | static int __init early_init_dt_scan_chosen(unsigned long node, | ||
1054 | const char *uname, int depth, void *data) | ||
1055 | { | ||
1056 | u32 *prop; | ||
1057 | u64 *prop64; | ||
1058 | |||
1059 | DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname); | ||
1060 | |||
1061 | if (depth != 1 || strcmp(uname, "chosen") != 0) | ||
1062 | return 0; | ||
1063 | |||
1064 | /* get platform type */ | ||
1065 | prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); | ||
1066 | if (prop == NULL) | ||
1067 | return 0; | ||
1068 | _machine = *prop; | ||
1069 | |||
1070 | /* check if iommu is forced on or off */ | ||
1071 | if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) | ||
1072 | iommu_is_off = 1; | ||
1073 | if (of_get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL) | ||
1074 | iommu_force_on = 1; | ||
1075 | |||
1076 | prop64 = (u64*)of_get_flat_dt_prop(node, "linux,memory-limit", NULL); | ||
1077 | if (prop64) | ||
1078 | memory_limit = *prop64; | ||
1079 | |||
1080 | prop64 = (u64*)of_get_flat_dt_prop(node, "linux,tce-alloc-start",NULL); | ||
1081 | if (prop64) | ||
1082 | tce_alloc_start = *prop64; | ||
1083 | |||
1084 | prop64 = (u64*)of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); | ||
1085 | if (prop64) | ||
1086 | tce_alloc_end = *prop64; | ||
1087 | |||
1088 | #ifdef CONFIG_PPC_RTAS | ||
1089 | /* To help early debugging via the front panel, we retreive a minimal | ||
1090 | * set of RTAS infos now if available | ||
1091 | */ | ||
1092 | { | ||
1093 | u64 *basep, *entryp; | ||
1094 | |||
1095 | basep = (u64*)of_get_flat_dt_prop(node, | ||
1096 | "linux,rtas-base", NULL); | ||
1097 | entryp = (u64*)of_get_flat_dt_prop(node, | ||
1098 | "linux,rtas-entry", NULL); | ||
1099 | prop = (u32*)of_get_flat_dt_prop(node, | ||
1100 | "linux,rtas-size", NULL); | ||
1101 | if (basep && entryp && prop) { | ||
1102 | rtas.base = *basep; | ||
1103 | rtas.entry = *entryp; | ||
1104 | rtas.size = *prop; | ||
1105 | } | ||
1106 | } | ||
1107 | #endif /* CONFIG_PPC_RTAS */ | ||
1108 | |||
1109 | /* break now */ | ||
1110 | return 1; | ||
1111 | } | ||
1112 | |||
1113 | static int __init early_init_dt_scan_root(unsigned long node, | ||
1114 | const char *uname, int depth, void *data) | ||
1115 | { | ||
1116 | u32 *prop; | ||
1117 | |||
1118 | if (depth != 0) | ||
1119 | return 0; | ||
1120 | |||
1121 | prop = (u32 *)of_get_flat_dt_prop(node, "#size-cells", NULL); | ||
1122 | dt_root_size_cells = (prop == NULL) ? 1 : *prop; | ||
1123 | DBG("dt_root_size_cells = %x\n", dt_root_size_cells); | ||
1124 | |||
1125 | prop = (u32 *)of_get_flat_dt_prop(node, "#address-cells", NULL); | ||
1126 | dt_root_addr_cells = (prop == NULL) ? 2 : *prop; | ||
1127 | DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells); | ||
1128 | |||
1129 | /* break now */ | ||
1130 | return 1; | ||
1131 | } | ||
1132 | |||
1133 | static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp) | ||
1134 | { | ||
1135 | cell_t *p = *cellp; | ||
1136 | unsigned long r = 0; | ||
1137 | |||
1138 | /* Ignore more than 2 cells */ | ||
1139 | while (s > 2) { | ||
1140 | p++; | ||
1141 | s--; | ||
1142 | } | ||
1143 | while (s) { | ||
1144 | r <<= 32; | ||
1145 | r |= *(p++); | ||
1146 | s--; | ||
1147 | } | ||
1148 | |||
1149 | *cellp = p; | ||
1150 | return r; | ||
1151 | } | ||
1152 | |||
1153 | |||
1154 | static int __init early_init_dt_scan_memory(unsigned long node, | ||
1155 | const char *uname, int depth, void *data) | ||
1156 | { | ||
1157 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | ||
1158 | cell_t *reg, *endp; | ||
1159 | unsigned long l; | ||
1160 | |||
1161 | /* We are scanning "memory" nodes only */ | ||
1162 | if (type == NULL || strcmp(type, "memory") != 0) | ||
1163 | return 0; | ||
1164 | |||
1165 | reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); | ||
1166 | if (reg == NULL) | ||
1167 | return 0; | ||
1168 | |||
1169 | endp = reg + (l / sizeof(cell_t)); | ||
1170 | |||
1171 | DBG("memory scan node %s ..., reg size %ld, data: %x %x %x %x, ...\n", | ||
1172 | uname, l, reg[0], reg[1], reg[2], reg[3]); | ||
1173 | |||
1174 | while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { | ||
1175 | unsigned long base, size; | ||
1176 | |||
1177 | base = dt_mem_next_cell(dt_root_addr_cells, ®); | ||
1178 | size = dt_mem_next_cell(dt_root_size_cells, ®); | ||
1179 | |||
1180 | if (size == 0) | ||
1181 | continue; | ||
1182 | DBG(" - %lx , %lx\n", base, size); | ||
1183 | if (iommu_is_off) { | ||
1184 | if (base >= 0x80000000ul) | ||
1185 | continue; | ||
1186 | if ((base + size) > 0x80000000ul) | ||
1187 | size = 0x80000000ul - base; | ||
1188 | } | ||
1189 | lmb_add(base, size); | ||
1190 | } | ||
1191 | return 0; | ||
1192 | } | ||
1193 | |||
1194 | static void __init early_reserve_mem(void) | ||
1195 | { | ||
1196 | u64 base, size; | ||
1197 | u64 *reserve_map = (u64 *)(((unsigned long)initial_boot_params) + | ||
1198 | initial_boot_params->off_mem_rsvmap); | ||
1199 | while (1) { | ||
1200 | base = *(reserve_map++); | ||
1201 | size = *(reserve_map++); | ||
1202 | if (size == 0) | ||
1203 | break; | ||
1204 | DBG("reserving: %lx -> %lx\n", base, size); | ||
1205 | lmb_reserve(base, size); | ||
1206 | } | ||
1207 | |||
1208 | #if 0 | ||
1209 | DBG("memory reserved, lmbs :\n"); | ||
1210 | lmb_dump_all(); | ||
1211 | #endif | ||
1212 | } | ||
1213 | |||
1214 | void __init early_init_devtree(void *params) | ||
1215 | { | ||
1216 | DBG(" -> early_init_devtree()\n"); | ||
1217 | |||
1218 | /* Setup flat device-tree pointer */ | ||
1219 | initial_boot_params = params; | ||
1220 | |||
1221 | /* Retreive various informations from the /chosen node of the | ||
1222 | * device-tree, including the platform type, initrd location and | ||
1223 | * size, TCE reserve, and more ... | ||
1224 | */ | ||
1225 | of_scan_flat_dt(early_init_dt_scan_chosen, NULL); | ||
1226 | |||
1227 | /* Scan memory nodes and rebuild LMBs */ | ||
1228 | lmb_init(); | ||
1229 | of_scan_flat_dt(early_init_dt_scan_root, NULL); | ||
1230 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | ||
1231 | lmb_enforce_memory_limit(memory_limit); | ||
1232 | lmb_analyze(); | ||
1233 | lmb_reserve(0, __pa(klimit)); | ||
1234 | |||
1235 | /* Reserve LMB regions used by kernel, initrd, dt, etc... */ | ||
1236 | early_reserve_mem(); | ||
1237 | |||
1238 | DBG("Scanning CPUs ...\n"); | ||
1239 | |||
1240 | /* Retreive hash table size from flattened tree plus other | ||
1241 | * CPU related informations (altivec support, boot CPU ID, ...) | ||
1242 | */ | ||
1243 | of_scan_flat_dt(early_init_dt_scan_cpus, NULL); | ||
1244 | |||
1245 | DBG(" <- early_init_devtree()\n"); | ||
1246 | } | ||
1247 | |||
1248 | #undef printk | ||
1249 | |||
1250 | int | ||
1251 | prom_n_addr_cells(struct device_node* np) | ||
1252 | { | ||
1253 | int* ip; | ||
1254 | do { | ||
1255 | if (np->parent) | ||
1256 | np = np->parent; | ||
1257 | ip = (int *) get_property(np, "#address-cells", NULL); | ||
1258 | if (ip != NULL) | ||
1259 | return *ip; | ||
1260 | } while (np->parent); | ||
1261 | /* No #address-cells property for the root node, default to 1 */ | ||
1262 | return 1; | ||
1263 | } | ||
1264 | EXPORT_SYMBOL_GPL(prom_n_addr_cells); | ||
1265 | |||
1266 | int | ||
1267 | prom_n_size_cells(struct device_node* np) | ||
1268 | { | ||
1269 | int* ip; | ||
1270 | do { | ||
1271 | if (np->parent) | ||
1272 | np = np->parent; | ||
1273 | ip = (int *) get_property(np, "#size-cells", NULL); | ||
1274 | if (ip != NULL) | ||
1275 | return *ip; | ||
1276 | } while (np->parent); | ||
1277 | /* No #size-cells property for the root node, default to 1 */ | ||
1278 | return 1; | ||
1279 | } | ||
1280 | EXPORT_SYMBOL_GPL(prom_n_size_cells); | ||
1281 | |||
1282 | /** | ||
1283 | * Work out the sense (active-low level / active-high edge) | ||
1284 | * of each interrupt from the device tree. | ||
1285 | */ | ||
1286 | void __init prom_get_irq_senses(unsigned char *senses, int off, int max) | ||
1287 | { | ||
1288 | struct device_node *np; | ||
1289 | int i, j; | ||
1290 | |||
1291 | /* default to level-triggered */ | ||
1292 | memset(senses, 1, max - off); | ||
1293 | |||
1294 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1295 | for (j = 0; j < np->n_intrs; j++) { | ||
1296 | i = np->intrs[j].line; | ||
1297 | if (i >= off && i < max) | ||
1298 | senses[i-off] = np->intrs[j].sense ? | ||
1299 | IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE : | ||
1300 | IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE; | ||
1301 | } | ||
1302 | } | ||
1303 | } | ||
1304 | |||
1305 | /** | ||
1306 | * Construct and return a list of the device_nodes with a given name. | ||
1307 | */ | ||
1308 | struct device_node * | ||
1309 | find_devices(const char *name) | ||
1310 | { | ||
1311 | struct device_node *head, **prevp, *np; | ||
1312 | |||
1313 | prevp = &head; | ||
1314 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1315 | if (np->name != 0 && strcasecmp(np->name, name) == 0) { | ||
1316 | *prevp = np; | ||
1317 | prevp = &np->next; | ||
1318 | } | ||
1319 | } | ||
1320 | *prevp = NULL; | ||
1321 | return head; | ||
1322 | } | ||
1323 | EXPORT_SYMBOL(find_devices); | ||
1324 | |||
1325 | /** | ||
1326 | * Construct and return a list of the device_nodes with a given type. | ||
1327 | */ | ||
1328 | struct device_node * | ||
1329 | find_type_devices(const char *type) | ||
1330 | { | ||
1331 | struct device_node *head, **prevp, *np; | ||
1332 | |||
1333 | prevp = &head; | ||
1334 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1335 | if (np->type != 0 && strcasecmp(np->type, type) == 0) { | ||
1336 | *prevp = np; | ||
1337 | prevp = &np->next; | ||
1338 | } | ||
1339 | } | ||
1340 | *prevp = NULL; | ||
1341 | return head; | ||
1342 | } | ||
1343 | EXPORT_SYMBOL(find_type_devices); | ||
1344 | |||
1345 | /** | ||
1346 | * Returns all nodes linked together | ||
1347 | */ | ||
1348 | struct device_node * | ||
1349 | find_all_nodes(void) | ||
1350 | { | ||
1351 | struct device_node *head, **prevp, *np; | ||
1352 | |||
1353 | prevp = &head; | ||
1354 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1355 | *prevp = np; | ||
1356 | prevp = &np->next; | ||
1357 | } | ||
1358 | *prevp = NULL; | ||
1359 | return head; | ||
1360 | } | ||
1361 | EXPORT_SYMBOL(find_all_nodes); | ||
1362 | |||
1363 | /** Checks if the given "compat" string matches one of the strings in | ||
1364 | * the device's "compatible" property | ||
1365 | */ | ||
1366 | int | ||
1367 | device_is_compatible(struct device_node *device, const char *compat) | ||
1368 | { | ||
1369 | const char* cp; | ||
1370 | int cplen, l; | ||
1371 | |||
1372 | cp = (char *) get_property(device, "compatible", &cplen); | ||
1373 | if (cp == NULL) | ||
1374 | return 0; | ||
1375 | while (cplen > 0) { | ||
1376 | if (strncasecmp(cp, compat, strlen(compat)) == 0) | ||
1377 | return 1; | ||
1378 | l = strlen(cp) + 1; | ||
1379 | cp += l; | ||
1380 | cplen -= l; | ||
1381 | } | ||
1382 | |||
1383 | return 0; | ||
1384 | } | ||
1385 | EXPORT_SYMBOL(device_is_compatible); | ||
1386 | |||
1387 | |||
1388 | /** | ||
1389 | * Indicates whether the root node has a given value in its | ||
1390 | * compatible property. | ||
1391 | */ | ||
1392 | int | ||
1393 | machine_is_compatible(const char *compat) | ||
1394 | { | ||
1395 | struct device_node *root; | ||
1396 | int rc = 0; | ||
1397 | |||
1398 | root = of_find_node_by_path("/"); | ||
1399 | if (root) { | ||
1400 | rc = device_is_compatible(root, compat); | ||
1401 | of_node_put(root); | ||
1402 | } | ||
1403 | return rc; | ||
1404 | } | ||
1405 | EXPORT_SYMBOL(machine_is_compatible); | ||
1406 | |||
1407 | /** | ||
1408 | * Construct and return a list of the device_nodes with a given type | ||
1409 | * and compatible property. | ||
1410 | */ | ||
1411 | struct device_node * | ||
1412 | find_compatible_devices(const char *type, const char *compat) | ||
1413 | { | ||
1414 | struct device_node *head, **prevp, *np; | ||
1415 | |||
1416 | prevp = &head; | ||
1417 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1418 | if (type != NULL | ||
1419 | && !(np->type != 0 && strcasecmp(np->type, type) == 0)) | ||
1420 | continue; | ||
1421 | if (device_is_compatible(np, compat)) { | ||
1422 | *prevp = np; | ||
1423 | prevp = &np->next; | ||
1424 | } | ||
1425 | } | ||
1426 | *prevp = NULL; | ||
1427 | return head; | ||
1428 | } | ||
1429 | EXPORT_SYMBOL(find_compatible_devices); | ||
1430 | |||
1431 | /** | ||
1432 | * Find the device_node with a given full_name. | ||
1433 | */ | ||
1434 | struct device_node * | ||
1435 | find_path_device(const char *path) | ||
1436 | { | ||
1437 | struct device_node *np; | ||
1438 | |||
1439 | for (np = allnodes; np != 0; np = np->allnext) | ||
1440 | if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0) | ||
1441 | return np; | ||
1442 | return NULL; | ||
1443 | } | ||
1444 | EXPORT_SYMBOL(find_path_device); | ||
1445 | |||
1446 | /******* | ||
1447 | * | ||
1448 | * New implementation of the OF "find" APIs, return a refcounted | ||
1449 | * object, call of_node_put() when done. The device tree and list | ||
1450 | * are protected by a rw_lock. | ||
1451 | * | ||
1452 | * Note that property management will need some locking as well, | ||
1453 | * this isn't dealt with yet. | ||
1454 | * | ||
1455 | *******/ | ||
1456 | |||
1457 | /** | ||
1458 | * of_find_node_by_name - Find a node by its "name" property | ||
1459 | * @from: The node to start searching from or NULL, the node | ||
1460 | * you pass will not be searched, only the next one | ||
1461 | * will; typically, you pass what the previous call | ||
1462 | * returned. of_node_put() will be called on it | ||
1463 | * @name: The name string to match against | ||
1464 | * | ||
1465 | * Returns a node pointer with refcount incremented, use | ||
1466 | * of_node_put() on it when done. | ||
1467 | */ | ||
1468 | struct device_node *of_find_node_by_name(struct device_node *from, | ||
1469 | const char *name) | ||
1470 | { | ||
1471 | struct device_node *np; | ||
1472 | |||
1473 | read_lock(&devtree_lock); | ||
1474 | np = from ? from->allnext : allnodes; | ||
1475 | for (; np != 0; np = np->allnext) | ||
1476 | if (np->name != 0 && strcasecmp(np->name, name) == 0 | ||
1477 | && of_node_get(np)) | ||
1478 | break; | ||
1479 | if (from) | ||
1480 | of_node_put(from); | ||
1481 | read_unlock(&devtree_lock); | ||
1482 | return np; | ||
1483 | } | ||
1484 | EXPORT_SYMBOL(of_find_node_by_name); | ||
1485 | |||
1486 | /** | ||
1487 | * of_find_node_by_type - Find a node by its "device_type" property | ||
1488 | * @from: The node to start searching from or NULL, the node | ||
1489 | * you pass will not be searched, only the next one | ||
1490 | * will; typically, you pass what the previous call | ||
1491 | * returned. of_node_put() will be called on it | ||
1492 | * @name: The type string to match against | ||
1493 | * | ||
1494 | * Returns a node pointer with refcount incremented, use | ||
1495 | * of_node_put() on it when done. | ||
1496 | */ | ||
1497 | struct device_node *of_find_node_by_type(struct device_node *from, | ||
1498 | const char *type) | ||
1499 | { | ||
1500 | struct device_node *np; | ||
1501 | |||
1502 | read_lock(&devtree_lock); | ||
1503 | np = from ? from->allnext : allnodes; | ||
1504 | for (; np != 0; np = np->allnext) | ||
1505 | if (np->type != 0 && strcasecmp(np->type, type) == 0 | ||
1506 | && of_node_get(np)) | ||
1507 | break; | ||
1508 | if (from) | ||
1509 | of_node_put(from); | ||
1510 | read_unlock(&devtree_lock); | ||
1511 | return np; | ||
1512 | } | ||
1513 | EXPORT_SYMBOL(of_find_node_by_type); | ||
1514 | |||
1515 | /** | ||
1516 | * of_find_compatible_node - Find a node based on type and one of the | ||
1517 | * tokens in its "compatible" property | ||
1518 | * @from: The node to start searching from or NULL, the node | ||
1519 | * you pass will not be searched, only the next one | ||
1520 | * will; typically, you pass what the previous call | ||
1521 | * returned. of_node_put() will be called on it | ||
1522 | * @type: The type string to match "device_type" or NULL to ignore | ||
1523 | * @compatible: The string to match to one of the tokens in the device | ||
1524 | * "compatible" list. | ||
1525 | * | ||
1526 | * Returns a node pointer with refcount incremented, use | ||
1527 | * of_node_put() on it when done. | ||
1528 | */ | ||
1529 | struct device_node *of_find_compatible_node(struct device_node *from, | ||
1530 | const char *type, const char *compatible) | ||
1531 | { | ||
1532 | struct device_node *np; | ||
1533 | |||
1534 | read_lock(&devtree_lock); | ||
1535 | np = from ? from->allnext : allnodes; | ||
1536 | for (; np != 0; np = np->allnext) { | ||
1537 | if (type != NULL | ||
1538 | && !(np->type != 0 && strcasecmp(np->type, type) == 0)) | ||
1539 | continue; | ||
1540 | if (device_is_compatible(np, compatible) && of_node_get(np)) | ||
1541 | break; | ||
1542 | } | ||
1543 | if (from) | ||
1544 | of_node_put(from); | ||
1545 | read_unlock(&devtree_lock); | ||
1546 | return np; | ||
1547 | } | ||
1548 | EXPORT_SYMBOL(of_find_compatible_node); | ||
1549 | |||
1550 | /** | ||
1551 | * of_find_node_by_path - Find a node matching a full OF path | ||
1552 | * @path: The full path to match | ||
1553 | * | ||
1554 | * Returns a node pointer with refcount incremented, use | ||
1555 | * of_node_put() on it when done. | ||
1556 | */ | ||
1557 | struct device_node *of_find_node_by_path(const char *path) | ||
1558 | { | ||
1559 | struct device_node *np = allnodes; | ||
1560 | |||
1561 | read_lock(&devtree_lock); | ||
1562 | for (; np != 0; np = np->allnext) { | ||
1563 | if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0 | ||
1564 | && of_node_get(np)) | ||
1565 | break; | ||
1566 | } | ||
1567 | read_unlock(&devtree_lock); | ||
1568 | return np; | ||
1569 | } | ||
1570 | EXPORT_SYMBOL(of_find_node_by_path); | ||
1571 | |||
1572 | /** | ||
1573 | * of_find_node_by_phandle - Find a node given a phandle | ||
1574 | * @handle: phandle of the node to find | ||
1575 | * | ||
1576 | * Returns a node pointer with refcount incremented, use | ||
1577 | * of_node_put() on it when done. | ||
1578 | */ | ||
1579 | struct device_node *of_find_node_by_phandle(phandle handle) | ||
1580 | { | ||
1581 | struct device_node *np; | ||
1582 | |||
1583 | read_lock(&devtree_lock); | ||
1584 | for (np = allnodes; np != 0; np = np->allnext) | ||
1585 | if (np->linux_phandle == handle) | ||
1586 | break; | ||
1587 | if (np) | ||
1588 | of_node_get(np); | ||
1589 | read_unlock(&devtree_lock); | ||
1590 | return np; | ||
1591 | } | ||
1592 | EXPORT_SYMBOL(of_find_node_by_phandle); | ||
1593 | |||
1594 | /** | ||
1595 | * of_find_all_nodes - Get next node in global list | ||
1596 | * @prev: Previous node or NULL to start iteration | ||
1597 | * of_node_put() will be called on it | ||
1598 | * | ||
1599 | * Returns a node pointer with refcount incremented, use | ||
1600 | * of_node_put() on it when done. | ||
1601 | */ | ||
1602 | struct device_node *of_find_all_nodes(struct device_node *prev) | ||
1603 | { | ||
1604 | struct device_node *np; | ||
1605 | |||
1606 | read_lock(&devtree_lock); | ||
1607 | np = prev ? prev->allnext : allnodes; | ||
1608 | for (; np != 0; np = np->allnext) | ||
1609 | if (of_node_get(np)) | ||
1610 | break; | ||
1611 | if (prev) | ||
1612 | of_node_put(prev); | ||
1613 | read_unlock(&devtree_lock); | ||
1614 | return np; | ||
1615 | } | ||
1616 | EXPORT_SYMBOL(of_find_all_nodes); | ||
1617 | |||
1618 | /** | ||
1619 | * of_get_parent - Get a node's parent if any | ||
1620 | * @node: Node to get parent | ||
1621 | * | ||
1622 | * Returns a node pointer with refcount incremented, use | ||
1623 | * of_node_put() on it when done. | ||
1624 | */ | ||
1625 | struct device_node *of_get_parent(const struct device_node *node) | ||
1626 | { | ||
1627 | struct device_node *np; | ||
1628 | |||
1629 | if (!node) | ||
1630 | return NULL; | ||
1631 | |||
1632 | read_lock(&devtree_lock); | ||
1633 | np = of_node_get(node->parent); | ||
1634 | read_unlock(&devtree_lock); | ||
1635 | return np; | ||
1636 | } | ||
1637 | EXPORT_SYMBOL(of_get_parent); | ||
1638 | |||
1639 | /** | ||
1640 | * of_get_next_child - Iterate a node childs | ||
1641 | * @node: parent node | ||
1642 | * @prev: previous child of the parent node, or NULL to get first | ||
1643 | * | ||
1644 | * Returns a node pointer with refcount incremented, use | ||
1645 | * of_node_put() on it when done. | ||
1646 | */ | ||
1647 | struct device_node *of_get_next_child(const struct device_node *node, | ||
1648 | struct device_node *prev) | ||
1649 | { | ||
1650 | struct device_node *next; | ||
1651 | |||
1652 | read_lock(&devtree_lock); | ||
1653 | next = prev ? prev->sibling : node->child; | ||
1654 | for (; next != 0; next = next->sibling) | ||
1655 | if (of_node_get(next)) | ||
1656 | break; | ||
1657 | if (prev) | ||
1658 | of_node_put(prev); | ||
1659 | read_unlock(&devtree_lock); | ||
1660 | return next; | ||
1661 | } | ||
1662 | EXPORT_SYMBOL(of_get_next_child); | ||
1663 | |||
1664 | /** | ||
1665 | * of_node_get - Increment refcount of a node | ||
1666 | * @node: Node to inc refcount, NULL is supported to | ||
1667 | * simplify writing of callers | ||
1668 | * | ||
1669 | * Returns node. | ||
1670 | */ | ||
1671 | struct device_node *of_node_get(struct device_node *node) | ||
1672 | { | ||
1673 | if (node) | ||
1674 | kref_get(&node->kref); | ||
1675 | return node; | ||
1676 | } | ||
1677 | EXPORT_SYMBOL(of_node_get); | ||
1678 | |||
1679 | static inline struct device_node * kref_to_device_node(struct kref *kref) | ||
1680 | { | ||
1681 | return container_of(kref, struct device_node, kref); | ||
1682 | } | ||
1683 | |||
1684 | /** | ||
1685 | * of_node_release - release a dynamically allocated node | ||
1686 | * @kref: kref element of the node to be released | ||
1687 | * | ||
1688 | * In of_node_put() this function is passed to kref_put() | ||
1689 | * as the destructor. | ||
1690 | */ | ||
1691 | static void of_node_release(struct kref *kref) | ||
1692 | { | ||
1693 | struct device_node *node = kref_to_device_node(kref); | ||
1694 | struct property *prop = node->properties; | ||
1695 | |||
1696 | if (!OF_IS_DYNAMIC(node)) | ||
1697 | return; | ||
1698 | while (prop) { | ||
1699 | struct property *next = prop->next; | ||
1700 | kfree(prop->name); | ||
1701 | kfree(prop->value); | ||
1702 | kfree(prop); | ||
1703 | prop = next; | ||
1704 | } | ||
1705 | kfree(node->intrs); | ||
1706 | kfree(node->addrs); | ||
1707 | kfree(node->full_name); | ||
1708 | kfree(node->data); | ||
1709 | kfree(node); | ||
1710 | } | ||
1711 | |||
1712 | /** | ||
1713 | * of_node_put - Decrement refcount of a node | ||
1714 | * @node: Node to dec refcount, NULL is supported to | ||
1715 | * simplify writing of callers | ||
1716 | * | ||
1717 | */ | ||
1718 | void of_node_put(struct device_node *node) | ||
1719 | { | ||
1720 | if (node) | ||
1721 | kref_put(&node->kref, of_node_release); | ||
1722 | } | ||
1723 | EXPORT_SYMBOL(of_node_put); | ||
1724 | |||
1725 | /* | ||
1726 | * Fix up the uninitialized fields in a new device node: | ||
1727 | * name, type, n_addrs, addrs, n_intrs, intrs, and pci-specific fields | ||
1728 | * | ||
1729 | * A lot of boot-time code is duplicated here, because functions such | ||
1730 | * as finish_node_interrupts, interpret_pci_props, etc. cannot use the | ||
1731 | * slab allocator. | ||
1732 | * | ||
1733 | * This should probably be split up into smaller chunks. | ||
1734 | */ | ||
1735 | |||
1736 | static int of_finish_dynamic_node(struct device_node *node, | ||
1737 | unsigned long *unused1, int unused2, | ||
1738 | int unused3, int unused4) | ||
1739 | { | ||
1740 | struct device_node *parent = of_get_parent(node); | ||
1741 | int err = 0; | ||
1742 | phandle *ibm_phandle; | ||
1743 | |||
1744 | node->name = get_property(node, "name", NULL); | ||
1745 | node->type = get_property(node, "device_type", NULL); | ||
1746 | |||
1747 | if (!parent) { | ||
1748 | err = -ENODEV; | ||
1749 | goto out; | ||
1750 | } | ||
1751 | |||
1752 | /* We don't support that function on PowerMac, at least | ||
1753 | * not yet | ||
1754 | */ | ||
1755 | if (_machine == PLATFORM_POWERMAC) | ||
1756 | return -ENODEV; | ||
1757 | |||
1758 | /* fix up new node's linux_phandle field */ | ||
1759 | if ((ibm_phandle = (unsigned int *)get_property(node, "ibm,phandle", NULL))) | ||
1760 | node->linux_phandle = *ibm_phandle; | ||
1761 | |||
1762 | out: | ||
1763 | of_node_put(parent); | ||
1764 | return err; | ||
1765 | } | ||
1766 | |||
1767 | /* | ||
1768 | * Plug a device node into the tree and global list. | ||
1769 | */ | ||
1770 | void of_attach_node(struct device_node *np) | ||
1771 | { | ||
1772 | write_lock(&devtree_lock); | ||
1773 | np->sibling = np->parent->child; | ||
1774 | np->allnext = allnodes; | ||
1775 | np->parent->child = np; | ||
1776 | allnodes = np; | ||
1777 | write_unlock(&devtree_lock); | ||
1778 | } | ||
1779 | |||
1780 | /* | ||
1781 | * "Unplug" a node from the device tree. The caller must hold | ||
1782 | * a reference to the node. The memory associated with the node | ||
1783 | * is not freed until its refcount goes to zero. | ||
1784 | */ | ||
1785 | void of_detach_node(const struct device_node *np) | ||
1786 | { | ||
1787 | struct device_node *parent; | ||
1788 | |||
1789 | write_lock(&devtree_lock); | ||
1790 | |||
1791 | parent = np->parent; | ||
1792 | |||
1793 | if (allnodes == np) | ||
1794 | allnodes = np->allnext; | ||
1795 | else { | ||
1796 | struct device_node *prev; | ||
1797 | for (prev = allnodes; | ||
1798 | prev->allnext != np; | ||
1799 | prev = prev->allnext) | ||
1800 | ; | ||
1801 | prev->allnext = np->allnext; | ||
1802 | } | ||
1803 | |||
1804 | if (parent->child == np) | ||
1805 | parent->child = np->sibling; | ||
1806 | else { | ||
1807 | struct device_node *prevsib; | ||
1808 | for (prevsib = np->parent->child; | ||
1809 | prevsib->sibling != np; | ||
1810 | prevsib = prevsib->sibling) | ||
1811 | ; | ||
1812 | prevsib->sibling = np->sibling; | ||
1813 | } | ||
1814 | |||
1815 | write_unlock(&devtree_lock); | ||
1816 | } | ||
1817 | |||
1818 | static int prom_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node) | ||
1819 | { | ||
1820 | int err; | ||
1821 | |||
1822 | switch (action) { | ||
1823 | case PSERIES_RECONFIG_ADD: | ||
1824 | err = finish_node(node, NULL, of_finish_dynamic_node, 0, 0, 0); | ||
1825 | if (err < 0) { | ||
1826 | printk(KERN_ERR "finish_node returned %d\n", err); | ||
1827 | err = NOTIFY_BAD; | ||
1828 | } | ||
1829 | break; | ||
1830 | default: | ||
1831 | err = NOTIFY_DONE; | ||
1832 | break; | ||
1833 | } | ||
1834 | return err; | ||
1835 | } | ||
1836 | |||
1837 | static struct notifier_block prom_reconfig_nb = { | ||
1838 | .notifier_call = prom_reconfig_notifier, | ||
1839 | .priority = 10, /* This one needs to run first */ | ||
1840 | }; | ||
1841 | |||
1842 | static int __init prom_reconfig_setup(void) | ||
1843 | { | ||
1844 | return pSeries_reconfig_notifier_register(&prom_reconfig_nb); | ||
1845 | } | ||
1846 | __initcall(prom_reconfig_setup); | ||
1847 | |||
1848 | /* | ||
1849 | * Find a property with a given name for a given node | ||
1850 | * and return the value. | ||
1851 | */ | ||
1852 | unsigned char * | ||
1853 | get_property(struct device_node *np, const char *name, int *lenp) | ||
1854 | { | ||
1855 | struct property *pp; | ||
1856 | |||
1857 | for (pp = np->properties; pp != 0; pp = pp->next) | ||
1858 | if (strcmp(pp->name, name) == 0) { | ||
1859 | if (lenp != 0) | ||
1860 | *lenp = pp->length; | ||
1861 | return pp->value; | ||
1862 | } | ||
1863 | return NULL; | ||
1864 | } | ||
1865 | EXPORT_SYMBOL(get_property); | ||
1866 | |||
1867 | /* | ||
1868 | * Add a property to a node. | ||
1869 | */ | ||
1870 | int | ||
1871 | prom_add_property(struct device_node* np, struct property* prop) | ||
1872 | { | ||
1873 | struct property **next; | ||
1874 | |||
1875 | prop->next = NULL; | ||
1876 | write_lock(&devtree_lock); | ||
1877 | next = &np->properties; | ||
1878 | while (*next) { | ||
1879 | if (strcmp(prop->name, (*next)->name) == 0) { | ||
1880 | /* duplicate ! don't insert it */ | ||
1881 | write_unlock(&devtree_lock); | ||
1882 | return -1; | ||
1883 | } | ||
1884 | next = &(*next)->next; | ||
1885 | } | ||
1886 | *next = prop; | ||
1887 | write_unlock(&devtree_lock); | ||
1888 | |||
1889 | /* try to add to proc as well if it was initialized */ | ||
1890 | if (np->pde) | ||
1891 | proc_device_tree_add_prop(np->pde, prop); | ||
1892 | |||
1893 | return 0; | ||
1894 | } | ||
1895 | |||
1896 | #if 0 | ||
1897 | void | ||
1898 | print_properties(struct device_node *np) | ||
1899 | { | ||
1900 | struct property *pp; | ||
1901 | char *cp; | ||
1902 | int i, n; | ||
1903 | |||
1904 | for (pp = np->properties; pp != 0; pp = pp->next) { | ||
1905 | printk(KERN_INFO "%s", pp->name); | ||
1906 | for (i = strlen(pp->name); i < 16; ++i) | ||
1907 | printk(" "); | ||
1908 | cp = (char *) pp->value; | ||
1909 | for (i = pp->length; i > 0; --i, ++cp) | ||
1910 | if ((i > 1 && (*cp < 0x20 || *cp > 0x7e)) | ||
1911 | || (i == 1 && *cp != 0)) | ||
1912 | break; | ||
1913 | if (i == 0 && pp->length > 1) { | ||
1914 | /* looks like a string */ | ||
1915 | printk(" %s\n", (char *) pp->value); | ||
1916 | } else { | ||
1917 | /* dump it in hex */ | ||
1918 | n = pp->length; | ||
1919 | if (n > 64) | ||
1920 | n = 64; | ||
1921 | if (pp->length % 4 == 0) { | ||
1922 | unsigned int *p = (unsigned int *) pp->value; | ||
1923 | |||
1924 | n /= 4; | ||
1925 | for (i = 0; i < n; ++i) { | ||
1926 | if (i != 0 && (i % 4) == 0) | ||
1927 | printk("\n "); | ||
1928 | printk(" %08x", *p++); | ||
1929 | } | ||
1930 | } else { | ||
1931 | unsigned char *bp = pp->value; | ||
1932 | |||
1933 | for (i = 0; i < n; ++i) { | ||
1934 | if (i != 0 && (i % 16) == 0) | ||
1935 | printk("\n "); | ||
1936 | printk(" %02x", *bp++); | ||
1937 | } | ||
1938 | } | ||
1939 | printk("\n"); | ||
1940 | if (pp->length > 64) | ||
1941 | printk(" ... (length = %d)\n", | ||
1942 | pp->length); | ||
1943 | } | ||
1944 | } | ||
1945 | } | ||
1946 | #endif | ||
1947 | |||
1948 | |||
1949 | |||
1950 | |||
1951 | |||
1952 | |||
1953 | |||
1954 | |||
1955 | |||
1956 | |||
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c deleted file mode 100644 index 6375f40b23db..000000000000 --- a/arch/ppc64/kernel/prom_init.c +++ /dev/null | |||
@@ -1,2051 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * | ||
4 | * Procedures for interfacing to Open Firmware. | ||
5 | * | ||
6 | * Paul Mackerras August 1996. | ||
7 | * Copyright (C) 1996 Paul Mackerras. | ||
8 | * | ||
9 | * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. | ||
10 | * {engebret|bergner}@us.ibm.com | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version | ||
15 | * 2 of the License, or (at your option) any later version. | ||
16 | */ | ||
17 | |||
18 | #undef DEBUG_PROM | ||
19 | |||
20 | #include <stdarg.h> | ||
21 | #include <linux/config.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/string.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/threads.h> | ||
26 | #include <linux/spinlock.h> | ||
27 | #include <linux/types.h> | ||
28 | #include <linux/pci.h> | ||
29 | #include <linux/proc_fs.h> | ||
30 | #include <linux/stringify.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/initrd.h> | ||
33 | #include <linux/bitops.h> | ||
34 | #include <asm/prom.h> | ||
35 | #include <asm/rtas.h> | ||
36 | #include <asm/abs_addr.h> | ||
37 | #include <asm/page.h> | ||
38 | #include <asm/processor.h> | ||
39 | #include <asm/irq.h> | ||
40 | #include <asm/io.h> | ||
41 | #include <asm/smp.h> | ||
42 | #include <asm/system.h> | ||
43 | #include <asm/mmu.h> | ||
44 | #include <asm/pgtable.h> | ||
45 | #include <asm/pci.h> | ||
46 | #include <asm/iommu.h> | ||
47 | #include <asm/btext.h> | ||
48 | #include <asm/sections.h> | ||
49 | #include <asm/machdep.h> | ||
50 | |||
51 | #ifdef CONFIG_LOGO_LINUX_CLUT224 | ||
52 | #include <linux/linux_logo.h> | ||
53 | extern const struct linux_logo logo_linux_clut224; | ||
54 | #endif | ||
55 | |||
56 | /* | ||
57 | * Properties whose value is longer than this get excluded from our | ||
58 | * copy of the device tree. This value does need to be big enough to | ||
59 | * ensure that we don't lose things like the interrupt-map property | ||
60 | * on a PCI-PCI bridge. | ||
61 | */ | ||
62 | #define MAX_PROPERTY_LENGTH (1UL * 1024 * 1024) | ||
63 | |||
64 | /* | ||
65 | * Eventually bump that one up | ||
66 | */ | ||
67 | #define DEVTREE_CHUNK_SIZE 0x100000 | ||
68 | |||
69 | /* | ||
70 | * This is the size of the local memory reserve map that gets copied | ||
71 | * into the boot params passed to the kernel. That size is totally | ||
72 | * flexible as the kernel just reads the list until it encounters an | ||
73 | * entry with size 0, so it can be changed without breaking binary | ||
74 | * compatibility | ||
75 | */ | ||
76 | #define MEM_RESERVE_MAP_SIZE 8 | ||
77 | |||
78 | /* | ||
79 | * prom_init() is called very early on, before the kernel text | ||
80 | * and data have been mapped to KERNELBASE. At this point the code | ||
81 | * is running at whatever address it has been loaded at, so | ||
82 | * references to extern and static variables must be relocated | ||
83 | * explicitly. The procedure reloc_offset() returns the address | ||
84 | * we're currently running at minus the address we were linked at. | ||
85 | * (Note that strings count as static variables.) | ||
86 | * | ||
87 | * Because OF may have mapped I/O devices into the area starting at | ||
88 | * KERNELBASE, particularly on CHRP machines, we can't safely call | ||
89 | * OF once the kernel has been mapped to KERNELBASE. Therefore all | ||
90 | * OF calls should be done within prom_init(), and prom_init() | ||
91 | * and all routines called within it must be careful to relocate | ||
92 | * references as necessary. | ||
93 | * | ||
94 | * Note that the bss is cleared *after* prom_init runs, so we have | ||
95 | * to make sure that any static or extern variables it accesses | ||
96 | * are put in the data segment. | ||
97 | */ | ||
98 | |||
99 | |||
100 | #define PROM_BUG() do { \ | ||
101 | prom_printf("kernel BUG at %s line 0x%x!\n", \ | ||
102 | RELOC(__FILE__), __LINE__); \ | ||
103 | __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \ | ||
104 | } while (0) | ||
105 | |||
106 | #ifdef DEBUG_PROM | ||
107 | #define prom_debug(x...) prom_printf(x) | ||
108 | #else | ||
109 | #define prom_debug(x...) | ||
110 | #endif | ||
111 | |||
112 | |||
113 | typedef u32 prom_arg_t; | ||
114 | |||
115 | struct prom_args { | ||
116 | u32 service; | ||
117 | u32 nargs; | ||
118 | u32 nret; | ||
119 | prom_arg_t args[10]; | ||
120 | prom_arg_t *rets; /* Pointer to return values in args[16]. */ | ||
121 | }; | ||
122 | |||
123 | struct prom_t { | ||
124 | unsigned long entry; | ||
125 | ihandle root; | ||
126 | ihandle chosen; | ||
127 | int cpu; | ||
128 | ihandle stdout; | ||
129 | ihandle disp_node; | ||
130 | struct prom_args args; | ||
131 | unsigned long version; | ||
132 | unsigned long root_size_cells; | ||
133 | unsigned long root_addr_cells; | ||
134 | }; | ||
135 | |||
136 | struct pci_reg_property { | ||
137 | struct pci_address addr; | ||
138 | u32 size_hi; | ||
139 | u32 size_lo; | ||
140 | }; | ||
141 | |||
142 | struct mem_map_entry { | ||
143 | u64 base; | ||
144 | u64 size; | ||
145 | }; | ||
146 | |||
147 | typedef u32 cell_t; | ||
148 | |||
149 | extern void __start(unsigned long r3, unsigned long r4, unsigned long r5); | ||
150 | |||
151 | extern void enter_prom(struct prom_args *args, unsigned long entry); | ||
152 | extern void copy_and_flush(unsigned long dest, unsigned long src, | ||
153 | unsigned long size, unsigned long offset); | ||
154 | |||
155 | extern unsigned long klimit; | ||
156 | |||
157 | /* prom structure */ | ||
158 | static struct prom_t __initdata prom; | ||
159 | |||
160 | #define PROM_SCRATCH_SIZE 256 | ||
161 | |||
162 | static char __initdata of_stdout_device[256]; | ||
163 | static char __initdata prom_scratch[PROM_SCRATCH_SIZE]; | ||
164 | |||
165 | static unsigned long __initdata dt_header_start; | ||
166 | static unsigned long __initdata dt_struct_start, dt_struct_end; | ||
167 | static unsigned long __initdata dt_string_start, dt_string_end; | ||
168 | |||
169 | static unsigned long __initdata prom_initrd_start, prom_initrd_end; | ||
170 | |||
171 | static int __initdata iommu_force_on; | ||
172 | static int __initdata ppc64_iommu_off; | ||
173 | static int __initdata of_platform; | ||
174 | |||
175 | static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; | ||
176 | |||
177 | static unsigned long __initdata prom_memory_limit; | ||
178 | static unsigned long __initdata prom_tce_alloc_start; | ||
179 | static unsigned long __initdata prom_tce_alloc_end; | ||
180 | |||
181 | static unsigned long __initdata alloc_top; | ||
182 | static unsigned long __initdata alloc_top_high; | ||
183 | static unsigned long __initdata alloc_bottom; | ||
184 | static unsigned long __initdata rmo_top; | ||
185 | static unsigned long __initdata ram_top; | ||
186 | |||
187 | static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE]; | ||
188 | static int __initdata mem_reserve_cnt; | ||
189 | |||
190 | static cell_t __initdata regbuf[1024]; | ||
191 | |||
192 | |||
193 | #define MAX_CPU_THREADS 2 | ||
194 | |||
195 | /* TO GO */ | ||
196 | #ifdef CONFIG_HMT | ||
197 | struct { | ||
198 | unsigned int pir; | ||
199 | unsigned int threadid; | ||
200 | } hmt_thread_data[NR_CPUS]; | ||
201 | #endif /* CONFIG_HMT */ | ||
202 | |||
203 | /* | ||
204 | * This are used in calls to call_prom. The 4th and following | ||
205 | * arguments to call_prom should be 32-bit values. 64 bit values | ||
206 | * are truncated to 32 bits (and fortunately don't get interpreted | ||
207 | * as two arguments). | ||
208 | */ | ||
209 | #define ADDR(x) (u32) ((unsigned long)(x) - offset) | ||
210 | |||
211 | /* | ||
212 | * Error results ... some OF calls will return "-1" on error, some | ||
213 | * will return 0, some will return either. To simplify, here are | ||
214 | * macros to use with any ihandle or phandle return value to check if | ||
215 | * it is valid | ||
216 | */ | ||
217 | |||
218 | #define PROM_ERROR (-1u) | ||
219 | #define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR) | ||
220 | #define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR) | ||
221 | |||
222 | |||
223 | /* This is the one and *ONLY* place where we actually call open | ||
224 | * firmware from, since we need to make sure we're running in 32b | ||
225 | * mode when we do. We switch back to 64b mode upon return. | ||
226 | */ | ||
227 | |||
228 | static int __init call_prom(const char *service, int nargs, int nret, ...) | ||
229 | { | ||
230 | int i; | ||
231 | unsigned long offset = reloc_offset(); | ||
232 | struct prom_t *_prom = PTRRELOC(&prom); | ||
233 | va_list list; | ||
234 | |||
235 | _prom->args.service = ADDR(service); | ||
236 | _prom->args.nargs = nargs; | ||
237 | _prom->args.nret = nret; | ||
238 | _prom->args.rets = (prom_arg_t *)&(_prom->args.args[nargs]); | ||
239 | |||
240 | va_start(list, nret); | ||
241 | for (i=0; i < nargs; i++) | ||
242 | _prom->args.args[i] = va_arg(list, prom_arg_t); | ||
243 | va_end(list); | ||
244 | |||
245 | for (i=0; i < nret ;i++) | ||
246 | _prom->args.rets[i] = 0; | ||
247 | |||
248 | enter_prom(&_prom->args, _prom->entry); | ||
249 | |||
250 | return (nret > 0) ? _prom->args.rets[0] : 0; | ||
251 | } | ||
252 | |||
253 | |||
254 | static unsigned int __init prom_claim(unsigned long virt, unsigned long size, | ||
255 | unsigned long align) | ||
256 | { | ||
257 | return (unsigned int)call_prom("claim", 3, 1, | ||
258 | (prom_arg_t)virt, (prom_arg_t)size, | ||
259 | (prom_arg_t)align); | ||
260 | } | ||
261 | |||
262 | static void __init prom_print(const char *msg) | ||
263 | { | ||
264 | const char *p, *q; | ||
265 | unsigned long offset = reloc_offset(); | ||
266 | struct prom_t *_prom = PTRRELOC(&prom); | ||
267 | |||
268 | if (_prom->stdout == 0) | ||
269 | return; | ||
270 | |||
271 | for (p = msg; *p != 0; p = q) { | ||
272 | for (q = p; *q != 0 && *q != '\n'; ++q) | ||
273 | ; | ||
274 | if (q > p) | ||
275 | call_prom("write", 3, 1, _prom->stdout, p, q - p); | ||
276 | if (*q == 0) | ||
277 | break; | ||
278 | ++q; | ||
279 | call_prom("write", 3, 1, _prom->stdout, ADDR("\r\n"), 2); | ||
280 | } | ||
281 | } | ||
282 | |||
283 | |||
284 | static void __init prom_print_hex(unsigned long val) | ||
285 | { | ||
286 | unsigned long offset = reloc_offset(); | ||
287 | int i, nibbles = sizeof(val)*2; | ||
288 | char buf[sizeof(val)*2+1]; | ||
289 | struct prom_t *_prom = PTRRELOC(&prom); | ||
290 | |||
291 | for (i = nibbles-1; i >= 0; i--) { | ||
292 | buf[i] = (val & 0xf) + '0'; | ||
293 | if (buf[i] > '9') | ||
294 | buf[i] += ('a'-'0'-10); | ||
295 | val >>= 4; | ||
296 | } | ||
297 | buf[nibbles] = '\0'; | ||
298 | call_prom("write", 3, 1, _prom->stdout, buf, nibbles); | ||
299 | } | ||
300 | |||
301 | |||
302 | static void __init prom_printf(const char *format, ...) | ||
303 | { | ||
304 | unsigned long offset = reloc_offset(); | ||
305 | const char *p, *q, *s; | ||
306 | va_list args; | ||
307 | unsigned long v; | ||
308 | struct prom_t *_prom = PTRRELOC(&prom); | ||
309 | |||
310 | va_start(args, format); | ||
311 | for (p = PTRRELOC(format); *p != 0; p = q) { | ||
312 | for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q) | ||
313 | ; | ||
314 | if (q > p) | ||
315 | call_prom("write", 3, 1, _prom->stdout, p, q - p); | ||
316 | if (*q == 0) | ||
317 | break; | ||
318 | if (*q == '\n') { | ||
319 | ++q; | ||
320 | call_prom("write", 3, 1, _prom->stdout, | ||
321 | ADDR("\r\n"), 2); | ||
322 | continue; | ||
323 | } | ||
324 | ++q; | ||
325 | if (*q == 0) | ||
326 | break; | ||
327 | switch (*q) { | ||
328 | case 's': | ||
329 | ++q; | ||
330 | s = va_arg(args, const char *); | ||
331 | prom_print(s); | ||
332 | break; | ||
333 | case 'x': | ||
334 | ++q; | ||
335 | v = va_arg(args, unsigned long); | ||
336 | prom_print_hex(v); | ||
337 | break; | ||
338 | } | ||
339 | } | ||
340 | } | ||
341 | |||
342 | |||
343 | static void __init __attribute__((noreturn)) prom_panic(const char *reason) | ||
344 | { | ||
345 | unsigned long offset = reloc_offset(); | ||
346 | |||
347 | prom_print(PTRRELOC(reason)); | ||
348 | /* ToDo: should put up an SRC here */ | ||
349 | call_prom("exit", 0, 0); | ||
350 | |||
351 | for (;;) /* should never get here */ | ||
352 | ; | ||
353 | } | ||
354 | |||
355 | |||
356 | static int __init prom_next_node(phandle *nodep) | ||
357 | { | ||
358 | phandle node; | ||
359 | |||
360 | if ((node = *nodep) != 0 | ||
361 | && (*nodep = call_prom("child", 1, 1, node)) != 0) | ||
362 | return 1; | ||
363 | if ((*nodep = call_prom("peer", 1, 1, node)) != 0) | ||
364 | return 1; | ||
365 | for (;;) { | ||
366 | if ((node = call_prom("parent", 1, 1, node)) == 0) | ||
367 | return 0; | ||
368 | if ((*nodep = call_prom("peer", 1, 1, node)) != 0) | ||
369 | return 1; | ||
370 | } | ||
371 | } | ||
372 | |||
373 | static int __init prom_getprop(phandle node, const char *pname, | ||
374 | void *value, size_t valuelen) | ||
375 | { | ||
376 | unsigned long offset = reloc_offset(); | ||
377 | |||
378 | return call_prom("getprop", 4, 1, node, ADDR(pname), | ||
379 | (u32)(unsigned long) value, (u32) valuelen); | ||
380 | } | ||
381 | |||
382 | static int __init prom_getproplen(phandle node, const char *pname) | ||
383 | { | ||
384 | unsigned long offset = reloc_offset(); | ||
385 | |||
386 | return call_prom("getproplen", 2, 1, node, ADDR(pname)); | ||
387 | } | ||
388 | |||
389 | static int __init prom_setprop(phandle node, const char *pname, | ||
390 | void *value, size_t valuelen) | ||
391 | { | ||
392 | unsigned long offset = reloc_offset(); | ||
393 | |||
394 | return call_prom("setprop", 4, 1, node, ADDR(pname), | ||
395 | (u32)(unsigned long) value, (u32) valuelen); | ||
396 | } | ||
397 | |||
398 | /* We can't use the standard versions because of RELOC headaches. */ | ||
399 | #define isxdigit(c) (('0' <= (c) && (c) <= '9') \ | ||
400 | || ('a' <= (c) && (c) <= 'f') \ | ||
401 | || ('A' <= (c) && (c) <= 'F')) | ||
402 | |||
403 | #define isdigit(c) ('0' <= (c) && (c) <= '9') | ||
404 | #define islower(c) ('a' <= (c) && (c) <= 'z') | ||
405 | #define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c)) | ||
406 | |||
407 | unsigned long prom_strtoul(const char *cp, const char **endp) | ||
408 | { | ||
409 | unsigned long result = 0, base = 10, value; | ||
410 | |||
411 | if (*cp == '0') { | ||
412 | base = 8; | ||
413 | cp++; | ||
414 | if (toupper(*cp) == 'X') { | ||
415 | cp++; | ||
416 | base = 16; | ||
417 | } | ||
418 | } | ||
419 | |||
420 | while (isxdigit(*cp) && | ||
421 | (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) { | ||
422 | result = result * base + value; | ||
423 | cp++; | ||
424 | } | ||
425 | |||
426 | if (endp) | ||
427 | *endp = cp; | ||
428 | |||
429 | return result; | ||
430 | } | ||
431 | |||
432 | unsigned long prom_memparse(const char *ptr, const char **retptr) | ||
433 | { | ||
434 | unsigned long ret = prom_strtoul(ptr, retptr); | ||
435 | int shift = 0; | ||
436 | |||
437 | /* | ||
438 | * We can't use a switch here because GCC *may* generate a | ||
439 | * jump table which won't work, because we're not running at | ||
440 | * the address we're linked at. | ||
441 | */ | ||
442 | if ('G' == **retptr || 'g' == **retptr) | ||
443 | shift = 30; | ||
444 | |||
445 | if ('M' == **retptr || 'm' == **retptr) | ||
446 | shift = 20; | ||
447 | |||
448 | if ('K' == **retptr || 'k' == **retptr) | ||
449 | shift = 10; | ||
450 | |||
451 | if (shift) { | ||
452 | ret <<= shift; | ||
453 | (*retptr)++; | ||
454 | } | ||
455 | |||
456 | return ret; | ||
457 | } | ||
458 | |||
459 | /* | ||
460 | * Early parsing of the command line passed to the kernel, used for | ||
461 | * "mem=x" and the options that affect the iommu | ||
462 | */ | ||
463 | static void __init early_cmdline_parse(void) | ||
464 | { | ||
465 | unsigned long offset = reloc_offset(); | ||
466 | struct prom_t *_prom = PTRRELOC(&prom); | ||
467 | char *opt, *p; | ||
468 | int l = 0; | ||
469 | |||
470 | RELOC(prom_cmd_line[0]) = 0; | ||
471 | p = RELOC(prom_cmd_line); | ||
472 | if ((long)_prom->chosen > 0) | ||
473 | l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1); | ||
474 | #ifdef CONFIG_CMDLINE | ||
475 | if (l == 0) /* dbl check */ | ||
476 | strlcpy(RELOC(prom_cmd_line), | ||
477 | RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line)); | ||
478 | #endif /* CONFIG_CMDLINE */ | ||
479 | prom_printf("command line: %s\n", RELOC(prom_cmd_line)); | ||
480 | |||
481 | opt = strstr(RELOC(prom_cmd_line), RELOC("iommu=")); | ||
482 | if (opt) { | ||
483 | prom_printf("iommu opt is: %s\n", opt); | ||
484 | opt += 6; | ||
485 | while (*opt && *opt == ' ') | ||
486 | opt++; | ||
487 | if (!strncmp(opt, RELOC("off"), 3)) | ||
488 | RELOC(ppc64_iommu_off) = 1; | ||
489 | else if (!strncmp(opt, RELOC("force"), 5)) | ||
490 | RELOC(iommu_force_on) = 1; | ||
491 | } | ||
492 | |||
493 | opt = strstr(RELOC(prom_cmd_line), RELOC("mem=")); | ||
494 | if (opt) { | ||
495 | opt += 4; | ||
496 | RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt); | ||
497 | /* Align to 16 MB == size of large page */ | ||
498 | RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000); | ||
499 | } | ||
500 | } | ||
501 | |||
502 | /* | ||
503 | * To tell the firmware what our capabilities are, we have to pass | ||
504 | * it a fake 32-bit ELF header containing a couple of PT_NOTE sections | ||
505 | * that contain structures that contain the actual values. | ||
506 | */ | ||
507 | static struct fake_elf { | ||
508 | Elf32_Ehdr elfhdr; | ||
509 | Elf32_Phdr phdr[2]; | ||
510 | struct chrpnote { | ||
511 | u32 namesz; | ||
512 | u32 descsz; | ||
513 | u32 type; | ||
514 | char name[8]; /* "PowerPC" */ | ||
515 | struct chrpdesc { | ||
516 | u32 real_mode; | ||
517 | u32 real_base; | ||
518 | u32 real_size; | ||
519 | u32 virt_base; | ||
520 | u32 virt_size; | ||
521 | u32 load_base; | ||
522 | } chrpdesc; | ||
523 | } chrpnote; | ||
524 | struct rpanote { | ||
525 | u32 namesz; | ||
526 | u32 descsz; | ||
527 | u32 type; | ||
528 | char name[24]; /* "IBM,RPA-Client-Config" */ | ||
529 | struct rpadesc { | ||
530 | u32 lpar_affinity; | ||
531 | u32 min_rmo_size; | ||
532 | u32 min_rmo_percent; | ||
533 | u32 max_pft_size; | ||
534 | u32 splpar; | ||
535 | u32 min_load; | ||
536 | u32 new_mem_def; | ||
537 | u32 ignore_me; | ||
538 | } rpadesc; | ||
539 | } rpanote; | ||
540 | } fake_elf = { | ||
541 | .elfhdr = { | ||
542 | .e_ident = { 0x7f, 'E', 'L', 'F', | ||
543 | ELFCLASS32, ELFDATA2MSB, EV_CURRENT }, | ||
544 | .e_type = ET_EXEC, /* yeah right */ | ||
545 | .e_machine = EM_PPC, | ||
546 | .e_version = EV_CURRENT, | ||
547 | .e_phoff = offsetof(struct fake_elf, phdr), | ||
548 | .e_phentsize = sizeof(Elf32_Phdr), | ||
549 | .e_phnum = 2 | ||
550 | }, | ||
551 | .phdr = { | ||
552 | [0] = { | ||
553 | .p_type = PT_NOTE, | ||
554 | .p_offset = offsetof(struct fake_elf, chrpnote), | ||
555 | .p_filesz = sizeof(struct chrpnote) | ||
556 | }, [1] = { | ||
557 | .p_type = PT_NOTE, | ||
558 | .p_offset = offsetof(struct fake_elf, rpanote), | ||
559 | .p_filesz = sizeof(struct rpanote) | ||
560 | } | ||
561 | }, | ||
562 | .chrpnote = { | ||
563 | .namesz = sizeof("PowerPC"), | ||
564 | .descsz = sizeof(struct chrpdesc), | ||
565 | .type = 0x1275, | ||
566 | .name = "PowerPC", | ||
567 | .chrpdesc = { | ||
568 | .real_mode = ~0U, /* ~0 means "don't care" */ | ||
569 | .real_base = ~0U, | ||
570 | .real_size = ~0U, | ||
571 | .virt_base = ~0U, | ||
572 | .virt_size = ~0U, | ||
573 | .load_base = ~0U | ||
574 | }, | ||
575 | }, | ||
576 | .rpanote = { | ||
577 | .namesz = sizeof("IBM,RPA-Client-Config"), | ||
578 | .descsz = sizeof(struct rpadesc), | ||
579 | .type = 0x12759999, | ||
580 | .name = "IBM,RPA-Client-Config", | ||
581 | .rpadesc = { | ||
582 | .lpar_affinity = 0, | ||
583 | .min_rmo_size = 64, /* in megabytes */ | ||
584 | .min_rmo_percent = 0, | ||
585 | .max_pft_size = 48, /* 2^48 bytes max PFT size */ | ||
586 | .splpar = 1, | ||
587 | .min_load = ~0U, | ||
588 | .new_mem_def = 0 | ||
589 | } | ||
590 | } | ||
591 | }; | ||
592 | |||
593 | static void __init prom_send_capabilities(void) | ||
594 | { | ||
595 | unsigned long offset = reloc_offset(); | ||
596 | ihandle elfloader; | ||
597 | |||
598 | elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); | ||
599 | if (elfloader == 0) { | ||
600 | prom_printf("couldn't open /packages/elf-loader\n"); | ||
601 | return; | ||
602 | } | ||
603 | call_prom("call-method", 3, 1, ADDR("process-elf-header"), | ||
604 | elfloader, ADDR(&fake_elf)); | ||
605 | call_prom("close", 1, 0, elfloader); | ||
606 | } | ||
607 | |||
608 | /* | ||
609 | * Memory allocation strategy... our layout is normally: | ||
610 | * | ||
611 | * at 14Mb or more we vmlinux, then a gap and initrd. In some rare cases, initrd | ||
612 | * might end up beeing before the kernel though. We assume this won't override | ||
613 | * the final kernel at 0, we have no provision to handle that in this version, | ||
614 | * but it should hopefully never happen. | ||
615 | * | ||
616 | * alloc_top is set to the top of RMO, eventually shrink down if the TCEs overlap | ||
617 | * alloc_bottom is set to the top of kernel/initrd | ||
618 | * | ||
619 | * from there, allocations are done that way : rtas is allocated topmost, and | ||
620 | * the device-tree is allocated from the bottom. We try to grow the device-tree | ||
621 | * allocation as we progress. If we can't, then we fail, we don't currently have | ||
622 | * a facility to restart elsewhere, but that shouldn't be necessary neither | ||
623 | * | ||
624 | * Note that calls to reserve_mem have to be done explicitely, memory allocated | ||
625 | * with either alloc_up or alloc_down isn't automatically reserved. | ||
626 | */ | ||
627 | |||
628 | |||
629 | /* | ||
630 | * Allocates memory in the RMO upward from the kernel/initrd | ||
631 | * | ||
632 | * When align is 0, this is a special case, it means to allocate in place | ||
633 | * at the current location of alloc_bottom or fail (that is basically | ||
634 | * extending the previous allocation). Used for the device-tree flattening | ||
635 | */ | ||
636 | static unsigned long __init alloc_up(unsigned long size, unsigned long align) | ||
637 | { | ||
638 | unsigned long offset = reloc_offset(); | ||
639 | unsigned long base = _ALIGN_UP(RELOC(alloc_bottom), align); | ||
640 | unsigned long addr = 0; | ||
641 | |||
642 | prom_debug("alloc_up(%x, %x)\n", size, align); | ||
643 | if (RELOC(ram_top) == 0) | ||
644 | prom_panic("alloc_up() called with mem not initialized\n"); | ||
645 | |||
646 | if (align) | ||
647 | base = _ALIGN_UP(RELOC(alloc_bottom), align); | ||
648 | else | ||
649 | base = RELOC(alloc_bottom); | ||
650 | |||
651 | for(; (base + size) <= RELOC(alloc_top); | ||
652 | base = _ALIGN_UP(base + 0x100000, align)) { | ||
653 | prom_debug(" trying: 0x%x\n\r", base); | ||
654 | addr = (unsigned long)prom_claim(base, size, 0); | ||
655 | if (addr != PROM_ERROR) | ||
656 | break; | ||
657 | addr = 0; | ||
658 | if (align == 0) | ||
659 | break; | ||
660 | } | ||
661 | if (addr == 0) | ||
662 | return 0; | ||
663 | RELOC(alloc_bottom) = addr; | ||
664 | |||
665 | prom_debug(" -> %x\n", addr); | ||
666 | prom_debug(" alloc_bottom : %x\n", RELOC(alloc_bottom)); | ||
667 | prom_debug(" alloc_top : %x\n", RELOC(alloc_top)); | ||
668 | prom_debug(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); | ||
669 | prom_debug(" rmo_top : %x\n", RELOC(rmo_top)); | ||
670 | prom_debug(" ram_top : %x\n", RELOC(ram_top)); | ||
671 | |||
672 | return addr; | ||
673 | } | ||
674 | |||
675 | /* | ||
676 | * Allocates memory downard, either from top of RMO, or if highmem | ||
677 | * is set, from the top of RAM. Note that this one doesn't handle | ||
678 | * failures. In does claim memory if highmem is not set. | ||
679 | */ | ||
680 | static unsigned long __init alloc_down(unsigned long size, unsigned long align, | ||
681 | int highmem) | ||
682 | { | ||
683 | unsigned long offset = reloc_offset(); | ||
684 | unsigned long base, addr = 0; | ||
685 | |||
686 | prom_debug("alloc_down(%x, %x, %s)\n", size, align, | ||
687 | highmem ? RELOC("(high)") : RELOC("(low)")); | ||
688 | if (RELOC(ram_top) == 0) | ||
689 | prom_panic("alloc_down() called with mem not initialized\n"); | ||
690 | |||
691 | if (highmem) { | ||
692 | /* Carve out storage for the TCE table. */ | ||
693 | addr = _ALIGN_DOWN(RELOC(alloc_top_high) - size, align); | ||
694 | if (addr <= RELOC(alloc_bottom)) | ||
695 | return 0; | ||
696 | else { | ||
697 | /* Will we bump into the RMO ? If yes, check out that we | ||
698 | * didn't overlap existing allocations there, if we did, | ||
699 | * we are dead, we must be the first in town ! | ||
700 | */ | ||
701 | if (addr < RELOC(rmo_top)) { | ||
702 | /* Good, we are first */ | ||
703 | if (RELOC(alloc_top) == RELOC(rmo_top)) | ||
704 | RELOC(alloc_top) = RELOC(rmo_top) = addr; | ||
705 | else | ||
706 | return 0; | ||
707 | } | ||
708 | RELOC(alloc_top_high) = addr; | ||
709 | } | ||
710 | goto bail; | ||
711 | } | ||
712 | |||
713 | base = _ALIGN_DOWN(RELOC(alloc_top) - size, align); | ||
714 | for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) { | ||
715 | prom_debug(" trying: 0x%x\n\r", base); | ||
716 | addr = (unsigned long)prom_claim(base, size, 0); | ||
717 | if (addr != PROM_ERROR) | ||
718 | break; | ||
719 | addr = 0; | ||
720 | } | ||
721 | if (addr == 0) | ||
722 | return 0; | ||
723 | RELOC(alloc_top) = addr; | ||
724 | |||
725 | bail: | ||
726 | prom_debug(" -> %x\n", addr); | ||
727 | prom_debug(" alloc_bottom : %x\n", RELOC(alloc_bottom)); | ||
728 | prom_debug(" alloc_top : %x\n", RELOC(alloc_top)); | ||
729 | prom_debug(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); | ||
730 | prom_debug(" rmo_top : %x\n", RELOC(rmo_top)); | ||
731 | prom_debug(" ram_top : %x\n", RELOC(ram_top)); | ||
732 | |||
733 | return addr; | ||
734 | } | ||
735 | |||
736 | /* | ||
737 | * Parse a "reg" cell | ||
738 | */ | ||
739 | static unsigned long __init prom_next_cell(int s, cell_t **cellp) | ||
740 | { | ||
741 | cell_t *p = *cellp; | ||
742 | unsigned long r = 0; | ||
743 | |||
744 | /* Ignore more than 2 cells */ | ||
745 | while (s > 2) { | ||
746 | p++; | ||
747 | s--; | ||
748 | } | ||
749 | while (s) { | ||
750 | r <<= 32; | ||
751 | r |= *(p++); | ||
752 | s--; | ||
753 | } | ||
754 | |||
755 | *cellp = p; | ||
756 | return r; | ||
757 | } | ||
758 | |||
759 | /* | ||
760 | * Very dumb function for adding to the memory reserve list, but | ||
761 | * we don't need anything smarter at this point | ||
762 | * | ||
763 | * XXX Eventually check for collisions. They should NEVER happen | ||
764 | * if problems seem to show up, it would be a good start to track | ||
765 | * them down. | ||
766 | */ | ||
767 | static void reserve_mem(unsigned long base, unsigned long size) | ||
768 | { | ||
769 | unsigned long offset = reloc_offset(); | ||
770 | unsigned long top = base + size; | ||
771 | unsigned long cnt = RELOC(mem_reserve_cnt); | ||
772 | |||
773 | if (size == 0) | ||
774 | return; | ||
775 | |||
776 | /* We need to always keep one empty entry so that we | ||
777 | * have our terminator with "size" set to 0 since we are | ||
778 | * dumb and just copy this entire array to the boot params | ||
779 | */ | ||
780 | base = _ALIGN_DOWN(base, PAGE_SIZE); | ||
781 | top = _ALIGN_UP(top, PAGE_SIZE); | ||
782 | size = top - base; | ||
783 | |||
784 | if (cnt >= (MEM_RESERVE_MAP_SIZE - 1)) | ||
785 | prom_panic("Memory reserve map exhausted !\n"); | ||
786 | RELOC(mem_reserve_map)[cnt].base = base; | ||
787 | RELOC(mem_reserve_map)[cnt].size = size; | ||
788 | RELOC(mem_reserve_cnt) = cnt + 1; | ||
789 | } | ||
790 | |||
791 | /* | ||
792 | * Initialize memory allocation mecanism, parse "memory" nodes and | ||
793 | * obtain that way the top of memory and RMO to setup out local allocator | ||
794 | */ | ||
795 | static void __init prom_init_mem(void) | ||
796 | { | ||
797 | phandle node; | ||
798 | char *path, type[64]; | ||
799 | unsigned int plen; | ||
800 | cell_t *p, *endp; | ||
801 | unsigned long offset = reloc_offset(); | ||
802 | struct prom_t *_prom = PTRRELOC(&prom); | ||
803 | |||
804 | /* | ||
805 | * We iterate the memory nodes to find | ||
806 | * 1) top of RMO (first node) | ||
807 | * 2) top of memory | ||
808 | */ | ||
809 | prom_debug("root_addr_cells: %x\n", (long)_prom->root_addr_cells); | ||
810 | prom_debug("root_size_cells: %x\n", (long)_prom->root_size_cells); | ||
811 | |||
812 | prom_debug("scanning memory:\n"); | ||
813 | path = RELOC(prom_scratch); | ||
814 | |||
815 | for (node = 0; prom_next_node(&node); ) { | ||
816 | type[0] = 0; | ||
817 | prom_getprop(node, "device_type", type, sizeof(type)); | ||
818 | |||
819 | if (strcmp(type, RELOC("memory"))) | ||
820 | continue; | ||
821 | |||
822 | plen = prom_getprop(node, "reg", RELOC(regbuf), sizeof(regbuf)); | ||
823 | if (plen > sizeof(regbuf)) { | ||
824 | prom_printf("memory node too large for buffer !\n"); | ||
825 | plen = sizeof(regbuf); | ||
826 | } | ||
827 | p = RELOC(regbuf); | ||
828 | endp = p + (plen / sizeof(cell_t)); | ||
829 | |||
830 | #ifdef DEBUG_PROM | ||
831 | memset(path, 0, PROM_SCRATCH_SIZE); | ||
832 | call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1); | ||
833 | prom_debug(" node %s :\n", path); | ||
834 | #endif /* DEBUG_PROM */ | ||
835 | |||
836 | while ((endp - p) >= (_prom->root_addr_cells + _prom->root_size_cells)) { | ||
837 | unsigned long base, size; | ||
838 | |||
839 | base = prom_next_cell(_prom->root_addr_cells, &p); | ||
840 | size = prom_next_cell(_prom->root_size_cells, &p); | ||
841 | |||
842 | if (size == 0) | ||
843 | continue; | ||
844 | prom_debug(" %x %x\n", base, size); | ||
845 | if (base == 0) | ||
846 | RELOC(rmo_top) = size; | ||
847 | if ((base + size) > RELOC(ram_top)) | ||
848 | RELOC(ram_top) = base + size; | ||
849 | } | ||
850 | } | ||
851 | |||
852 | RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(klimit) - offset + 0x4000); | ||
853 | |||
854 | /* Check if we have an initrd after the kernel, if we do move our bottom | ||
855 | * point to after it | ||
856 | */ | ||
857 | if (RELOC(prom_initrd_start)) { | ||
858 | if (RELOC(prom_initrd_end) > RELOC(alloc_bottom)) | ||
859 | RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(prom_initrd_end)); | ||
860 | } | ||
861 | |||
862 | /* | ||
863 | * If prom_memory_limit is set we reduce the upper limits *except* for | ||
864 | * alloc_top_high. This must be the real top of RAM so we can put | ||
865 | * TCE's up there. | ||
866 | */ | ||
867 | |||
868 | RELOC(alloc_top_high) = RELOC(ram_top); | ||
869 | |||
870 | if (RELOC(prom_memory_limit)) { | ||
871 | if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) { | ||
872 | prom_printf("Ignoring mem=%x <= alloc_bottom.\n", | ||
873 | RELOC(prom_memory_limit)); | ||
874 | RELOC(prom_memory_limit) = 0; | ||
875 | } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) { | ||
876 | prom_printf("Ignoring mem=%x >= ram_top.\n", | ||
877 | RELOC(prom_memory_limit)); | ||
878 | RELOC(prom_memory_limit) = 0; | ||
879 | } else { | ||
880 | RELOC(ram_top) = RELOC(prom_memory_limit); | ||
881 | RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit)); | ||
882 | } | ||
883 | } | ||
884 | |||
885 | /* | ||
886 | * Setup our top alloc point, that is top of RMO or top of | ||
887 | * segment 0 when running non-LPAR. | ||
888 | */ | ||
889 | if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR ) | ||
890 | RELOC(alloc_top) = RELOC(rmo_top); | ||
891 | else | ||
892 | /* Some RS64 machines have buggy firmware where claims up at 1GB | ||
893 | * fails. Cap at 768MB as a workaround. Still plenty of room. | ||
894 | */ | ||
895 | RELOC(alloc_top) = RELOC(rmo_top) = min(0x30000000ul, RELOC(ram_top)); | ||
896 | |||
897 | prom_printf("memory layout at init:\n"); | ||
898 | prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit)); | ||
899 | prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom)); | ||
900 | prom_printf(" alloc_top : %x\n", RELOC(alloc_top)); | ||
901 | prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); | ||
902 | prom_printf(" rmo_top : %x\n", RELOC(rmo_top)); | ||
903 | prom_printf(" ram_top : %x\n", RELOC(ram_top)); | ||
904 | } | ||
905 | |||
906 | |||
907 | /* | ||
908 | * Allocate room for and instanciate RTAS | ||
909 | */ | ||
910 | static void __init prom_instantiate_rtas(void) | ||
911 | { | ||
912 | unsigned long offset = reloc_offset(); | ||
913 | struct prom_t *_prom = PTRRELOC(&prom); | ||
914 | phandle rtas_node; | ||
915 | ihandle rtas_inst; | ||
916 | u32 base, entry = 0; | ||
917 | u32 size = 0; | ||
918 | |||
919 | prom_debug("prom_instantiate_rtas: start...\n"); | ||
920 | |||
921 | rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas")); | ||
922 | prom_debug("rtas_node: %x\n", rtas_node); | ||
923 | if (!PHANDLE_VALID(rtas_node)) | ||
924 | return; | ||
925 | |||
926 | prom_getprop(rtas_node, "rtas-size", &size, sizeof(size)); | ||
927 | if (size == 0) | ||
928 | return; | ||
929 | |||
930 | base = alloc_down(size, PAGE_SIZE, 0); | ||
931 | if (base == 0) { | ||
932 | prom_printf("RTAS allocation failed !\n"); | ||
933 | return; | ||
934 | } | ||
935 | |||
936 | rtas_inst = call_prom("open", 1, 1, ADDR("/rtas")); | ||
937 | if (!IHANDLE_VALID(rtas_inst)) { | ||
938 | prom_printf("opening rtas package failed"); | ||
939 | return; | ||
940 | } | ||
941 | |||
942 | prom_printf("instantiating rtas at 0x%x ...", base); | ||
943 | |||
944 | if (call_prom("call-method", 3, 2, | ||
945 | ADDR("instantiate-rtas"), | ||
946 | rtas_inst, base) != PROM_ERROR) { | ||
947 | entry = (long)_prom->args.rets[1]; | ||
948 | } | ||
949 | if (entry == 0) { | ||
950 | prom_printf(" failed\n"); | ||
951 | return; | ||
952 | } | ||
953 | prom_printf(" done\n"); | ||
954 | |||
955 | reserve_mem(base, size); | ||
956 | |||
957 | prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base)); | ||
958 | prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry)); | ||
959 | |||
960 | prom_debug("rtas base = 0x%x\n", base); | ||
961 | prom_debug("rtas entry = 0x%x\n", entry); | ||
962 | prom_debug("rtas size = 0x%x\n", (long)size); | ||
963 | |||
964 | prom_debug("prom_instantiate_rtas: end...\n"); | ||
965 | } | ||
966 | |||
967 | |||
968 | /* | ||
969 | * Allocate room for and initialize TCE tables | ||
970 | */ | ||
971 | static void __init prom_initialize_tce_table(void) | ||
972 | { | ||
973 | phandle node; | ||
974 | ihandle phb_node; | ||
975 | unsigned long offset = reloc_offset(); | ||
976 | char compatible[64], type[64], model[64]; | ||
977 | char *path = RELOC(prom_scratch); | ||
978 | u64 base, align; | ||
979 | u32 minalign, minsize; | ||
980 | u64 tce_entry, *tce_entryp; | ||
981 | u64 local_alloc_top, local_alloc_bottom; | ||
982 | u64 i; | ||
983 | |||
984 | if (RELOC(ppc64_iommu_off)) | ||
985 | return; | ||
986 | |||
987 | prom_debug("starting prom_initialize_tce_table\n"); | ||
988 | |||
989 | /* Cache current top of allocs so we reserve a single block */ | ||
990 | local_alloc_top = RELOC(alloc_top_high); | ||
991 | local_alloc_bottom = local_alloc_top; | ||
992 | |||
993 | /* Search all nodes looking for PHBs. */ | ||
994 | for (node = 0; prom_next_node(&node); ) { | ||
995 | compatible[0] = 0; | ||
996 | type[0] = 0; | ||
997 | model[0] = 0; | ||
998 | prom_getprop(node, "compatible", | ||
999 | compatible, sizeof(compatible)); | ||
1000 | prom_getprop(node, "device_type", type, sizeof(type)); | ||
1001 | prom_getprop(node, "model", model, sizeof(model)); | ||
1002 | |||
1003 | if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL)) | ||
1004 | continue; | ||
1005 | |||
1006 | /* Keep the old logic in tack to avoid regression. */ | ||
1007 | if (compatible[0] != 0) { | ||
1008 | if ((strstr(compatible, RELOC("python")) == NULL) && | ||
1009 | (strstr(compatible, RELOC("Speedwagon")) == NULL) && | ||
1010 | (strstr(compatible, RELOC("Winnipeg")) == NULL)) | ||
1011 | continue; | ||
1012 | } else if (model[0] != 0) { | ||
1013 | if ((strstr(model, RELOC("ython")) == NULL) && | ||
1014 | (strstr(model, RELOC("peedwagon")) == NULL) && | ||
1015 | (strstr(model, RELOC("innipeg")) == NULL)) | ||
1016 | continue; | ||
1017 | } | ||
1018 | |||
1019 | if (prom_getprop(node, "tce-table-minalign", &minalign, | ||
1020 | sizeof(minalign)) == PROM_ERROR) | ||
1021 | minalign = 0; | ||
1022 | if (prom_getprop(node, "tce-table-minsize", &minsize, | ||
1023 | sizeof(minsize)) == PROM_ERROR) | ||
1024 | minsize = 4UL << 20; | ||
1025 | |||
1026 | /* | ||
1027 | * Even though we read what OF wants, we just set the table | ||
1028 | * size to 4 MB. This is enough to map 2GB of PCI DMA space. | ||
1029 | * By doing this, we avoid the pitfalls of trying to DMA to | ||
1030 | * MMIO space and the DMA alias hole. | ||
1031 | * | ||
1032 | * On POWER4, firmware sets the TCE region by assuming | ||
1033 | * each TCE table is 8MB. Using this memory for anything | ||
1034 | * else will impact performance, so we always allocate 8MB. | ||
1035 | * Anton | ||
1036 | */ | ||
1037 | if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p)) | ||
1038 | minsize = 8UL << 20; | ||
1039 | else | ||
1040 | minsize = 4UL << 20; | ||
1041 | |||
1042 | /* Align to the greater of the align or size */ | ||
1043 | align = max(minalign, minsize); | ||
1044 | base = alloc_down(minsize, align, 1); | ||
1045 | if (base == 0) | ||
1046 | prom_panic("ERROR, cannot find space for TCE table.\n"); | ||
1047 | if (base < local_alloc_bottom) | ||
1048 | local_alloc_bottom = base; | ||
1049 | |||
1050 | /* Save away the TCE table attributes for later use. */ | ||
1051 | prom_setprop(node, "linux,tce-base", &base, sizeof(base)); | ||
1052 | prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize)); | ||
1053 | |||
1054 | /* It seems OF doesn't null-terminate the path :-( */ | ||
1055 | memset(path, 0, sizeof(path)); | ||
1056 | /* Call OF to setup the TCE hardware */ | ||
1057 | if (call_prom("package-to-path", 3, 1, node, | ||
1058 | path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) { | ||
1059 | prom_printf("package-to-path failed\n"); | ||
1060 | } | ||
1061 | |||
1062 | prom_debug("TCE table: %s\n", path); | ||
1063 | prom_debug("\tnode = 0x%x\n", node); | ||
1064 | prom_debug("\tbase = 0x%x\n", base); | ||
1065 | prom_debug("\tsize = 0x%x\n", minsize); | ||
1066 | |||
1067 | /* Initialize the table to have a one-to-one mapping | ||
1068 | * over the allocated size. | ||
1069 | */ | ||
1070 | tce_entryp = (unsigned long *)base; | ||
1071 | for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) { | ||
1072 | tce_entry = (i << PAGE_SHIFT); | ||
1073 | tce_entry |= 0x3; | ||
1074 | *tce_entryp = tce_entry; | ||
1075 | } | ||
1076 | |||
1077 | prom_printf("opening PHB %s", path); | ||
1078 | phb_node = call_prom("open", 1, 1, path); | ||
1079 | if (phb_node == 0) | ||
1080 | prom_printf("... failed\n"); | ||
1081 | else | ||
1082 | prom_printf("... done\n"); | ||
1083 | |||
1084 | call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"), | ||
1085 | phb_node, -1, minsize, | ||
1086 | (u32) base, (u32) (base >> 32)); | ||
1087 | call_prom("close", 1, 0, phb_node); | ||
1088 | } | ||
1089 | |||
1090 | reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom); | ||
1091 | |||
1092 | if (RELOC(prom_memory_limit)) { | ||
1093 | /* | ||
1094 | * We align the start to a 16MB boundary so we can map the TCE area | ||
1095 | * using large pages if possible. The end should be the top of RAM | ||
1096 | * so no need to align it. | ||
1097 | */ | ||
1098 | RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom, 0x1000000); | ||
1099 | RELOC(prom_tce_alloc_end) = local_alloc_top; | ||
1100 | } | ||
1101 | |||
1102 | /* Flag the first invalid entry */ | ||
1103 | prom_debug("ending prom_initialize_tce_table\n"); | ||
1104 | } | ||
1105 | |||
1106 | /* | ||
1107 | * With CHRP SMP we need to use the OF to start the other | ||
1108 | * processors so we can't wait until smp_boot_cpus (the OF is | ||
1109 | * trashed by then) so we have to put the processors into | ||
1110 | * a holding pattern controlled by the kernel (not OF) before | ||
1111 | * we destroy the OF. | ||
1112 | * | ||
1113 | * This uses a chunk of low memory, puts some holding pattern | ||
1114 | * code there and sends the other processors off to there until | ||
1115 | * smp_boot_cpus tells them to do something. The holding pattern | ||
1116 | * checks that address until its cpu # is there, when it is that | ||
1117 | * cpu jumps to __secondary_start(). smp_boot_cpus() takes care | ||
1118 | * of setting those values. | ||
1119 | * | ||
1120 | * We also use physical address 0x4 here to tell when a cpu | ||
1121 | * is in its holding pattern code. | ||
1122 | * | ||
1123 | * Fixup comment... DRENG / PPPBBB - Peter | ||
1124 | * | ||
1125 | * -- Cort | ||
1126 | */ | ||
1127 | static void __init prom_hold_cpus(void) | ||
1128 | { | ||
1129 | unsigned long i; | ||
1130 | unsigned int reg; | ||
1131 | phandle node; | ||
1132 | unsigned long offset = reloc_offset(); | ||
1133 | char type[64]; | ||
1134 | int cpuid = 0; | ||
1135 | unsigned int interrupt_server[MAX_CPU_THREADS]; | ||
1136 | unsigned int cpu_threads, hw_cpu_num; | ||
1137 | int propsize; | ||
1138 | extern void __secondary_hold(void); | ||
1139 | extern unsigned long __secondary_hold_spinloop; | ||
1140 | extern unsigned long __secondary_hold_acknowledge; | ||
1141 | unsigned long *spinloop | ||
1142 | = (void *)virt_to_abs(&__secondary_hold_spinloop); | ||
1143 | unsigned long *acknowledge | ||
1144 | = (void *)virt_to_abs(&__secondary_hold_acknowledge); | ||
1145 | unsigned long secondary_hold | ||
1146 | = virt_to_abs(*PTRRELOC((unsigned long *)__secondary_hold)); | ||
1147 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1148 | |||
1149 | prom_debug("prom_hold_cpus: start...\n"); | ||
1150 | prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop); | ||
1151 | prom_debug(" 1) *spinloop = 0x%x\n", *spinloop); | ||
1152 | prom_debug(" 1) acknowledge = 0x%x\n", | ||
1153 | (unsigned long)acknowledge); | ||
1154 | prom_debug(" 1) *acknowledge = 0x%x\n", *acknowledge); | ||
1155 | prom_debug(" 1) secondary_hold = 0x%x\n", secondary_hold); | ||
1156 | |||
1157 | /* Set the common spinloop variable, so all of the secondary cpus | ||
1158 | * will block when they are awakened from their OF spinloop. | ||
1159 | * This must occur for both SMP and non SMP kernels, since OF will | ||
1160 | * be trashed when we move the kernel. | ||
1161 | */ | ||
1162 | *spinloop = 0; | ||
1163 | |||
1164 | #ifdef CONFIG_HMT | ||
1165 | for (i=0; i < NR_CPUS; i++) { | ||
1166 | RELOC(hmt_thread_data)[i].pir = 0xdeadbeef; | ||
1167 | } | ||
1168 | #endif | ||
1169 | /* look for cpus */ | ||
1170 | for (node = 0; prom_next_node(&node); ) { | ||
1171 | type[0] = 0; | ||
1172 | prom_getprop(node, "device_type", type, sizeof(type)); | ||
1173 | if (strcmp(type, RELOC("cpu")) != 0) | ||
1174 | continue; | ||
1175 | |||
1176 | /* Skip non-configured cpus. */ | ||
1177 | if (prom_getprop(node, "status", type, sizeof(type)) > 0) | ||
1178 | if (strcmp(type, RELOC("okay")) != 0) | ||
1179 | continue; | ||
1180 | |||
1181 | reg = -1; | ||
1182 | prom_getprop(node, "reg", ®, sizeof(reg)); | ||
1183 | |||
1184 | prom_debug("\ncpuid = 0x%x\n", cpuid); | ||
1185 | prom_debug("cpu hw idx = 0x%x\n", reg); | ||
1186 | |||
1187 | /* Init the acknowledge var which will be reset by | ||
1188 | * the secondary cpu when it awakens from its OF | ||
1189 | * spinloop. | ||
1190 | */ | ||
1191 | *acknowledge = (unsigned long)-1; | ||
1192 | |||
1193 | propsize = prom_getprop(node, "ibm,ppc-interrupt-server#s", | ||
1194 | &interrupt_server, | ||
1195 | sizeof(interrupt_server)); | ||
1196 | if (propsize < 0) { | ||
1197 | /* no property. old hardware has no SMT */ | ||
1198 | cpu_threads = 1; | ||
1199 | interrupt_server[0] = reg; /* fake it with phys id */ | ||
1200 | } else { | ||
1201 | /* We have a threaded processor */ | ||
1202 | cpu_threads = propsize / sizeof(u32); | ||
1203 | if (cpu_threads > MAX_CPU_THREADS) { | ||
1204 | prom_printf("SMT: too many threads!\n" | ||
1205 | "SMT: found %x, max is %x\n", | ||
1206 | cpu_threads, MAX_CPU_THREADS); | ||
1207 | cpu_threads = 1; /* ToDo: panic? */ | ||
1208 | } | ||
1209 | } | ||
1210 | |||
1211 | hw_cpu_num = interrupt_server[0]; | ||
1212 | if (hw_cpu_num != _prom->cpu) { | ||
1213 | /* Primary Thread of non-boot cpu */ | ||
1214 | prom_printf("%x : starting cpu hw idx %x... ", cpuid, reg); | ||
1215 | call_prom("start-cpu", 3, 0, node, | ||
1216 | secondary_hold, reg); | ||
1217 | |||
1218 | for ( i = 0 ; (i < 100000000) && | ||
1219 | (*acknowledge == ((unsigned long)-1)); i++ ) | ||
1220 | mb(); | ||
1221 | |||
1222 | if (*acknowledge == reg) { | ||
1223 | prom_printf("done\n"); | ||
1224 | /* We have to get every CPU out of OF, | ||
1225 | * even if we never start it. */ | ||
1226 | if (cpuid >= NR_CPUS) | ||
1227 | goto next; | ||
1228 | } else { | ||
1229 | prom_printf("failed: %x\n", *acknowledge); | ||
1230 | } | ||
1231 | } | ||
1232 | #ifdef CONFIG_SMP | ||
1233 | else | ||
1234 | prom_printf("%x : boot cpu %x\n", cpuid, reg); | ||
1235 | #endif | ||
1236 | next: | ||
1237 | #ifdef CONFIG_SMP | ||
1238 | /* Init paca for secondary threads. They start later. */ | ||
1239 | for (i=1; i < cpu_threads; i++) { | ||
1240 | cpuid++; | ||
1241 | if (cpuid >= NR_CPUS) | ||
1242 | continue; | ||
1243 | } | ||
1244 | #endif /* CONFIG_SMP */ | ||
1245 | cpuid++; | ||
1246 | } | ||
1247 | #ifdef CONFIG_HMT | ||
1248 | /* Only enable HMT on processors that provide support. */ | ||
1249 | if (__is_processor(PV_PULSAR) || | ||
1250 | __is_processor(PV_ICESTAR) || | ||
1251 | __is_processor(PV_SSTAR)) { | ||
1252 | prom_printf(" starting secondary threads\n"); | ||
1253 | |||
1254 | for (i = 0; i < NR_CPUS; i += 2) { | ||
1255 | if (!cpu_online(i)) | ||
1256 | continue; | ||
1257 | |||
1258 | if (i == 0) { | ||
1259 | unsigned long pir = mfspr(SPRN_PIR); | ||
1260 | if (__is_processor(PV_PULSAR)) { | ||
1261 | RELOC(hmt_thread_data)[i].pir = | ||
1262 | pir & 0x1f; | ||
1263 | } else { | ||
1264 | RELOC(hmt_thread_data)[i].pir = | ||
1265 | pir & 0x3ff; | ||
1266 | } | ||
1267 | } | ||
1268 | } | ||
1269 | } else { | ||
1270 | prom_printf("Processor is not HMT capable\n"); | ||
1271 | } | ||
1272 | #endif | ||
1273 | |||
1274 | if (cpuid > NR_CPUS) | ||
1275 | prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS) | ||
1276 | ") exceeded: ignoring extras\n"); | ||
1277 | |||
1278 | prom_debug("prom_hold_cpus: end...\n"); | ||
1279 | } | ||
1280 | |||
1281 | |||
1282 | static void __init prom_init_client_services(unsigned long pp) | ||
1283 | { | ||
1284 | unsigned long offset = reloc_offset(); | ||
1285 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1286 | |||
1287 | /* Get a handle to the prom entry point before anything else */ | ||
1288 | _prom->entry = pp; | ||
1289 | |||
1290 | /* Init default value for phys size */ | ||
1291 | _prom->root_size_cells = 1; | ||
1292 | _prom->root_addr_cells = 2; | ||
1293 | |||
1294 | /* get a handle for the stdout device */ | ||
1295 | _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen")); | ||
1296 | if (!PHANDLE_VALID(_prom->chosen)) | ||
1297 | prom_panic("cannot find chosen"); /* msg won't be printed :( */ | ||
1298 | |||
1299 | /* get device tree root */ | ||
1300 | _prom->root = call_prom("finddevice", 1, 1, ADDR("/")); | ||
1301 | if (!PHANDLE_VALID(_prom->root)) | ||
1302 | prom_panic("cannot find device tree root"); /* msg won't be printed :( */ | ||
1303 | } | ||
1304 | |||
1305 | static void __init prom_init_stdout(void) | ||
1306 | { | ||
1307 | unsigned long offset = reloc_offset(); | ||
1308 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1309 | char *path = RELOC(of_stdout_device); | ||
1310 | char type[16]; | ||
1311 | u32 val; | ||
1312 | |||
1313 | if (prom_getprop(_prom->chosen, "stdout", &val, sizeof(val)) <= 0) | ||
1314 | prom_panic("cannot find stdout"); | ||
1315 | |||
1316 | _prom->stdout = val; | ||
1317 | |||
1318 | /* Get the full OF pathname of the stdout device */ | ||
1319 | memset(path, 0, 256); | ||
1320 | call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255); | ||
1321 | val = call_prom("instance-to-package", 1, 1, _prom->stdout); | ||
1322 | prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val)); | ||
1323 | prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device)); | ||
1324 | prom_setprop(_prom->chosen, "linux,stdout-path", | ||
1325 | RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1); | ||
1326 | |||
1327 | /* If it's a display, note it */ | ||
1328 | memset(type, 0, sizeof(type)); | ||
1329 | prom_getprop(val, "device_type", type, sizeof(type)); | ||
1330 | if (strcmp(type, RELOC("display")) == 0) { | ||
1331 | _prom->disp_node = val; | ||
1332 | prom_setprop(val, "linux,boot-display", NULL, 0); | ||
1333 | } | ||
1334 | } | ||
1335 | |||
1336 | static void __init prom_close_stdin(void) | ||
1337 | { | ||
1338 | unsigned long offset = reloc_offset(); | ||
1339 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1340 | ihandle val; | ||
1341 | |||
1342 | if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0) | ||
1343 | call_prom("close", 1, 0, val); | ||
1344 | } | ||
1345 | |||
1346 | static int __init prom_find_machine_type(void) | ||
1347 | { | ||
1348 | unsigned long offset = reloc_offset(); | ||
1349 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1350 | char compat[256]; | ||
1351 | int len, i = 0; | ||
1352 | phandle rtas; | ||
1353 | |||
1354 | len = prom_getprop(_prom->root, "compatible", | ||
1355 | compat, sizeof(compat)-1); | ||
1356 | if (len > 0) { | ||
1357 | compat[len] = 0; | ||
1358 | while (i < len) { | ||
1359 | char *p = &compat[i]; | ||
1360 | int sl = strlen(p); | ||
1361 | if (sl == 0) | ||
1362 | break; | ||
1363 | if (strstr(p, RELOC("Power Macintosh")) || | ||
1364 | strstr(p, RELOC("MacRISC4"))) | ||
1365 | return PLATFORM_POWERMAC; | ||
1366 | if (strstr(p, RELOC("Momentum,Maple"))) | ||
1367 | return PLATFORM_MAPLE; | ||
1368 | i += sl + 1; | ||
1369 | } | ||
1370 | } | ||
1371 | /* Default to pSeries. We need to know if we are running LPAR */ | ||
1372 | rtas = call_prom("finddevice", 1, 1, ADDR("/rtas")); | ||
1373 | if (PHANDLE_VALID(rtas)) { | ||
1374 | int x = prom_getproplen(rtas, "ibm,hypertas-functions"); | ||
1375 | if (x != PROM_ERROR) { | ||
1376 | prom_printf("Hypertas detected, assuming LPAR !\n"); | ||
1377 | return PLATFORM_PSERIES_LPAR; | ||
1378 | } | ||
1379 | } | ||
1380 | return PLATFORM_PSERIES; | ||
1381 | } | ||
1382 | |||
1383 | static int __init prom_set_color(ihandle ih, int i, int r, int g, int b) | ||
1384 | { | ||
1385 | unsigned long offset = reloc_offset(); | ||
1386 | |||
1387 | return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r); | ||
1388 | } | ||
1389 | |||
1390 | /* | ||
1391 | * If we have a display that we don't know how to drive, | ||
1392 | * we will want to try to execute OF's open method for it | ||
1393 | * later. However, OF will probably fall over if we do that | ||
1394 | * we've taken over the MMU. | ||
1395 | * So we check whether we will need to open the display, | ||
1396 | * and if so, open it now. | ||
1397 | */ | ||
1398 | static void __init prom_check_displays(void) | ||
1399 | { | ||
1400 | unsigned long offset = reloc_offset(); | ||
1401 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1402 | char type[16], *path; | ||
1403 | phandle node; | ||
1404 | ihandle ih; | ||
1405 | int i; | ||
1406 | |||
1407 | static unsigned char default_colors[] = { | ||
1408 | 0x00, 0x00, 0x00, | ||
1409 | 0x00, 0x00, 0xaa, | ||
1410 | 0x00, 0xaa, 0x00, | ||
1411 | 0x00, 0xaa, 0xaa, | ||
1412 | 0xaa, 0x00, 0x00, | ||
1413 | 0xaa, 0x00, 0xaa, | ||
1414 | 0xaa, 0xaa, 0x00, | ||
1415 | 0xaa, 0xaa, 0xaa, | ||
1416 | 0x55, 0x55, 0x55, | ||
1417 | 0x55, 0x55, 0xff, | ||
1418 | 0x55, 0xff, 0x55, | ||
1419 | 0x55, 0xff, 0xff, | ||
1420 | 0xff, 0x55, 0x55, | ||
1421 | 0xff, 0x55, 0xff, | ||
1422 | 0xff, 0xff, 0x55, | ||
1423 | 0xff, 0xff, 0xff | ||
1424 | }; | ||
1425 | const unsigned char *clut; | ||
1426 | |||
1427 | prom_printf("Looking for displays\n"); | ||
1428 | for (node = 0; prom_next_node(&node); ) { | ||
1429 | memset(type, 0, sizeof(type)); | ||
1430 | prom_getprop(node, "device_type", type, sizeof(type)); | ||
1431 | if (strcmp(type, RELOC("display")) != 0) | ||
1432 | continue; | ||
1433 | |||
1434 | /* It seems OF doesn't null-terminate the path :-( */ | ||
1435 | path = RELOC(prom_scratch); | ||
1436 | memset(path, 0, PROM_SCRATCH_SIZE); | ||
1437 | |||
1438 | /* | ||
1439 | * leave some room at the end of the path for appending extra | ||
1440 | * arguments | ||
1441 | */ | ||
1442 | if (call_prom("package-to-path", 3, 1, node, path, | ||
1443 | PROM_SCRATCH_SIZE-10) == PROM_ERROR) | ||
1444 | continue; | ||
1445 | prom_printf("found display : %s, opening ... ", path); | ||
1446 | |||
1447 | ih = call_prom("open", 1, 1, path); | ||
1448 | if (ih == 0) { | ||
1449 | prom_printf("failed\n"); | ||
1450 | continue; | ||
1451 | } | ||
1452 | |||
1453 | /* Success */ | ||
1454 | prom_printf("done\n"); | ||
1455 | prom_setprop(node, "linux,opened", NULL, 0); | ||
1456 | |||
1457 | /* | ||
1458 | * stdout wasn't a display node, pick the first we can find | ||
1459 | * for btext | ||
1460 | */ | ||
1461 | if (_prom->disp_node == 0) | ||
1462 | _prom->disp_node = node; | ||
1463 | |||
1464 | /* Setup a useable color table when the appropriate | ||
1465 | * method is available. Should update this to set-colors */ | ||
1466 | clut = RELOC(default_colors); | ||
1467 | for (i = 0; i < 32; i++, clut += 3) | ||
1468 | if (prom_set_color(ih, i, clut[0], clut[1], | ||
1469 | clut[2]) != 0) | ||
1470 | break; | ||
1471 | |||
1472 | #ifdef CONFIG_LOGO_LINUX_CLUT224 | ||
1473 | clut = PTRRELOC(RELOC(logo_linux_clut224.clut)); | ||
1474 | for (i = 0; i < RELOC(logo_linux_clut224.clutsize); i++, clut += 3) | ||
1475 | if (prom_set_color(ih, i + 32, clut[0], clut[1], | ||
1476 | clut[2]) != 0) | ||
1477 | break; | ||
1478 | #endif /* CONFIG_LOGO_LINUX_CLUT224 */ | ||
1479 | } | ||
1480 | } | ||
1481 | |||
1482 | |||
1483 | /* Return (relocated) pointer to this much memory: moves initrd if reqd. */ | ||
1484 | static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end, | ||
1485 | unsigned long needed, unsigned long align) | ||
1486 | { | ||
1487 | unsigned long offset = reloc_offset(); | ||
1488 | void *ret; | ||
1489 | |||
1490 | *mem_start = _ALIGN(*mem_start, align); | ||
1491 | while ((*mem_start + needed) > *mem_end) { | ||
1492 | unsigned long room, chunk; | ||
1493 | |||
1494 | prom_debug("Chunk exhausted, claiming more at %x...\n", | ||
1495 | RELOC(alloc_bottom)); | ||
1496 | room = RELOC(alloc_top) - RELOC(alloc_bottom); | ||
1497 | if (room > DEVTREE_CHUNK_SIZE) | ||
1498 | room = DEVTREE_CHUNK_SIZE; | ||
1499 | if (room < PAGE_SIZE) | ||
1500 | prom_panic("No memory for flatten_device_tree (no room)"); | ||
1501 | chunk = alloc_up(room, 0); | ||
1502 | if (chunk == 0) | ||
1503 | prom_panic("No memory for flatten_device_tree (claim failed)"); | ||
1504 | *mem_end = RELOC(alloc_top); | ||
1505 | } | ||
1506 | |||
1507 | ret = (void *)*mem_start; | ||
1508 | *mem_start += needed; | ||
1509 | |||
1510 | return ret; | ||
1511 | } | ||
1512 | |||
1513 | #define dt_push_token(token, mem_start, mem_end) \ | ||
1514 | do { *((u32 *)make_room(mem_start, mem_end, 4, 4)) = token; } while(0) | ||
1515 | |||
1516 | static unsigned long __init dt_find_string(char *str) | ||
1517 | { | ||
1518 | unsigned long offset = reloc_offset(); | ||
1519 | char *s, *os; | ||
1520 | |||
1521 | s = os = (char *)RELOC(dt_string_start); | ||
1522 | s += 4; | ||
1523 | while (s < (char *)RELOC(dt_string_end)) { | ||
1524 | if (strcmp(s, str) == 0) | ||
1525 | return s - os; | ||
1526 | s += strlen(s) + 1; | ||
1527 | } | ||
1528 | return 0; | ||
1529 | } | ||
1530 | |||
1531 | /* | ||
1532 | * The Open Firmware 1275 specification states properties must be 31 bytes or | ||
1533 | * less, however not all firmwares obey this. Make it 64 bytes to be safe. | ||
1534 | */ | ||
1535 | #define MAX_PROPERTY_NAME 64 | ||
1536 | |||
1537 | static void __init scan_dt_build_strings(phandle node, | ||
1538 | unsigned long *mem_start, | ||
1539 | unsigned long *mem_end) | ||
1540 | { | ||
1541 | unsigned long offset = reloc_offset(); | ||
1542 | char *prev_name, *namep, *sstart; | ||
1543 | unsigned long soff; | ||
1544 | phandle child; | ||
1545 | |||
1546 | sstart = (char *)RELOC(dt_string_start); | ||
1547 | |||
1548 | /* get and store all property names */ | ||
1549 | prev_name = RELOC(""); | ||
1550 | for (;;) { | ||
1551 | /* 64 is max len of name including nul. */ | ||
1552 | namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1); | ||
1553 | if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) { | ||
1554 | /* No more nodes: unwind alloc */ | ||
1555 | *mem_start = (unsigned long)namep; | ||
1556 | break; | ||
1557 | } | ||
1558 | |||
1559 | /* skip "name" */ | ||
1560 | if (strcmp(namep, RELOC("name")) == 0) { | ||
1561 | *mem_start = (unsigned long)namep; | ||
1562 | prev_name = RELOC("name"); | ||
1563 | continue; | ||
1564 | } | ||
1565 | /* get/create string entry */ | ||
1566 | soff = dt_find_string(namep); | ||
1567 | if (soff != 0) { | ||
1568 | *mem_start = (unsigned long)namep; | ||
1569 | namep = sstart + soff; | ||
1570 | } else { | ||
1571 | /* Trim off some if we can */ | ||
1572 | *mem_start = (unsigned long)namep + strlen(namep) + 1; | ||
1573 | RELOC(dt_string_end) = *mem_start; | ||
1574 | } | ||
1575 | prev_name = namep; | ||
1576 | } | ||
1577 | |||
1578 | /* do all our children */ | ||
1579 | child = call_prom("child", 1, 1, node); | ||
1580 | while (child != 0) { | ||
1581 | scan_dt_build_strings(child, mem_start, mem_end); | ||
1582 | child = call_prom("peer", 1, 1, child); | ||
1583 | } | ||
1584 | } | ||
1585 | |||
1586 | static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | ||
1587 | unsigned long *mem_end) | ||
1588 | { | ||
1589 | phandle child; | ||
1590 | char *namep, *prev_name, *sstart, *p, *ep, *lp, *path; | ||
1591 | unsigned long soff; | ||
1592 | unsigned char *valp; | ||
1593 | unsigned long offset = reloc_offset(); | ||
1594 | static char pname[MAX_PROPERTY_NAME]; | ||
1595 | int l; | ||
1596 | |||
1597 | dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end); | ||
1598 | |||
1599 | /* get the node's full name */ | ||
1600 | namep = (char *)*mem_start; | ||
1601 | l = call_prom("package-to-path", 3, 1, node, | ||
1602 | namep, *mem_end - *mem_start); | ||
1603 | if (l >= 0) { | ||
1604 | /* Didn't fit? Get more room. */ | ||
1605 | if ((l+1) > (*mem_end - *mem_start)) { | ||
1606 | namep = make_room(mem_start, mem_end, l+1, 1); | ||
1607 | call_prom("package-to-path", 3, 1, node, namep, l); | ||
1608 | } | ||
1609 | namep[l] = '\0'; | ||
1610 | |||
1611 | /* Fixup an Apple bug where they have bogus \0 chars in the | ||
1612 | * middle of the path in some properties | ||
1613 | */ | ||
1614 | for (p = namep, ep = namep + l; p < ep; p++) | ||
1615 | if (*p == '\0') { | ||
1616 | memmove(p, p+1, ep - p); | ||
1617 | ep--; l--; p--; | ||
1618 | } | ||
1619 | |||
1620 | /* now try to extract the unit name in that mess */ | ||
1621 | for (p = namep, lp = NULL; *p; p++) | ||
1622 | if (*p == '/') | ||
1623 | lp = p + 1; | ||
1624 | if (lp != NULL) | ||
1625 | memmove(namep, lp, strlen(lp) + 1); | ||
1626 | *mem_start = _ALIGN(((unsigned long) namep) + | ||
1627 | strlen(namep) + 1, 4); | ||
1628 | } | ||
1629 | |||
1630 | /* get it again for debugging */ | ||
1631 | path = RELOC(prom_scratch); | ||
1632 | memset(path, 0, PROM_SCRATCH_SIZE); | ||
1633 | call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1); | ||
1634 | |||
1635 | /* get and store all properties */ | ||
1636 | prev_name = RELOC(""); | ||
1637 | sstart = (char *)RELOC(dt_string_start); | ||
1638 | for (;;) { | ||
1639 | if (call_prom("nextprop", 3, 1, node, prev_name, | ||
1640 | RELOC(pname)) != 1) | ||
1641 | break; | ||
1642 | |||
1643 | /* skip "name" */ | ||
1644 | if (strcmp(RELOC(pname), RELOC("name")) == 0) { | ||
1645 | prev_name = RELOC("name"); | ||
1646 | continue; | ||
1647 | } | ||
1648 | |||
1649 | /* find string offset */ | ||
1650 | soff = dt_find_string(RELOC(pname)); | ||
1651 | if (soff == 0) { | ||
1652 | prom_printf("WARNING: Can't find string index for" | ||
1653 | " <%s>, node %s\n", RELOC(pname), path); | ||
1654 | break; | ||
1655 | } | ||
1656 | prev_name = sstart + soff; | ||
1657 | |||
1658 | /* get length */ | ||
1659 | l = call_prom("getproplen", 2, 1, node, RELOC(pname)); | ||
1660 | |||
1661 | /* sanity checks */ | ||
1662 | if (l == PROM_ERROR) | ||
1663 | continue; | ||
1664 | if (l > MAX_PROPERTY_LENGTH) { | ||
1665 | prom_printf("WARNING: ignoring large property "); | ||
1666 | /* It seems OF doesn't null-terminate the path :-( */ | ||
1667 | prom_printf("[%s] ", path); | ||
1668 | prom_printf("%s length 0x%x\n", RELOC(pname), l); | ||
1669 | continue; | ||
1670 | } | ||
1671 | |||
1672 | /* push property head */ | ||
1673 | dt_push_token(OF_DT_PROP, mem_start, mem_end); | ||
1674 | dt_push_token(l, mem_start, mem_end); | ||
1675 | dt_push_token(soff, mem_start, mem_end); | ||
1676 | |||
1677 | /* push property content */ | ||
1678 | valp = make_room(mem_start, mem_end, l, 4); | ||
1679 | call_prom("getprop", 4, 1, node, RELOC(pname), valp, l); | ||
1680 | *mem_start = _ALIGN(*mem_start, 4); | ||
1681 | } | ||
1682 | |||
1683 | /* Add a "linux,phandle" property. */ | ||
1684 | soff = dt_find_string(RELOC("linux,phandle")); | ||
1685 | if (soff == 0) | ||
1686 | prom_printf("WARNING: Can't find string index for" | ||
1687 | " <linux-phandle> node %s\n", path); | ||
1688 | else { | ||
1689 | dt_push_token(OF_DT_PROP, mem_start, mem_end); | ||
1690 | dt_push_token(4, mem_start, mem_end); | ||
1691 | dt_push_token(soff, mem_start, mem_end); | ||
1692 | valp = make_room(mem_start, mem_end, 4, 4); | ||
1693 | *(u32 *)valp = node; | ||
1694 | } | ||
1695 | |||
1696 | /* do all our children */ | ||
1697 | child = call_prom("child", 1, 1, node); | ||
1698 | while (child != 0) { | ||
1699 | scan_dt_build_struct(child, mem_start, mem_end); | ||
1700 | child = call_prom("peer", 1, 1, child); | ||
1701 | } | ||
1702 | |||
1703 | dt_push_token(OF_DT_END_NODE, mem_start, mem_end); | ||
1704 | } | ||
1705 | |||
1706 | static void __init flatten_device_tree(void) | ||
1707 | { | ||
1708 | phandle root; | ||
1709 | unsigned long offset = reloc_offset(); | ||
1710 | unsigned long mem_start, mem_end, room; | ||
1711 | struct boot_param_header *hdr; | ||
1712 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1713 | char *namep; | ||
1714 | u64 *rsvmap; | ||
1715 | |||
1716 | /* | ||
1717 | * Check how much room we have between alloc top & bottom (+/- a | ||
1718 | * few pages), crop to 4Mb, as this is our "chuck" size | ||
1719 | */ | ||
1720 | room = RELOC(alloc_top) - RELOC(alloc_bottom) - 0x4000; | ||
1721 | if (room > DEVTREE_CHUNK_SIZE) | ||
1722 | room = DEVTREE_CHUNK_SIZE; | ||
1723 | prom_debug("starting device tree allocs at %x\n", RELOC(alloc_bottom)); | ||
1724 | |||
1725 | /* Now try to claim that */ | ||
1726 | mem_start = (unsigned long)alloc_up(room, PAGE_SIZE); | ||
1727 | if (mem_start == 0) | ||
1728 | prom_panic("Can't allocate initial device-tree chunk\n"); | ||
1729 | mem_end = RELOC(alloc_top); | ||
1730 | |||
1731 | /* Get root of tree */ | ||
1732 | root = call_prom("peer", 1, 1, (phandle)0); | ||
1733 | if (root == (phandle)0) | ||
1734 | prom_panic ("couldn't get device tree root\n"); | ||
1735 | |||
1736 | /* Build header and make room for mem rsv map */ | ||
1737 | mem_start = _ALIGN(mem_start, 4); | ||
1738 | hdr = make_room(&mem_start, &mem_end, | ||
1739 | sizeof(struct boot_param_header), 4); | ||
1740 | RELOC(dt_header_start) = (unsigned long)hdr; | ||
1741 | rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8); | ||
1742 | |||
1743 | /* Start of strings */ | ||
1744 | mem_start = PAGE_ALIGN(mem_start); | ||
1745 | RELOC(dt_string_start) = mem_start; | ||
1746 | mem_start += 4; /* hole */ | ||
1747 | |||
1748 | /* Add "linux,phandle" in there, we'll need it */ | ||
1749 | namep = make_room(&mem_start, &mem_end, 16, 1); | ||
1750 | strcpy(namep, RELOC("linux,phandle")); | ||
1751 | mem_start = (unsigned long)namep + strlen(namep) + 1; | ||
1752 | |||
1753 | /* Build string array */ | ||
1754 | prom_printf("Building dt strings...\n"); | ||
1755 | scan_dt_build_strings(root, &mem_start, &mem_end); | ||
1756 | RELOC(dt_string_end) = mem_start; | ||
1757 | |||
1758 | /* Build structure */ | ||
1759 | mem_start = PAGE_ALIGN(mem_start); | ||
1760 | RELOC(dt_struct_start) = mem_start; | ||
1761 | prom_printf("Building dt structure...\n"); | ||
1762 | scan_dt_build_struct(root, &mem_start, &mem_end); | ||
1763 | dt_push_token(OF_DT_END, &mem_start, &mem_end); | ||
1764 | RELOC(dt_struct_end) = PAGE_ALIGN(mem_start); | ||
1765 | |||
1766 | /* Finish header */ | ||
1767 | hdr->boot_cpuid_phys = _prom->cpu; | ||
1768 | hdr->magic = OF_DT_HEADER; | ||
1769 | hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start); | ||
1770 | hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start); | ||
1771 | hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start); | ||
1772 | hdr->dt_strings_size = RELOC(dt_string_end) - RELOC(dt_string_start); | ||
1773 | hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start); | ||
1774 | hdr->version = OF_DT_VERSION; | ||
1775 | /* Version 16 is not backward compatible */ | ||
1776 | hdr->last_comp_version = 0x10; | ||
1777 | |||
1778 | /* Reserve the whole thing and copy the reserve map in, we | ||
1779 | * also bump mem_reserve_cnt to cause further reservations to | ||
1780 | * fail since it's too late. | ||
1781 | */ | ||
1782 | reserve_mem(RELOC(dt_header_start), hdr->totalsize); | ||
1783 | memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map)); | ||
1784 | |||
1785 | #ifdef DEBUG_PROM | ||
1786 | { | ||
1787 | int i; | ||
1788 | prom_printf("reserved memory map:\n"); | ||
1789 | for (i = 0; i < RELOC(mem_reserve_cnt); i++) | ||
1790 | prom_printf(" %x - %x\n", RELOC(mem_reserve_map)[i].base, | ||
1791 | RELOC(mem_reserve_map)[i].size); | ||
1792 | } | ||
1793 | #endif | ||
1794 | RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE; | ||
1795 | |||
1796 | prom_printf("Device tree strings 0x%x -> 0x%x\n", | ||
1797 | RELOC(dt_string_start), RELOC(dt_string_end)); | ||
1798 | prom_printf("Device tree struct 0x%x -> 0x%x\n", | ||
1799 | RELOC(dt_struct_start), RELOC(dt_struct_end)); | ||
1800 | |||
1801 | } | ||
1802 | |||
1803 | |||
1804 | static void __init fixup_device_tree(void) | ||
1805 | { | ||
1806 | unsigned long offset = reloc_offset(); | ||
1807 | phandle u3, i2c, mpic; | ||
1808 | u32 u3_rev; | ||
1809 | u32 interrupts[2]; | ||
1810 | u32 parent; | ||
1811 | |||
1812 | /* Some G5s have a missing interrupt definition, fix it up here */ | ||
1813 | u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000")); | ||
1814 | if (!PHANDLE_VALID(u3)) | ||
1815 | return; | ||
1816 | i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000")); | ||
1817 | if (!PHANDLE_VALID(i2c)) | ||
1818 | return; | ||
1819 | mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000")); | ||
1820 | if (!PHANDLE_VALID(mpic)) | ||
1821 | return; | ||
1822 | |||
1823 | /* check if proper rev of u3 */ | ||
1824 | if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) | ||
1825 | == PROM_ERROR) | ||
1826 | return; | ||
1827 | if (u3_rev < 0x35 || u3_rev > 0x39) | ||
1828 | return; | ||
1829 | /* does it need fixup ? */ | ||
1830 | if (prom_getproplen(i2c, "interrupts") > 0) | ||
1831 | return; | ||
1832 | |||
1833 | prom_printf("fixing up bogus interrupts for u3 i2c...\n"); | ||
1834 | |||
1835 | /* interrupt on this revision of u3 is number 0 and level */ | ||
1836 | interrupts[0] = 0; | ||
1837 | interrupts[1] = 1; | ||
1838 | prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts)); | ||
1839 | parent = (u32)mpic; | ||
1840 | prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent)); | ||
1841 | } | ||
1842 | |||
1843 | |||
1844 | static void __init prom_find_boot_cpu(void) | ||
1845 | { | ||
1846 | unsigned long offset = reloc_offset(); | ||
1847 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1848 | u32 getprop_rval; | ||
1849 | ihandle prom_cpu; | ||
1850 | phandle cpu_pkg; | ||
1851 | |||
1852 | if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(prom_cpu)) <= 0) | ||
1853 | prom_panic("cannot find boot cpu"); | ||
1854 | |||
1855 | cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu); | ||
1856 | |||
1857 | prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval)); | ||
1858 | _prom->cpu = getprop_rval; | ||
1859 | |||
1860 | prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu); | ||
1861 | } | ||
1862 | |||
1863 | static void __init prom_check_initrd(unsigned long r3, unsigned long r4) | ||
1864 | { | ||
1865 | #ifdef CONFIG_BLK_DEV_INITRD | ||
1866 | unsigned long offset = reloc_offset(); | ||
1867 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1868 | |||
1869 | if ( r3 && r4 && r4 != 0xdeadbeef) { | ||
1870 | u64 val; | ||
1871 | |||
1872 | RELOC(prom_initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3; | ||
1873 | RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4; | ||
1874 | |||
1875 | val = (u64)RELOC(prom_initrd_start); | ||
1876 | prom_setprop(_prom->chosen, "linux,initrd-start", &val, sizeof(val)); | ||
1877 | val = (u64)RELOC(prom_initrd_end); | ||
1878 | prom_setprop(_prom->chosen, "linux,initrd-end", &val, sizeof(val)); | ||
1879 | |||
1880 | reserve_mem(RELOC(prom_initrd_start), | ||
1881 | RELOC(prom_initrd_end) - RELOC(prom_initrd_start)); | ||
1882 | |||
1883 | prom_debug("initrd_start=0x%x\n", RELOC(prom_initrd_start)); | ||
1884 | prom_debug("initrd_end=0x%x\n", RELOC(prom_initrd_end)); | ||
1885 | } | ||
1886 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
1887 | } | ||
1888 | |||
1889 | /* | ||
1890 | * We enter here early on, when the Open Firmware prom is still | ||
1891 | * handling exceptions and the MMU hash table for us. | ||
1892 | */ | ||
1893 | |||
1894 | unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long pp, | ||
1895 | unsigned long r6, unsigned long r7) | ||
1896 | { | ||
1897 | unsigned long offset = reloc_offset(); | ||
1898 | struct prom_t *_prom = PTRRELOC(&prom); | ||
1899 | unsigned long phys = KERNELBASE - offset; | ||
1900 | u32 getprop_rval; | ||
1901 | |||
1902 | /* | ||
1903 | * First zero the BSS | ||
1904 | */ | ||
1905 | memset(PTRRELOC(&__bss_start), 0, __bss_stop - __bss_start); | ||
1906 | |||
1907 | /* | ||
1908 | * Init interface to Open Firmware, get some node references, | ||
1909 | * like /chosen | ||
1910 | */ | ||
1911 | prom_init_client_services(pp); | ||
1912 | |||
1913 | /* | ||
1914 | * Init prom stdout device | ||
1915 | */ | ||
1916 | prom_init_stdout(); | ||
1917 | prom_debug("klimit=0x%x\n", RELOC(klimit)); | ||
1918 | prom_debug("offset=0x%x\n", offset); | ||
1919 | |||
1920 | /* | ||
1921 | * Check for an initrd | ||
1922 | */ | ||
1923 | prom_check_initrd(r3, r4); | ||
1924 | |||
1925 | /* | ||
1926 | * Get default machine type. At this point, we do not differenciate | ||
1927 | * between pSeries SMP and pSeries LPAR | ||
1928 | */ | ||
1929 | RELOC(of_platform) = prom_find_machine_type(); | ||
1930 | getprop_rval = RELOC(of_platform); | ||
1931 | prom_setprop(_prom->chosen, "linux,platform", | ||
1932 | &getprop_rval, sizeof(getprop_rval)); | ||
1933 | |||
1934 | /* | ||
1935 | * On pSeries, inform the firmware about our capabilities | ||
1936 | */ | ||
1937 | if (RELOC(of_platform) == PLATFORM_PSERIES || | ||
1938 | RELOC(of_platform) == PLATFORM_PSERIES_LPAR) | ||
1939 | prom_send_capabilities(); | ||
1940 | |||
1941 | /* | ||
1942 | * On pSeries and Cell, copy the CPU hold code | ||
1943 | */ | ||
1944 | if (RELOC(of_platform) & (PLATFORM_PSERIES | PLATFORM_CELL)) | ||
1945 | copy_and_flush(0, KERNELBASE - offset, 0x100, 0); | ||
1946 | |||
1947 | /* | ||
1948 | * Get memory cells format | ||
1949 | */ | ||
1950 | getprop_rval = 1; | ||
1951 | prom_getprop(_prom->root, "#size-cells", | ||
1952 | &getprop_rval, sizeof(getprop_rval)); | ||
1953 | _prom->root_size_cells = getprop_rval; | ||
1954 | getprop_rval = 2; | ||
1955 | prom_getprop(_prom->root, "#address-cells", | ||
1956 | &getprop_rval, sizeof(getprop_rval)); | ||
1957 | _prom->root_addr_cells = getprop_rval; | ||
1958 | |||
1959 | /* | ||
1960 | * Do early parsing of command line | ||
1961 | */ | ||
1962 | early_cmdline_parse(); | ||
1963 | |||
1964 | /* | ||
1965 | * Initialize memory management within prom_init | ||
1966 | */ | ||
1967 | prom_init_mem(); | ||
1968 | |||
1969 | /* | ||
1970 | * Determine which cpu is actually running right _now_ | ||
1971 | */ | ||
1972 | prom_find_boot_cpu(); | ||
1973 | |||
1974 | /* | ||
1975 | * Initialize display devices | ||
1976 | */ | ||
1977 | prom_check_displays(); | ||
1978 | |||
1979 | /* | ||
1980 | * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else | ||
1981 | * that uses the allocator, we need to make sure we get the top of memory | ||
1982 | * available for us here... | ||
1983 | */ | ||
1984 | if (RELOC(of_platform) == PLATFORM_PSERIES) | ||
1985 | prom_initialize_tce_table(); | ||
1986 | |||
1987 | /* | ||
1988 | * On non-powermacs, try to instantiate RTAS and puts all CPUs | ||
1989 | * in spin-loops. PowerMacs don't have a working RTAS and use | ||
1990 | * a different way to spin CPUs | ||
1991 | */ | ||
1992 | if (RELOC(of_platform) != PLATFORM_POWERMAC) { | ||
1993 | prom_instantiate_rtas(); | ||
1994 | prom_hold_cpus(); | ||
1995 | } | ||
1996 | |||
1997 | /* | ||
1998 | * Fill in some infos for use by the kernel later on | ||
1999 | */ | ||
2000 | if (RELOC(ppc64_iommu_off)) | ||
2001 | prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0); | ||
2002 | |||
2003 | if (RELOC(iommu_force_on)) | ||
2004 | prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0); | ||
2005 | |||
2006 | if (RELOC(prom_memory_limit)) | ||
2007 | prom_setprop(_prom->chosen, "linux,memory-limit", | ||
2008 | PTRRELOC(&prom_memory_limit), sizeof(RELOC(prom_memory_limit))); | ||
2009 | |||
2010 | if (RELOC(prom_tce_alloc_start)) { | ||
2011 | prom_setprop(_prom->chosen, "linux,tce-alloc-start", | ||
2012 | PTRRELOC(&prom_tce_alloc_start), sizeof(RELOC(prom_tce_alloc_start))); | ||
2013 | prom_setprop(_prom->chosen, "linux,tce-alloc-end", | ||
2014 | PTRRELOC(&prom_tce_alloc_end), sizeof(RELOC(prom_tce_alloc_end))); | ||
2015 | } | ||
2016 | |||
2017 | /* | ||
2018 | * Fixup any known bugs in the device-tree | ||
2019 | */ | ||
2020 | fixup_device_tree(); | ||
2021 | |||
2022 | /* | ||
2023 | * Now finally create the flattened device-tree | ||
2024 | */ | ||
2025 | prom_printf("copying OF device tree ...\n"); | ||
2026 | flatten_device_tree(); | ||
2027 | |||
2028 | /* in case stdin is USB and still active on IBM machines... */ | ||
2029 | prom_close_stdin(); | ||
2030 | |||
2031 | /* | ||
2032 | * Call OF "quiesce" method to shut down pending DMA's from | ||
2033 | * devices etc... | ||
2034 | */ | ||
2035 | prom_printf("Calling quiesce ...\n"); | ||
2036 | call_prom("quiesce", 0, 0); | ||
2037 | |||
2038 | /* | ||
2039 | * And finally, call the kernel passing it the flattened device | ||
2040 | * tree and NULL as r5, thus triggering the new entry point which | ||
2041 | * is common to us and kexec | ||
2042 | */ | ||
2043 | prom_printf("returning from prom_init\n"); | ||
2044 | prom_debug("->dt_header_start=0x%x\n", RELOC(dt_header_start)); | ||
2045 | prom_debug("->phys=0x%x\n", phys); | ||
2046 | |||
2047 | __start(RELOC(dt_header_start), phys, 0); | ||
2048 | |||
2049 | return 0; | ||
2050 | } | ||
2051 | |||
diff --git a/arch/ppc64/kernel/semaphore.c b/arch/ppc64/kernel/semaphore.c deleted file mode 100644 index a1c1db573e9c..000000000000 --- a/arch/ppc64/kernel/semaphore.c +++ /dev/null | |||
@@ -1,136 +0,0 @@ | |||
1 | /* | ||
2 | * | ||
3 | * | ||
4 | * PowerPC-specific semaphore code. | ||
5 | * | ||
6 | * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * April 2001 - Reworked by Paul Mackerras <paulus@samba.org> | ||
14 | * to eliminate the SMP races in the old version between the updates | ||
15 | * of `count' and `waking'. Now we use negative `count' values to | ||
16 | * indicate that some process(es) are waiting for the semaphore. | ||
17 | */ | ||
18 | |||
19 | #include <linux/sched.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/module.h> | ||
22 | |||
23 | #include <asm/atomic.h> | ||
24 | #include <asm/semaphore.h> | ||
25 | #include <asm/errno.h> | ||
26 | |||
27 | /* | ||
28 | * Atomically update sem->count. | ||
29 | * This does the equivalent of the following: | ||
30 | * | ||
31 | * old_count = sem->count; | ||
32 | * tmp = MAX(old_count, 0) + incr; | ||
33 | * sem->count = tmp; | ||
34 | * return old_count; | ||
35 | */ | ||
36 | static inline int __sem_update_count(struct semaphore *sem, int incr) | ||
37 | { | ||
38 | int old_count, tmp; | ||
39 | |||
40 | __asm__ __volatile__("\n" | ||
41 | "1: lwarx %0,0,%3\n" | ||
42 | " srawi %1,%0,31\n" | ||
43 | " andc %1,%0,%1\n" | ||
44 | " add %1,%1,%4\n" | ||
45 | " stwcx. %1,0,%3\n" | ||
46 | " bne 1b" | ||
47 | : "=&r" (old_count), "=&r" (tmp), "=m" (sem->count) | ||
48 | : "r" (&sem->count), "r" (incr), "m" (sem->count) | ||
49 | : "cc"); | ||
50 | |||
51 | return old_count; | ||
52 | } | ||
53 | |||
54 | void __up(struct semaphore *sem) | ||
55 | { | ||
56 | /* | ||
57 | * Note that we incremented count in up() before we came here, | ||
58 | * but that was ineffective since the result was <= 0, and | ||
59 | * any negative value of count is equivalent to 0. | ||
60 | * This ends up setting count to 1, unless count is now > 0 | ||
61 | * (i.e. because some other cpu has called up() in the meantime), | ||
62 | * in which case we just increment count. | ||
63 | */ | ||
64 | __sem_update_count(sem, 1); | ||
65 | wake_up(&sem->wait); | ||
66 | } | ||
67 | EXPORT_SYMBOL(__up); | ||
68 | |||
69 | /* | ||
70 | * Note that when we come in to __down or __down_interruptible, | ||
71 | * we have already decremented count, but that decrement was | ||
72 | * ineffective since the result was < 0, and any negative value | ||
73 | * of count is equivalent to 0. | ||
74 | * Thus it is only when we decrement count from some value > 0 | ||
75 | * that we have actually got the semaphore. | ||
76 | */ | ||
77 | void __sched __down(struct semaphore *sem) | ||
78 | { | ||
79 | struct task_struct *tsk = current; | ||
80 | DECLARE_WAITQUEUE(wait, tsk); | ||
81 | |||
82 | __set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
83 | add_wait_queue_exclusive(&sem->wait, &wait); | ||
84 | |||
85 | /* | ||
86 | * Try to get the semaphore. If the count is > 0, then we've | ||
87 | * got the semaphore; we decrement count and exit the loop. | ||
88 | * If the count is 0 or negative, we set it to -1, indicating | ||
89 | * that we are asleep, and then sleep. | ||
90 | */ | ||
91 | while (__sem_update_count(sem, -1) <= 0) { | ||
92 | schedule(); | ||
93 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | ||
94 | } | ||
95 | remove_wait_queue(&sem->wait, &wait); | ||
96 | __set_task_state(tsk, TASK_RUNNING); | ||
97 | |||
98 | /* | ||
99 | * If there are any more sleepers, wake one of them up so | ||
100 | * that it can either get the semaphore, or set count to -1 | ||
101 | * indicating that there are still processes sleeping. | ||
102 | */ | ||
103 | wake_up(&sem->wait); | ||
104 | } | ||
105 | EXPORT_SYMBOL(__down); | ||
106 | |||
107 | int __sched __down_interruptible(struct semaphore * sem) | ||
108 | { | ||
109 | int retval = 0; | ||
110 | struct task_struct *tsk = current; | ||
111 | DECLARE_WAITQUEUE(wait, tsk); | ||
112 | |||
113 | __set_task_state(tsk, TASK_INTERRUPTIBLE); | ||
114 | add_wait_queue_exclusive(&sem->wait, &wait); | ||
115 | |||
116 | while (__sem_update_count(sem, -1) <= 0) { | ||
117 | if (signal_pending(current)) { | ||
118 | /* | ||
119 | * A signal is pending - give up trying. | ||
120 | * Set sem->count to 0 if it is negative, | ||
121 | * since we are no longer sleeping. | ||
122 | */ | ||
123 | __sem_update_count(sem, 0); | ||
124 | retval = -EINTR; | ||
125 | break; | ||
126 | } | ||
127 | schedule(); | ||
128 | set_task_state(tsk, TASK_INTERRUPTIBLE); | ||
129 | } | ||
130 | remove_wait_queue(&sem->wait, &wait); | ||
131 | __set_task_state(tsk, TASK_RUNNING); | ||
132 | |||
133 | wake_up(&sem->wait); | ||
134 | return retval; | ||
135 | } | ||
136 | EXPORT_SYMBOL(__down_interruptible); | ||
diff --git a/arch/ppc64/kernel/vdso.c b/arch/ppc64/kernel/vdso.c deleted file mode 100644 index 1bbacac44988..000000000000 --- a/arch/ppc64/kernel/vdso.c +++ /dev/null | |||
@@ -1,625 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/ppc64/kernel/vdso.c | ||
3 | * | ||
4 | * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp. | ||
5 | * <benh@kernel.crashing.org> | ||
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/config.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/errno.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/mm.h> | ||
19 | #include <linux/smp.h> | ||
20 | #include <linux/smp_lock.h> | ||
21 | #include <linux/stddef.h> | ||
22 | #include <linux/unistd.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/user.h> | ||
25 | #include <linux/elf.h> | ||
26 | #include <linux/security.h> | ||
27 | #include <linux/bootmem.h> | ||
28 | |||
29 | #include <asm/pgtable.h> | ||
30 | #include <asm/system.h> | ||
31 | #include <asm/processor.h> | ||
32 | #include <asm/mmu.h> | ||
33 | #include <asm/mmu_context.h> | ||
34 | #include <asm/machdep.h> | ||
35 | #include <asm/cputable.h> | ||
36 | #include <asm/sections.h> | ||
37 | #include <asm/systemcfg.h> | ||
38 | #include <asm/vdso.h> | ||
39 | |||
40 | #undef DEBUG | ||
41 | |||
42 | #ifdef DEBUG | ||
43 | #define DBG(fmt...) printk(fmt) | ||
44 | #else | ||
45 | #define DBG(fmt...) | ||
46 | #endif | ||
47 | |||
48 | |||
49 | /* | ||
50 | * The vDSOs themselves are here | ||
51 | */ | ||
52 | extern char vdso64_start, vdso64_end; | ||
53 | extern char vdso32_start, vdso32_end; | ||
54 | |||
55 | static void *vdso64_kbase = &vdso64_start; | ||
56 | static void *vdso32_kbase = &vdso32_start; | ||
57 | |||
58 | unsigned int vdso64_pages; | ||
59 | unsigned int vdso32_pages; | ||
60 | |||
61 | /* Signal trampolines user addresses */ | ||
62 | |||
63 | unsigned long vdso64_rt_sigtramp; | ||
64 | unsigned long vdso32_sigtramp; | ||
65 | unsigned long vdso32_rt_sigtramp; | ||
66 | |||
67 | /* Format of the patch table */ | ||
68 | struct vdso_patch_def | ||
69 | { | ||
70 | u32 pvr_mask, pvr_value; | ||
71 | const char *gen_name; | ||
72 | const char *fix_name; | ||
73 | }; | ||
74 | |||
75 | /* Table of functions to patch based on the CPU type/revision | ||
76 | * | ||
77 | * TODO: Improve by adding whole lists for each entry | ||
78 | */ | ||
79 | static struct vdso_patch_def vdso_patches[] = { | ||
80 | { | ||
81 | 0xffff0000, 0x003a0000, /* POWER5 */ | ||
82 | "__kernel_sync_dicache", "__kernel_sync_dicache_p5" | ||
83 | }, | ||
84 | { | ||
85 | 0xffff0000, 0x003b0000, /* POWER5 */ | ||
86 | "__kernel_sync_dicache", "__kernel_sync_dicache_p5" | ||
87 | }, | ||
88 | }; | ||
89 | |||
90 | /* | ||
91 | * Some infos carried around for each of them during parsing at | ||
92 | * boot time. | ||
93 | */ | ||
94 | struct lib32_elfinfo | ||
95 | { | ||
96 | Elf32_Ehdr *hdr; /* ptr to ELF */ | ||
97 | Elf32_Sym *dynsym; /* ptr to .dynsym section */ | ||
98 | unsigned long dynsymsize; /* size of .dynsym section */ | ||
99 | char *dynstr; /* ptr to .dynstr section */ | ||
100 | unsigned long text; /* offset of .text section in .so */ | ||
101 | }; | ||
102 | |||
103 | struct lib64_elfinfo | ||
104 | { | ||
105 | Elf64_Ehdr *hdr; | ||
106 | Elf64_Sym *dynsym; | ||
107 | unsigned long dynsymsize; | ||
108 | char *dynstr; | ||
109 | unsigned long text; | ||
110 | }; | ||
111 | |||
112 | |||
113 | #ifdef __DEBUG | ||
114 | static void dump_one_vdso_page(struct page *pg, struct page *upg) | ||
115 | { | ||
116 | printk("kpg: %p (c:%d,f:%08lx)", __va(page_to_pfn(pg) << PAGE_SHIFT), | ||
117 | page_count(pg), | ||
118 | pg->flags); | ||
119 | if (upg/* && pg != upg*/) { | ||
120 | printk(" upg: %p (c:%d,f:%08lx)", __va(page_to_pfn(upg) << PAGE_SHIFT), | ||
121 | page_count(upg), | ||
122 | upg->flags); | ||
123 | } | ||
124 | printk("\n"); | ||
125 | } | ||
126 | |||
127 | static void dump_vdso_pages(struct vm_area_struct * vma) | ||
128 | { | ||
129 | int i; | ||
130 | |||
131 | if (!vma || test_thread_flag(TIF_32BIT)) { | ||
132 | printk("vDSO32 @ %016lx:\n", (unsigned long)vdso32_kbase); | ||
133 | for (i=0; i<vdso32_pages; i++) { | ||
134 | struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE); | ||
135 | struct page *upg = (vma && vma->vm_mm) ? | ||
136 | follow_page(vma->vm_mm, vma->vm_start + i*PAGE_SIZE, 0) | ||
137 | : NULL; | ||
138 | dump_one_vdso_page(pg, upg); | ||
139 | } | ||
140 | } | ||
141 | if (!vma || !test_thread_flag(TIF_32BIT)) { | ||
142 | printk("vDSO64 @ %016lx:\n", (unsigned long)vdso64_kbase); | ||
143 | for (i=0; i<vdso64_pages; i++) { | ||
144 | struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE); | ||
145 | struct page *upg = (vma && vma->vm_mm) ? | ||
146 | follow_page(vma->vm_mm, vma->vm_start + i*PAGE_SIZE, 0) | ||
147 | : NULL; | ||
148 | dump_one_vdso_page(pg, upg); | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | #endif /* DEBUG */ | ||
153 | |||
154 | /* | ||
155 | * Keep a dummy vma_close for now, it will prevent VMA merging. | ||
156 | */ | ||
157 | static void vdso_vma_close(struct vm_area_struct * vma) | ||
158 | { | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Our nopage() function, maps in the actual vDSO kernel pages, they will | ||
163 | * be mapped read-only by do_no_page(), and eventually COW'ed, either | ||
164 | * right away for an initial write access, or by do_wp_page(). | ||
165 | */ | ||
166 | static struct page * vdso_vma_nopage(struct vm_area_struct * vma, | ||
167 | unsigned long address, int *type) | ||
168 | { | ||
169 | unsigned long offset = address - vma->vm_start; | ||
170 | struct page *pg; | ||
171 | void *vbase = test_thread_flag(TIF_32BIT) ? vdso32_kbase : vdso64_kbase; | ||
172 | |||
173 | DBG("vdso_vma_nopage(current: %s, address: %016lx, off: %lx)\n", | ||
174 | current->comm, address, offset); | ||
175 | |||
176 | if (address < vma->vm_start || address > vma->vm_end) | ||
177 | return NOPAGE_SIGBUS; | ||
178 | |||
179 | /* | ||
180 | * Last page is systemcfg. | ||
181 | */ | ||
182 | if ((vma->vm_end - address) <= PAGE_SIZE) | ||
183 | pg = virt_to_page(_systemcfg); | ||
184 | else | ||
185 | pg = virt_to_page(vbase + offset); | ||
186 | |||
187 | get_page(pg); | ||
188 | DBG(" ->page count: %d\n", page_count(pg)); | ||
189 | |||
190 | return pg; | ||
191 | } | ||
192 | |||
193 | static struct vm_operations_struct vdso_vmops = { | ||
194 | .close = vdso_vma_close, | ||
195 | .nopage = vdso_vma_nopage, | ||
196 | }; | ||
197 | |||
198 | /* | ||
199 | * This is called from binfmt_elf, we create the special vma for the | ||
200 | * vDSO and insert it into the mm struct tree | ||
201 | */ | ||
202 | int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack) | ||
203 | { | ||
204 | struct mm_struct *mm = current->mm; | ||
205 | struct vm_area_struct *vma; | ||
206 | unsigned long vdso_pages; | ||
207 | unsigned long vdso_base; | ||
208 | |||
209 | if (test_thread_flag(TIF_32BIT)) { | ||
210 | vdso_pages = vdso32_pages; | ||
211 | vdso_base = VDSO32_MBASE; | ||
212 | } else { | ||
213 | vdso_pages = vdso64_pages; | ||
214 | vdso_base = VDSO64_MBASE; | ||
215 | } | ||
216 | |||
217 | current->thread.vdso_base = 0; | ||
218 | |||
219 | /* vDSO has a problem and was disabled, just don't "enable" it for the | ||
220 | * process | ||
221 | */ | ||
222 | if (vdso_pages == 0) | ||
223 | return 0; | ||
224 | |||
225 | vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); | ||
226 | if (vma == NULL) | ||
227 | return -ENOMEM; | ||
228 | |||
229 | memset(vma, 0, sizeof(*vma)); | ||
230 | |||
231 | /* | ||
232 | * pick a base address for the vDSO in process space. We try to put it | ||
233 | * at vdso_base which is the "natural" base for it, but we might fail | ||
234 | * and end up putting it elsewhere. | ||
235 | */ | ||
236 | vdso_base = get_unmapped_area(NULL, vdso_base, | ||
237 | vdso_pages << PAGE_SHIFT, 0, 0); | ||
238 | if (vdso_base & ~PAGE_MASK) { | ||
239 | kmem_cache_free(vm_area_cachep, vma); | ||
240 | return (int)vdso_base; | ||
241 | } | ||
242 | |||
243 | current->thread.vdso_base = vdso_base; | ||
244 | |||
245 | vma->vm_mm = mm; | ||
246 | vma->vm_start = current->thread.vdso_base; | ||
247 | |||
248 | /* | ||
249 | * the VMA size is one page more than the vDSO since systemcfg | ||
250 | * is mapped in the last one | ||
251 | */ | ||
252 | vma->vm_end = vma->vm_start + ((vdso_pages + 1) << PAGE_SHIFT); | ||
253 | |||
254 | /* | ||
255 | * our vma flags don't have VM_WRITE so by default, the process isn't allowed | ||
256 | * to write those pages. | ||
257 | * gdb can break that with ptrace interface, and thus trigger COW on those | ||
258 | * pages but it's then your responsibility to never do that on the "data" page | ||
259 | * of the vDSO or you'll stop getting kernel updates and your nice userland | ||
260 | * gettimeofday will be totally dead. It's fine to use that for setting | ||
261 | * breakpoints in the vDSO code pages though | ||
262 | */ | ||
263 | vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC | VM_RESERVED; | ||
264 | vma->vm_flags |= mm->def_flags; | ||
265 | vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; | ||
266 | vma->vm_ops = &vdso_vmops; | ||
267 | |||
268 | down_write(&mm->mmap_sem); | ||
269 | if (insert_vm_struct(mm, vma)) { | ||
270 | up_write(&mm->mmap_sem); | ||
271 | kmem_cache_free(vm_area_cachep, vma); | ||
272 | return -ENOMEM; | ||
273 | } | ||
274 | mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; | ||
275 | up_write(&mm->mmap_sem); | ||
276 | |||
277 | return 0; | ||
278 | } | ||
279 | |||
280 | static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname, | ||
281 | unsigned long *size) | ||
282 | { | ||
283 | Elf32_Shdr *sechdrs; | ||
284 | unsigned int i; | ||
285 | char *secnames; | ||
286 | |||
287 | /* Grab section headers and strings so we can tell who is who */ | ||
288 | sechdrs = (void *)ehdr + ehdr->e_shoff; | ||
289 | secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset; | ||
290 | |||
291 | /* Find the section they want */ | ||
292 | for (i = 1; i < ehdr->e_shnum; i++) { | ||
293 | if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) { | ||
294 | if (size) | ||
295 | *size = sechdrs[i].sh_size; | ||
296 | return (void *)ehdr + sechdrs[i].sh_offset; | ||
297 | } | ||
298 | } | ||
299 | *size = 0; | ||
300 | return NULL; | ||
301 | } | ||
302 | |||
303 | static void * __init find_section64(Elf64_Ehdr *ehdr, const char *secname, | ||
304 | unsigned long *size) | ||
305 | { | ||
306 | Elf64_Shdr *sechdrs; | ||
307 | unsigned int i; | ||
308 | char *secnames; | ||
309 | |||
310 | /* Grab section headers and strings so we can tell who is who */ | ||
311 | sechdrs = (void *)ehdr + ehdr->e_shoff; | ||
312 | secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset; | ||
313 | |||
314 | /* Find the section they want */ | ||
315 | for (i = 1; i < ehdr->e_shnum; i++) { | ||
316 | if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) { | ||
317 | if (size) | ||
318 | *size = sechdrs[i].sh_size; | ||
319 | return (void *)ehdr + sechdrs[i].sh_offset; | ||
320 | } | ||
321 | } | ||
322 | if (size) | ||
323 | *size = 0; | ||
324 | return NULL; | ||
325 | } | ||
326 | |||
327 | static Elf32_Sym * __init find_symbol32(struct lib32_elfinfo *lib, const char *symname) | ||
328 | { | ||
329 | unsigned int i; | ||
330 | char name[32], *c; | ||
331 | |||
332 | for (i = 0; i < (lib->dynsymsize / sizeof(Elf32_Sym)); i++) { | ||
333 | if (lib->dynsym[i].st_name == 0) | ||
334 | continue; | ||
335 | strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, 32); | ||
336 | c = strchr(name, '@'); | ||
337 | if (c) | ||
338 | *c = 0; | ||
339 | if (strcmp(symname, name) == 0) | ||
340 | return &lib->dynsym[i]; | ||
341 | } | ||
342 | return NULL; | ||
343 | } | ||
344 | |||
345 | static Elf64_Sym * __init find_symbol64(struct lib64_elfinfo *lib, const char *symname) | ||
346 | { | ||
347 | unsigned int i; | ||
348 | char name[32], *c; | ||
349 | |||
350 | for (i = 0; i < (lib->dynsymsize / sizeof(Elf64_Sym)); i++) { | ||
351 | if (lib->dynsym[i].st_name == 0) | ||
352 | continue; | ||
353 | strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, 32); | ||
354 | c = strchr(name, '@'); | ||
355 | if (c) | ||
356 | *c = 0; | ||
357 | if (strcmp(symname, name) == 0) | ||
358 | return &lib->dynsym[i]; | ||
359 | } | ||
360 | return NULL; | ||
361 | } | ||
362 | |||
363 | /* Note that we assume the section is .text and the symbol is relative to | ||
364 | * the library base | ||
365 | */ | ||
366 | static unsigned long __init find_function32(struct lib32_elfinfo *lib, const char *symname) | ||
367 | { | ||
368 | Elf32_Sym *sym = find_symbol32(lib, symname); | ||
369 | |||
370 | if (sym == NULL) { | ||
371 | printk(KERN_WARNING "vDSO32: function %s not found !\n", symname); | ||
372 | return 0; | ||
373 | } | ||
374 | return sym->st_value - VDSO32_LBASE; | ||
375 | } | ||
376 | |||
377 | /* Note that we assume the section is .text and the symbol is relative to | ||
378 | * the library base | ||
379 | */ | ||
380 | static unsigned long __init find_function64(struct lib64_elfinfo *lib, const char *symname) | ||
381 | { | ||
382 | Elf64_Sym *sym = find_symbol64(lib, symname); | ||
383 | |||
384 | if (sym == NULL) { | ||
385 | printk(KERN_WARNING "vDSO64: function %s not found !\n", symname); | ||
386 | return 0; | ||
387 | } | ||
388 | #ifdef VDS64_HAS_DESCRIPTORS | ||
389 | return *((u64 *)(vdso64_kbase + sym->st_value - VDSO64_LBASE)) - VDSO64_LBASE; | ||
390 | #else | ||
391 | return sym->st_value - VDSO64_LBASE; | ||
392 | #endif | ||
393 | } | ||
394 | |||
395 | |||
396 | static __init int vdso_do_find_sections(struct lib32_elfinfo *v32, | ||
397 | struct lib64_elfinfo *v64) | ||
398 | { | ||
399 | void *sect; | ||
400 | |||
401 | /* | ||
402 | * Locate symbol tables & text section | ||
403 | */ | ||
404 | |||
405 | v32->dynsym = find_section32(v32->hdr, ".dynsym", &v32->dynsymsize); | ||
406 | v32->dynstr = find_section32(v32->hdr, ".dynstr", NULL); | ||
407 | if (v32->dynsym == NULL || v32->dynstr == NULL) { | ||
408 | printk(KERN_ERR "vDSO32: a required symbol section was not found\n"); | ||
409 | return -1; | ||
410 | } | ||
411 | sect = find_section32(v32->hdr, ".text", NULL); | ||
412 | if (sect == NULL) { | ||
413 | printk(KERN_ERR "vDSO32: the .text section was not found\n"); | ||
414 | return -1; | ||
415 | } | ||
416 | v32->text = sect - vdso32_kbase; | ||
417 | |||
418 | v64->dynsym = find_section64(v64->hdr, ".dynsym", &v64->dynsymsize); | ||
419 | v64->dynstr = find_section64(v64->hdr, ".dynstr", NULL); | ||
420 | if (v64->dynsym == NULL || v64->dynstr == NULL) { | ||
421 | printk(KERN_ERR "vDSO64: a required symbol section was not found\n"); | ||
422 | return -1; | ||
423 | } | ||
424 | sect = find_section64(v64->hdr, ".text", NULL); | ||
425 | if (sect == NULL) { | ||
426 | printk(KERN_ERR "vDSO64: the .text section was not found\n"); | ||
427 | return -1; | ||
428 | } | ||
429 | v64->text = sect - vdso64_kbase; | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | static __init void vdso_setup_trampolines(struct lib32_elfinfo *v32, | ||
435 | struct lib64_elfinfo *v64) | ||
436 | { | ||
437 | /* | ||
438 | * Find signal trampolines | ||
439 | */ | ||
440 | |||
441 | vdso64_rt_sigtramp = find_function64(v64, "__kernel_sigtramp_rt64"); | ||
442 | vdso32_sigtramp = find_function32(v32, "__kernel_sigtramp32"); | ||
443 | vdso32_rt_sigtramp = find_function32(v32, "__kernel_sigtramp_rt32"); | ||
444 | } | ||
445 | |||
446 | static __init int vdso_fixup_datapage(struct lib32_elfinfo *v32, | ||
447 | struct lib64_elfinfo *v64) | ||
448 | { | ||
449 | Elf32_Sym *sym32; | ||
450 | Elf64_Sym *sym64; | ||
451 | |||
452 | sym32 = find_symbol32(v32, "__kernel_datapage_offset"); | ||
453 | if (sym32 == NULL) { | ||
454 | printk(KERN_ERR "vDSO32: Can't find symbol __kernel_datapage_offset !\n"); | ||
455 | return -1; | ||
456 | } | ||
457 | *((int *)(vdso32_kbase + (sym32->st_value - VDSO32_LBASE))) = | ||
458 | (vdso32_pages << PAGE_SHIFT) - (sym32->st_value - VDSO32_LBASE); | ||
459 | |||
460 | sym64 = find_symbol64(v64, "__kernel_datapage_offset"); | ||
461 | if (sym64 == NULL) { | ||
462 | printk(KERN_ERR "vDSO64: Can't find symbol __kernel_datapage_offset !\n"); | ||
463 | return -1; | ||
464 | } | ||
465 | *((int *)(vdso64_kbase + sym64->st_value - VDSO64_LBASE)) = | ||
466 | (vdso64_pages << PAGE_SHIFT) - (sym64->st_value - VDSO64_LBASE); | ||
467 | |||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int vdso_do_func_patch32(struct lib32_elfinfo *v32, | ||
472 | struct lib64_elfinfo *v64, | ||
473 | const char *orig, const char *fix) | ||
474 | { | ||
475 | Elf32_Sym *sym32_gen, *sym32_fix; | ||
476 | |||
477 | sym32_gen = find_symbol32(v32, orig); | ||
478 | if (sym32_gen == NULL) { | ||
479 | printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", orig); | ||
480 | return -1; | ||
481 | } | ||
482 | sym32_fix = find_symbol32(v32, fix); | ||
483 | if (sym32_fix == NULL) { | ||
484 | printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", fix); | ||
485 | return -1; | ||
486 | } | ||
487 | sym32_gen->st_value = sym32_fix->st_value; | ||
488 | sym32_gen->st_size = sym32_fix->st_size; | ||
489 | sym32_gen->st_info = sym32_fix->st_info; | ||
490 | sym32_gen->st_other = sym32_fix->st_other; | ||
491 | sym32_gen->st_shndx = sym32_fix->st_shndx; | ||
492 | |||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | static int vdso_do_func_patch64(struct lib32_elfinfo *v32, | ||
497 | struct lib64_elfinfo *v64, | ||
498 | const char *orig, const char *fix) | ||
499 | { | ||
500 | Elf64_Sym *sym64_gen, *sym64_fix; | ||
501 | |||
502 | sym64_gen = find_symbol64(v64, orig); | ||
503 | if (sym64_gen == NULL) { | ||
504 | printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", orig); | ||
505 | return -1; | ||
506 | } | ||
507 | sym64_fix = find_symbol64(v64, fix); | ||
508 | if (sym64_fix == NULL) { | ||
509 | printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", fix); | ||
510 | return -1; | ||
511 | } | ||
512 | sym64_gen->st_value = sym64_fix->st_value; | ||
513 | sym64_gen->st_size = sym64_fix->st_size; | ||
514 | sym64_gen->st_info = sym64_fix->st_info; | ||
515 | sym64_gen->st_other = sym64_fix->st_other; | ||
516 | sym64_gen->st_shndx = sym64_fix->st_shndx; | ||
517 | |||
518 | return 0; | ||
519 | } | ||
520 | |||
521 | static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32, | ||
522 | struct lib64_elfinfo *v64) | ||
523 | { | ||
524 | u32 pvr; | ||
525 | int i; | ||
526 | |||
527 | pvr = mfspr(SPRN_PVR); | ||
528 | for (i = 0; i < ARRAY_SIZE(vdso_patches); i++) { | ||
529 | struct vdso_patch_def *patch = &vdso_patches[i]; | ||
530 | int match = (pvr & patch->pvr_mask) == patch->pvr_value; | ||
531 | |||
532 | DBG("patch %d (mask: %x, pvr: %x) : %s\n", | ||
533 | i, patch->pvr_mask, patch->pvr_value, match ? "match" : "skip"); | ||
534 | |||
535 | if (!match) | ||
536 | continue; | ||
537 | |||
538 | DBG("replacing %s with %s...\n", patch->gen_name, patch->fix_name); | ||
539 | |||
540 | /* | ||
541 | * Patch the 32 bits and 64 bits symbols. Note that we do not patch | ||
542 | * the "." symbol on 64 bits. It would be easy to do, but doesn't | ||
543 | * seem to be necessary, patching the OPD symbol is enough. | ||
544 | */ | ||
545 | vdso_do_func_patch32(v32, v64, patch->gen_name, patch->fix_name); | ||
546 | vdso_do_func_patch64(v32, v64, patch->gen_name, patch->fix_name); | ||
547 | } | ||
548 | |||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | |||
553 | static __init int vdso_setup(void) | ||
554 | { | ||
555 | struct lib32_elfinfo v32; | ||
556 | struct lib64_elfinfo v64; | ||
557 | |||
558 | v32.hdr = vdso32_kbase; | ||
559 | v64.hdr = vdso64_kbase; | ||
560 | |||
561 | if (vdso_do_find_sections(&v32, &v64)) | ||
562 | return -1; | ||
563 | |||
564 | if (vdso_fixup_datapage(&v32, &v64)) | ||
565 | return -1; | ||
566 | |||
567 | if (vdso_fixup_alt_funcs(&v32, &v64)) | ||
568 | return -1; | ||
569 | |||
570 | vdso_setup_trampolines(&v32, &v64); | ||
571 | |||
572 | return 0; | ||
573 | } | ||
574 | |||
575 | void __init vdso_init(void) | ||
576 | { | ||
577 | int i; | ||
578 | |||
579 | vdso64_pages = (&vdso64_end - &vdso64_start) >> PAGE_SHIFT; | ||
580 | vdso32_pages = (&vdso32_end - &vdso32_start) >> PAGE_SHIFT; | ||
581 | |||
582 | DBG("vdso64_kbase: %p, 0x%x pages, vdso32_kbase: %p, 0x%x pages\n", | ||
583 | vdso64_kbase, vdso64_pages, vdso32_kbase, vdso32_pages); | ||
584 | |||
585 | /* | ||
586 | * Initialize the vDSO images in memory, that is do necessary | ||
587 | * fixups of vDSO symbols, locate trampolines, etc... | ||
588 | */ | ||
589 | if (vdso_setup()) { | ||
590 | printk(KERN_ERR "vDSO setup failure, not enabled !\n"); | ||
591 | /* XXX should free pages here ? */ | ||
592 | vdso64_pages = vdso32_pages = 0; | ||
593 | return; | ||
594 | } | ||
595 | |||
596 | /* Make sure pages are in the correct state */ | ||
597 | for (i = 0; i < vdso64_pages; i++) { | ||
598 | struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE); | ||
599 | ClearPageReserved(pg); | ||
600 | get_page(pg); | ||
601 | } | ||
602 | for (i = 0; i < vdso32_pages; i++) { | ||
603 | struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE); | ||
604 | ClearPageReserved(pg); | ||
605 | get_page(pg); | ||
606 | } | ||
607 | |||
608 | get_page(virt_to_page(_systemcfg)); | ||
609 | } | ||
610 | |||
611 | int in_gate_area_no_task(unsigned long addr) | ||
612 | { | ||
613 | return 0; | ||
614 | } | ||
615 | |||
616 | int in_gate_area(struct task_struct *task, unsigned long addr) | ||
617 | { | ||
618 | return 0; | ||
619 | } | ||
620 | |||
621 | struct vm_area_struct *get_gate_vma(struct task_struct *tsk) | ||
622 | { | ||
623 | return NULL; | ||
624 | } | ||
625 | |||
diff --git a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S deleted file mode 100644 index 022f220e772f..000000000000 --- a/arch/ppc64/kernel/vmlinux.lds.S +++ /dev/null | |||
@@ -1,151 +0,0 @@ | |||
1 | #include <asm/page.h> | ||
2 | #include <asm-generic/vmlinux.lds.h> | ||
3 | |||
4 | OUTPUT_ARCH(powerpc:common64) | ||
5 | jiffies = jiffies_64; | ||
6 | SECTIONS | ||
7 | { | ||
8 | /* Sections to be discarded. */ | ||
9 | /DISCARD/ : { | ||
10 | *(.exitcall.exit) | ||
11 | } | ||
12 | |||
13 | |||
14 | /* Read-only sections, merged into text segment: */ | ||
15 | .text : { | ||
16 | *(.text .text.*) | ||
17 | SCHED_TEXT | ||
18 | LOCK_TEXT | ||
19 | KPROBES_TEXT | ||
20 | *(.fixup) | ||
21 | . = ALIGN(PAGE_SIZE); | ||
22 | _etext = .; | ||
23 | } | ||
24 | |||
25 | __ex_table : { | ||
26 | __start___ex_table = .; | ||
27 | *(__ex_table) | ||
28 | __stop___ex_table = .; | ||
29 | } | ||
30 | |||
31 | __bug_table : { | ||
32 | __start___bug_table = .; | ||
33 | *(__bug_table) | ||
34 | __stop___bug_table = .; | ||
35 | } | ||
36 | |||
37 | __ftr_fixup : { | ||
38 | __start___ftr_fixup = .; | ||
39 | *(__ftr_fixup) | ||
40 | __stop___ftr_fixup = .; | ||
41 | } | ||
42 | |||
43 | RODATA | ||
44 | |||
45 | |||
46 | /* will be freed after init */ | ||
47 | . = ALIGN(PAGE_SIZE); | ||
48 | __init_begin = .; | ||
49 | |||
50 | .init.text : { | ||
51 | _sinittext = .; | ||
52 | *(.init.text) | ||
53 | _einittext = .; | ||
54 | } | ||
55 | |||
56 | .init.data : { | ||
57 | *(.init.data) | ||
58 | } | ||
59 | |||
60 | . = ALIGN(16); | ||
61 | .init.setup : { | ||
62 | __setup_start = .; | ||
63 | *(.init.setup) | ||
64 | __setup_end = .; | ||
65 | } | ||
66 | |||
67 | .initcall.init : { | ||
68 | __initcall_start = .; | ||
69 | *(.initcall1.init) | ||
70 | *(.initcall2.init) | ||
71 | *(.initcall3.init) | ||
72 | *(.initcall4.init) | ||
73 | *(.initcall5.init) | ||
74 | *(.initcall6.init) | ||
75 | *(.initcall7.init) | ||
76 | __initcall_end = .; | ||
77 | } | ||
78 | |||
79 | .con_initcall.init : { | ||
80 | __con_initcall_start = .; | ||
81 | *(.con_initcall.init) | ||
82 | __con_initcall_end = .; | ||
83 | } | ||
84 | |||
85 | SECURITY_INIT | ||
86 | |||
87 | . = ALIGN(PAGE_SIZE); | ||
88 | .init.ramfs : { | ||
89 | __initramfs_start = .; | ||
90 | *(.init.ramfs) | ||
91 | __initramfs_end = .; | ||
92 | } | ||
93 | |||
94 | .data.percpu : { | ||
95 | __per_cpu_start = .; | ||
96 | *(.data.percpu) | ||
97 | __per_cpu_end = .; | ||
98 | } | ||
99 | |||
100 | . = ALIGN(PAGE_SIZE); | ||
101 | . = ALIGN(16384); | ||
102 | __init_end = .; | ||
103 | /* freed after init ends here */ | ||
104 | |||
105 | |||
106 | /* Read/write sections */ | ||
107 | . = ALIGN(PAGE_SIZE); | ||
108 | . = ALIGN(16384); | ||
109 | _sdata = .; | ||
110 | /* The initial task and kernel stack */ | ||
111 | .data.init_task : { | ||
112 | *(.data.init_task) | ||
113 | } | ||
114 | |||
115 | . = ALIGN(PAGE_SIZE); | ||
116 | .data.page_aligned : { | ||
117 | *(.data.page_aligned) | ||
118 | } | ||
119 | |||
120 | .data.cacheline_aligned : { | ||
121 | *(.data.cacheline_aligned) | ||
122 | } | ||
123 | |||
124 | .data : { | ||
125 | *(.data .data.rel* .toc1) | ||
126 | *(.branch_lt) | ||
127 | } | ||
128 | |||
129 | .opd : { | ||
130 | *(.opd) | ||
131 | } | ||
132 | |||
133 | .got : { | ||
134 | __toc_start = .; | ||
135 | *(.got) | ||
136 | *(.toc) | ||
137 | . = ALIGN(PAGE_SIZE); | ||
138 | _edata = .; | ||
139 | } | ||
140 | |||
141 | |||
142 | . = ALIGN(PAGE_SIZE); | ||
143 | .bss : { | ||
144 | __bss_start = .; | ||
145 | *(.bss) | ||
146 | __bss_stop = .; | ||
147 | } | ||
148 | |||
149 | . = ALIGN(PAGE_SIZE); | ||
150 | _end = . ; | ||
151 | } | ||
diff --git a/arch/ppc64/xmon/privinst.h b/arch/ppc64/xmon/privinst.h deleted file mode 100644 index 02eb40dac0b3..000000000000 --- a/arch/ppc64/xmon/privinst.h +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996 Paul Mackerras. | ||
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 | #define GETREG(reg) \ | ||
11 | static inline unsigned long get_ ## reg (void) \ | ||
12 | { unsigned long ret; asm volatile ("mf" #reg " %0" : "=r" (ret) :); return ret; } | ||
13 | |||
14 | #define SETREG(reg) \ | ||
15 | static inline void set_ ## reg (unsigned long val) \ | ||
16 | { asm volatile ("mt" #reg " %0" : : "r" (val)); } | ||
17 | |||
18 | GETREG(msr) | ||
19 | SETREG(msrd) | ||
20 | GETREG(cr) | ||
21 | |||
22 | #define GSETSPR(n, name) \ | ||
23 | static inline long get_ ## name (void) \ | ||
24 | { long ret; asm volatile ("mfspr %0," #n : "=r" (ret) : ); return ret; } \ | ||
25 | static inline void set_ ## name (long val) \ | ||
26 | { asm volatile ("mtspr " #n ",%0" : : "r" (val)); } | ||
27 | |||
28 | GSETSPR(0, mq) | ||
29 | GSETSPR(1, xer) | ||
30 | GSETSPR(4, rtcu) | ||
31 | GSETSPR(5, rtcl) | ||
32 | GSETSPR(8, lr) | ||
33 | GSETSPR(9, ctr) | ||
34 | GSETSPR(18, dsisr) | ||
35 | GSETSPR(19, dar) | ||
36 | GSETSPR(22, dec) | ||
37 | GSETSPR(25, sdr1) | ||
38 | GSETSPR(26, srr0) | ||
39 | GSETSPR(27, srr1) | ||
40 | GSETSPR(272, sprg0) | ||
41 | GSETSPR(273, sprg1) | ||
42 | GSETSPR(274, sprg2) | ||
43 | GSETSPR(275, sprg3) | ||
44 | GSETSPR(282, ear) | ||
45 | GSETSPR(287, pvr) | ||
46 | GSETSPR(1008, hid0) | ||
47 | GSETSPR(1009, hid1) | ||
48 | GSETSPR(1010, iabr) | ||
49 | GSETSPR(1023, pir) | ||
50 | |||
51 | static inline void store_inst(void *p) | ||
52 | { | ||
53 | asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p)); | ||
54 | } | ||
55 | |||
56 | static inline void cflush(void *p) | ||
57 | { | ||
58 | asm volatile ("dcbf 0,%0; icbi 0,%0" : : "r" (p)); | ||
59 | } | ||
60 | |||
61 | static inline void cinval(void *p) | ||
62 | { | ||
63 | asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p)); | ||
64 | } | ||
diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h deleted file mode 100644 index 3efc3288f7e9..000000000000 --- a/include/asm-ppc64/page.h +++ /dev/null | |||
@@ -1,328 +0,0 @@ | |||
1 | #ifndef _PPC64_PAGE_H | ||
2 | #define _PPC64_PAGE_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (C) 2001 PPC64 Team, IBM Corp | ||
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/config.h> | ||
14 | #include <asm/asm-compat.h> | ||
15 | |||
16 | /* | ||
17 | * We support either 4k or 64k software page size. When using 64k pages | ||
18 | * however, wether we are really supporting 64k pages in HW or not is | ||
19 | * irrelevant to those definitions. We always define HW_PAGE_SHIFT to 12 | ||
20 | * as use of 64k pages remains a linux kernel specific, every notion of | ||
21 | * page number shared with the firmware, TCEs, iommu, etc... still assumes | ||
22 | * a page size of 4096. | ||
23 | */ | ||
24 | #ifdef CONFIG_PPC_64K_PAGES | ||
25 | #define PAGE_SHIFT 16 | ||
26 | #else | ||
27 | #define PAGE_SHIFT 12 | ||
28 | #endif | ||
29 | |||
30 | #define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT) | ||
31 | #define PAGE_MASK (~(PAGE_SIZE-1)) | ||
32 | |||
33 | /* HW_PAGE_SHIFT is always 4k pages */ | ||
34 | #define HW_PAGE_SHIFT 12 | ||
35 | #define HW_PAGE_SIZE (ASM_CONST(1) << HW_PAGE_SHIFT) | ||
36 | #define HW_PAGE_MASK (~(HW_PAGE_SIZE-1)) | ||
37 | |||
38 | /* PAGE_FACTOR is the number of bits factor between PAGE_SHIFT and | ||
39 | * HW_PAGE_SHIFT, that is 4k pages | ||
40 | */ | ||
41 | #define PAGE_FACTOR (PAGE_SHIFT - HW_PAGE_SHIFT) | ||
42 | |||
43 | /* Segment size */ | ||
44 | #define SID_SHIFT 28 | ||
45 | #define SID_MASK 0xfffffffffUL | ||
46 | #define ESID_MASK 0xfffffffff0000000UL | ||
47 | #define GET_ESID(x) (((x) >> SID_SHIFT) & SID_MASK) | ||
48 | |||
49 | /* Large pages size */ | ||
50 | |||
51 | #ifndef __ASSEMBLY__ | ||
52 | extern unsigned int HPAGE_SHIFT; | ||
53 | #define HPAGE_SIZE ((1UL) << HPAGE_SHIFT) | ||
54 | #define HPAGE_MASK (~(HPAGE_SIZE - 1)) | ||
55 | #define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) | ||
56 | #endif /* __ASSEMBLY__ */ | ||
57 | |||
58 | #ifdef CONFIG_HUGETLB_PAGE | ||
59 | |||
60 | |||
61 | #define HTLB_AREA_SHIFT 40 | ||
62 | #define HTLB_AREA_SIZE (1UL << HTLB_AREA_SHIFT) | ||
63 | #define GET_HTLB_AREA(x) ((x) >> HTLB_AREA_SHIFT) | ||
64 | |||
65 | #define LOW_ESID_MASK(addr, len) (((1U << (GET_ESID(addr+len-1)+1)) \ | ||
66 | - (1U << GET_ESID(addr))) & 0xffff) | ||
67 | #define HTLB_AREA_MASK(addr, len) (((1U << (GET_HTLB_AREA(addr+len-1)+1)) \ | ||
68 | - (1U << GET_HTLB_AREA(addr))) & 0xffff) | ||
69 | |||
70 | #define ARCH_HAS_HUGEPAGE_ONLY_RANGE | ||
71 | #define ARCH_HAS_PREPARE_HUGEPAGE_RANGE | ||
72 | #define ARCH_HAS_SETCLEAR_HUGE_PTE | ||
73 | |||
74 | #define touches_hugepage_low_range(mm, addr, len) \ | ||
75 | (LOW_ESID_MASK((addr), (len)) & (mm)->context.low_htlb_areas) | ||
76 | #define touches_hugepage_high_range(mm, addr, len) \ | ||
77 | (HTLB_AREA_MASK((addr), (len)) & (mm)->context.high_htlb_areas) | ||
78 | |||
79 | #define __within_hugepage_low_range(addr, len, segmask) \ | ||
80 | ((LOW_ESID_MASK((addr), (len)) | (segmask)) == (segmask)) | ||
81 | #define within_hugepage_low_range(addr, len) \ | ||
82 | __within_hugepage_low_range((addr), (len), \ | ||
83 | current->mm->context.low_htlb_areas) | ||
84 | #define __within_hugepage_high_range(addr, len, zonemask) \ | ||
85 | ((HTLB_AREA_MASK((addr), (len)) | (zonemask)) == (zonemask)) | ||
86 | #define within_hugepage_high_range(addr, len) \ | ||
87 | __within_hugepage_high_range((addr), (len), \ | ||
88 | current->mm->context.high_htlb_areas) | ||
89 | |||
90 | #define is_hugepage_only_range(mm, addr, len) \ | ||
91 | (touches_hugepage_high_range((mm), (addr), (len)) || \ | ||
92 | touches_hugepage_low_range((mm), (addr), (len))) | ||
93 | #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA | ||
94 | |||
95 | #define in_hugepage_area(context, addr) \ | ||
96 | (cpu_has_feature(CPU_FTR_16M_PAGE) && \ | ||
97 | ( ((1 << GET_HTLB_AREA(addr)) & (context).high_htlb_areas) || \ | ||
98 | ( ((addr) < 0x100000000L) && \ | ||
99 | ((1 << GET_ESID(addr)) & (context).low_htlb_areas) ) ) ) | ||
100 | |||
101 | #else /* !CONFIG_HUGETLB_PAGE */ | ||
102 | |||
103 | #define in_hugepage_area(mm, addr) 0 | ||
104 | |||
105 | #endif /* !CONFIG_HUGETLB_PAGE */ | ||
106 | |||
107 | /* align addr on a size boundary - adjust address up/down if needed */ | ||
108 | #define _ALIGN_UP(addr,size) (((addr)+((size)-1))&(~((size)-1))) | ||
109 | #define _ALIGN_DOWN(addr,size) ((addr)&(~((size)-1))) | ||
110 | |||
111 | /* align addr on a size boundary - adjust address up if needed */ | ||
112 | #define _ALIGN(addr,size) _ALIGN_UP(addr,size) | ||
113 | |||
114 | /* to align the pointer to the (next) page boundary */ | ||
115 | #define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE) | ||
116 | |||
117 | #ifdef __KERNEL__ | ||
118 | #ifndef __ASSEMBLY__ | ||
119 | #include <asm/cache.h> | ||
120 | |||
121 | #undef STRICT_MM_TYPECHECKS | ||
122 | |||
123 | #define REGION_SIZE 4UL | ||
124 | #define REGION_SHIFT 60UL | ||
125 | #define REGION_MASK (((1UL<<REGION_SIZE)-1UL)<<REGION_SHIFT) | ||
126 | |||
127 | static __inline__ void clear_page(void *addr) | ||
128 | { | ||
129 | unsigned long lines, line_size; | ||
130 | |||
131 | line_size = ppc64_caches.dline_size; | ||
132 | lines = ppc64_caches.dlines_per_page; | ||
133 | |||
134 | __asm__ __volatile__( | ||
135 | "mtctr %1 # clear_page\n\ | ||
136 | 1: dcbz 0,%0\n\ | ||
137 | add %0,%0,%3\n\ | ||
138 | bdnz+ 1b" | ||
139 | : "=r" (addr) | ||
140 | : "r" (lines), "0" (addr), "r" (line_size) | ||
141 | : "ctr", "memory"); | ||
142 | } | ||
143 | |||
144 | extern void copy_4K_page(void *to, void *from); | ||
145 | |||
146 | #ifdef CONFIG_PPC_64K_PAGES | ||
147 | static inline void copy_page(void *to, void *from) | ||
148 | { | ||
149 | unsigned int i; | ||
150 | for (i=0; i < (1 << (PAGE_SHIFT - 12)); i++) { | ||
151 | copy_4K_page(to, from); | ||
152 | to += 4096; | ||
153 | from += 4096; | ||
154 | } | ||
155 | } | ||
156 | #else /* CONFIG_PPC_64K_PAGES */ | ||
157 | static inline void copy_page(void *to, void *from) | ||
158 | { | ||
159 | copy_4K_page(to, from); | ||
160 | } | ||
161 | #endif /* CONFIG_PPC_64K_PAGES */ | ||
162 | |||
163 | struct page; | ||
164 | extern void clear_user_page(void *page, unsigned long vaddr, struct page *pg); | ||
165 | extern void copy_user_page(void *to, void *from, unsigned long vaddr, struct page *p); | ||
166 | |||
167 | #ifdef STRICT_MM_TYPECHECKS | ||
168 | /* | ||
169 | * These are used to make use of C type-checking. | ||
170 | * Entries in the pte table are 64b, while entries in the pgd & pmd are 32b. | ||
171 | */ | ||
172 | |||
173 | /* PTE level */ | ||
174 | typedef struct { unsigned long pte; } pte_t; | ||
175 | #define pte_val(x) ((x).pte) | ||
176 | #define __pte(x) ((pte_t) { (x) }) | ||
177 | |||
178 | /* 64k pages additionally define a bigger "real PTE" type that gathers | ||
179 | * the "second half" part of the PTE for pseudo 64k pages | ||
180 | */ | ||
181 | #ifdef CONFIG_PPC_64K_PAGES | ||
182 | typedef struct { pte_t pte; unsigned long hidx; } real_pte_t; | ||
183 | #else | ||
184 | typedef struct { pte_t pte; } real_pte_t; | ||
185 | #endif | ||
186 | |||
187 | /* PMD level */ | ||
188 | typedef struct { unsigned long pmd; } pmd_t; | ||
189 | #define pmd_val(x) ((x).pmd) | ||
190 | #define __pmd(x) ((pmd_t) { (x) }) | ||
191 | |||
192 | /* PUD level exusts only on 4k pages */ | ||
193 | #ifndef CONFIG_PPC_64K_PAGES | ||
194 | typedef struct { unsigned long pud; } pud_t; | ||
195 | #define pud_val(x) ((x).pud) | ||
196 | #define __pud(x) ((pud_t) { (x) }) | ||
197 | #endif | ||
198 | |||
199 | /* PGD level */ | ||
200 | typedef struct { unsigned long pgd; } pgd_t; | ||
201 | #define pgd_val(x) ((x).pgd) | ||
202 | #define __pgd(x) ((pgd_t) { (x) }) | ||
203 | |||
204 | /* Page protection bits */ | ||
205 | typedef struct { unsigned long pgprot; } pgprot_t; | ||
206 | #define pgprot_val(x) ((x).pgprot) | ||
207 | #define __pgprot(x) ((pgprot_t) { (x) }) | ||
208 | |||
209 | #else | ||
210 | |||
211 | /* | ||
212 | * .. while these make it easier on the compiler | ||
213 | */ | ||
214 | |||
215 | typedef unsigned long pte_t; | ||
216 | #define pte_val(x) (x) | ||
217 | #define __pte(x) (x) | ||
218 | |||
219 | #ifdef CONFIG_PPC_64K_PAGES | ||
220 | typedef struct { pte_t pte; unsigned long hidx; } real_pte_t; | ||
221 | #else | ||
222 | typedef unsigned long real_pte_t; | ||
223 | #endif | ||
224 | |||
225 | |||
226 | typedef unsigned long pmd_t; | ||
227 | #define pmd_val(x) (x) | ||
228 | #define __pmd(x) (x) | ||
229 | |||
230 | #ifndef CONFIG_PPC_64K_PAGES | ||
231 | typedef unsigned long pud_t; | ||
232 | #define pud_val(x) (x) | ||
233 | #define __pud(x) (x) | ||
234 | #endif | ||
235 | |||
236 | typedef unsigned long pgd_t; | ||
237 | #define pgd_val(x) (x) | ||
238 | #define pgprot_val(x) (x) | ||
239 | |||
240 | typedef unsigned long pgprot_t; | ||
241 | #define __pgd(x) (x) | ||
242 | #define __pgprot(x) (x) | ||
243 | |||
244 | #endif | ||
245 | |||
246 | #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) | ||
247 | |||
248 | extern int page_is_ram(unsigned long pfn); | ||
249 | |||
250 | extern u64 ppc64_pft_size; /* Log 2 of page table size */ | ||
251 | |||
252 | /* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */ | ||
253 | #define __HAVE_ARCH_GATE_AREA 1 | ||
254 | |||
255 | #endif /* __ASSEMBLY__ */ | ||
256 | |||
257 | #ifdef MODULE | ||
258 | #define __page_aligned __attribute__((__aligned__(PAGE_SIZE))) | ||
259 | #else | ||
260 | #define __page_aligned \ | ||
261 | __attribute__((__aligned__(PAGE_SIZE), \ | ||
262 | __section__(".data.page_aligned"))) | ||
263 | #endif | ||
264 | |||
265 | |||
266 | /* This must match the -Ttext linker address */ | ||
267 | /* Note: tophys & tovirt make assumptions about how */ | ||
268 | /* KERNELBASE is defined for performance reasons. */ | ||
269 | /* When KERNELBASE moves, those macros may have */ | ||
270 | /* to change! */ | ||
271 | #define PAGE_OFFSET ASM_CONST(0xC000000000000000) | ||
272 | #define KERNELBASE PAGE_OFFSET | ||
273 | #define VMALLOCBASE ASM_CONST(0xD000000000000000) | ||
274 | |||
275 | #define VMALLOC_REGION_ID (VMALLOCBASE >> REGION_SHIFT) | ||
276 | #define KERNEL_REGION_ID (KERNELBASE >> REGION_SHIFT) | ||
277 | #define USER_REGION_ID (0UL) | ||
278 | #define REGION_ID(ea) (((unsigned long)(ea)) >> REGION_SHIFT) | ||
279 | |||
280 | #define __va(x) ((void *)((unsigned long)(x) + KERNELBASE)) | ||
281 | |||
282 | #ifdef CONFIG_FLATMEM | ||
283 | #define pfn_to_page(pfn) (mem_map + (pfn)) | ||
284 | #define page_to_pfn(page) ((unsigned long)((page) - mem_map)) | ||
285 | #define pfn_valid(pfn) ((pfn) < max_mapnr) | ||
286 | #endif | ||
287 | |||
288 | #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) | ||
289 | #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) | ||
290 | |||
291 | #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) | ||
292 | |||
293 | /* | ||
294 | * Unfortunately the PLT is in the BSS in the PPC32 ELF ABI, | ||
295 | * and needs to be executable. This means the whole heap ends | ||
296 | * up being executable. | ||
297 | */ | ||
298 | #define VM_DATA_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \ | ||
299 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
300 | |||
301 | #define VM_DATA_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \ | ||
302 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
303 | |||
304 | #define VM_DATA_DEFAULT_FLAGS \ | ||
305 | (test_thread_flag(TIF_32BIT) ? \ | ||
306 | VM_DATA_DEFAULT_FLAGS32 : VM_DATA_DEFAULT_FLAGS64) | ||
307 | |||
308 | /* | ||
309 | * This is the default if a program doesn't have a PT_GNU_STACK | ||
310 | * program header entry. The PPC64 ELF ABI has a non executable stack | ||
311 | * stack by default, so in the absense of a PT_GNU_STACK program header | ||
312 | * we turn execute permission off. | ||
313 | */ | ||
314 | #define VM_STACK_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \ | ||
315 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
316 | |||
317 | #define VM_STACK_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \ | ||
318 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | ||
319 | |||
320 | #define VM_STACK_DEFAULT_FLAGS \ | ||
321 | (test_thread_flag(TIF_32BIT) ? \ | ||
322 | VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64) | ||
323 | |||
324 | #endif /* __KERNEL__ */ | ||
325 | |||
326 | #include <asm-generic/page.h> | ||
327 | |||
328 | #endif /* _PPC64_PAGE_H */ | ||